mirror of
https://github.com/GTNewHorizons/Postea.git
synced 2026-10-26 14:24:19 +00:00
Run versioned transformers on player data read and write
This commit is contained in:
5 files changed
+138
No files matched your search
@@ -1,8 +1,55 @@
|
||||
package com.gtnewhorizons.postea.api;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
|
||||
import com.gtnewhorizons.postea.utility.NbtItemStacks;
|
||||
import com.gtnewhorizons.postea.utility.VersionStamps;
|
||||
|
||||
/**
|
||||
* A player's saved data as handed to {@link IVersionedTransformer#transformPlayer}: the root tag about to be
|
||||
* loaded into the player, which holds the inventory, ender chest, {@code ForgeData}, and every extended-properties
|
||||
* compound. The player object is constructed but not yet loaded from the tag.
|
||||
*/
|
||||
public final class PlayerDataTransformContext {
|
||||
|
||||
public static final int UNSTAMPED = VersionStamps.UNSTAMPED;
|
||||
|
||||
private final EntityPlayerMP player;
|
||||
private final NBTTagCompound playerTag;
|
||||
private final int storedVersion;
|
||||
private final int currentVersion;
|
||||
|
||||
public PlayerDataTransformContext(EntityPlayerMP player, NBTTagCompound playerTag, int storedVersion,
|
||||
int currentVersion) {
|
||||
this.player = player;
|
||||
this.playerTag = playerTag;
|
||||
this.storedVersion = storedVersion;
|
||||
this.currentVersion = currentVersion;
|
||||
}
|
||||
|
||||
public EntityPlayerMP player() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public NBTTagCompound playerTag() {
|
||||
return playerTag;
|
||||
}
|
||||
|
||||
public int storedVersion() {
|
||||
return storedVersion;
|
||||
}
|
||||
|
||||
public int currentVersion() {
|
||||
return currentVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits every serialized item stack anywhere in the player's data; see {@link NbtItemStacks#forEach}.
|
||||
*/
|
||||
public void forEachItemStackTag(Consumer<NBTTagCompound> visitor) {
|
||||
NbtItemStacks.forEach(playerTag, visitor);
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,7 @@ public final class PosteaLoadingPlugin implements IEarlyMixinLoader, IFMLLoading
|
||||
final List<String> mixins = new ArrayList<>();
|
||||
mixins.add("MixinItemStack");
|
||||
mixins.add("MixinChunk");
|
||||
mixins.add("MixinEntity");
|
||||
mixins.add("MixinAnvilChunkLoader");
|
||||
mixins.add("MixinNBTTagList");
|
||||
return mixins;
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.gtnewhorizons.postea.mixins.early;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import com.gtnewhorizons.postea.utility.PlayerDataFixerUtility;
|
||||
|
||||
@Mixin(Entity.class)
|
||||
public abstract class MixinEntity {
|
||||
|
||||
@Unique
|
||||
private NBTTagCompound postea$versionStamps;
|
||||
|
||||
@Inject(method = "readFromNBT", at = @At("HEAD"), require = 1)
|
||||
private void postea$transformPlayerData(NBTTagCompound tag, CallbackInfo ci) {
|
||||
if ((Object) this instanceof EntityPlayerMP player) {
|
||||
postea$versionStamps = PlayerDataFixerUtility.onPlayerRead(player, tag);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "writeToNBT", at = @At("RETURN"), require = 1)
|
||||
private void postea$stampPlayerData(NBTTagCompound tag, CallbackInfo ci) {
|
||||
if ((Object) this instanceof EntityPlayerMP) {
|
||||
PlayerDataFixerUtility.onPlayerWrite(tag, postea$versionStamps);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.gtnewhorizons.postea.utility;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.ReportedException;
|
||||
|
||||
import com.gtnewhorizons.postea.Postea;
|
||||
import com.gtnewhorizons.postea.api.IVersionedTransformer;
|
||||
import com.gtnewhorizons.postea.api.PlayerDataTransformContext;
|
||||
import com.gtnewhorizons.postea.api.VersionedReplacementManager;
|
||||
|
||||
/**
|
||||
* Runs versioned transformers over a server player's NBT as it is read, and stamps it as it is written. Hooked on
|
||||
* {@code Entity.readFromNBT}/{@code writeToNBT} so both the {@code playerdata/<uuid>.dat} files and the
|
||||
* single-player host's copy inside {@code level.dat} are covered.
|
||||
*/
|
||||
public final class PlayerDataFixerUtility {
|
||||
|
||||
private PlayerDataFixerUtility() {}
|
||||
|
||||
/**
|
||||
* Transforms {@code tag} in place and returns a copy of the stamps it carried (null when unstamped).
|
||||
*/
|
||||
public static NBTTagCompound onPlayerRead(EntityPlayerMP player, NBTTagCompound tag) {
|
||||
NBTTagCompound stamps = VersionStamps.read(tag);
|
||||
for (IVersionedTransformer transformer : VersionedReplacementManager.transformers()) {
|
||||
int current = transformer.currentVersion();
|
||||
int stored = VersionStamps.stored(stamps, transformer.key());
|
||||
if (stored == current) continue;
|
||||
Postea.LOG.debug(
|
||||
"{}: player {} from version {} to {}",
|
||||
transformer.key(),
|
||||
player.getCommandSenderName(),
|
||||
stored,
|
||||
current);
|
||||
try {
|
||||
transformer.transformPlayer(new PlayerDataTransformContext(player, tag, stored, current));
|
||||
} catch (Throwable t) {
|
||||
throw new ReportedException(
|
||||
ChunkFixerUtility.describe(
|
||||
t,
|
||||
transformer,
|
||||
stored,
|
||||
current,
|
||||
"Player",
|
||||
player.getCommandSenderName() + " (" + player.getUniqueID() + ")"));
|
||||
}
|
||||
}
|
||||
return stamps == null ? null : (NBTTagCompound) stamps.copy();
|
||||
}
|
||||
|
||||
public static void onPlayerWrite(NBTTagCompound tag, NBTTagCompound carried) {
|
||||
VersionStamps.write(tag, carried, VersionedReplacementManager.transformers());
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@
|
||||
"mixins": [
|
||||
"MixinAnvilChunkLoader",
|
||||
"MixinChunk",
|
||||
"MixinEntity",
|
||||
"MixinItemStack",
|
||||
"MixinNBTTagList"
|
||||
],
|
||||
|
||||
Reference in new issue
Block a user