Expanded SyncController scope to allow syncing based on string operation keys instead of just int ids (i.e ability keys)

This commit is contained in:
bigguy345 committed 2026-04-02 00:24:15 +02:00
1 parent 22de352dd9
commit facee7c388
5 files changed
+84 -44

No files matched your search

@@ -4,8 +4,6 @@ import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import kamkeel.npcdbc.network.DBCPacketHandler;
import kamkeel.npcdbc.network.packets.get.DBCInfoSyncPacket;
import kamkeel.npcs.addon.DBCAddon;
import kamkeel.npcs.controllers.sync.SyncHandler;
import kamkeel.npcs.controllers.sync.SyncRegistry;
@@ -26,7 +24,6 @@ import noppes.npcs.LogWriter;
import noppes.npcs.client.ClientCacheHandler;
import noppes.npcs.controllers.data.PlayerData;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
@@ -146,7 +143,7 @@ public class SyncController {
* revision state. Used after the login handshake and by server-side callers
* that need to refresh a player's global cached sync families.
*/
public static void syncPlayer(EntityPlayerMP player) {
public static void dispatchSyncForAllTypes(EntityPlayerMP player) {
PlayerSyncState state = playerSyncState.computeIfAbsent(player.getUniqueID(), PlayerSyncState::new);
// Registry-driven login iteration: iterate only cached types
@@ -194,7 +191,7 @@ public class SyncController {
else // The client and server agree on identity, so seed the stored state from the report.
state.applyHandshake(clientRevisions);
syncPlayer(player);
dispatchSyncForAllTypes(player);
}
@@ -217,21 +214,42 @@ public class SyncController {
// ═══════════════════════════════════════════════════════════════════════
// Server-side dispatchers — registry-driven
// ═══════════════════════════════════════════════════════════════════════
public static void syncUpdate(SyncType type, NBTTagCompound compound) {
Map<SyncType, Integer> revisions = invalidateCaches(type);
int revision = getRequestedInvalidationRevision(type, revisions);
PacketHandler.Instance.sendToAll(new SyncPacket(type, EnumSyncAction.UPDATE, -1, null, revision, compound));
updateAllPlayerRevisions(revisions);
}
public static void syncRemove(SyncType syncType, int id) {
Map<SyncType, Integer> revisions = invalidateCaches(syncType);
int revision = getRequestedInvalidationRevision(syncType, revisions);
PacketHandler.Instance.sendToAll(new SyncPacket(syncType, EnumSyncAction.REMOVE, id, revision, new NBTTagCompound()));
public static void syncUpdate(SyncType type, String key, NBTTagCompound compound) {
Map<SyncType, Integer> revisions = invalidateCaches(type);
int revision = getRequestedInvalidationRevision(type, revisions);
PacketHandler.Instance.sendToAll(new SyncPacket(type, EnumSyncAction.UPDATE, -1, key, revision, compound));
updateAllPlayerRevisions(revisions);
}
public static void syncUpdate(SyncType type, int cat, NBTTagCompound compound) {
Map<SyncType, Integer> revisions = invalidateCaches(type);
int revision = getRequestedInvalidationRevision(type, revisions);
PacketHandler.Instance.sendToAll(new SyncPacket(type, EnumSyncAction.UPDATE, cat, revision, compound));
PacketHandler.Instance.sendToAll(new SyncPacket(type, EnumSyncAction.UPDATE, cat, null, revision, compound));
updateAllPlayerRevisions(revisions);
}
public static void syncRemove(SyncType syncType, String key) {
Map<SyncType, Integer> revisions = invalidateCaches(syncType);
int revision = getRequestedInvalidationRevision(syncType, revisions);
PacketHandler.Instance.sendToAll(new SyncPacket(syncType, EnumSyncAction.REMOVE, -1, key, revision, null));
updateAllPlayerRevisions(revisions);
}
public static void syncRemove(SyncType syncType, int id) {
Map<SyncType, Integer> revisions = invalidateCaches(syncType);
int revision = getRequestedInvalidationRevision(syncType, revisions);
PacketHandler.Instance.sendToAll(new SyncPacket(syncType, EnumSyncAction.REMOVE, id, null, revision, null));
updateAllPlayerRevisions(revisions);
}
// ═══════════════════════════════════════════════════════════════════════
// Client-side handlers — registry-driven handler delegation
// ═══════════════════════════════════════════════════════════════════════
@@ -250,11 +268,12 @@ public class SyncController {
}
@SideOnly(Side.CLIENT)
public static void clientHandleUpdate(SyncType syncType, int category_id, int revision, NBTTagCompound compound) {
public static void clientHandleUpdate(SyncType syncType, int id, String key, int revision, NBTTagCompound compound) {
SyncHandler handler = SyncRegistry.getHandler(syncType);
if (handler == null) return;
try {
handler.clientHandleUpdate(compound, category_id);
handler.clientHandleUpdate(compound, id);
handler.clientHandleUpdate(compound, key);
} catch (Exception e) {
LogWriter.error("[SyncController] Failed to handle UPDATE for sync type " + syncType, e);
}
@@ -263,12 +282,12 @@ public class SyncController {
}
@SideOnly(Side.CLIENT)
public static void clientHandleRemove(SyncType syncType, int id, int revision, NBTTagCompound compound) {
public static void clientHandleRemove(SyncType syncType, int id, String key, int revision) {
SyncHandler handler = SyncRegistry.getHandler(syncType);
if (handler == null) return;
try {
handler.clientHandleRemove(id);
handler.clientHandleRemove(compound);
handler.clientHandleRemove(key);
} catch (Exception e) {
LogWriter.error("[SyncController] Failed to handle REMOVE for sync type " + syncType, e);
}
@@ -52,8 +52,26 @@ public interface SyncHandler {
* @param fullCompound the full serialized dataset from {@link #serializeAll()}
*/
@SideOnly(Side.CLIENT)
void clientHandleReload(NBTTagCompound fullCompound);
default void clientHandleReload(NBTTagCompound fullCompound){
// No-op: type does not support individual updates
}
/**
* Handle an UPDATE action on the client.
* Deserialize a single object and insert/replace it in the client-side data.
*
* <p>Default: no-op. Types that don't support individual updates
* use {@code syncAll()} for full reload instead.</p>
*
* @param compound the serialized single object
* @param categoryKey the parent category key (null if not applicable)
*/
@SideOnly(Side.CLIENT)
default void clientHandleUpdate(NBTTagCompound compound, String categoryKey) {
// No-op: type does not support individual updates
}
/**
* Handle an UPDATE action on the client. Deserialize a single
* entity and insert/replace it in the client-side data.
@@ -75,7 +93,7 @@ public interface SyncHandler {
* Int-keyed handlers should override {@link #clientHandleRemove(int)} instead.
*/
@SideOnly(Side.CLIENT)
default void clientHandleRemove(NBTTagCompound compound) {
default void clientHandleRemove(String key) {
}
/**
@@ -28,6 +28,7 @@ public final class SyncPacket extends LargeAbstractPacket {
private EnumSyncAction enumSyncAction;
private NBTTagCompound syncData;
private int operationID;
private String operationKey;
private int revision = -1;
private byte[] cachedPayload;
private byte[][] cachedChunks;
@@ -36,14 +37,15 @@ public final class SyncPacket extends LargeAbstractPacket {
}
public SyncPacket(SyncType syncType, EnumSyncAction enumSyncAction, int catId, NBTTagCompound syncData) {
this(syncType, enumSyncAction, catId, -1, syncData);
this(syncType, enumSyncAction, catId, null, -1, syncData);
}
public SyncPacket(SyncType syncType, EnumSyncAction enumSyncAction, int catId, int revision, NBTTagCompound syncData) {
public SyncPacket(SyncType syncType, EnumSyncAction enumSyncAction, int operationId, String operationKey, int revision, NBTTagCompound syncData) {
this.syncType = syncType;
this.enumSyncAction = enumSyncAction;
this.syncData = syncData;
this.operationID = catId;
this.operationID = operationId;
this.operationKey = operationKey;
this.revision = revision;
}
@@ -72,13 +74,19 @@ public final class SyncPacket extends LargeAbstractPacket {
return cachedPayload;
}
boolean hasKey = operationKey != null;
boolean hasNbt = syncData != null;
ByteBuf buffer = Unpooled.buffer();
try {
buffer.writeInt(syncType.ordinal());
buffer.writeInt(enumSyncAction.ordinal());
buffer.writeInt(operationID);
buffer.writeBoolean(hasKey);
if (hasKey) ByteBufUtils.writeString(buffer, operationKey);
buffer.writeInt(revision);
ByteBufUtils.writeBigNBT(buffer, syncData);
buffer.writeBoolean(hasNbt);
if (hasNbt) ByteBufUtils.writeBigNBT(buffer, syncData);
byte[] bytes = new byte[buffer.readableBytes()];
buffer.readBytes(bytes);
@@ -126,39 +134,32 @@ public final class SyncPacket extends LargeAbstractPacket {
int syncTypeOrdinal = data.readInt();
int syncActionOrdinal = data.readInt();
int categoryID = data.readInt();
int incomingRevision = data.readInt();
operationID = data.readInt();
if (data.readBoolean()) operationKey = ByteBufUtils.readString(data);
revision = data.readInt();
if (data.readBoolean()) syncData = ByteBufUtils.readBigNBT(data);
SyncType type = SyncType.byOrdinal(syncTypeOrdinal);
if (type == null) {
syncType = SyncType.byOrdinal(syncTypeOrdinal);
if (syncType == null) {
LogWriter.error("[SyncPacket] Unknown sync type ordinal: " + syncTypeOrdinal + "; skipping");
return;
}
EnumSyncAction action = EnumSyncAction.values()[syncActionOrdinal];
try {
NBTTagCompound tag = ByteBufUtils.readBigNBT(data);
handleSyncPacketClient(type, action, categoryID, incomingRevision, tag);
} catch (RuntimeException e) {
LogWriter.error(String.format("Attempted to Sync %s but it was too big", type.toString()));
}
handleSync(syncType, action, operationID, operationKey, revision, syncData);
}
private void handleSyncPacketClient(
SyncType syncType,
EnumSyncAction enumSyncAction,
int id,
int incomingRevision,
NBTTagCompound data
) {
switch (enumSyncAction) {
private void handleSync(SyncType type, EnumSyncAction action, int id, String key, int revision, NBTTagCompound data) {
switch (action) {
case RELOAD:
SyncController.clientHandleAll(syncType, incomingRevision, data);
SyncController.clientHandleAll(type, revision, data);
break;
case UPDATE:
SyncController.clientHandleUpdate(syncType, id, incomingRevision, data);
SyncController.clientHandleUpdate(type, id, key, revision, data);
break;
case REMOVE:
SyncController.clientHandleRemove(syncType, id, incomingRevision, data);
SyncController.clientHandleRemove(type, id, key, revision);
break;
}
}
@@ -640,7 +640,7 @@ public class NoppesUtilServer {
playerdata.save();
}
if (pl != null) {
SyncController.syncPlayer((EntityPlayerMP) pl);
SyncController.dispatchSyncForAllTypes((EntityPlayerMP) pl);
}
sendPlayerData(type, player, name);
}
@@ -1229,7 +1229,7 @@ public class NoppesUtilServer {
playerdata.save();
if (pl != null) {
SyncController.syncPlayer((EntityPlayerMP) pl);
SyncController.dispatchSyncForAllTypes((EntityPlayerMP) pl);
}
}
@@ -1261,7 +1261,7 @@ public class NoppesUtilServer {
playerdata.save();
if (pl != null) {
SyncController.syncPlayer((EntityPlayerMP) pl);
SyncController.dispatchSyncForAllTypes((EntityPlayerMP) pl);
}
}
}
@@ -260,6 +260,7 @@ public class ServerEventsHandler {
SyncType.WORKBENCH_RECIPES,
EnumSyncAction.RELOAD,
-1,
null,
SyncController.getCurrentServerRevision(SyncType.WORKBENCH_RECIPES),
WorkbenchRecipeSyncHandler.getInstance().serializeAll()
), (EntityPlayerMP) player);
@@ -269,6 +270,7 @@ public class ServerEventsHandler {
SyncType.CARPENTRY_RECIPES,
EnumSyncAction.RELOAD,
-1,
null,
SyncController.getCurrentServerRevision(SyncType.CARPENTRY_RECIPES),
CarpentryRecipeSyncHandler.getInstance().serializeAll()
), (EntityPlayerMP) player);