Skip to content

Commit

Permalink
/back implementation begin
Browse files Browse the repository at this point in the history
  • Loading branch information
TheCurle committed Mar 2, 2025
1 parent 5982b58 commit 89e8f76
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 0 deletions.
8 changes: 8 additions & 0 deletions src/main/java/uk/gemwire/bareessentials/BareEssentials.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import uk.gemwire.bareessentials.commands.PermissionNodes;
import uk.gemwire.bareessentials.data.Bank;
import uk.gemwire.bareessentials.data.Homes;
import uk.gemwire.bareessentials.data.TeleportRewind;


/**
Expand Down Expand Up @@ -112,6 +113,7 @@ public class BareEssentials {
public static GameRules.Key<GameRules.IntegerValue> CURRENCY_SYMBOL = GameRules.register("be.currencySymbol", GameRules.Category.CHAT, GameRules.IntegerValue.create(0));
public static GameRules.Key<GameRules.IntegerValue> STARTING_BALANCE = GameRules.register("be.bankStartingBalance", GameRules.Category.PLAYER, GameRules.IntegerValue.create(500));
public static GameRules.Key<GameRules.IntegerValue> DAILY_INCOME = GameRules.register("be.bankDailyIncome", GameRules.Category.PLAYER, GameRules.IntegerValue.create(10));
// TODO
public static GameRules.Key<GameRules.IntegerValue> MAX_HOMES = GameRules.register("be.maxHomes", GameRules.Category.PLAYER, GameRules.IntegerValue.create(1));
public static GameRules.Key<GameRules.IntegerValue> TPA_COST = GameRules.register("be.tpaCost", GameRules.Category.PLAYER, GameRules.IntegerValue.create(0));
public static GameRules.Key<GameRules.IntegerValue> SPAWN_COST = GameRules.register("be.spawnCost", GameRules.Category.PLAYER, GameRules.IntegerValue.create(0));
Expand All @@ -120,6 +122,9 @@ public class BareEssentials {

public static GameRules.Key<GameRules.BooleanValue> OP_OVERRIDES_COOLDOWN = GameRules.register("be.opOverridesCooldowns", GameRules.Category.PLAYER, GameRules.BooleanValue.create(false));

// Whether /back will traverse the stack of back-able events. If you go to the nether and then accept a tpa back to the overworld, you can /back twice to return to the Overworld nether portal, if stacking is enabled.
public static GameRules.Key<GameRules.BooleanValue> BACK_STACK = GameRules.register("be.backStack", GameRules.Category.PLAYER, GameRules.BooleanValue.create(true));

public static ObjectiveCriteria BANK_ACCOUNT_VALUE = ObjectiveCriteria.registerCustom("bank_value");
public static Objective BANK_ACCOUNT_SORTED_OBJECTIVE;

Expand Down Expand Up @@ -154,6 +159,9 @@ public static void login(PlayerEvent.PlayerLoggedInEvent e) {
// Ensure the new player has a bank account so they receive income while offline.
Bank accts = Bank.getOrCreate(e.getEntity().getServer().overworld());
accts.getUserBalance((ServerPlayer) e.getEntity());
// Ensure the player's last rewind position is available as soon as they log in.
TeleportRewind rewinds = TeleportRewind.getOrCreate(e.getEntity().getServer().overworld());

}

@SubscribeEvent
Expand Down
103 changes: 103 additions & 0 deletions src/main/java/uk/gemwire/bareessentials/data/TeleportRewind.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package uk.gemwire.bareessentials.data;

import net.minecraft.core.BlockPos;
import net.minecraft.core.HolderLookup;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.saveddata.SavedData;

import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
import java.util.UUID;

public class TeleportRewind extends SavedData {

// Every player has a list of things they can undo.
public Map<UUID, Stack<TeleportEvent>> playerBacks = new HashMap<>();

private static final Factory<TeleportRewind> rewindFactory
= new Factory<>(TeleportRewind::new, TeleportRewind::load, null);

public TeleportRewind() {
}

public TeleportRewind(Map<UUID, TeleportEvent> firstBacks) {
for (Map.Entry<UUID, TeleportEvent> tele : firstBacks.entrySet()) {
playerBacks.put(tele.getKey(), new Stack<>());
playerBacks.get(tele.getKey()).add(tele.getValue());
}
}

@Override
public CompoundTag save(final CompoundTag tag, final HolderLookup.Provider registries) {
CompoundTag map = new CompoundTag();
for (var tele : playerBacks.entrySet()) {
TeleportEvent event = tele.getValue().pop();
CompoundTag entry = new CompoundTag();
CompoundTag source = new CompoundTag();
source.putInt("x", event.origin.getX());
source.putInt("y", event.origin.getX());
source.putInt("z", event.origin.getX());
CompoundTag destination = new CompoundTag();
destination.putInt("x", event.destination.getX());
destination.putInt("y", event.destination.getX());
destination.putInt("z", event.destination.getX());
entry.put("source", source);
entry.put("destination", destination);
entry.putString("type", event.type.getName());
map.put(tele.getKey().toString(), entry);
}
tag.put("be_rewinds", map);
return tag;
}

public static TeleportRewind load(CompoundTag tag, final HolderLookup.Provider prov) {
CompoundTag map = tag.getCompound("be_rewinds");
Map<UUID, TeleportEvent> teleports = new HashMap<>();
for (String key : map.getAllKeys()) {
UUID player = UUID.fromString(key);
CompoundTag entry = (CompoundTag) map.get(key);
CompoundTag source = (CompoundTag) entry.get("source");
BlockPos sourcePos = new BlockPos(source.getInt("x"), source.getInt("y"), source.getInt("z"));
CompoundTag destination = (CompoundTag) entry.get("destination");
BlockPos destPos = new BlockPos(destination.getInt("x"), destination.getInt("y"), destination.getInt("z"));
TeleportEvent evt = new TeleportEvent(EventType.fromString(entry.getString("type")), sourcePos, destPos);

teleports.put(player,evt);
}

return new TeleportRewind(teleports);
}

public static TeleportRewind getOrCreate(ServerLevel level) {
return level.getDataStorage().computeIfAbsent(rewindFactory, "be_back");
}


/**
* Teleport Events are a record of Type,Source,Destination
*/
public enum EventType {
DEATH("DEATH"), // Death moves you to spawn / bed
PORTAL("PORTAL"), // End/Nether/Modded Portal; onTravelToDimension via Entity#changeDimension
COMMAND("COMMAND"); // Entity#moveto, via /tp. /tpa

String name;
EventType(String name) { this.name = name; }

public String getName() { return name; }

public static EventType fromString(String name) {
return switch (name) {
case "DEATH" -> DEATH;
case "PORTAL" -> PORTAL;
case "COMMAND" -> COMMAND;
default -> throw new IllegalStateException("Unexpected value: " + name);
};
}
}

public record TeleportEvent(EventType type, BlockPos origin, BlockPos destination) {
}
}

0 comments on commit 89e8f76

Please sign in to comment.