Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/main/java/net/tfminecraft/games/Games.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,13 @@ public void onEnable() {
@Override
public void onDisable() {
TableManager.get().stopClock();
TableManager.get().despawnWorldAll();
try {
TableManager.get().despawnWorldAll();
} finally {
// Tables that were not reset above (money held for review) still get their last
// card changes written.
TableManager.get().flushUnsaved();
}
DisplayManager.get().shutdown();
ProtocolLibBridge.shutdown();
if(ownershipActive && TableManager.get().tables().stream().noneMatch(table->table.ownershipHeld() || table.moneyBlocked()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ public Conflict(String message) {
public record Row(
Path path, UUID id, UUID account, UUID character, OwnershipKind kind, JsonObject raw) {}

private record Source(Path path, String hash, JsonObject raw) {}
/**
* The bytes this store last saw at a table's path. {@code durable} is set only when this
* process wrote them itself and the whole write, directory flush included, succeeded.
*/
private record Source(Path path, String hash, JsonObject raw, boolean durable) {}

private final Path folder;
private final OwnershipMigration migration;
Expand Down Expand Up @@ -64,7 +68,10 @@ private void captureSource(Path file) throws IOException {
conflicts.add(id);
throw new Conflict("Duplicate table ID");
}
sources.put(id, new Source(file, OwnershipMigration.hash(Files.readAllBytes(file)), raw));
String hash = OwnershipMigration.hash(Files.readAllBytes(file));
// Reading back the very bytes this process wrote keeps them known as fully written.
boolean durable = previous != null && previous.durable() && previous.hash().equals(hash);
sources.put(id, new Source(file, hash, raw, durable));
rememberWagers(id, raw);
}

Expand Down Expand Up @@ -153,17 +160,33 @@ public void save(UUID id, JsonObject known) throws IOException {
JsonObject next = previous == null ? known.deepCopy() : overlay(id, previous.raw(), known);
OwnershipMigration.validateRow(next);
String text = RawJson.JSON.toJson(next);
String hash = OwnershipMigration.hash(text.getBytes(java.nio.charset.StandardCharsets.UTF_8));
// check() has just read the file and found exactly the bytes this process last wrote
// there in full, so the same bytes again need no new write or flush. A failed write never
// reaches sources, so whatever it tried to write is still written next time.
if (previous != null && previous.durable() && previous.hash().equals(hash)) return;
DurableFiles.write(file, text);
sources.put(
id,
new Source(
file,
OwnershipMigration.hash(
text.getBytes(java.nio.charset.StandardCharsets.UTF_8)),
next));
sources.put(id, new Source(file, hash, next, true));
rememberWagers(id, next);
}

/**
* The file and raw row this store last wrote or read for a table, or null. Callers that
* trust it must run {@link #check(UUID)} first.
*/
public Row source(UUID id) {
Source source = sources.get(id);
if (source == null) return null;
JsonObject raw = source.raw().deepCopy();
return new Row(
source.path(),
id,
RawJson.uuid(raw.get("ownerPlayer")),
RawJson.uuid(raw.get("ownerCharacterId")),
OwnershipKind.of(raw),
raw);
}

public void publish(Row before, JsonObject next) throws IOException {
if (!before.raw().equals(row(before.path()).raw())) {
conflicts.add(before.id());
Expand All @@ -182,7 +205,7 @@ public void publish(Row before, JsonObject next) throws IOException {
if (Files.isRegularFile(before.path())
&& afterHash.equals(
OwnershipMigration.hash(Files.readAllBytes(before.path())))) {
sources.put(before.id(), new Source(before.path(), afterHash, next));
sources.put(before.id(), new Source(before.path(), afterHash, next, false));
publicationPending.add(before.id());
}
throw ex;
Expand All @@ -194,7 +217,8 @@ public void publish(Row before, JsonObject next) throws IOException {
before.path(),
OwnershipMigration.hash(
text.getBytes(java.nio.charset.StandardCharsets.UTF_8)),
next));
next,
true));
rememberWagers(before.id(), next);
}

Expand Down
Loading
Loading