mirror of
https://github.com/KAMKEEL/CustomNPC-Plus.git
synced 2026-11-12 21:17:32 +00:00
Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
ddb4072ac1
23 files changed
+62
-201
No files matched your search
@@ -19,56 +19,12 @@ import noppes.npcs.controllers.data.IScriptUnit;
|
||||
import noppes.npcs.items.ItemNpcTool;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class PacketUtil {
|
||||
|
||||
// ==================== SCRIPT SESSION TOKEN SYSTEM ====================
|
||||
// Prevents saving script data before the client has received it from the server.
|
||||
// Each GET generates a token sent to the client; each SAVE must echo it back.
|
||||
// Multiple tokens per player are allowed so concurrent script editors don't invalidate each other.
|
||||
// Tokens are consumed on successful verify to prevent unbounded growth.
|
||||
|
||||
private static final int MAX_TOKENS_PER_PLAYER = 10;
|
||||
private static final Map<UUID, Set<String>> scriptSessionTokens = new ConcurrentHashMap<>();
|
||||
|
||||
public static String createScriptSession(EntityPlayerMP player) {
|
||||
String token = Long.toHexString(ThreadLocalRandom.current().nextLong());
|
||||
Set<String> tokens = scriptSessionTokens.computeIfAbsent(player.getUniqueID(), k -> new LinkedHashSet<>());
|
||||
synchronized (tokens) {
|
||||
// Evict oldest tokens if at capacity
|
||||
while (tokens.size() >= MAX_TOKENS_PER_PLAYER) {
|
||||
Iterator<String> it = tokens.iterator();
|
||||
it.next();
|
||||
it.remove();
|
||||
}
|
||||
tokens.add(token);
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
public static boolean verifyScriptSession(EntityPlayer player, String token) {
|
||||
if (token == null || token.isEmpty())
|
||||
return false;
|
||||
Set<String> tokens = scriptSessionTokens.get(player.getUniqueID());
|
||||
if (tokens == null)
|
||||
return false;
|
||||
synchronized (tokens) {
|
||||
return tokens.remove(token);
|
||||
}
|
||||
}
|
||||
|
||||
public static void clearScriptSession(EntityPlayer player) {
|
||||
scriptSessionTokens.remove(player.getUniqueID());
|
||||
}
|
||||
|
||||
public static boolean verifyItemPacket(String name, EnumItemPacketType type, EntityPlayer player) {
|
||||
if (player == null)
|
||||
return false;
|
||||
@@ -260,14 +216,11 @@ public class PacketUtil {
|
||||
}
|
||||
|
||||
public static void getScripts(IScriptHandler data, EntityPlayerMP player) {
|
||||
String token = createScriptSession(player);
|
||||
|
||||
NBTTagCompound compound = new NBTTagCompound();
|
||||
compound.setBoolean("ScriptEnabled", data.getEnabled());
|
||||
compound.setString("ScriptLanguage", data.getLanguage());
|
||||
compound.setTag("Languages", ScriptController.Instance.nbtLanguages());
|
||||
compound.setTag("ScriptConsole", NBTTags.NBTLongStringMap(data.getConsoleText()));
|
||||
compound.setString("ScriptSessionToken", token);
|
||||
GuiDataPacket.sendGuiData(player, compound);
|
||||
List<IScriptUnit> containers = data.getScripts();
|
||||
for (int i = 0; i < containers.size(); i++) {
|
||||
@@ -284,18 +237,9 @@ public class PacketUtil {
|
||||
GuiDataPacket.sendGuiData(player, loadComplete);
|
||||
}
|
||||
|
||||
public static boolean saveScripts(IScriptHandler data, ByteBuf buffer, EntityPlayer player) throws IOException {
|
||||
public static void saveScripts(IScriptHandler data, ByteBuf buffer) throws IOException {
|
||||
int tab = buffer.readInt();
|
||||
int totalScripts = buffer.readInt();
|
||||
NBTTagCompound compound = ByteBufUtils.readNBT(buffer);
|
||||
|
||||
// Verify script session token to prevent saving unloaded defaults
|
||||
String token = compound.getString("ScriptSessionToken");
|
||||
if (!verifyScriptSession(player, token)) {
|
||||
LogWriter.error(String.format("Rejected script save from %s: session not verified (data not loaded)", player.getCommandSenderName()));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (totalScripts == 0) {
|
||||
data.getScripts().clear();
|
||||
}
|
||||
@@ -306,10 +250,12 @@ public class PacketUtil {
|
||||
} else while (data.getScripts().size() < totalScripts) {
|
||||
data.getScripts().add(new ScriptContainer(data));
|
||||
}
|
||||
NBTTagCompound tabCompound = ByteBufUtils.readNBT(buffer);
|
||||
// Use factory method to create correct script unit type based on NBT
|
||||
IScriptUnit script = IScriptUnit.createFromNBT(compound, data);
|
||||
IScriptUnit script = IScriptUnit.createFromNBT(tabCompound, data);
|
||||
data.getScripts().set(tab, script);
|
||||
} else {
|
||||
NBTTagCompound compound = ByteBufUtils.readNBT(buffer);
|
||||
data.setLanguage(compound.getString("ScriptLanguage"));
|
||||
if (!ScriptController.Instance.languages.containsKey(data.getLanguage())) {
|
||||
if (!ScriptController.Instance.languages.isEmpty()) {
|
||||
@@ -320,6 +266,5 @@ public class PacketUtil {
|
||||
}
|
||||
data.setEnabled(compound.getBoolean("ScriptEnabled"));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,6 @@ import kamkeel.npcs.network.PacketClient;
|
||||
import kamkeel.npcs.network.PacketHandler;
|
||||
import kamkeel.npcs.network.enums.EnumPlayerPacket;
|
||||
import kamkeel.npcs.network.packets.data.npc.UpdateNpcPacket;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
@@ -17,16 +16,10 @@ import net.minecraft.nbt.NBTTagCompound;
|
||||
import noppes.npcs.entity.EntityNPCInterface;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
public class RequestProperSpawnData extends AbstractPacket {
|
||||
public static final String packetName = "Player|SpawnData";
|
||||
private static final int BATCH_LIMIT = 5;
|
||||
|
||||
private static final Set<Integer> entitiesToFix = new HashSet<>();
|
||||
private static long lastBatchAttemptMillis = 0L;
|
||||
private static final long REQUEST_COOLDOWN_MILLIS = 1000L;
|
||||
private int entityId;
|
||||
|
||||
public RequestProperSpawnData() {}
|
||||
@@ -37,8 +30,7 @@ public class RequestProperSpawnData extends AbstractPacket {
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public static void clear() {
|
||||
entitiesToFix.clear();
|
||||
lastBatchAttemptMillis = 0L;
|
||||
// No backlog queue to clear.
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -81,40 +73,24 @@ public class RequestProperSpawnData extends AbstractPacket {
|
||||
if (entityID <= 0)
|
||||
return;
|
||||
|
||||
if (npc.clientFixAttempts++ < 3) {
|
||||
PacketClient.sendClient(new RequestProperSpawnData(entityID));
|
||||
} else {
|
||||
entitiesToFix.add(entityID);
|
||||
}
|
||||
long now = System.currentTimeMillis();
|
||||
if (now - npc.clientFixLastRequestMillis < REQUEST_COOLDOWN_MILLIS)
|
||||
return;
|
||||
if (npc.clientFixAttempts >= 3)
|
||||
return;
|
||||
|
||||
npc.clientFixLastRequestMillis = now;
|
||||
npc.clientFixAttempts++;
|
||||
PacketClient.sendClient(new RequestProperSpawnData(entityID));
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public static boolean canDoBatchUpdate() {
|
||||
return System.currentTimeMillis() - lastBatchAttemptMillis >= 5000;
|
||||
return false;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public static void handleBacklog() {
|
||||
Minecraft mc = Minecraft.getMinecraft();
|
||||
if (mc == null || mc.theWorld == null || mc.thePlayer == null)
|
||||
return;
|
||||
|
||||
if (entitiesToFix.isEmpty())
|
||||
return;
|
||||
// Remove entity checks if they're no longer loaded
|
||||
entitiesToFix.removeIf(value -> !(mc.theWorld.getEntityByID(value) instanceof EntityNPCInterface));
|
||||
|
||||
Iterator<Integer> it = entitiesToFix.iterator();
|
||||
int count = 0;
|
||||
|
||||
while (it.hasNext() && count < BATCH_LIMIT) {
|
||||
PacketClient.sendClient(new RequestProperSpawnData(it.next()));
|
||||
it.remove();
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count != 0) {
|
||||
lastBatchAttemptMillis = System.currentTimeMillis();
|
||||
}
|
||||
// No batch backlog. Requests are immediate and throttled in reportMissingData().
|
||||
}
|
||||
}
|
||||
@@ -98,7 +98,7 @@ public final class AbilityScriptPacket extends AbstractPacket {
|
||||
if (requestedAction == Action.GET) {
|
||||
PacketUtil.getScripts((IScriptHandler) data, (EntityPlayerMP) player);
|
||||
} else {
|
||||
data.saveScript(in, player);
|
||||
data.saveScript(in);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -107,8 +107,7 @@ public final class AbilityScriptPacket extends AbstractPacket {
|
||||
if (requestedAction == Action.GET) {
|
||||
PacketUtil.getScripts((IScriptHandler) data, (EntityPlayerMP) player);
|
||||
} else {
|
||||
if (!data.saveScript(in, player))
|
||||
return;
|
||||
data.saveScript(in);
|
||||
// Persist to disk
|
||||
AbilityController.Instance.saveCustomAbility(ability);
|
||||
if (ConfigDebug.PlayerLogging && FMLCommonHandler.instance().getEffectiveSide() == Side.SERVER) {
|
||||
|
||||
@@ -7,7 +7,6 @@ import kamkeel.npcs.network.AbstractPacket;
|
||||
import kamkeel.npcs.network.PacketChannel;
|
||||
import kamkeel.npcs.network.PacketClient;
|
||||
import kamkeel.npcs.network.PacketHandler;
|
||||
import kamkeel.npcs.network.PacketUtil;
|
||||
import kamkeel.npcs.network.enums.EnumRequestPacket;
|
||||
import kamkeel.npcs.network.packets.data.large.GuiDataPacket;
|
||||
import kamkeel.npcs.util.ByteBufUtils;
|
||||
@@ -16,7 +15,6 @@ import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import noppes.npcs.CustomNpcsPermissions;
|
||||
import noppes.npcs.LogWriter;
|
||||
import noppes.npcs.blocks.tiles.TileScripted;
|
||||
import noppes.npcs.config.ConfigScript;
|
||||
import noppes.npcs.controllers.ScriptController;
|
||||
@@ -83,10 +81,8 @@ public final class BlockScriptPacket extends AbstractPacket {
|
||||
TileEntity tile = player.worldObj.getTileEntity(in.readInt(), in.readInt(), in.readInt());
|
||||
if (!(tile instanceof TileScripted))
|
||||
return;
|
||||
String token = PacketUtil.createScriptSession((EntityPlayerMP) player);
|
||||
NBTTagCompound compound = ((TileScripted) tile).getNBT(new NBTTagCompound());
|
||||
compound.setTag("Languages", ScriptController.Instance.nbtLanguages());
|
||||
compound.setString("ScriptSessionToken", token);
|
||||
GuiDataPacket.sendGuiData((EntityPlayerMP) player, compound);
|
||||
|
||||
NBTTagCompound loadComplete = new NBTTagCompound();
|
||||
@@ -99,14 +95,8 @@ public final class BlockScriptPacket extends AbstractPacket {
|
||||
TileEntity tile = player.worldObj.getTileEntity(in.readInt(), in.readInt(), in.readInt());
|
||||
if (!(tile instanceof TileScripted))
|
||||
return;
|
||||
NBTTagCompound compound = ByteBufUtils.readNBT(in);
|
||||
String token = compound.getString("ScriptSessionToken");
|
||||
if (!PacketUtil.verifyScriptSession(player, token)) {
|
||||
LogWriter.error(String.format("Rejected block script save from %s: session not verified", player.getCommandSenderName()));
|
||||
return;
|
||||
}
|
||||
TileScripted script = (TileScripted) tile;
|
||||
script.setNBT(compound);
|
||||
script.setNBT(ByteBufUtils.readNBT(in));
|
||||
script.lastInited = -1;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -98,7 +98,7 @@ public final class ChainedAbilityScriptPacket extends AbstractPacket {
|
||||
if (requestedAction == Action.GET) {
|
||||
PacketUtil.getScripts((IScriptHandler) data, (EntityPlayerMP) player);
|
||||
} else {
|
||||
data.saveScript(in, player);
|
||||
data.saveScript(in);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -107,8 +107,7 @@ public final class ChainedAbilityScriptPacket extends AbstractPacket {
|
||||
if (requestedAction == Action.GET) {
|
||||
PacketUtil.getScripts((IScriptHandler) data, (EntityPlayerMP) player);
|
||||
} else {
|
||||
if (!data.saveScript(in, player))
|
||||
return;
|
||||
data.saveScript(in);
|
||||
// Persist to disk
|
||||
AbilityController.Instance.saveChainedAbility(chain);
|
||||
if (ConfigDebug.PlayerLogging && FMLCommonHandler.instance().getEffectiveSide() == Side.SERVER) {
|
||||
|
||||
@@ -90,8 +90,7 @@ public final class EffectScriptPacket extends AbstractPacket {
|
||||
if (requestedAction == Action.GET) {
|
||||
PacketUtil.getScripts((IScriptHandler) data, (EntityPlayerMP) player);
|
||||
} else {
|
||||
if (!data.saveScript(in, player))
|
||||
return;
|
||||
data.saveScript(in);
|
||||
if (ConfigDebug.PlayerLogging && FMLCommonHandler.instance().getEffectiveSide() == Side.SERVER) {
|
||||
LogWriter.script(String.format("[%s] (Player) %s SAVED EFFECT %s [%s]", "EFFECT SCRIPTS", player.getCommandSenderName(), effect.getName(), effect.id));
|
||||
}
|
||||
|
||||
@@ -89,8 +89,7 @@ public final class EventScriptPacket extends AbstractPacket {
|
||||
if (requestedAction == Action.GET) {
|
||||
PacketUtil.getScripts(data, (EntityPlayerMP) player);
|
||||
} else {
|
||||
if (!PacketUtil.saveScripts(data, in, player))
|
||||
return;
|
||||
PacketUtil.saveScripts(data, in);
|
||||
npc.updateAI = true;
|
||||
npc.script.hasInited = false;
|
||||
if (ConfigDebug.PlayerLogging && FMLCommonHandler.instance().getEffectiveSide() == Side.SERVER) {
|
||||
|
||||
@@ -84,8 +84,7 @@ public final class ForgeScriptPacket extends AbstractPacket {
|
||||
PacketUtil.getScripts((IScriptHandler) data, (EntityPlayerMP) player);
|
||||
} else {
|
||||
int tab = in.getInt(in.readerIndex());
|
||||
if (!PacketUtil.saveScripts(data, in, player))
|
||||
return;
|
||||
PacketUtil.saveScripts(data, in);
|
||||
ScriptController.Instance.lastForgeUpdate = System.currentTimeMillis();
|
||||
if (tab == -1)
|
||||
ScriptController.Instance.saveForgeScriptsSync();
|
||||
|
||||
+1
-2
@@ -84,8 +84,7 @@ public final class GlobalNPCScriptPacket extends AbstractPacket {
|
||||
PacketUtil.getScripts((IScriptHandler) data, (EntityPlayerMP) player);
|
||||
} else {
|
||||
int tab = in.getInt(in.readerIndex());
|
||||
if (!PacketUtil.saveScripts(data, in, player))
|
||||
return;
|
||||
PacketUtil.saveScripts(data, in);
|
||||
ScriptController.Instance.lastGlobalNpcUpdate = System.currentTimeMillis();
|
||||
if (tab == -1)
|
||||
ScriptController.Instance.saveGlobalScriptsSync();
|
||||
|
||||
@@ -81,19 +81,11 @@ public final class NPCScriptPacket extends AbstractPacket {
|
||||
|
||||
Action requestedAction = Action.values()[in.readInt()];
|
||||
if (requestedAction == Action.GET) {
|
||||
String token = PacketUtil.createScriptSession((EntityPlayerMP) player);
|
||||
NBTTagCompound compound = npc.script.writeToNBT(new NBTTagCompound());
|
||||
compound.setTag("Languages", ScriptController.Instance.nbtLanguages());
|
||||
compound.setString("ScriptSessionToken", token);
|
||||
GuiDataPacket.sendGuiData((EntityPlayerMP) player, compound);
|
||||
} else {
|
||||
NBTTagCompound compound = ByteBufUtils.readNBT(in);
|
||||
String token = compound.getString("ScriptSessionToken");
|
||||
if (!PacketUtil.verifyScriptSession(player, token)) {
|
||||
LogWriter.error(String.format("Rejected NPC script save from %s: session not verified", player.getCommandSenderName()));
|
||||
return;
|
||||
}
|
||||
npc.script.readFromNBT(compound);
|
||||
npc.script.readFromNBT(ByteBufUtils.readNBT(in));
|
||||
npc.updateAI = true;
|
||||
npc.script.hasInited = false;
|
||||
if (ConfigDebug.PlayerLogging && FMLCommonHandler.instance().getEffectiveSide() == Side.SERVER) {
|
||||
|
||||
@@ -84,8 +84,7 @@ public final class PlayerScriptPacket extends AbstractPacket {
|
||||
PacketUtil.getScripts((IScriptHandler) data, (EntityPlayerMP) player);
|
||||
} else {
|
||||
int tab = in.getInt(in.readerIndex());
|
||||
if (!PacketUtil.saveScripts(data, in, player))
|
||||
return;
|
||||
PacketUtil.saveScripts(data, in);
|
||||
ScriptController.Instance.lastPlayerUpdate = System.currentTimeMillis();
|
||||
if (tab == -1)
|
||||
ScriptController.Instance.savePlayerScriptsSync();
|
||||
|
||||
@@ -102,8 +102,7 @@ public final class RecipeScriptPacket extends AbstractPacket {
|
||||
if (action == Action.GET) {
|
||||
PacketUtil.getScripts(script, player);
|
||||
} else {
|
||||
if (!script.saveScript(in, player))
|
||||
return;
|
||||
script.saveScript(in);
|
||||
if (ConfigDebug.PlayerLogging && FMLCommonHandler.instance().getEffectiveSide() == Side.SERVER) {
|
||||
// TODO: Log Recipe Script Saving
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import kamkeel.npcs.network.AbstractPacket;
|
||||
import kamkeel.npcs.network.PacketChannel;
|
||||
import kamkeel.npcs.network.PacketClient;
|
||||
import kamkeel.npcs.network.PacketHandler;
|
||||
import kamkeel.npcs.network.PacketUtil;
|
||||
import kamkeel.npcs.network.enums.EnumRequestPacket;
|
||||
import kamkeel.npcs.network.packets.data.large.GuiDataPacket;
|
||||
import kamkeel.npcs.util.ByteBufUtils;
|
||||
@@ -15,7 +14,6 @@ import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import noppes.npcs.CustomNpcsPermissions;
|
||||
import noppes.npcs.LogWriter;
|
||||
import noppes.npcs.config.ConfigScript;
|
||||
import noppes.npcs.controllers.ScriptController;
|
||||
import noppes.npcs.scripted.NpcAPI;
|
||||
@@ -74,10 +72,8 @@ public final class ItemScriptPacket extends AbstractPacket {
|
||||
if (requestedAction == Action.GET) {
|
||||
ScriptCustomItem iw = (ScriptCustomItem) NpcAPI.Instance().getIItemStack(player.getHeldItem());
|
||||
iw.loadScriptData();
|
||||
String token = PacketUtil.createScriptSession((EntityPlayerMP) player);
|
||||
NBTTagCompound compound = iw.getMCNbt();
|
||||
compound.setTag("Languages", ScriptController.Instance.nbtLanguages());
|
||||
compound.setString("ScriptSessionToken", token);
|
||||
GuiDataPacket.sendGuiData((EntityPlayerMP) player, compound);
|
||||
|
||||
NBTTagCompound loadComplete = new NBTTagCompound();
|
||||
@@ -89,11 +85,6 @@ public final class ItemScriptPacket extends AbstractPacket {
|
||||
}
|
||||
|
||||
NBTTagCompound compound = ByteBufUtils.readNBT(in);
|
||||
String token = compound.getString("ScriptSessionToken");
|
||||
if (!PacketUtil.verifyScriptSession(player, token)) {
|
||||
LogWriter.error(String.format("Rejected item script save from %s: session not verified", player.getCommandSenderName()));
|
||||
return;
|
||||
}
|
||||
ScriptCustomItem wrapper = (ScriptCustomItem) NpcAPI.Instance().getIItemStack(player.getHeldItem());
|
||||
wrapper.setMCNbt(compound);
|
||||
wrapper.saveScriptData();
|
||||
|
||||
+1
-2
@@ -90,8 +90,7 @@ public final class LinkedItemScriptPacket extends AbstractPacket {
|
||||
if (requestedAction == Action.GET) {
|
||||
PacketUtil.getScripts((IScriptHandler) data, (EntityPlayerMP) player);
|
||||
} else {
|
||||
if (!data.saveScript(in, player))
|
||||
return;
|
||||
data.saveScript(in);
|
||||
if (ConfigDebug.PlayerLogging && FMLCommonHandler.instance().getEffectiveSide() == Side.SERVER) {
|
||||
LogWriter.script(String.format("[%s] (Player) %s SAVED LINKED ITEM [%s]", "LINKED ITEM SCRIPTS", player.getCommandSenderName(), linkedItem.getName()));
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import cpw.mods.fml.common.gameevent.TickEvent;
|
||||
import cpw.mods.fml.common.gameevent.TickEvent.Phase;
|
||||
import kamkeel.npcs.controllers.ProfileController;
|
||||
import kamkeel.npcs.controllers.SyncController;
|
||||
import kamkeel.npcs.network.PacketUtil;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import noppes.npcs.controllers.AuctionController;
|
||||
@@ -79,8 +78,5 @@ public class ServerTickHandler {
|
||||
|
||||
// Save and unload the player's profile data on logout
|
||||
ProfileController.Instance.logout(event.player);
|
||||
|
||||
// Clear script session tokens
|
||||
PacketUtil.clearScriptSession(event.player);
|
||||
}
|
||||
}
|
||||
@@ -188,11 +188,8 @@ public class TileScripted extends TileEntity implements IScriptBlockHandler, ISc
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sync(String sessionToken) {
|
||||
NBTTagCompound compound = getNBT(new NBTTagCompound());
|
||||
if (sessionToken != null && !sessionToken.isEmpty())
|
||||
compound.setString("ScriptSessionToken", sessionToken);
|
||||
sendSavePacket(-1, getScripts().size(), compound);
|
||||
public void sync() {
|
||||
sendSavePacket(-1, getScripts().size(), getNBT(new NBTTagCompound()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -193,8 +193,6 @@ public class ClientTickHandler {
|
||||
return;
|
||||
|
||||
if (mc.theWorld.getTotalWorldTime() % 20 == 0) { // Update every second
|
||||
if (RequestProperSpawnData.canDoBatchUpdate())
|
||||
RequestProperSpawnData.handleBacklog();
|
||||
updateCompassMarks();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -343,8 +343,6 @@ public class GuiScript extends GuiScriptInterface {
|
||||
@Override
|
||||
public void setGuiData(NBTTagCompound compound) {
|
||||
script.readFromNBT(compound);
|
||||
if (compound.hasKey("ScriptSessionToken"))
|
||||
scriptSessionToken = compound.getString("ScriptSessionToken");
|
||||
loadLanguagesData(compound);
|
||||
loaded = true;
|
||||
}
|
||||
@@ -353,10 +351,7 @@ public class GuiScript extends GuiScriptInterface {
|
||||
public void save() {
|
||||
if (loaded) {
|
||||
setScript();
|
||||
NBTTagCompound compound = script.writeToNBT(new NBTTagCompound());
|
||||
if (scriptSessionToken != null)
|
||||
compound.setString("ScriptSessionToken", scriptSessionToken);
|
||||
NPCScriptPacket.Save(compound);
|
||||
NPCScriptPacket.Save(script.writeToNBT(new NBTTagCompound()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,9 +49,8 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb
|
||||
public Map<String, List<String>> languages = new HashMap();
|
||||
protected int scriptLimit = 1;
|
||||
public List<String> hookList = new ArrayList<String>();
|
||||
protected volatile boolean loaded = false;
|
||||
protected boolean loaded = false;
|
||||
protected boolean serverDataReceived = false;
|
||||
protected String scriptSessionToken = null;
|
||||
|
||||
protected Map<Integer, GuiScriptTextArea> textAreas = new HashMap<>();
|
||||
protected GuiScreen parent;
|
||||
@@ -756,8 +755,6 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb
|
||||
return;
|
||||
}
|
||||
if (result.kind == IScriptHandlerPacket.GuiDataKind.METADATA) {
|
||||
if (compound.hasKey("ScriptSessionToken"))
|
||||
scriptSessionToken = compound.getString("ScriptSessionToken");
|
||||
loadLanguagesData(compound);
|
||||
return;
|
||||
}
|
||||
@@ -768,8 +765,6 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb
|
||||
return;
|
||||
}
|
||||
|
||||
if (compound.hasKey("ScriptSessionToken"))
|
||||
scriptSessionToken = compound.getString("ScriptSessionToken");
|
||||
loadLanguagesData(compound);
|
||||
}
|
||||
|
||||
@@ -819,7 +814,9 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb
|
||||
this.setScript();
|
||||
|
||||
if (handler instanceof IScriptHandlerPacket)
|
||||
((IScriptHandlerPacket) handler).sync(scriptSessionToken);
|
||||
((IScriptHandlerPacket) handler).sync();
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void textUpdate(String text) {
|
||||
|
||||
@@ -71,29 +71,16 @@ public interface IScriptHandlerPacket extends IScriptHandler {
|
||||
* GuiScriptInterface is responsible for updating the active {@link IScriptUnit} with current editor text first.
|
||||
*/
|
||||
default void sync() {
|
||||
sync(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit save packets with a session token for server-side verification.
|
||||
* The token prevents saving unloaded default data due to race conditions.
|
||||
*/
|
||||
default void sync(String sessionToken) {
|
||||
List<IScriptUnit> containers = getScripts();
|
||||
for (int i = 0; i < containers.size(); i++) {
|
||||
IScriptUnit container = containers.get(i);
|
||||
NBTTagCompound nbt = container.writeToNBT(new NBTTagCompound());
|
||||
if (sessionToken != null && !sessionToken.isEmpty())
|
||||
nbt.setString("ScriptSessionToken", sessionToken);
|
||||
sendSavePacket(i, containers.size(), nbt);
|
||||
sendSavePacket(i, containers.size(), container.writeToNBT(new NBTTagCompound()));
|
||||
}
|
||||
|
||||
NBTTagCompound scriptData = new NBTTagCompound();
|
||||
scriptData.setString("ScriptLanguage", getLanguage());
|
||||
scriptData.setBoolean("ScriptEnabled", getEnabled());
|
||||
scriptData.setTag("ScriptConsole", NBTTags.NBTLongStringMap(getConsoleText()));
|
||||
if (sessionToken != null && !sessionToken.isEmpty())
|
||||
scriptData.setString("ScriptSessionToken", sessionToken);
|
||||
sendSavePacket(-1, containers.size(), scriptData);
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,7 @@ package noppes.npcs.controllers.data;
|
||||
|
||||
import cpw.mods.fml.common.eventhandler.Event;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import kamkeel.npcs.network.PacketUtil;
|
||||
import kamkeel.npcs.util.ByteBufUtils;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraftforge.common.util.Constants;
|
||||
import noppes.npcs.CustomNpcs;
|
||||
@@ -119,16 +117,9 @@ public abstract class SingleScriptHandler extends ScriptHandler {
|
||||
* - tab == 0: Script content NBT follows
|
||||
* - tab != 0 (typically -1): Script metadata (language, enabled) follows
|
||||
*/
|
||||
public boolean saveScript(ByteBuf buffer, EntityPlayer player) throws IOException {
|
||||
public void saveScript(ByteBuf buffer) throws IOException {
|
||||
int tab = buffer.readInt();
|
||||
int totalScripts = buffer.readInt();
|
||||
NBTTagCompound compound = ByteBufUtils.readNBT(buffer);
|
||||
|
||||
// Verify session token
|
||||
String token = compound.getString("ScriptSessionToken");
|
||||
if (!PacketUtil.verifyScriptSession(player, token)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (totalScripts == 0) {
|
||||
this.container = null;
|
||||
@@ -136,14 +127,15 @@ public abstract class SingleScriptHandler extends ScriptHandler {
|
||||
|
||||
if (tab == 0) {
|
||||
// Script content
|
||||
this.container = IScriptUnit.createFromNBT(compound, this);
|
||||
NBTTagCompound tabCompound = ByteBufUtils.readNBT(buffer);
|
||||
this.container = IScriptUnit.createFromNBT(tabCompound, this);
|
||||
} else {
|
||||
// Metadata (language, enabled)
|
||||
NBTTagCompound compound = ByteBufUtils.readNBT(buffer);
|
||||
this.setLanguage(compound.getString("ScriptLanguage"));
|
||||
normalizeLanguage();
|
||||
this.setEnabled(compound.getBoolean("ScriptEnabled"));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -236,6 +236,7 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti
|
||||
|
||||
// For Client-Side Use Only
|
||||
public int clientFixAttempts = 0;
|
||||
public long clientFixLastRequestMillis = 0L;
|
||||
|
||||
public EntityNPCInterface(World world) {
|
||||
super(world);
|
||||
@@ -483,7 +484,14 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti
|
||||
}
|
||||
|
||||
if (wasKilled != isKilled() && wasKilled) {
|
||||
reset();
|
||||
if (!worldObj.isRemote) {
|
||||
reset();
|
||||
} else {
|
||||
// Client-side full reset can create health oscillation when spawn data is being repaired.
|
||||
deathTime = 0;
|
||||
currentAnimation = EnumAnimation.NONE;
|
||||
updateHitbox();
|
||||
}
|
||||
}
|
||||
|
||||
wasKilled = isKilled();
|
||||
@@ -1838,6 +1846,7 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti
|
||||
NBTTagCompound compound = new NBTTagCompound();
|
||||
display.writeToNBT(compound);
|
||||
compound.setDouble("MaxHealth", stats.maxHealth);
|
||||
compound.setFloat("CurrentHealth", getHealth());
|
||||
compound.setTag("Armor", NBTTags.nbtItemStackList(inventory.getArmor()));
|
||||
compound.setTag("Weapons", NBTTags.nbtItemStackList(inventory.getWeapons()));
|
||||
compound.setInteger("Speed", ais.getWalkingSpeed());
|
||||
@@ -1892,6 +1901,7 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti
|
||||
return;
|
||||
}
|
||||
|
||||
float preservedHealth = getHealth();
|
||||
stats.maxHealth = compound.getDouble("MaxHealth");
|
||||
ais.setWalkingSpeed(compound.getInteger("Speed"));
|
||||
stats.hideKilledBody = compound.getBoolean("DeadBody");
|
||||
@@ -1916,6 +1926,12 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti
|
||||
ais.bodyOffsetY = compound.getFloat("OffsetY");
|
||||
|
||||
this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(stats.maxHealth);
|
||||
if (compound.hasKey("CurrentHealth", Constants.NBT.TAG_FLOAT)) {
|
||||
setHealth(MathHelper.clamp_float(compound.getFloat("CurrentHealth"), 0.0F, getMaxHealth()));
|
||||
} else {
|
||||
// Keep previous client health if packet came from an older sender format.
|
||||
setHealth(MathHelper.clamp_float(preservedHealth, 0.0F, getMaxHealth()));
|
||||
}
|
||||
inventory.setArmor(NBTTags.getItemStackList(compound.getTagList("Armor", 10)));
|
||||
inventory.setWeapons(NBTTags.getItemStackList(compound.getTagList("Weapons", 10)));
|
||||
advanced.setRole(compound.getInteger("Role"));
|
||||
@@ -1990,6 +2006,7 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti
|
||||
return true;
|
||||
}
|
||||
clientFixAttempts = 0;
|
||||
clientFixLastRequestMillis = 0L;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -99,11 +99,8 @@ public class ScriptCustomItem extends ScriptCustomizableItem implements IItemCus
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sync(String sessionToken) {
|
||||
NBTTagCompound compound = getMCNbt();
|
||||
if (sessionToken != null && !sessionToken.isEmpty())
|
||||
compound.setString("ScriptSessionToken", sessionToken);
|
||||
sendSavePacket(-1, getScripts().size(), compound);
|
||||
public void sync() {
|
||||
sendSavePacket(-1, getScripts().size(), getMCNbt());
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
|
||||
Reference in new issue
Block a user