Skip to content

Commit

Permalink
Sane serialization, working, will need to refine / cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
Desoroxxx committed Oct 25, 2024
1 parent f62529e commit 3aa419a
Show file tree
Hide file tree
Showing 21 changed files with 71 additions and 144 deletions.
96 changes: 69 additions & 27 deletions src/main/java/com/paneedah/mwc/network/TypeRegistry.java
Original file line number Diff line number Diff line change
@@ -1,49 +1,85 @@
package com.paneedah.mwc.network;

import com.paneedah.weaponlib.*;
import com.paneedah.weaponlib.electronics.HandheldState;
import com.paneedah.weaponlib.electronics.PlayerHandheldInstance;
import com.paneedah.weaponlib.electronics.PlayerTabletInstance;
import com.paneedah.weaponlib.electronics.TabletState;
import com.paneedah.weaponlib.grenade.GrenadeState;
import com.paneedah.weaponlib.grenade.PlayerGrenadeInstance;
import com.paneedah.weaponlib.melee.MeleeAttachmentAspect;
import com.paneedah.weaponlib.melee.MeleeState;
import com.paneedah.weaponlib.melee.PlayerMeleeInstance;
import com.paneedah.weaponlib.state.Permit;
import io.netty.buffer.ByteBuf;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.HashMap;
import java.util.UUID;

import static com.paneedah.mwc.ProjectConstants.LOGGER;
import static com.paneedah.mwc.ProjectConstants.RED_LOGGER;

@NoArgsConstructor
public final class TypeRegistry {

@Getter private static final TypeRegistry INSTANCE = new TypeRegistry();

private final HashMap<UUID, Class<? extends ISerializable>> typeRegistry = new HashMap<>();

public <T extends ISerializable> void register(Class<T> cls) {
typeRegistry.put(getUuid(cls), cls);
private final HashMap<String, Class<? extends ISerializable>> typeRegistry = new HashMap<>();

static {
INSTANCE.register(PlayerItemInstance.class);
INSTANCE.register(PlayerWeaponInstance.class);
INSTANCE.register(PlayerMagazineInstance.class);
INSTANCE.register(PlayerMeleeInstance.class);
INSTANCE.register(PlayerGrenadeInstance.class);
INSTANCE.register(PlayerHandheldInstance.class);
INSTANCE.register(PlayerTabletInstance.class);

INSTANCE.register(WeaponState.class);
INSTANCE.register(MagazineState.class);
INSTANCE.register(MeleeState.class);
INSTANCE.register(GrenadeState.class);
INSTANCE.register(HandheldState.class);
INSTANCE.register(TabletState.class);

INSTANCE.register(Permit.class);
INSTANCE.register(WeaponAttachmentAspect.EnterAttachmentModePermit.class);
INSTANCE.register(WeaponAttachmentAspect.ExitAttachmentModePermit.class);
INSTANCE.register(WeaponAttachmentAspect.ChangeAttachmentPermit.class);
INSTANCE.register(MeleeAttachmentAspect.EnterAttachmentModePermit.class);
INSTANCE.register(MeleeAttachmentAspect.ExitAttachmentModePermit.class);
INSTANCE.register(MeleeAttachmentAspect.ChangeAttachmentPermit.class);
INSTANCE.register(WeaponReloadAspect.LoadPermit.class);
INSTANCE.register(WeaponReloadAspect.UnloadPermit.class);
INSTANCE.register(WeaponReloadAspect.CompoundPermit.class);
INSTANCE.register(MagazineReloadAspect.LoadPermit.class);
INSTANCE.register(MagazineReloadAspect.UnloadPermit.class);

INSTANCE.register(LightExposure.class);
INSTANCE.register(SpreadableExposure.class);
}

public UUID getUuid(final Class<?> aClass) {
try {
final SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(aClass.getName().getBytes());
return new UUID(secureRandom.nextLong(), secureRandom.nextLong());
} catch (NoSuchAlgorithmException noSuchAlgorithmException) {
RED_LOGGER.printFramedError("Networking", "Failed to create a secure random", "", noSuchAlgorithmException.getMessage());
throw new RuntimeException(noSuchAlgorithmException);
}

private <T extends ISerializable> void register(Class<T> cls) {
typeRegistry.put(cls.getName(), cls);
}

public <T extends ISerializable> void toBytes(final T object, final ByteBuf byteBuf) {
final UUID uuid = getUuid(object.getClass());
final String className = object.getClass().getName();

if (!typeRegistry.containsKey(uuid)) {
if (!typeRegistry.containsKey(className)) {
RED_LOGGER.printFramedError("Networking", "Failed to write object because its class is not registered", "", "Object: " + object, "Class: " + object.getClass());
throw new RuntimeException();
throw new IllegalStateException("Failed to write object because its class is not registered");
}

byteBuf.writeLong(uuid.getMostSignificantBits());
byteBuf.writeLong(uuid.getLeastSignificantBits());
byte[] classNameBytes = className.getBytes(StandardCharsets.UTF_8);
byteBuf.writeByte((byte) classNameBytes.length);
byteBuf.writeBytes(classNameBytes);

if (object.getClass().isEnum()) {
byteBuf.writeInt(((Enum<?>) object).ordinal());
} else {
Expand All @@ -52,16 +88,22 @@ public <T extends ISerializable> void toBytes(final T object, final ByteBuf byte
}

public <T extends ISerializable> T fromBytes(final ByteBuf byteBuf) {
long mostSigBits = byteBuf.readLong();
long leastSigBits = byteBuf.readLong();
UUID typeUuid = new UUID(mostSigBits, leastSigBits);
Class<T> targetClass;

final byte[] classNameBytes = new byte[byteBuf.readByte()];
byteBuf.readBytes(classNameBytes);
final String className = new String(classNameBytes, StandardCharsets.UTF_8);

if (!typeRegistry.containsKey(className)) {
RED_LOGGER.printFramedError("Networking", "Failed to deserialize object because its class is not registered", "Weapon will reset to it's default state");
return null;
}

Class<T> targetClass = (Class<T>) typeRegistry.get(typeUuid);
targetClass = (Class<T>) typeRegistry.get(className);

if (targetClass == null) {
RED_LOGGER.printFramedError("Networking", "Failed to deserialize object.\nDid you forget to register type?", "");
throw new RuntimeException();
RED_LOGGER.printFramedError("Networking", "Failed to deserialize object", "Weapon will reset to it's default state");
return null;
}

T instance;
Expand All @@ -72,8 +114,8 @@ public <T extends ISerializable> T fromBytes(final ByteBuf byteBuf) {
try {
instance = targetClass.newInstance();
} catch (InstantiationException | IllegalAccessException exception) {
RED_LOGGER.printFramedError("Networking", "Failed to create instance", "", exception.getMessage(), exception.getStackTrace()[3].toString());
throw new RuntimeException();
RED_LOGGER.printFramedError("Networking", "Failed to create instance", "Weapon will reset to it's default state", exception.getMessage(), exception.getStackTrace()[3].toString());
return null;
}

instance.read(byteBuf);
Expand Down
27 changes: 0 additions & 27 deletions src/main/java/com/paneedah/weaponlib/CommonModContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,33 +49,6 @@

public class CommonModContext implements ModContext {

static {
TypeRegistry.getINSTANCE().register(LoadPermit.class);
TypeRegistry.getINSTANCE().register(MagazineState.class);
TypeRegistry.getINSTANCE().register(PlayerItemInstance.class);
TypeRegistry.getINSTANCE().register(PlayerWeaponInstance.class);
TypeRegistry.getINSTANCE().register(PlayerMagazineInstance.class);
TypeRegistry.getINSTANCE().register(PlayerWeaponInstance.class);
TypeRegistry.getINSTANCE().register(Permit.class);
TypeRegistry.getINSTANCE().register(EnterAttachmentModePermit.class);
TypeRegistry.getINSTANCE().register(ExitAttachmentModePermit.class);
TypeRegistry.getINSTANCE().register(ChangeAttachmentPermit.class);
TypeRegistry.getINSTANCE().register(CompoundPermit.class);
TypeRegistry.getINSTANCE().register(UnloadPermit.class);
TypeRegistry.getINSTANCE().register(LoadPermit.class);
TypeRegistry.getINSTANCE().register(PlayerWeaponInstance.class);
TypeRegistry.getINSTANCE().register(WeaponState.class);
TypeRegistry.getINSTANCE().register(PlayerMeleeInstance.class);
TypeRegistry.getINSTANCE().register(PlayerGrenadeInstance.class);
TypeRegistry.getINSTANCE().register(PlayerTabletInstance.class);
TypeRegistry.getINSTANCE().register(PlayerHandheldInstance.class);
TypeRegistry.getINSTANCE().register(MeleeState.class);
TypeRegistry.getINSTANCE().register(TabletState.class);
TypeRegistry.getINSTANCE().register(HandheldState.class);
TypeRegistry.getINSTANCE().register(SpreadableExposure.class);
TypeRegistry.getINSTANCE().register(LightExposure.class);
}

static class BulletImpactSoundKey {
private final Material material;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,6 @@

public class MagazineReloadAspect implements Aspect<MagazineState, PlayerMagazineInstance> {

static {
TypeRegistry.getINSTANCE().register(LoadPermit.class);
TypeRegistry.getINSTANCE().register(UnloadPermit.class);
}

private static final Set<MagazineState> allowedUpdateFromStates = new HashSet<>(
Arrays.asList(
MagazineState.LOAD_REQUESTED,
Expand Down
6 changes: 0 additions & 6 deletions src/main/java/com/paneedah/weaponlib/MagazineState.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,4 @@ public void read(ByteBuf byteBuf) {
public void write(ByteBuf byteBuf) {
// not need to write anything, parent type registry should take care of it
}

static {
TypeRegistry.getINSTANCE().register(MagazineState.class);
}


}
4 changes: 0 additions & 4 deletions src/main/java/com/paneedah/weaponlib/PlayerItemInstance.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,6 @@
@NoArgsConstructor
public class PlayerItemInstance<S extends ManagedState<S>> extends UniversalObject implements ExtendedState<S> {

static {
TypeRegistry.getINSTANCE().register(PlayerItemInstance.class);
}

protected boolean compoundMagSwapCompleted = false;

@Getter @Setter protected int itemInventoryIndex;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ private PlayerItemInstance<?> createItemInstance(final EntityPlayer player, fina

result.setItemInventoryIndex(slot);
result.setPlayer(player);

Tags.setInstance(itemStack, result);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@
@NoArgsConstructor
public class PlayerMagazineInstance extends PlayerItemInstance<MagazineState> {

static {
TypeRegistry.getINSTANCE().register(PlayerMagazineInstance.class);
}

// private int ammo;

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@ public class PlayerWeaponInstance extends PlayerItemInstance<WeaponState> implem

private static final int SERIAL_VERSION = 9;

static {
TypeRegistry.getINSTANCE().register(PlayerWeaponInstance.class);
}

private static final UUID NIGHT_VISION_SOURCE_UUID = UUID.randomUUID();
private static final UUID VIGNETTE_SOURCE_UUID = UUID.randomUUID();
private static final UUID BLUR_SOURCE_UUID = UUID.randomUUID();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,6 @@

public final class WeaponAttachmentAspect implements Aspect<WeaponState, PlayerWeaponInstance> {

static {
TypeRegistry.getINSTANCE().register(EnterAttachmentModePermit.class);
TypeRegistry.getINSTANCE().register(ExitAttachmentModePermit.class);
TypeRegistry.getINSTANCE().register(ChangeAttachmentPermit.class);
}

private static class AttachmentLookupResult {
CompatibleAttachment<Weapon> compatibleAttachment;
int index = -1;
Expand Down
7 changes: 0 additions & 7 deletions src/main/java/com/paneedah/weaponlib/WeaponReloadAspect.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,6 @@ public class WeaponReloadAspect implements Aspect<WeaponState, PlayerWeaponInsta
private static final long INSPECT_TIMEOUT = 500;
private static final long UNLOAD_TIMEOUT = 1000;

static {
TypeRegistry.getINSTANCE().register(CompoundPermit.class);
TypeRegistry.getINSTANCE().register(UnloadPermit.class);
TypeRegistry.getINSTANCE().register(LoadPermit.class);
TypeRegistry.getINSTANCE().register(PlayerWeaponInstance.class); // TODO: move it out
}

private static final Set<WeaponState> ALLOWED_UPDATE_FROM_STATES = new HashSet<>(Arrays.asList(
WeaponState.AWAIT_FURTHER_LOAD_INSTRUCTIONS,
WeaponState.COMPOUND_REQUESTED,
Expand Down
4 changes: 0 additions & 4 deletions src/main/java/com/paneedah/weaponlib/WeaponState.java
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,5 @@ public void read(ByteBuf byteBuf) {
public void write(ByteBuf byteBuf) {
// No need to write anything, parent type registry should take care of it
}

static {
TypeRegistry.getINSTANCE().register(WeaponState.class);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,4 @@ public void read(ByteBuf byteBuf) {
public void write(ByteBuf byteBuf) {
// not need to write anything, parent type registry should take care of it
}

static {
TypeRegistry.getINSTANCE().register(HandheldState.class);
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@ public class PlayerHandheldInstance extends PlayerItemInstance<HandheldState> {

private static final int SERIAL_VERSION = 1;

static {
TypeRegistry.getINSTANCE().register(PlayerHandheldInstance.class);
}

public PlayerHandheldInstance(int itemInventoryIndex, EntityLivingBase player, ItemStack itemStack) {
super(itemInventoryIndex, player, itemStack);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ public class PlayerTabletInstance extends PlayerItemInstance<TabletState> {

private static final int SERIAL_VERSION = 1;

static {
TypeRegistry.getINSTANCE().register(PlayerTabletInstance.class);
}

private int activeWatchIndex;

public PlayerTabletInstance(int itemInventoryIndex, EntityLivingBase player, ItemStack itemStack) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,4 @@ public void read(ByteBuf byteBuf) {
public void write(ByteBuf byteBuf) {
// not need to write anything, parent type registry should take care of it
}

static {
TypeRegistry.getINSTANCE().register(TabletState.class);
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,4 @@ public void read(ByteBuf byteBuf) {
public void write(ByteBuf byteBuf) {
// not need to write anything, parent type registry should take care of it
}

static {
TypeRegistry.getINSTANCE().register(GrenadeState.class);
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,6 @@ public class PlayerGrenadeInstance extends PlayerItemInstance<GrenadeState> {

private static final int SERIAL_VERSION = 11;

static {
TypeRegistry.getINSTANCE().register(PlayerGrenadeInstance.class);
}

private int ammo;
private long activationTimestamp;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,6 @@

public final class MeleeAttachmentAspect implements Aspect<MeleeState, PlayerMeleeInstance> {

static {
TypeRegistry.getINSTANCE().register(EnterAttachmentModePermit.class);
TypeRegistry.getINSTANCE().register(ExitAttachmentModePermit.class);
TypeRegistry.getINSTANCE().register(ChangeAttachmentPermit.class);
}

private static class AttachmentLookupResult {
CompatibleAttachment<ItemMelee> compatibleAttachment;
int index = -1;
Expand Down
6 changes: 0 additions & 6 deletions src/main/java/com/paneedah/weaponlib/melee/MeleeState.java
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,4 @@ public void read(ByteBuf byteBuf) {
public void write(ByteBuf byteBuf) {
// not need to write anything, parent type registry should take care of it
}

static {
TypeRegistry.getINSTANCE().register(MeleeState.class);
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@ public class PlayerMeleeInstance extends PlayerItemInstance<MeleeState> {

private static final int SERIAL_VERSION = 7;

static {
TypeRegistry.getINSTANCE().register(PlayerMeleeInstance.class);
}

private int ammo;
private long lastFireTimestamp;
private byte activeTextureIndex;
Expand Down
4 changes: 0 additions & 4 deletions src/main/java/com/paneedah/weaponlib/state/Permit.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@

public class Permit<S extends ManagedState<S>> extends UniversalObject {

static {
TypeRegistry.getINSTANCE().register(Permit.class);
}

public enum Status {REQUESTED, GRANTED, DENIED, UNKNOWN}

protected S state;
Expand Down

0 comments on commit 3aa419a

Please sign in to comment.