diff --git a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/launcher/NovaMinecraft.java b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/launcher/NovaMinecraft.java index 5201d012d..679d24d03 100644 --- a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/launcher/NovaMinecraft.java +++ b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/launcher/NovaMinecraft.java @@ -49,6 +49,7 @@ import nova.core.wrapper.mc.forge.v17.wrapper.cuboid.CuboidConverter; import nova.core.wrapper.mc.forge.v17.wrapper.data.DataWrapper; import nova.core.wrapper.mc.forge.v17.wrapper.entity.EntityConverter; +import nova.core.wrapper.mc.forge.v17.wrapper.identifier.IdentifierConverter; import nova.core.wrapper.mc.forge.v17.wrapper.inventory.InventoryConverter; import nova.core.wrapper.mc.forge.v17.wrapper.item.ItemConverter; import nova.core.wrapper.mc.forge.v17.wrapper.item.OreDictionaryIntegration; @@ -120,6 +121,7 @@ public void preInit(FMLPreInitializationEvent evt) { Game.natives().registerConverter(new WorldConverter()); Game.natives().registerConverter(new CuboidConverter()); Game.natives().registerConverter(new InventoryConverter()); + Game.natives().registerConverter(new IdentifierConverter()); /** * Initiate recipe and ore dictionary integration diff --git a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/recipes/MinecraftItemIngredient.java b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/recipes/MinecraftItemIngredient.java index 97582befa..80ca24af7 100644 --- a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/recipes/MinecraftItemIngredient.java +++ b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/recipes/MinecraftItemIngredient.java @@ -29,6 +29,6 @@ */ public class MinecraftItemIngredient extends SpecificItemIngredient { public MinecraftItemIngredient(net.minecraft.item.ItemStack itemStack) { - super(((Item) Game.natives().toNova(itemStack)).getID()); + super(((Item) Game.natives().toNova(itemStack)).getID()); // TODO? } } diff --git a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/BlockConverter.java b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/BlockConverter.java index 58b2c817a..bd48ca1ca 100644 --- a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/BlockConverter.java +++ b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/BlockConverter.java @@ -32,6 +32,7 @@ import nova.core.event.BlockEvent; import nova.core.loader.Loadable; import nova.core.nativewrapper.NativeConverter; +import nova.core.util.id.StringIdentifier; import nova.core.wrapper.mc.forge.v17.launcher.NovaMinecraft; import nova.core.wrapper.mc.forge.v17.util.ModCreativeTab; import nova.core.wrapper.mc.forge.v17.wrapper.block.backward.BWBlock; @@ -107,7 +108,7 @@ private void registerMinecraftToNOVA() { BlockManager blockManager = Game.blocks(); net.minecraft.block.Block.blockRegistry.forEach(obj -> blockManager.register( - new BlockFactory(net.minecraft.block.Block.blockRegistry.getNameForObject(obj).toString(), + new BlockFactory(new StringIdentifier(net.minecraft.block.Block.blockRegistry.getNameForObject(obj)), () -> new BWBlock((net.minecraft.block.Block) obj), evt -> { }) ) @@ -118,7 +119,7 @@ private void registerNOVAToMinecraft() { BlockManager blockManager = Game.blocks(); //Register air block - BlockFactory airBlock = new BlockFactory("air", () -> new BWBlock(Blocks.air) { + BlockFactory airBlock = new BlockFactory(new StringIdentifier("air"), () -> new BWBlock(Blocks.air) { @Override public boolean canReplace() { return true; @@ -136,7 +137,7 @@ private void registerNovaBlock(BlockFactory blockFactory) { FWBlock blockWrapper = new FWBlock(blockFactory); blockFactoryMap.put(blockFactory, blockWrapper); NovaMinecraft.proxy.registerBlock(blockWrapper); - GameRegistry.registerBlock(blockWrapper, FWItemBlock.class, blockFactory.getID()); + GameRegistry.registerBlock(blockWrapper, FWItemBlock.class, blockFactory.getID().asString()); if (blockWrapper.dummy.components.has(Category.class) && FMLCommonHandler.instance().getSide().isClient()) { //Add into creative tab diff --git a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/forward/FWBlock.java b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/forward/FWBlock.java index 123d2e4f9..5656eae8c 100644 --- a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/forward/FWBlock.java +++ b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/forward/FWBlock.java @@ -91,7 +91,7 @@ public FWBlock(BlockFactory factory) { this.factory = factory; this.dummy = factory.build(); this.blockClass = dummy.getClass(); - this.setBlockName(dummy.getID()); + this.setBlockName(dummy.getID().asString()); // Recalculate super constructor things after loading the block properly this.opaque = isOpaqueCube(); diff --git a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/forward/FWTileLoader.java b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/forward/FWTileLoader.java index 64c75e154..2c5ec60df 100644 --- a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/forward/FWTileLoader.java +++ b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/forward/FWTileLoader.java @@ -23,6 +23,8 @@ import net.minecraft.nbt.NBTTagCompound; import nova.core.block.Block; import nova.core.block.BlockFactory; +import nova.core.retention.Data; +import nova.core.util.id.Identifier; import nova.core.wrapper.mc.forge.v17.asm.lib.ComponentInjector; import nova.internal.core.Game; @@ -40,8 +42,8 @@ private FWTileLoader() { public static FWTile loadTile(NBTTagCompound data) { try { - String blockID = data.getString("novaID"); - Block block = createBlock(blockID); + Data blockID = Game.natives().toNova(data.getCompoundTag("novaID")); + Block block = createBlock((Identifier) Data.unserialize(blockID)); FWTile tile = injector.inject(block, new Class[0], new Object[0]); tile.setBlock(block); return tile; @@ -50,7 +52,7 @@ public static FWTile loadTile(NBTTagCompound data) { } } - public static FWTile loadTile(String blockID) { + public static FWTile loadTile(Identifier blockID) { try { Block block = createBlock(blockID); FWTile tile = injector.inject(block, new Class[] { String.class }, new Object[] { blockID }); @@ -61,7 +63,7 @@ public static FWTile loadTile(String blockID) { } } - private static Block createBlock(String blockID) { + private static Block createBlock(Identifier blockID) { Optional blockFactory = Game.blocks().get(blockID); if (blockFactory.isPresent()) { return blockFactory.get().build(); diff --git a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/world/BWWorld.java b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/world/BWWorld.java index 28f892222..858f4bc37 100644 --- a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/world/BWWorld.java +++ b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/block/world/BWWorld.java @@ -29,6 +29,8 @@ import nova.core.entity.EntityFactory; import nova.core.item.Item; import nova.core.sound.Sound; +import nova.core.util.id.Identifier; +import nova.core.util.id.StringIdentifier; import nova.core.util.shape.Cuboid; import nova.core.world.World; import nova.core.wrapper.mc.forge.v17.launcher.NovaMinecraft; @@ -144,12 +146,12 @@ public Optional getEntity(String uniqueID) { } @Override - public String getID() { - return world().provider.getDimensionName(); + public Identifier getID() { + return new StringIdentifier(world().provider.getDimensionName()); } @Override public void playSoundAtPosition(Vector3D position, Sound sound) { - world().playSound(position.getX(), position.getY(), position.getZ(), sound.getID(), sound.pitch, sound.volume, false); + world().playSound(position.getX(), position.getY(), position.getZ(), sound.getID().asString(), sound.pitch, sound.volume, false); } } diff --git a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/entity/EntityConverter.java b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/entity/EntityConverter.java index 1fcb3a453..b86f98d64 100644 --- a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/entity/EntityConverter.java +++ b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/entity/EntityConverter.java @@ -26,6 +26,9 @@ import nova.core.entity.EntityFactory; import nova.core.loader.Loadable; import nova.core.nativewrapper.NativeConverter; +import nova.core.util.id.ClassIdentifier; +import nova.core.util.id.Identifier; +import nova.core.util.id.NamespacedStringIdentifier; import nova.core.wrapper.mc.forge.v17.wrapper.entity.backward.BWEntity; import nova.core.wrapper.mc.forge.v17.wrapper.entity.backward.BWEntityFX; import nova.core.wrapper.mc.forge.v17.wrapper.entity.forward.FWEntity; @@ -55,7 +58,7 @@ public Entity toNova(net.minecraft.entity.Entity mcEntity) { //TODO: Make this BWRegistry non-lazy //Lazy registry - String id = mcEntity.getClass().getName(); + Identifier id = new ClassIdentifier(mcEntity.getClass()); Optional entityFactory = Game.entities().get(id); if (entityFactory.isPresent()) { @@ -84,6 +87,6 @@ public void preInit() { */ //Look up for particle factory and pass it into BWEntityFX - BWEntityFX.fxMap.forEach((k, v) -> Game.entities().register(Game.info().name + ":" + k, () -> new BWEntityFX(k))); + BWEntityFX.fxMap.forEach((k, v) -> Game.entities().register(new NamespacedStringIdentifier(Game.info().name, k), () -> new BWEntityFX(k))); } } \ No newline at end of file diff --git a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/entity/backward/BWEntity.java b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/entity/backward/BWEntity.java index bc58ff023..83dda3ee3 100644 --- a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/entity/backward/BWEntity.java +++ b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/entity/backward/BWEntity.java @@ -28,6 +28,8 @@ import nova.core.entity.Entity; import nova.core.entity.component.Living; import nova.core.entity.component.Player; +import nova.core.util.id.Identifier; +import nova.core.util.id.UUIDIdentifier; import nova.core.wrapper.mc.forge.v17.wrapper.entity.forward.MCEntityTransform; import nova.core.wrapper.mc.forge.v17.wrapper.inventory.BWInventory; import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; @@ -88,8 +90,8 @@ public String getUsername() { } @Override - public String getID() { - return entity.getGameProfile().getId().toString(); + public Identifier getID() { + return new UUIDIdentifier(entity.getGameProfile().getId()); } @Override diff --git a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/entity/forward/FWEntity.java b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/entity/forward/FWEntity.java index 02a7bb50e..5775d49b8 100644 --- a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/entity/forward/FWEntity.java +++ b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/entity/forward/FWEntity.java @@ -30,9 +30,12 @@ import nova.core.component.transform.EntityTransform; import nova.core.entity.Entity; import nova.core.entity.EntityFactory; +import nova.core.network.Packet; import nova.core.retention.Data; import nova.core.retention.Storable; +import nova.core.util.id.Identifier; import nova.core.util.shape.Cuboid; +import nova.core.wrapper.mc.forge.v17.network.MCPacket; import nova.core.wrapper.mc.forge.v17.wrapper.data.DataWrapper; import nova.internal.core.Game; @@ -64,7 +67,9 @@ protected void readEntityFromNBT(NBTTagCompound nbt) { } if (wrapped == null) { //This entity was saved to disk. - setWrapped(Game.entities().get(nbt.getString("novaID")).get().build()); + NBTTagCompound novaId = nbt.getCompoundTag("novaID"); + Data d = Game.natives().toNova(novaId); + setWrapped(Game.entities().get((Identifier) Data.unserialize(d)).get().build()); } } @@ -75,11 +80,21 @@ protected void writeEntityToNBT(NBTTagCompound nbt) { ((Storable) wrapped).save(data); DataWrapper.instance().toNative(nbt, data); } - nbt.setString("novaID", wrapped.getID()); + Data data = new Data(); + data.put("novaID", wrapped.getID()); + NBTTagCompound novaId = new NBTTagCompound(); + DataWrapper.instance().toNative(novaId, data); + nbt.setTag("novaID", novaId); } @Override public void writeSpawnData(ByteBuf buffer) { + Packet packet = new MCPacket(buffer); + Data data = new Data(); + data.put("novaID", wrapped.getID()); + packet.writeData(data); + + /* //Write the ID of the entity to client String id = wrapped.getID(); char[] chars = id.toCharArray(); @@ -87,10 +102,17 @@ public void writeSpawnData(ByteBuf buffer) { for (char c : chars) buffer.writeChar(c); + */ } @Override public void readSpawnData(ByteBuf buffer) { + Packet packet = new MCPacket(buffer); + Data d = packet.readData(); + + setWrapped(Game.entities().get((Identifier) Data.unserialize(d)).get().build()); + + /* //Load the client ID String id = ""; int length = buffer.readInt(); @@ -98,6 +120,7 @@ public void readSpawnData(ByteBuf buffer) { id += buffer.readChar(); setWrapped(Game.entities().get(id).get().build()); + */ } public Entity getWrapped() { diff --git a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/identifier/IdentifierConverter.java b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/identifier/IdentifierConverter.java new file mode 100644 index 000000000..6381c231a --- /dev/null +++ b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/identifier/IdentifierConverter.java @@ -0,0 +1,32 @@ +package nova.core.wrapper.mc.forge.v17.wrapper.identifier; + +import net.minecraft.util.ResourceLocation; +import nova.core.nativewrapper.NativeConverter; +import nova.core.util.id.NamespacedStringIdentifier; + +/** + * @author soniex2 + */ +public class IdentifierConverter implements NativeConverter { + + @Override + public Class getNovaSide() { + return NamespacedStringIdentifier.class; + } + + @Override + public Class getNativeSide() { + return ResourceLocation.class; + } + + @Override + public NamespacedStringIdentifier toNova(ResourceLocation nativeObj) { + return new NamespacedStringIdentifier(nativeObj.toString()); + } + + @Override + public ResourceLocation toNative(NamespacedStringIdentifier novaObj) { + NamespacedStringIdentifier.NamespacedString ns = novaObj.asNamespacedString(); + return new ResourceLocation(ns.getNamespace(), ns.getName()); + } +} diff --git a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/item/BWItem.java b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/item/BWItem.java index 9bb8b6925..ac6dd4aaa 100644 --- a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/item/BWItem.java +++ b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/item/BWItem.java @@ -97,6 +97,6 @@ public net.minecraft.item.ItemStack makeItemStack(int stackSize) { @Override public String toString() { - return getID(); + return getID().asString(); } } diff --git a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/item/BWItemFactory.java b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/item/BWItemFactory.java index fa9f5ae35..a0a7e2885 100644 --- a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/item/BWItemFactory.java +++ b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/item/BWItemFactory.java @@ -21,10 +21,14 @@ package nova.core.wrapper.mc.forge.v17.wrapper.item; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.ResourceLocation; import nova.core.component.misc.FactoryProvider; import nova.core.item.Item; import nova.core.item.ItemFactory; import nova.core.retention.Data; +import nova.core.util.id.Identifier; +import nova.core.util.id.NamespacedStringIdentifier; +import nova.core.util.id.StringIdentifier; import nova.internal.core.Game; /** @@ -36,8 +40,13 @@ public class BWItemFactory extends ItemFactory { private final net.minecraft.item.Item item; private final int meta; + private static Identifier idFromItem(net.minecraft.item.Item item, int meta) { + // 1.7 used strings instead of ResourceLocation. + return new StringIdentifier(net.minecraft.item.Item.itemRegistry.getNameForObject(item) + (item.getHasSubtypes() ? ":" + meta : "")); + } + public BWItemFactory(net.minecraft.item.Item item, int meta) { - super(net.minecraft.item.Item.itemRegistry.getNameForObject(item) + (item.getHasSubtypes() ? ":" + meta : ""), () -> new BWItem(item, meta, null)); + super(idFromItem(item, meta), () -> new BWItem(item, meta, null)); this.item = item; this.meta = meta; diff --git a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/item/FWItem.java b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/item/FWItem.java index 7c4e8c8ec..23eb6731b 100644 --- a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/item/FWItem.java +++ b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/item/FWItem.java @@ -38,7 +38,7 @@ public class FWItem extends net.minecraft.item.Item implements ItemWrapperMethod public FWItem(ItemFactory item) { this.itemFactory = item; - setUnlocalizedName(item.getID()); + setUnlocalizedName(item.getID().asString()); setMaxStackSize(item.build().getMaxCount()); } diff --git a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/item/ItemConverter.java b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/item/ItemConverter.java index 969162193..f158eff99 100644 --- a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/item/ItemConverter.java +++ b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/wrapper/item/ItemConverter.java @@ -35,6 +35,7 @@ import nova.core.loader.Loadable; import nova.core.nativewrapper.NativeConverter; import nova.core.retention.Data; +import nova.core.util.id.Identifier; import nova.core.wrapper.mc.forge.v17.launcher.NovaMinecraft; import nova.core.wrapper.mc.forge.v17.util.ModCreativeTab; import nova.core.wrapper.mc.forge.v17.wrapper.block.BlockConverter; @@ -106,7 +107,7 @@ public ItemStack toNative(Item item) { if (item instanceof BWItem) { return ((BWItem) item).makeItemStack(item.count()); } else { - ItemFactory itemFactory = Game.items().get(item.getID()).get(); + ItemFactory itemFactory = Game.items().get(item.getID()).get(); // TODO? FWNBTTagCompound tag = new FWNBTTagCompound(item); MinecraftItemMapping mapping = get(itemFactory); @@ -133,7 +134,7 @@ public ItemStack toNative(ItemFactory itemFactory) { return result; } - public ItemStack toNative(String id) { + public ItemStack toNative(Identifier id) { return toNative(Game.items().get(id).get().build().setCount(1)); } @@ -202,7 +203,7 @@ private void registerNOVAItem(ItemFactory itemFactory) { // Don't register ItemBlocks twice if (!(dummy instanceof ItemBlock)) { NovaMinecraft.proxy.registerItem((FWItem) itemWrapper); - GameRegistry.registerItem(itemWrapper, itemFactory.getID()); + GameRegistry.registerItem(itemWrapper, itemFactory.getID().asString()); if (dummy.components.has(Category.class) && FMLCommonHandler.instance().getSide().isClient()) { //Add into creative tab @@ -239,14 +240,14 @@ private void onIDNotFound(ItemIDNotFoundEvent event) { // if item minecraft:planks:2 is detected, this code will register minecraft:planks:2 dynamically // we cannot do this up front since there is **NO** reliable way to get the sub-items of an item - int lastColon = event.id.lastIndexOf(':'); + int lastColon = event.id.asString().lastIndexOf(':'); if (lastColon < 0) { return; } try { - int meta = Integer.parseInt(event.id.substring(lastColon + 1)); - String itemID = event.id.substring(0, lastColon); + int meta = Integer.parseInt(event.id.asString().substring(lastColon + 1)); + String itemID = event.id.asString().substring(0, lastColon); net.minecraft.item.Item item = (net.minecraft.item.Item) net.minecraft.item.Item.itemRegistry.getObject(itemID); if (item == null || !item.getHasSubtypes()) { diff --git a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/launcher/NovaMinecraft.java b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/launcher/NovaMinecraft.java index eb0a0f321..c371d63b0 100644 --- a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/launcher/NovaMinecraft.java +++ b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/launcher/NovaMinecraft.java @@ -50,6 +50,7 @@ import nova.core.wrapper.mc.forge.v18.wrapper.cuboid.CuboidConverter; import nova.core.wrapper.mc.forge.v18.wrapper.data.DataWrapper; import nova.core.wrapper.mc.forge.v18.wrapper.entity.EntityConverter; +import nova.core.wrapper.mc.forge.v18.wrapper.identifier.IdentifierConverter; import nova.core.wrapper.mc.forge.v18.wrapper.inventory.InventoryConverter; import nova.core.wrapper.mc.forge.v18.wrapper.item.ItemConverter; import nova.core.wrapper.mc.forge.v18.wrapper.item.OreDictionaryIntegration; @@ -122,6 +123,7 @@ public void preInit(FMLPreInitializationEvent evt) { Game.natives().registerConverter(new CuboidConverter()); Game.natives().registerConverter(new InventoryConverter()); Game.natives().registerConverter(new VectorConverter()); + Game.natives().registerConverter(new IdentifierConverter()); /** * Initiate recipe and ore dictionary integration diff --git a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/recipes/MinecraftItemIngredient.java b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/recipes/MinecraftItemIngredient.java index 72116bf5e..34873b89f 100644 --- a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/recipes/MinecraftItemIngredient.java +++ b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/recipes/MinecraftItemIngredient.java @@ -29,6 +29,6 @@ */ public class MinecraftItemIngredient extends SpecificItemIngredient { public MinecraftItemIngredient(net.minecraft.item.ItemStack itemStack) { - super(((Item) Game.natives().toNova(itemStack)).getID()); + super(((Item) Game.natives().toNova(itemStack)).getID()); // TODO? } } diff --git a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/BlockConverter.java b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/BlockConverter.java index 17514f534..aba205a81 100644 --- a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/BlockConverter.java +++ b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/BlockConverter.java @@ -32,6 +32,7 @@ import nova.core.event.BlockEvent; import nova.core.loader.Loadable; import nova.core.nativewrapper.NativeConverter; +import nova.core.util.id.StringIdentifier; import nova.core.wrapper.mc.forge.v18.launcher.NovaMinecraft; import nova.core.wrapper.mc.forge.v18.util.ModCreativeTab; import nova.core.wrapper.mc.forge.v18.wrapper.block.backward.BWBlock; @@ -108,7 +109,8 @@ private void registerMinecraftToNOVA() { BlockManager blockManager = Game.blocks(); net.minecraft.block.Block.blockRegistry.forEach(obj -> blockManager.register( - new BlockFactory(net.minecraft.block.Block.blockRegistry.getNameForObject(obj).toString(), + // TODO check + new BlockFactory(Game.natives().toNova(net.minecraft.block.Block.blockRegistry.getNameForObject(obj)), () -> new BWBlock((net.minecraft.block.Block) obj), evt -> { }) ) @@ -119,7 +121,7 @@ private void registerNOVAToMinecraft() { BlockManager blockManager = Game.blocks(); //Register air block - BlockFactory airBlock = new BlockFactory("air", () -> new BWBlock(Blocks.air) { + BlockFactory airBlock = new BlockFactory(new StringIdentifier("air"), () -> new BWBlock(Blocks.air) { @Override public boolean canReplace() { return true; @@ -136,7 +138,7 @@ public boolean canReplace() { private void registerNovaBlock(BlockFactory blockFactory) { FWBlock blockWrapper = new FWBlock(blockFactory); blockFactoryMap.put(blockFactory, blockWrapper); - GameRegistry.registerBlock(blockWrapper, FWItemBlock.class, blockFactory.getID()); + GameRegistry.registerBlock(blockWrapper, FWItemBlock.class, blockFactory.getID().asString()); NovaMinecraft.proxy.postRegisterBlock(blockWrapper); if (blockWrapper.dummy.components.has(Category.class) && FMLCommonHandler.instance().getSide().isClient()) { diff --git a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/forward/FWBlock.java b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/forward/FWBlock.java index 36d9eb71a..4074e7785 100644 --- a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/forward/FWBlock.java +++ b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/forward/FWBlock.java @@ -99,7 +99,7 @@ public FWBlock(BlockFactory factory) { this.stepSound = soundTypeStone; } this.blockClass = dummy.getClass(); - this.setUnlocalizedName(dummy.getID()); + this.setUnlocalizedName(dummy.getID().asString()); // Recalculate super constructor things after loading the block properly this.fullBlock = isOpaqueCube(); diff --git a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/forward/FWBlockSound.java b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/forward/FWBlockSound.java index f7f1326ab..3d97adda7 100644 --- a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/forward/FWBlockSound.java +++ b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/forward/FWBlockSound.java @@ -26,7 +26,7 @@ public String getBreakSound() { if (sound.domain.isEmpty() && !sound.name.contains(".")) { return "dig." + sound.name; } - return sound.getID(); + return sound.getID().asString(); } return super.getBreakSound(); } @@ -38,7 +38,7 @@ public String getStepSound() { if (sound.domain.isEmpty() && !sound.name.contains(".")) { return "step." + sound.name; } - return sound.getID(); + return sound.getID().asString(); } return super.getStepSound(); } @@ -50,7 +50,7 @@ public String getPlaceSound() { if (sound.domain.isEmpty()) { return sound.name; } - return sound.getID(); + return sound.getID().asString(); } // By default MC uses the block break sound for block placement return this.getBreakSound(); diff --git a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/forward/FWTileLoader.java b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/forward/FWTileLoader.java index 907633c88..42cab8d1b 100644 --- a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/forward/FWTileLoader.java +++ b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/forward/FWTileLoader.java @@ -24,6 +24,8 @@ import nova.core.block.Block; import nova.core.block.BlockFactory; import nova.core.component.Updater; +import nova.core.retention.Data; +import nova.core.util.id.Identifier; import nova.core.wrapper.mc.forge.v18.asm.lib.ComponentInjector; import nova.internal.core.Game; @@ -42,8 +44,8 @@ private FWTileLoader() { public static FWTile loadTile(NBTTagCompound data) { try { - String blockID = data.getString("novaID"); - Block block = createBlock(blockID); + Data blockID = Game.natives().toNova(data.getCompoundTag("novaID")); + Block block = createBlock((Identifier) Data.unserialize(blockID)); FWTile tile = (block instanceof Updater) ? updaterInjector.inject(block, new Class[0], new Object[0]) : injector.inject(block, new Class[0], new Object[0]); tile.setBlock(block); return tile; @@ -52,7 +54,7 @@ public static FWTile loadTile(NBTTagCompound data) { } } - public static FWTile loadTile(String blockID) { + public static FWTile loadTile(Identifier blockID) { try { Block block = createBlock(blockID); FWTile tile = (block instanceof Updater) ? updaterInjector.inject(block, new Class[] { String.class }, new Object[] { blockID }) : injector.inject(block, new Class[] { @@ -64,7 +66,7 @@ public static FWTile loadTile(String blockID) { } } - private static Block createBlock(String blockID) { + private static Block createBlock(Identifier blockID) { Optional blockFactory = Game.blocks().get(blockID); if (blockFactory.isPresent()) { return blockFactory.get().build(); diff --git a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/world/BWWorld.java b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/world/BWWorld.java index d53baf619..36eea8f77 100644 --- a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/world/BWWorld.java +++ b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/block/world/BWWorld.java @@ -31,6 +31,8 @@ import nova.core.entity.EntityFactory; import nova.core.item.Item; import nova.core.sound.Sound; +import nova.core.util.id.Identifier; +import nova.core.util.id.StringIdentifier; import nova.core.util.shape.Cuboid; import nova.core.world.World; import nova.core.wrapper.mc.forge.v18.launcher.NovaMinecraft; @@ -153,12 +155,12 @@ public Optional getEntity(String uniqueID) { } @Override - public String getID() { - return world().provider.getDimensionName(); + public Identifier getID() { + return new StringIdentifier(world().provider.getDimensionName()); } @Override public void playSoundAtPosition(Vector3D position, Sound sound) { - world().playSoundEffect(position.getX(), position.getY(), position.getZ(), sound.getID(), sound.volume, sound.pitch); + world().playSoundEffect(position.getX(), position.getY(), position.getZ(), sound.getID().asString(), sound.volume, sound.pitch); } } diff --git a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/entity/EntityConverter.java b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/entity/EntityConverter.java index 23c7ad671..e0f3658e6 100644 --- a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/entity/EntityConverter.java +++ b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/entity/EntityConverter.java @@ -27,6 +27,9 @@ import nova.core.entity.EntityFactory; import nova.core.loader.Loadable; import nova.core.nativewrapper.NativeConverter; +import nova.core.util.id.ClassIdentifier; +import nova.core.util.id.Identifier; +import nova.core.util.id.NamespacedStringIdentifier; import nova.core.wrapper.mc.forge.v18.wrapper.entity.backward.BWEntity; import nova.core.wrapper.mc.forge.v18.wrapper.entity.backward.BWEntityFX; import nova.core.wrapper.mc.forge.v18.wrapper.entity.forward.FWEntity; @@ -56,7 +59,7 @@ public Entity toNova(net.minecraft.entity.Entity mcEntity) { //TODO: Make this BWRegistry non-lazy //Lazy registry - String id = mcEntity.getClass().getName(); + Identifier id = new ClassIdentifier(mcEntity.getClass()); Optional entityFactory = Game.entities().get(id); if (entityFactory.isPresent()) { @@ -85,7 +88,7 @@ public void preInit() { */ //Look up for particle factory and pass it into BWEntityFX for (EnumParticleTypes type : EnumParticleTypes.values()) { - Game.entities().register(Game.info().name + ":" + type.getParticleName(), () -> new BWEntityFX(type.getParticleID())); + Game.entities().register(new NamespacedStringIdentifier(Game.info().name, type.getParticleName()), () -> new BWEntityFX(type.getParticleID())); } } } \ No newline at end of file diff --git a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/entity/backward/BWEntity.java b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/entity/backward/BWEntity.java index eb68b58ff..acb33bc20 100644 --- a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/entity/backward/BWEntity.java +++ b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/entity/backward/BWEntity.java @@ -28,6 +28,8 @@ import nova.core.entity.Entity; import nova.core.entity.component.Living; import nova.core.entity.component.Player; +import nova.core.util.id.Identifier; +import nova.core.util.id.UUIDIdentifier; import nova.core.wrapper.mc.forge.v18.wrapper.entity.forward.MCEntityTransform; import nova.core.wrapper.mc.forge.v18.wrapper.inventory.BWInventory; import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; @@ -88,8 +90,8 @@ public String getUsername() { } @Override - public String getID() { - return entity.getGameProfile().getId().toString(); + public Identifier getID() { + return new UUIDIdentifier(entity.getGameProfile().getId()); } @Override diff --git a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/entity/forward/FWEntity.java b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/entity/forward/FWEntity.java index d01763dc2..6d2871a37 100644 --- a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/entity/forward/FWEntity.java +++ b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/entity/forward/FWEntity.java @@ -30,9 +30,12 @@ import nova.core.component.transform.EntityTransform; import nova.core.entity.Entity; import nova.core.entity.EntityFactory; +import nova.core.network.Packet; import nova.core.retention.Data; import nova.core.retention.Storable; +import nova.core.util.id.Identifier; import nova.core.util.shape.Cuboid; +import nova.core.wrapper.mc.forge.v18.network.MCPacket; import nova.core.wrapper.mc.forge.v18.wrapper.data.DataWrapper; import nova.internal.core.Game; @@ -64,7 +67,9 @@ protected void readEntityFromNBT(NBTTagCompound nbt) { } if (wrapped == null) { //This entity was saved to disk. - setWrapped(Game.entities().get(nbt.getString("novaID")).get().build()); + NBTTagCompound novaId = nbt.getCompoundTag("novaID"); + Data d = Game.natives().toNova(novaId); + setWrapped(Game.entities().get((Identifier) Data.unserialize(d)).get().build()); } } @@ -75,11 +80,21 @@ protected void writeEntityToNBT(NBTTagCompound nbt) { ((Storable) wrapped).save(data); DataWrapper.instance().toNative(nbt, data); } - nbt.setString("novaID", wrapped.getID()); + Data data = new Data(); + data.put("novaID", wrapped.getID()); + NBTTagCompound novaId = new NBTTagCompound(); + DataWrapper.instance().toNative(novaId, data); + nbt.setTag("novaID", novaId); } @Override public void writeSpawnData(ByteBuf buffer) { + Packet packet = new MCPacket(buffer); + Data data = new Data(); + data.put("novaID", wrapped.getID()); + packet.writeData(data); + + /* //Write the ID of the entity to client String id = wrapped.getID(); char[] chars = id.toCharArray(); @@ -87,10 +102,17 @@ public void writeSpawnData(ByteBuf buffer) { for (char c : chars) buffer.writeChar(c); + */ } @Override public void readSpawnData(ByteBuf buffer) { + Packet packet = new MCPacket(buffer); + Data d = packet.readData(); + + setWrapped(Game.entities().get((Identifier) Data.unserialize(d)).get().build()); + + /* //Load the client ID String id = ""; int length = buffer.readInt(); @@ -98,6 +120,7 @@ public void readSpawnData(ByteBuf buffer) { id += buffer.readChar(); setWrapped(Game.entities().get(id).get().build()); + */ } public Entity getWrapped() { diff --git a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/identifier/IdentifierConverter.java b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/identifier/IdentifierConverter.java new file mode 100644 index 000000000..86e99d961 --- /dev/null +++ b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/identifier/IdentifierConverter.java @@ -0,0 +1,32 @@ +package nova.core.wrapper.mc.forge.v18.wrapper.identifier; + +import net.minecraft.util.ResourceLocation; +import nova.core.nativewrapper.NativeConverter; +import nova.core.util.id.NamespacedStringIdentifier; + +/** + * @author soniex2 + */ +public class IdentifierConverter implements NativeConverter { + + @Override + public Class getNovaSide() { + return NamespacedStringIdentifier.class; + } + + @Override + public Class getNativeSide() { + return ResourceLocation.class; + } + + @Override + public NamespacedStringIdentifier toNova(ResourceLocation nativeObj) { + return new NamespacedStringIdentifier(nativeObj.toString()); + } + + @Override + public ResourceLocation toNative(NamespacedStringIdentifier novaObj) { + NamespacedStringIdentifier.NamespacedString ns = novaObj.asNamespacedString(); + return new ResourceLocation(ns.getNamespace(), ns.getName()); + } +} diff --git a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/item/BWItem.java b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/item/BWItem.java index 7476b9d26..da8cfc6b5 100644 --- a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/item/BWItem.java +++ b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/item/BWItem.java @@ -66,6 +66,6 @@ public ItemStack makeItemStack(int stackSize) { @Override public String toString() { - return getID(); + return getID().asString(); } } diff --git a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/item/BWItemFactory.java b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/item/BWItemFactory.java index e28085d10..aa97ed2ae 100644 --- a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/item/BWItemFactory.java +++ b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/item/BWItemFactory.java @@ -21,10 +21,13 @@ package nova.core.wrapper.mc.forge.v18.wrapper.item; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.ResourceLocation; import nova.core.component.misc.FactoryProvider; import nova.core.item.Item; import nova.core.item.ItemFactory; import nova.core.retention.Data; +import nova.core.util.id.Identifier; +import nova.core.util.id.NamespacedStringIdentifier; import nova.internal.core.Game; /** @@ -36,8 +39,19 @@ public class BWItemFactory extends ItemFactory { private final net.minecraft.item.Item item; private final int meta; + private static Identifier idFromItem(net.minecraft.item.Item item, int meta) { + // We don't use Game().natives().toNova() here because we need to add stuff to the identifier + ResourceLocation resloc = (ResourceLocation) net.minecraft.item.Item.itemRegistry.getNameForObject(item); + String namespace = resloc.getResourceDomain(); + String name = resloc.getResourcePath(); + if (item.getHasSubtypes()) { + name = name + ":" + meta; + } + return new NamespacedStringIdentifier(namespace, name); + } + public BWItemFactory(net.minecraft.item.Item item, int meta) { - super(net.minecraft.item.Item.itemRegistry.getNameForObject(item) + (item.getHasSubtypes() ? ":" + meta : ""), () -> new BWItem(item, meta, null)); + super(idFromItem(item, meta), () -> new BWItem(item, meta, null)); this.item = item; this.meta = meta; diff --git a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/item/FWItem.java b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/item/FWItem.java index 6ce3b84a4..3f8ae89a8 100644 --- a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/item/FWItem.java +++ b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/item/FWItem.java @@ -38,7 +38,7 @@ public class FWItem extends net.minecraft.item.Item implements ItemWrapperMethod public FWItem(ItemFactory item) { this.itemFactory = item; - setUnlocalizedName(item.getID()); + setUnlocalizedName(item.getID().asString()); setMaxStackSize(item.build().getMaxCount()); } diff --git a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/item/ItemConverter.java b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/item/ItemConverter.java index 793bb2fd1..715032225 100644 --- a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/item/ItemConverter.java +++ b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/wrapper/item/ItemConverter.java @@ -36,6 +36,7 @@ import nova.core.loader.Loadable; import nova.core.nativewrapper.NativeConverter; import nova.core.retention.Data; +import nova.core.util.id.Identifier; import nova.core.wrapper.mc.forge.v18.launcher.NovaMinecraft; import nova.core.wrapper.mc.forge.v18.util.ModCreativeTab; import nova.core.wrapper.mc.forge.v18.wrapper.block.BlockConverter; @@ -134,7 +135,7 @@ public ItemStack toNative(ItemFactory itemFactory) { return result; } - public ItemStack toNative(String id) { + public ItemStack toNative(Identifier id) { return toNative(Game.items().get(id).get().build().setCount(1)); } @@ -204,7 +205,7 @@ private void registerNOVAItem(ItemFactory itemFactory) { // Don't register ItemBlocks twice if (!(dummy instanceof ItemBlock)) { NovaMinecraft.proxy.registerItem((FWItem) itemWrapper); - GameRegistry.registerItem(itemWrapper, itemFactory.getID()); + GameRegistry.registerItem(itemWrapper, itemFactory.getID().asString()); if (dummy.components.has(Category.class) && FMLCommonHandler.instance().getSide().isClient()) { //Add into creative tab @@ -241,14 +242,17 @@ private void onIDNotFound(ItemIDNotFoundEvent event) { // if item minecraft:planks:2 is detected, this code will register minecraft:planks:2 dynamically // we cannot do this up front since there is **NO** reliable way to get the sub-items of an item - int lastColon = event.id.lastIndexOf(':'); + int lastColon = event.id.asString().lastIndexOf(':'); if (lastColon < 0) { return; } try { - int meta = Integer.parseInt(event.id.substring(lastColon + 1)); - String itemID = event.id.substring(0, lastColon); + int meta = Integer.parseInt(event.id.asString().substring(lastColon + 1)); + // FML will magically convert this result into a ResourceLocation for you, + // which simplifies our end. + // Any Identifier-related fluff would only be strictness checks. + String itemID = event.id.asString().substring(0, lastColon); net.minecraft.item.Item item = (net.minecraft.item.Item) net.minecraft.item.Item.itemRegistry.getObject(itemID); if (item == null || !item.getHasSubtypes()) { diff --git a/src/main/java/nova/core/block/Block.java b/src/main/java/nova/core/block/Block.java index 7b7f4fb6a..1e0e04bf4 100644 --- a/src/main/java/nova/core/block/Block.java +++ b/src/main/java/nova/core/block/Block.java @@ -30,7 +30,8 @@ import nova.core.item.Item; import nova.core.item.ItemFactory; import nova.core.util.Direction; -import nova.core.util.Identifiable; +import nova.core.util.id.Identifiable; +import nova.core.util.id.Identifier; import nova.core.world.World; import nova.internal.core.Game; import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; @@ -59,7 +60,7 @@ public final BlockFactory getFactory() { } @Override - public final String getID() { + public final Identifier getID() { return getFactory().getID(); } diff --git a/src/main/java/nova/core/block/BlockFactory.java b/src/main/java/nova/core/block/BlockFactory.java index 29e947504..8a8111964 100644 --- a/src/main/java/nova/core/block/BlockFactory.java +++ b/src/main/java/nova/core/block/BlockFactory.java @@ -24,6 +24,7 @@ import nova.core.event.BlockEvent; import nova.core.event.bus.EventListener; import nova.core.item.ItemBlock; +import nova.core.util.id.Identifier; import nova.core.util.registry.Factory; import nova.internal.core.Game; @@ -35,11 +36,11 @@ * @author Calclavia */ public class BlockFactory extends Factory { - public BlockFactory(String id, Supplier constructor, Function processor) { + public BlockFactory(Identifier id, Supplier constructor, Function processor) { super(id, constructor, processor); } - public BlockFactory(String id, Supplier constructor) { + public BlockFactory(Identifier id, Supplier constructor) { this(id, constructor, evt -> { Game.items().register(id, () -> new ItemBlock(evt.blockFactory)); }); @@ -51,7 +52,7 @@ public BlockFactory(String id, Supplier constructor) { * @param constructor The constructor function * @param postCreate Function for registering item blocks */ - public BlockFactory(String id, Supplier constructor, EventListener postCreate) { + public BlockFactory(Identifier id, Supplier constructor, EventListener postCreate) { super(id, constructor); postCreate(postCreate); } @@ -61,7 +62,7 @@ protected void postCreate(EventListener postCreate) { } @Override - protected BlockFactory selfConstructor(String id, Supplier constructor, Function processor) { + protected BlockFactory selfConstructor(Identifier id, Supplier constructor, Function processor) { return new BlockFactory(id, constructor, processor); } diff --git a/src/main/java/nova/core/block/BlockManager.java b/src/main/java/nova/core/block/BlockManager.java index 41a28f90f..b5f27151f 100644 --- a/src/main/java/nova/core/block/BlockManager.java +++ b/src/main/java/nova/core/block/BlockManager.java @@ -21,6 +21,8 @@ package nova.core.block; import nova.core.event.BlockEvent; +import nova.core.util.id.Identifier; +import nova.core.util.id.StringIdentifier; import nova.core.util.registry.FactoryManager; import nova.core.util.registry.Registry; import nova.internal.core.Game; @@ -38,7 +40,7 @@ private BlockManager(Registry registry) { * @return The air block factory */ public BlockFactory getAirBlock() { - return get("air").get(); + return get(new StringIdentifier("air")).get(); } /** @@ -47,7 +49,7 @@ public BlockFactory getAirBlock() { * @return Dummy block */ @Override - public BlockFactory register(String id, Supplier constructor) { + public BlockFactory register(Identifier id, Supplier constructor) { return register(new BlockFactory(id, constructor)); } diff --git a/src/main/java/nova/core/component/Category.java b/src/main/java/nova/core/component/Category.java index 95c8002d4..f8cd3a0df 100644 --- a/src/main/java/nova/core/component/Category.java +++ b/src/main/java/nova/core/component/Category.java @@ -21,7 +21,9 @@ package nova.core.component; import nova.core.item.Item; -import nova.core.util.Identifiable; +import nova.core.util.id.Identifiable; +import nova.core.util.id.Identifier; +import nova.core.util.id.StringIdentifier; import java.util.Optional; @@ -46,7 +48,7 @@ public Category(String name) { } @Override - public String getID() { - return name; + public Identifier getID() { + return new StringIdentifier(name); } } diff --git a/src/main/java/nova/core/component/Component.java b/src/main/java/nova/core/component/Component.java index df2ecd0d4..a0a854b6a 100644 --- a/src/main/java/nova/core/component/Component.java +++ b/src/main/java/nova/core/component/Component.java @@ -21,7 +21,9 @@ package nova.core.component; import nova.core.component.exception.ComponentException; -import nova.core.util.Identifiable; +import nova.core.util.id.ClassIdentifier; +import nova.core.util.id.Identifiable; +import nova.core.util.id.Identifier; /** * Base interface for all Components. @@ -51,7 +53,7 @@ public void onProviderChange() { } @Override - public String getID() { - return getClass().getSimpleName(); + public Identifier getID() { + return new ClassIdentifier(getClass()); } } diff --git a/src/main/java/nova/core/component/fluid/Fluid.java b/src/main/java/nova/core/component/fluid/Fluid.java index 809e968ca..0eda1cc46 100644 --- a/src/main/java/nova/core/component/fluid/Fluid.java +++ b/src/main/java/nova/core/component/fluid/Fluid.java @@ -24,7 +24,9 @@ import nova.core.retention.Data; import nova.core.retention.Storable; import nova.core.retention.Store; -import nova.core.util.Identifiable; +import nova.core.util.id.AbstractIdentifier; +import nova.core.util.id.Identifiable; +import nova.core.util.id.Identifier; import nova.internal.core.Game; import java.util.Optional; @@ -126,7 +128,7 @@ public boolean sameType(Fluid stack) { } @Override - public final String getID() { + public final Identifier getID() { return factory.getID(); } @@ -144,6 +146,6 @@ public void save(Data data) { @Override public void load(Data data) { Storable.super.load(data); - factory = Game.fluids().get(data.get("id")).get(); + factory = Game.fluids().get(data.getDataConvertible("id")).get(); } } diff --git a/src/main/java/nova/core/component/fluid/FluidFactory.java b/src/main/java/nova/core/component/fluid/FluidFactory.java index 4b5af7ced..b6353d764 100644 --- a/src/main/java/nova/core/component/fluid/FluidFactory.java +++ b/src/main/java/nova/core/component/fluid/FluidFactory.java @@ -20,6 +20,7 @@ package nova.core.component.fluid; +import nova.core.util.id.Identifier; import nova.core.util.registry.Factory; import java.util.function.Function; @@ -30,11 +31,11 @@ */ public class FluidFactory extends Factory { - public FluidFactory(String id, Supplier constructor, Function processor) { + public FluidFactory(Identifier id, Supplier constructor, Function processor) { super(id, constructor, processor); } - public FluidFactory(String id, Supplier constructor) { + public FluidFactory(Identifier id, Supplier constructor) { super(id, constructor); } @@ -46,7 +47,7 @@ public Fluid build() { } @Override - protected FluidFactory selfConstructor(String id, Supplier constructor, Function processor) { + protected FluidFactory selfConstructor(Identifier id, Supplier constructor, Function processor) { return new FluidFactory(id, constructor, processor); } } diff --git a/src/main/java/nova/core/component/fluid/FluidManager.java b/src/main/java/nova/core/component/fluid/FluidManager.java index f5a1b2d73..1759a5ff6 100644 --- a/src/main/java/nova/core/component/fluid/FluidManager.java +++ b/src/main/java/nova/core/component/fluid/FluidManager.java @@ -20,6 +20,8 @@ package nova.core.component.fluid; +import nova.core.util.id.Identifier; +import nova.core.util.id.StringIdentifier; import nova.core.util.registry.FactoryManager; import nova.core.util.registry.Registry; @@ -32,12 +34,12 @@ public class FluidManager extends FactoryManager fluidRegistry) { super(fluidRegistry); //TODO: Too Minecraft specific. Implementation should be hidden. - this.water = register("water", Fluid::new); - this.lava = register("lava", Fluid::new); + this.water = register(new StringIdentifier("water"), Fluid::new); + this.lava = register(new StringIdentifier("lava"), Fluid::new); } @Override - public FluidFactory register(String id, Supplier constructor) { + public FluidFactory register(Identifier id, Supplier constructor) { return register(new FluidFactory(id, constructor)); } diff --git a/src/main/java/nova/core/component/misc/Damageable.java b/src/main/java/nova/core/component/misc/Damageable.java index 5f4c63c7d..e5e6c9771 100644 --- a/src/main/java/nova/core/component/misc/Damageable.java +++ b/src/main/java/nova/core/component/misc/Damageable.java @@ -21,7 +21,9 @@ package nova.core.component.misc; import nova.core.component.Component; -import nova.core.util.Identifiable; +import nova.core.util.id.Identifiable; +import nova.core.util.id.Identifier; +import nova.core.util.id.StringIdentifier; /** * Applied to objects that can take damage. @@ -46,8 +48,8 @@ public DamageType(String name) { } @Override - public String getID() { - return name; + public Identifier getID() { + return new StringIdentifier(name); } } } diff --git a/src/main/java/nova/core/entity/Entity.java b/src/main/java/nova/core/entity/Entity.java index c0943e100..e8edd4958 100644 --- a/src/main/java/nova/core/entity/Entity.java +++ b/src/main/java/nova/core/entity/Entity.java @@ -24,8 +24,10 @@ import nova.core.component.ComponentProvider; import nova.core.component.misc.FactoryProvider; import nova.core.component.transform.EntityTransform; -import nova.core.util.Identifiable; -import nova.core.util.UniqueIdentifiable; +import nova.core.util.id.Identifiable; +import nova.core.util.id.UniqueIdentifiable; +import nova.core.util.id.Identifier; +import nova.core.util.id.UUIDIdentifier; import nova.core.world.World; import org.apache.commons.math3.geometry.euclidean.threed.Rotation; import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; @@ -96,12 +98,12 @@ public final EntityFactory getFactory() { } @Override - public final String getID() { + public final Identifier getID() { return getFactory().getID(); } @Override - public String getUniqueID() { + public UUIDIdentifier getUniqueID() { return components.get(UniqueIdentifiable.class).getUniqueID(); } } diff --git a/src/main/java/nova/core/entity/EntityFactory.java b/src/main/java/nova/core/entity/EntityFactory.java index 7a1712b7e..c7c352189 100644 --- a/src/main/java/nova/core/entity/EntityFactory.java +++ b/src/main/java/nova/core/entity/EntityFactory.java @@ -21,6 +21,7 @@ package nova.core.entity; import nova.core.component.misc.FactoryProvider; +import nova.core.util.id.Identifier; import nova.core.util.registry.Factory; import java.util.function.Function; @@ -31,16 +32,16 @@ * @author Calclavia */ public class EntityFactory extends Factory { - public EntityFactory(String id, Supplier constructor, Function processor) { + public EntityFactory(Identifier id, Supplier constructor, Function processor) { super(id, constructor, processor); } - public EntityFactory(String id, Supplier constructor) { + public EntityFactory(Identifier id, Supplier constructor) { super(id, constructor); } @Override - protected EntityFactory selfConstructor(String id, Supplier constructor, Function processor) { + protected EntityFactory selfConstructor(Identifier id, Supplier constructor, Function processor) { return new EntityFactory(id, constructor, processor); } diff --git a/src/main/java/nova/core/entity/EntityManager.java b/src/main/java/nova/core/entity/EntityManager.java index c49ec3731..91cc06ecb 100644 --- a/src/main/java/nova/core/entity/EntityManager.java +++ b/src/main/java/nova/core/entity/EntityManager.java @@ -20,6 +20,7 @@ package nova.core.entity; +import nova.core.util.id.Identifier; import nova.core.util.registry.FactoryManager; import nova.core.util.registry.Registry; import nova.internal.core.Game; @@ -38,7 +39,7 @@ private EntityManager(Registry registry) { * @return The entity factory */ @Override - public EntityFactory register(String id, Supplier constructor) { + public EntityFactory register(Identifier id, Supplier constructor) { return register(new EntityFactory(id, constructor)); } diff --git a/src/main/java/nova/core/item/Item.java b/src/main/java/nova/core/item/Item.java index 61f6c86e1..255314bc7 100644 --- a/src/main/java/nova/core/item/Item.java +++ b/src/main/java/nova/core/item/Item.java @@ -27,7 +27,8 @@ import nova.core.render.Color; import nova.core.retention.Storable; import nova.core.util.Direction; -import nova.core.util.Identifiable; +import nova.core.util.id.Identifiable; +import nova.core.util.id.Identifier; import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; import java.util.List; @@ -50,7 +51,7 @@ public final ItemFactory getFactory() { } @Override - public final String getID() { + public final Identifier getID() { return getFactory().getID(); } diff --git a/src/main/java/nova/core/item/ItemFactory.java b/src/main/java/nova/core/item/ItemFactory.java index a31f83599..ff7ec53fd 100644 --- a/src/main/java/nova/core/item/ItemFactory.java +++ b/src/main/java/nova/core/item/ItemFactory.java @@ -23,8 +23,9 @@ import nova.core.component.misc.FactoryProvider; import nova.core.retention.Data; import nova.core.retention.Storable; +import nova.core.util.id.Identifier; import nova.core.util.registry.Factory; -import nova.core.util.Identifiable; +import nova.core.util.id.Identifiable; import java.util.function.Function; import java.util.function.Supplier; @@ -33,11 +34,11 @@ * @author Calclavia */ public class ItemFactory extends Factory implements Identifiable { - public ItemFactory(String id, Supplier constructor, Function processor) { + public ItemFactory(Identifier id, Supplier constructor, Function processor) { super(id, constructor, processor); } - public ItemFactory(String id, Supplier constructor) { + public ItemFactory(Identifier id, Supplier constructor) { super(id, constructor); } @@ -74,7 +75,7 @@ public Data save(Item item) { } @Override - protected ItemFactory selfConstructor(String id, Supplier constructor, Function processor) { + protected ItemFactory selfConstructor(Identifier id, Supplier constructor, Function processor) { return new ItemFactory(id, constructor, processor); } } diff --git a/src/main/java/nova/core/item/ItemManager.java b/src/main/java/nova/core/item/ItemManager.java index d31b79dcb..85841a55c 100644 --- a/src/main/java/nova/core/item/ItemManager.java +++ b/src/main/java/nova/core/item/ItemManager.java @@ -24,6 +24,7 @@ import nova.core.block.BlockManager; import nova.core.event.bus.CancelableEvent; import nova.core.item.event.ItemIDNotFoundEvent; +import nova.core.util.id.Identifier; import nova.core.util.registry.FactoryManager; import nova.core.util.registry.Registry; import nova.internal.core.Game; @@ -46,7 +47,7 @@ private ItemManager(Registry itemRegistry, Supplier b * @return Dummy item */ @Override - public ItemFactory register(String id, Supplier constructor) { + public ItemFactory register(Identifier id, Supplier constructor) { return register(new ItemFactory(id, constructor)); } @@ -66,7 +67,7 @@ public Optional getBlockFromItem(Item item) { } @Override - public Optional get(String name) { + public Optional get(Identifier name) { if (!registry.contains(name)) { ItemIDNotFoundEvent event = new ItemIDNotFoundEvent(name); Game.events().publish(event); diff --git a/src/main/java/nova/core/item/event/ItemIDNotFoundEvent.java b/src/main/java/nova/core/item/event/ItemIDNotFoundEvent.java index 160eaf06b..5ff0bdf10 100644 --- a/src/main/java/nova/core/item/event/ItemIDNotFoundEvent.java +++ b/src/main/java/nova/core/item/event/ItemIDNotFoundEvent.java @@ -20,16 +20,17 @@ import nova.core.event.bus.Event; import nova.core.item.ItemFactory; +import nova.core.util.id.Identifier; /** * @author Stan */ public class ItemIDNotFoundEvent extends Event { - public final String id; + public final Identifier id; private ItemFactory remappedFactory = null; - public ItemIDNotFoundEvent(String id) { + public ItemIDNotFoundEvent(Identifier id) { this.id = id; } diff --git a/src/main/java/nova/core/network/Packet.java b/src/main/java/nova/core/network/Packet.java index 2ad0c0484..258c5c60f 100644 --- a/src/main/java/nova/core/network/Packet.java +++ b/src/main/java/nova/core/network/Packet.java @@ -26,16 +26,12 @@ import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; import org.apache.commons.math3.geometry.euclidean.twod.Vector2D; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Optional; -import java.util.Set; +import java.util.*; import java.util.stream.IntStream; /** * A packet of data that is writable or readable. + * * @author Calclavia */ public interface Packet { @@ -47,6 +43,7 @@ public interface Packet { /** * Sets the ID of this packet, allowing it to be sent accordingly. + * * @return The packet itself. */ Packet setID(int id); @@ -58,6 +55,7 @@ public interface Packet { /** * Writes an arbitrary object, automatically finding the relevant class. + * * @param data Object to write * @return This packet */ @@ -82,6 +80,8 @@ default Packet write(Object data) { writeString((String) data); } else if (data instanceof Enum) { writeEnum((Enum) data); + } else if (data instanceof Class) { + writeClass((Class) data); } else if (data instanceof Optional) { writeOptional((Optional) data); } else if (data instanceof Data) { @@ -101,6 +101,8 @@ default Packet write(Object data) { } else if (data instanceof Vector2D) { writeDouble(((Vector2D) data).getX()); writeDouble(((Vector2D) data).getY()); + } else if (data instanceof UUID) { + writeString(data.toString()); } else { throw new IllegalArgumentException("Packet attempt to write an invalid object: " + data); } @@ -115,6 +117,7 @@ default Packet write(Object data) { /** * Sets the specified boolean at the current {@code writerIndex} * and increases the {@code writerIndex} by {@code 1} in this buffer. + * * @param value Data to write * @return This packet * @throws IndexOutOfBoundsException if {@code this.writableBytes} is less than {@code 1} @@ -125,6 +128,7 @@ default Packet write(Object data) { * Sets the specified byte at the current {@code writerIndex} * and increases the {@code writerIndex} by {@code 1} in this buffer. * The 24 high-order bits of the specified value are ignored. + * * @param value Data to write * @return This packet * @throws IndexOutOfBoundsException if {@code this.writableBytes} is less than {@code 1} @@ -135,6 +139,7 @@ default Packet write(Object data) { * Sets the specified 16-bit short integer at the current * {@code writerIndex} and increases the {@code writerIndex} by {@code 2} * in this buffer. The 16 high-order bits of the specified value are ignored. + * * @param value Data to write * @return This packet * @throws IndexOutOfBoundsException if {@code this.writableBytes} is less than {@code 2} @@ -144,6 +149,7 @@ default Packet write(Object data) { /** * Sets the specified 32-bit integer at the current {@code writerIndex} * and increases the {@code writerIndex} by {@code 4} in this buffer. + * * @param value Data to write * @return This packet * @throws IndexOutOfBoundsException if {@code this.writableBytes} is less than {@code 4} @@ -154,6 +160,7 @@ default Packet write(Object data) { * Sets the specified 64-bit long integer at the current * {@code writerIndex} and increases the {@code writerIndex} by {@code 8} * in this buffer. + * * @param value Data to write * @return This packet * @throws IndexOutOfBoundsException if {@code this.writableBytes} is less than {@code 8} @@ -164,6 +171,7 @@ default Packet write(Object data) { * Sets the specified 2-byte UTF-16 character at the current * {@code writerIndex} and increases the {@code writerIndex} by {@code 2} * in this buffer. The 16 high-order bits of the specified value are ignored. + * * @param value Data to write * @return This packet * @throws IndexOutOfBoundsException if {@code this.writableBytes} is less than {@code 2} @@ -174,6 +182,7 @@ default Packet write(Object data) { * Sets the specified 32-bit floating point number at the current * {@code writerIndex} and increases the {@code writerIndex} by {@code 4} * in this buffer. + * * @param value Data to write * @return This packet * @throws IndexOutOfBoundsException if {@code this.writableBytes} is less than {@code 4} @@ -184,6 +193,7 @@ default Packet write(Object data) { * Sets the specified 64-bit floating point number at the current * {@code writerIndex} and increases the {@code writerIndex} by {@code 8} * in this buffer. + * * @param value Data to write * @return This packet * @throws IndexOutOfBoundsException if {@code this.writableBytes} is less than {@code 8} @@ -199,6 +209,11 @@ default Packet writeEnum(Enum data) { return this; } + default Packet writeClass(Class data) { + writeString(data.getName()); + return this; + } + default int getType(Class compare) { return IntStream .range(0, Data.dataTypes.length) @@ -258,6 +273,7 @@ default Packet writeOptional(Optional optional) { /** * Gets a boolean at the current {@code readerIndex} and increases * the {@code readerIndex} by {@code 1} in this buffer. + * * @return Data read from this packet * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 1} */ @@ -266,6 +282,7 @@ default Packet writeOptional(Optional optional) { /** * Gets a byte at the current {@code readerIndex} and increases * the {@code readerIndex} by {@code 1} in this buffer. + * * @return Data read from this packet * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 1} */ @@ -274,6 +291,7 @@ default Packet writeOptional(Optional optional) { /** * Gets an unsigned byte at the current {@code readerIndex} and increases * the {@code readerIndex} by {@code 1} in this buffer. + * * @return Data read from this packet * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 1} */ @@ -282,6 +300,7 @@ default Packet writeOptional(Optional optional) { /** * Gets a 16-bit short integer at the current {@code readerIndex} * and increases the {@code readerIndex} by {@code 2} in this buffer. + * * @return Data read from this packet * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 2} */ @@ -290,6 +309,7 @@ default Packet writeOptional(Optional optional) { /** * Gets a 32-bit integer at the current {@code readerIndex} * and increases the {@code readerIndex} by {@code 4} in this buffer. + * * @return Data read from this packet * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 4} */ @@ -298,6 +318,7 @@ default Packet writeOptional(Optional optional) { /** * Gets an unsigned 32-bit integer at the current {@code readerIndex} * and increases the {@code readerIndex} by {@code 4} in this buffer. + * * @return Data read from this packet * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 4} */ @@ -306,6 +327,7 @@ default Packet writeOptional(Optional optional) { /** * Gets a 64-bit integer at the current {@code readerIndex} * and increases the {@code readerIndex} by {@code 8} in this buffer. + * * @return Data read from this packet * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 8} */ @@ -314,6 +336,7 @@ default Packet writeOptional(Optional optional) { /** * Gets a 2-byte UTF-16 character at the current {@code readerIndex} * and increases the {@code readerIndex} by {@code 2} in this buffer. + * * @return Data read from this packet * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 2} */ @@ -322,6 +345,7 @@ default Packet writeOptional(Optional optional) { /** * Gets a 32-bit floating point number at the current {@code readerIndex} * and increases the {@code readerIndex} by {@code 4} in this buffer. + * * @return Data read from this packet * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 4} */ @@ -330,6 +354,7 @@ default Packet writeOptional(Optional optional) { /** * Gets a 64-bit floating point number at the current {@code readerIndex} * and increases the {@code readerIndex} by {@code 8} in this buffer. + * * @return Data read from this packet * @throws IndexOutOfBoundsException if {@code this.readableBytes} is less than {@code 8} */ @@ -426,6 +451,20 @@ default Vector3D readVector3D() { return new Vector3D(readDouble(), readDouble(), readDouble()); } + default Class readClass() { + try { + String classClassName = readString(); + Class classClass = (Class) Class.forName(classClassName); + return classClass; + } catch (Exception e) { + throw new NetworkException("Failed to read enum.", e); + } + } + + default UUID readUUID() { + return UUID.fromString(readString()); + } + default T read(Class clazz) { if (clazz == Boolean.class || clazz == boolean.class) { return (T) Boolean.valueOf(readBoolean()); @@ -459,6 +498,10 @@ else if (Syncable.class.isAssignableFrom(clazz)) { return (T) readVector3D(); } else if (Vector2D.class.isAssignableFrom(clazz)) { return (T) readVector2D(); + } else if (Class.class.isAssignableFrom(clazz)) { + return (T) readClass(); + } else if (UUID.class.isAssignableFrom(clazz)) { + return (T) readUUID(); } else if (List.class.isAssignableFrom(clazz)) { return (T) readList(); } else if (Set.class.isAssignableFrom(clazz)) { diff --git a/src/main/java/nova/core/recipes/crafting/CraftingRecipe.java b/src/main/java/nova/core/recipes/crafting/CraftingRecipe.java index 5703176f4..d0f72233f 100755 --- a/src/main/java/nova/core/recipes/crafting/CraftingRecipe.java +++ b/src/main/java/nova/core/recipes/crafting/CraftingRecipe.java @@ -22,6 +22,7 @@ import nova.core.item.Item; import nova.core.recipes.Recipe; +import nova.core.util.id.Identifier; import java.util.Collection; import java.util.Optional; @@ -73,7 +74,7 @@ public interface CraftingRecipe extends Recipe { * * @return The items */ - default Optional> getPossibleItemsInFirstSlot() { + default Optional> getPossibleItemsInFirstSlot() { return Optional.empty(); } } diff --git a/src/main/java/nova/core/recipes/crafting/CraftingRecipeManager.java b/src/main/java/nova/core/recipes/crafting/CraftingRecipeManager.java index 6648c79ce..77eafda4c 100644 --- a/src/main/java/nova/core/recipes/crafting/CraftingRecipeManager.java +++ b/src/main/java/nova/core/recipes/crafting/CraftingRecipeManager.java @@ -24,6 +24,7 @@ import nova.core.recipes.RecipeAddedEvent; import nova.core.recipes.RecipeManager; import nova.core.recipes.RecipeRemovedEvent; +import nova.core.util.id.Identifier; import java.util.ArrayList; import java.util.Collection; @@ -39,7 +40,7 @@ public class CraftingRecipeManager { private final RecipeManager recipeManager; private final List dynamicRecipes; - private final Multimap staticRecipes; + private final Multimap staticRecipes; public CraftingRecipeManager(RecipeManager recipeManager) { this.recipeManager = recipeManager; @@ -86,7 +87,7 @@ public Optional getRecipe(CraftingGrid grid) { return Optional.empty(); } - String firstItemId = firstItem.get().getID(); + Identifier firstItemId = firstItem.get().getID(); if (!staticRecipes.containsKey(firstItemId)) { return Optional.empty(); } @@ -105,9 +106,9 @@ public Optional getRecipe(CraftingGrid grid) { // ####################### private void onCraftingRecipeAdded(RecipeAddedEvent e) { - Optional> possibleFirstItemIds = e.getRecipe().getPossibleItemsInFirstSlot(); + Optional> possibleFirstItemIds = e.getRecipe().getPossibleItemsInFirstSlot(); if (possibleFirstItemIds.isPresent()) { - for (String itemId : possibleFirstItemIds.get()) { + for (Identifier itemId : possibleFirstItemIds.get()) { staticRecipes.put(itemId, e.getRecipe()); } } else { @@ -116,9 +117,9 @@ private void onCraftingRecipeAdded(RecipeAddedEvent void onCraftingRecipeRemoved(RecipeRemovedEvent e) { - Optional> possibleFirstItemIds = e.getRecipe().getPossibleItemsInFirstSlot(); + Optional> possibleFirstItemIds = e.getRecipe().getPossibleItemsInFirstSlot(); if (possibleFirstItemIds.isPresent()) { - for (String itemId : possibleFirstItemIds.get()) { + for (Identifier itemId : possibleFirstItemIds.get()) { staticRecipes.remove(itemId, e.getRecipe()); } } else { diff --git a/src/main/java/nova/core/recipes/crafting/ItemIngredient.java b/src/main/java/nova/core/recipes/crafting/ItemIngredient.java index 5aa41d22e..a53ca3d3b 100755 --- a/src/main/java/nova/core/recipes/crafting/ItemIngredient.java +++ b/src/main/java/nova/core/recipes/crafting/ItemIngredient.java @@ -21,6 +21,7 @@ package nova.core.recipes.crafting; import nova.core.item.Item; +import nova.core.util.id.Identifier; import java.util.Collection; import java.util.Optional; @@ -38,7 +39,7 @@ public interface ItemIngredient { * @param itemId item ID * @return ingredient */ - static ItemIngredient forItem(String itemId) { + static ItemIngredient forItem(Identifier itemId) { return new SpecificItemIngredient(itemId); } @@ -58,7 +59,7 @@ static ItemIngredient forDictionary(String id) { * * @return possible items */ - Optional> getPossibleItemIds(); + Optional> getPossibleItemIds(); /** * Returns a list of example items. This list could be used to render diff --git a/src/main/java/nova/core/recipes/crafting/OreItemIngredient.java b/src/main/java/nova/core/recipes/crafting/OreItemIngredient.java index 6a4661d8e..9db60d659 100644 --- a/src/main/java/nova/core/recipes/crafting/OreItemIngredient.java +++ b/src/main/java/nova/core/recipes/crafting/OreItemIngredient.java @@ -21,6 +21,7 @@ package nova.core.recipes.crafting; import nova.core.item.Item; +import nova.core.util.id.Identifier; import nova.internal.core.Game; import java.util.ArrayList; @@ -45,7 +46,7 @@ public String getName() { } @Override - public Optional> getPossibleItemIds() { + public Optional> getPossibleItemIds() { return Optional.of(Game.itemDictionary().get(name).stream().map(Item::getID).collect(Collectors.toList())); } diff --git a/src/main/java/nova/core/recipes/crafting/ShapedCraftingRecipe.java b/src/main/java/nova/core/recipes/crafting/ShapedCraftingRecipe.java index dfd095fc8..06b3d43a3 100755 --- a/src/main/java/nova/core/recipes/crafting/ShapedCraftingRecipe.java +++ b/src/main/java/nova/core/recipes/crafting/ShapedCraftingRecipe.java @@ -21,6 +21,7 @@ package nova.core.recipes.crafting; import nova.core.item.Item; +import nova.core.util.id.Identifier; import org.apache.commons.math3.geometry.euclidean.twod.Vector2D; import java.util.Collection; @@ -270,19 +271,19 @@ public void consumeItems(CraftingGrid craftingGrid) { } @Override - public Optional> getPossibleItemsInFirstSlot() { + public Optional> getPossibleItemsInFirstSlot() { if (isMirrored()) { - Optional> optionsForFirstItem = ingredients[0].getPossibleItemIds(); + Optional> optionsForFirstItem = ingredients[0].getPossibleItemIds(); if (!optionsForFirstItem.isPresent()) { return Optional.empty(); } - Optional> optionsForSecondItem = ingredients[lastIngredientIndexOnFirstLine].getPossibleItemIds(); + Optional> optionsForSecondItem = ingredients[lastIngredientIndexOnFirstLine].getPossibleItemIds(); if (!optionsForSecondItem.isPresent()) { return Optional.empty(); } - Set result = new HashSet<>(); + Set result = new HashSet<>(); result.addAll(optionsForFirstItem.get()); result.addAll(optionsForSecondItem.get()); return Optional.of(result); diff --git a/src/main/java/nova/core/recipes/crafting/SpecificItemIngredient.java b/src/main/java/nova/core/recipes/crafting/SpecificItemIngredient.java index d3b2330ca..6e2c4d914 100644 --- a/src/main/java/nova/core/recipes/crafting/SpecificItemIngredient.java +++ b/src/main/java/nova/core/recipes/crafting/SpecificItemIngredient.java @@ -21,6 +21,7 @@ import nova.core.item.Item; import nova.core.item.ItemFactory; import nova.core.util.exception.RegistrationException; +import nova.core.util.id.Identifier; import nova.internal.core.Game; import java.util.Collection; @@ -32,18 +33,18 @@ * @author Stan Hebben */ public class SpecificItemIngredient implements ItemIngredient { - private final String itemId; + private final Identifier itemId; - public SpecificItemIngredient(String itemId) { + public SpecificItemIngredient(Identifier itemId) { this.itemId = itemId; } - public String getItemId() { + public Identifier getItemId() { return itemId; } @Override - public Optional> getPossibleItemIds() { + public Optional> getPossibleItemIds() { return Optional.of(Collections.singleton(itemId)); } @@ -96,7 +97,7 @@ public int hashCode() { return itemId.hashCode(); } - private Item getItem(String itemId) { + private Item getItem(Identifier itemId) { Optional itemFactory = Game.items().get(itemId); if (itemFactory.isPresent()) { diff --git a/src/main/java/nova/core/render/Asset.java b/src/main/java/nova/core/render/Asset.java index b5f9b96ec..75bf1228c 100644 --- a/src/main/java/nova/core/render/Asset.java +++ b/src/main/java/nova/core/render/Asset.java @@ -20,7 +20,9 @@ package nova.core.render; -import nova.core.util.Identifiable; +import nova.core.util.id.Identifiable; +import nova.core.util.id.Identifier; +import nova.core.util.id.NamespacedStringIdentifier; /** * @author Calclavia @@ -48,7 +50,7 @@ public boolean equals(Object obj) { } @Override - public final String getID() { - return domain + ":" + name; + public final Identifier getID() { + return new NamespacedStringIdentifier(domain, name); } } diff --git a/src/main/java/nova/core/render/texture/Texture.java b/src/main/java/nova/core/render/texture/Texture.java index ee7596cfa..0fcfd3248 100644 --- a/src/main/java/nova/core/render/texture/Texture.java +++ b/src/main/java/nova/core/render/texture/Texture.java @@ -16,9 +16,13 @@ * * You should have received a copy of the GNU General Public License * along with NOVA. If not, see . - */package nova.core.render.texture; + */ + +package nova.core.render.texture; -import nova.core.util.Identifiable; +import nova.core.util.id.Identifiable; +import nova.core.util.id.Identifier; +import nova.core.util.id.NamespacedStringIdentifier; import nova.core.util.math.Vector2DUtil; import nova.internal.core.Game; import org.apache.commons.math3.geometry.euclidean.twod.Vector2D; @@ -60,8 +64,8 @@ public String toString() { } @Override - public final String getID() { - return getResource(); + public final Identifier getID() { + return new NamespacedStringIdentifier(domain, resource); } @Override diff --git a/src/main/java/nova/core/retention/Data.java b/src/main/java/nova/core/retention/Data.java index 71d689c74..3044dc7e2 100755 --- a/src/main/java/nova/core/retention/Data.java +++ b/src/main/java/nova/core/retention/Data.java @@ -23,10 +23,7 @@ import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; import org.apache.commons.math3.geometry.euclidean.twod.Vector2D; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; +import java.util.*; /** * The data class is capable of storing named data. @@ -45,6 +42,7 @@ * - Enumerator * - Storable (Converted into Data) * - Data + * * @author Calclavia */ //TODO: Add collection and array support @@ -66,7 +64,9 @@ public class Data extends HashMap { Data.class, Collection.class, Vector3D.class, - Vector2D.class }; + Vector2D.class, + Class.class, + UUID.class }; public String className; @@ -82,6 +82,7 @@ public Data(Class clazz) { /** * Saves an object, serializing its data. * This map can be reloaded and its class with be reconstructed. + * * @param obj The object to store. * @return The data of the object with */ @@ -96,6 +97,7 @@ public static Data serialize(Storable obj) { /** * Loads an object from its stored data, with an unknown class. * The class of the object must be stored within the data. + * * @param data The data * @return The object loaded with given data. */ @@ -103,11 +105,20 @@ public static Object unserialize(Data data) { try { Class clazz = (Class) Class.forName((String) data.get("class")); if (clazz.isEnum()) { - return Enum.valueOf(clazz, data.get("value")); + return Enum.valueOf(clazz, (String) data.get("value")); } else if (clazz == Vector3D.class) { return new Vector3D(data.get("x"), data.get("y"), data.get("z")); } else if (clazz == Vector2D.class) { return new Vector2D(data.get("x"), (double) data.get("y")); + } else if (clazz == UUID.class) { + return UUID.fromString(data.get("uuid")); + } else if (clazz == Class.class) { + return Class.forName(data.get("name")); + } else if (clazz.isAnnotationPresent(DataConvertible.class)) { + DataConvertible annotation = (DataConvertible) clazz.getAnnotation(DataConvertible.class); + DataConverter dataConverter = annotation.value().newInstance(); + Object o = dataConverter.fromData(data); + return clazz.cast(o); // throws ClassCastException if your DataConverter is bad. } else { return unserialize(clazz, data); } @@ -119,6 +130,7 @@ public static Object unserialize(Data data) { /** * Loads an object from its stored data, given its class. + * * @param clazz - The class to load * @param data - The data * @return The object loaded with given data. @@ -148,7 +160,7 @@ public Object put(String key, Object value) { assert key != null && value != null; assert !key.equals("class"); final Object check = value; - assert Arrays.stream(dataTypes).anyMatch(clazz -> clazz.isAssignableFrom(check.getClass())); + assert Arrays.stream(dataTypes).anyMatch(clazz -> clazz.isAssignableFrom(check.getClass())) || check.getClass().isAnnotationPresent(DataConvertible.class); if (value instanceof Enum) { Data enumData = new Data(value.getClass()); @@ -165,6 +177,24 @@ public Object put(String key, Object value) { vectorData.put("x", ((Vector2D) value).getX()); vectorData.put("y", ((Vector2D) value).getY()); value = vectorData; + } else if (value instanceof UUID) { + Data uuidData = new Data(UUID.class); + uuidData.put("uuid", value.toString()); + value = uuidData; + } else if (value instanceof Class) { + Data classData = new Data(Class.class); + classData.put("name", ((Class) value).getName()); + value = classData; + } else if (value.getClass().isAnnotationPresent(DataConvertible.class)) { + try { + DataConvertible annotation = value.getClass().getAnnotation(DataConvertible.class); + DataConverter dataConverter = annotation.value().newInstance(); + Data d = new Data(value.getClass()); + dataConverter.toData(value, d); + value = d; + } catch (Exception e) { + throw new DataException(e); + } } else if (value instanceof Storable) { value = serialize((Storable) value); } @@ -180,6 +210,22 @@ public T get(String key) { return (T) super.get(key); } + @SuppressWarnings("unchecked") + public T getDataConvertible(String key) { + Data data = get(key); + try { + @SuppressWarnings("unchecked") + Class clazz = (Class) Class.forName(data.className); + DataConvertible dataConvertible = clazz.getAnnotation(DataConvertible.class); + if (dataConvertible == null) { + throw new ClassCastException(); + } + return (T) dataConvertible.value().newInstance().fromData(data); + } catch (Exception e) { + throw new DataException(e); + } + } + public > T getEnum(String key) { Data enumData = get(key); try { @@ -214,4 +260,19 @@ public T getStorable(String key) { } } + public Class getClass(String key) { + Data classData = get(key); + try { + @SuppressWarnings("unchecked") + Class classClass = (Class) Class.forName(classData.className); + return classClass; + } catch (Exception e) { + throw new DataException(e); + } + } + + public UUID getUUID(String key) { + Data data = get(key); + return UUID.fromString(data.get("uuid")); + } } diff --git a/src/main/java/nova/core/retention/DataConverter.java b/src/main/java/nova/core/retention/DataConverter.java new file mode 100644 index 000000000..4f41d0e4a --- /dev/null +++ b/src/main/java/nova/core/retention/DataConverter.java @@ -0,0 +1,10 @@ +package nova.core.retention; + +/** + * @author soniex2 + */ +public interface DataConverter { + Object fromData(Data d); + + void toData(Object o, Data data); +} diff --git a/src/main/java/nova/core/retention/DataConvertible.java b/src/main/java/nova/core/retention/DataConvertible.java new file mode 100644 index 000000000..5d1e38005 --- /dev/null +++ b/src/main/java/nova/core/retention/DataConvertible.java @@ -0,0 +1,14 @@ +package nova.core.retention; + +import java.lang.annotation.*; + +/** + * Annotation for immutable objects that can be converted to/from Data. + * @author soniex2 + */ +@Documented +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface DataConvertible { + Class value(); +} diff --git a/src/main/java/nova/core/retention/Storable.java b/src/main/java/nova/core/retention/Storable.java index 84fcfbed7..2e1fdb586 100644 --- a/src/main/java/nova/core/retention/Storable.java +++ b/src/main/java/nova/core/retention/Storable.java @@ -61,11 +61,11 @@ default void load(Data data) { if (data.containsKey(name)) { try { field.setAccessible(true); - Class type = field.getType(); + Class type = field.getType(); // FIXME Object fieldValue = field.get(this); Object value = data.get(name); - if (Storable.class.isAssignableFrom(type) || value instanceof Data) { - if (fieldValue instanceof Storable && value instanceof Data) { + if (Storable.class.isAssignableFrom(type) || value instanceof Data) { // FIXME should test things based on `data` + if (fieldValue instanceof Storable && value instanceof Data) { // this one is fine tho //We already have an instance. Don't need to create the object. ((Storable) fieldValue).load((Data) value); } else { diff --git a/src/main/java/nova/core/sound/Sound.java b/src/main/java/nova/core/sound/Sound.java index 127bc23d3..6dc35697d 100644 --- a/src/main/java/nova/core/sound/Sound.java +++ b/src/main/java/nova/core/sound/Sound.java @@ -21,7 +21,7 @@ package nova.core.sound; import nova.core.render.Asset; -import nova.core.util.Identifiable; +import nova.core.util.id.Identifiable; /** * An object representing a sound. (including the modification to pitch and volume, etc...) diff --git a/src/main/java/nova/core/util/id/AbstractIdentifier.java b/src/main/java/nova/core/util/id/AbstractIdentifier.java new file mode 100644 index 000000000..e1ba4d65a --- /dev/null +++ b/src/main/java/nova/core/util/id/AbstractIdentifier.java @@ -0,0 +1,44 @@ +package nova.core.util.id; + +import java.util.Objects; + +/** + * Basic implementation of Identifier. + * + * @author soniex2 + */ +public abstract class AbstractIdentifier implements Identifier { + /** + * The ID. + */ + protected final T id; + + /** + * Constructs a new AbstractIdentifier. + * + * @param id The ID. + */ + public AbstractIdentifier(T id) { + this.id = Objects.requireNonNull(id); + } + + @Override + public String asString() { + return id.toString(); + } + + @Override + public String toString() { + return id.toString(); + } + + @Override + public final int hashCode() { + return id.hashCode(); + } + + @Override + public final boolean equals(Object o) { + return this == o || (o != null && getClass() == o.getClass() && id.equals(((AbstractIdentifier) o).id)); + } +} diff --git a/src/main/java/nova/core/util/id/ClassIdentifier.java b/src/main/java/nova/core/util/id/ClassIdentifier.java new file mode 100644 index 000000000..ff7ad1122 --- /dev/null +++ b/src/main/java/nova/core/util/id/ClassIdentifier.java @@ -0,0 +1,55 @@ +package nova.core.util.id; + +import nova.core.retention.Data; +import nova.core.retention.DataConverter; +import nova.core.retention.DataConvertible; +import nova.core.retention.DataException; + +/** + * A Class Identifier. + * + * @author soniex2 + */ +@DataConvertible(ClassIdentifier.Converter.class) +public final class ClassIdentifier extends AbstractIdentifier> implements Identifier { + + /** + * Constructs a new ClassIdentifier. + * + * @param id The Class. + */ + public ClassIdentifier(Class id) { + super(id); + } + + @Override + public String asString() { + return id.getSimpleName(); + } + + /** + * Returns this Identifier's Class. + * + * @return The Class. + */ + public Class asClass() { + return id; + } + + public static final class Converter implements DataConverter { + @Override + public Object fromData(Data d) { + try { + Class c = Class.forName(d.get("value")); + return new ClassIdentifier(c); + } catch (ClassNotFoundException e) { + throw new DataException(e); + } + } + + @Override + public void toData(Object o, Data data) { + data.put("value", ((ClassIdentifier) o).asClass().getName()); + } + } +} diff --git a/src/main/java/nova/core/util/Identifiable.java b/src/main/java/nova/core/util/id/Identifiable.java similarity index 96% rename from src/main/java/nova/core/util/Identifiable.java rename to src/main/java/nova/core/util/id/Identifiable.java index e98159e43..3ff8c86ff 100644 --- a/src/main/java/nova/core/util/Identifiable.java +++ b/src/main/java/nova/core/util/id/Identifiable.java @@ -18,7 +18,7 @@ * along with NOVA. If not, see . */ -package nova.core.util; +package nova.core.util.id; /** * A generic interface signifying that this object is identifiable @@ -30,7 +30,7 @@ public interface Identifiable { * * @return the ID */ - String getID(); + Identifier getID(); /** * Compares the ID of the Identifialbes diff --git a/src/main/java/nova/core/util/id/Identifier.java b/src/main/java/nova/core/util/id/Identifier.java new file mode 100644 index 000000000..7453cef99 --- /dev/null +++ b/src/main/java/nova/core/util/id/Identifier.java @@ -0,0 +1,19 @@ +package nova.core.util.id; + +/** + * The interface for all identifiers. + *

+ * Implementations should override {@link Object#equals(Object)}, {@link Object#hashCode()} and {@link Object#toString()}. + *

+ * + * @author soniex2 + */ +public interface Identifier { + /** + * Converts this Identifier into a String. + * The output from this method may be different than {@link Object#toString()}. + * + * @return A string representation of this Identifier. + */ + String asString(); +} diff --git a/src/main/java/nova/core/util/id/NamespacedStringIdentifier.java b/src/main/java/nova/core/util/id/NamespacedStringIdentifier.java new file mode 100644 index 000000000..68a108629 --- /dev/null +++ b/src/main/java/nova/core/util/id/NamespacedStringIdentifier.java @@ -0,0 +1,153 @@ +package nova.core.util.id; + +import nova.core.retention.Data; +import nova.core.retention.DataConverter; +import nova.core.retention.DataConvertible; + +import java.util.Objects; + +/** + * A namespace:name identifier + * + * @author soniex2 + */ +@DataConvertible(NamespacedStringIdentifier.Converter.class) +public final class NamespacedStringIdentifier extends AbstractIdentifier { + + /** + * Constructs a new NamespacedStringIdentifier. + * + * @param namespace The namespace. + * @param name The name. + */ + public NamespacedStringIdentifier(String namespace, String name) { + super(new NamespacedString(namespace, name)); + } + + /** + * Constructs a new NamespacedStringIdentifier. + * + * @param namespacedname The colon-separated namespaced name. + */ + public NamespacedStringIdentifier(String namespacedname) { + super(new NamespacedString(namespacedname)); + } + + /** + * Constructs a new NamespacedStringIdentifier. + * + * @param namespacedstring The NamespacedString. + */ + public NamespacedStringIdentifier(NamespacedString namespacedstring) { + super(namespacedstring); + } + + /** + * Returns the namespaced string. + * + * @return The namespaced string. + */ + public NamespacedString asNamespacedString() { + return id; + } + + public static final class NamespacedString { + private final String namespace; + private final String name; + + /** + * Constructs a new NamespacedString. + * + * @param namespace The namespace. + * @param name The name. + */ + public NamespacedString(String namespace, String name) { + if (namespace.contains(":")) { + throw new IllegalArgumentException("Namespace must not contain a colon"); + } + this.namespace = Objects.requireNonNull(namespace).intern(); + this.name = Objects.requireNonNull(name).intern(); + } + + /** + * Constructs a new NamespacedString. + * + * @param namespacedname The colon-separated namespaced name. + */ + public NamespacedString(String namespacedname) { + this(nsOf(namespacedname), nameOf(namespacedname)); + } + + /** + * Returns the namespace. + * + * @return The namespace. + */ + public String getNamespace() { + return namespace; + } + + /** + * Returns the name. + * + * @return The name. + */ + public String getName() { + return name; + } + + @Override + public String toString() { + return namespace + ":" + name; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + NamespacedString that = (NamespacedString) o; + + return namespace.equals(that.namespace) && name.equals(that.name); + } + + @Override + public int hashCode() { + return 31 * namespace.hashCode() + name.hashCode(); + } + + private static String nameOf(String namespacedname) { + int index = namespacedname.indexOf(':'); + if (index < 0) { + return namespacedname; + } else { + return namespacedname.substring(index + 1); + } + } + + private static String nsOf(String namespacedname) { + int index = namespacedname.indexOf(':'); + if (index < 0) { + return ""; + } else { + return namespacedname.substring(0, index); + } + } + } + + public static final class Converter implements DataConverter { + @Override + public Object fromData(Data d) { + return new NamespacedStringIdentifier(d.get("namespace"), d.get("name")); + } + + @Override + public void toData(Object o, Data data) { + NamespacedStringIdentifier id = (NamespacedStringIdentifier) o; + data.put("namespace", id.asNamespacedString().getNamespace()); + data.put("name", id.asNamespacedString().getName()); + } + } +} diff --git a/src/main/java/nova/core/util/id/StringIdentifier.java b/src/main/java/nova/core/util/id/StringIdentifier.java new file mode 100644 index 000000000..5e26c8cf4 --- /dev/null +++ b/src/main/java/nova/core/util/id/StringIdentifier.java @@ -0,0 +1,35 @@ +package nova.core.util.id; + +import nova.core.retention.Data; +import nova.core.retention.DataConverter; +import nova.core.retention.DataConvertible; + +/** + * A String Identifier. + * + * @author soniex2 + */ +@DataConvertible(StringIdentifier.Converter.class) +public final class StringIdentifier extends AbstractIdentifier implements Identifier { + + /** + * Constructs a new StringIdentifier. + * + * @param id The String. + */ + public StringIdentifier(String id) { + super(id); + } + + public static final class Converter implements DataConverter { + @Override + public Object fromData(Data d) { + return new StringIdentifier(d.get("value")); + } + + @Override + public void toData(Object o, Data data) { + data.put("value", ((StringIdentifier) o).asString()); + } + } +} diff --git a/src/main/java/nova/core/util/id/UUIDIdentifier.java b/src/main/java/nova/core/util/id/UUIDIdentifier.java new file mode 100644 index 000000000..dfa26b8b4 --- /dev/null +++ b/src/main/java/nova/core/util/id/UUIDIdentifier.java @@ -0,0 +1,46 @@ +package nova.core.util.id; + +import nova.core.retention.Data; +import nova.core.retention.DataConverter; +import nova.core.retention.DataConvertible; + +import java.util.UUID; + +/** + * An UUID Identifier. + * + * @author soniex2 + */ +@DataConvertible(UUIDIdentifier.Converter.class) +public final class UUIDIdentifier extends AbstractIdentifier implements Identifier { + + /** + * Constructs a new UUIDIdentifier. + * + * @param id The UUID. + */ + public UUIDIdentifier(UUID id) { + super(id); + } + + /** + * Returns this Identifier's UUID. + * + * @return The UUID. + */ + public UUID asUUID() { + return id; + } + + public static final class Converter implements DataConverter { + @Override + public Object fromData(Data d) { + return new UUIDIdentifier(UUID.fromString(d.get("value"))); + } + + @Override + public void toData(Object o, Data data) { + data.put("value", ((UUIDIdentifier) o).asString()); + } + } +} diff --git a/src/main/java/nova/core/util/UniqueIdentifiable.java b/src/main/java/nova/core/util/id/UniqueIdentifiable.java similarity index 87% rename from src/main/java/nova/core/util/UniqueIdentifiable.java rename to src/main/java/nova/core/util/id/UniqueIdentifiable.java index a795892d1..ae37ad60f 100644 --- a/src/main/java/nova/core/util/UniqueIdentifiable.java +++ b/src/main/java/nova/core/util/id/UniqueIdentifiable.java @@ -18,7 +18,9 @@ * along with NOVA. If not, see . */ -package nova.core.util; +package nova.core.util.id; + +import nova.core.util.id.UUIDIdentifier; /** * A generic interface signifying that this object is uniquely identifiable @@ -30,5 +32,5 @@ public interface UniqueIdentifiable { * * @return the ID */ - String getUniqueID(); + UUIDIdentifier getUniqueID(); // TODO maybe this should return a simple Identifier } diff --git a/src/main/java/nova/core/util/registry/Factory.java b/src/main/java/nova/core/util/registry/Factory.java index 7ce169d1e..f4c5bbc07 100644 --- a/src/main/java/nova/core/util/registry/Factory.java +++ b/src/main/java/nova/core/util/registry/Factory.java @@ -20,20 +20,22 @@ package nova.core.util.registry; -import nova.core.util.Identifiable; +import nova.core.util.id.Identifiable; +import nova.core.util.id.Identifier; import java.util.function.Function; import java.util.function.Supplier; /** * Factories are immutable object builders that create objects. + * * @param The self type * @param Type of produced object * @author Calclavia */ public abstract class Factory, T extends Identifiable> implements Identifiable { //The ID of the factory - protected final String id; + protected final Identifier id; //The constructor function protected final Supplier constructor; @@ -46,22 +48,24 @@ public abstract class Factory, T extends Identifiable> i * and with a processor that is capable of mutating the instantiated object after its initialization. * * A factory's processor may be modified to allow specific customization of instantiated objects before it is used. + * * @param id The identifier for this factory type * @param constructor The construction function * @param processor The processor function */ - public Factory(String id, Supplier constructor, Function processor) { + public Factory(Identifier id, Supplier constructor, Function processor) { this.id = id; this.constructor = constructor; this.processor = processor; } - public Factory(String id, Supplier constructor) { + public Factory(Identifier id, Supplier constructor) { this(id, constructor, obj -> obj); } /** * Adds a processor to the factory + * * @param processor A processor that mutates the construction * @return Self */ @@ -69,7 +73,7 @@ public S process(Function processor) { return selfConstructor(id, constructor, this.processor.compose(processor)); } - protected abstract S selfConstructor(String id, Supplier constructor, Function processor); + protected abstract S selfConstructor(Identifier id, Supplier constructor, Function processor); /** * @return A new instance of T based on the construction method @@ -78,7 +82,7 @@ public T build() { return processor.apply(constructor.get()); } - public String getID() { + public Identifier getID() { return id; } } diff --git a/src/main/java/nova/core/util/registry/FactoryManager.java b/src/main/java/nova/core/util/registry/FactoryManager.java index 20a38d558..a03be1971 100644 --- a/src/main/java/nova/core/util/registry/FactoryManager.java +++ b/src/main/java/nova/core/util/registry/FactoryManager.java @@ -20,7 +20,8 @@ package nova.core.util.registry; -import nova.core.util.Identifiable; +import nova.core.util.id.Identifiable; +import nova.core.util.id.Identifier; import java.util.Optional; import java.util.function.Supplier; @@ -44,7 +45,7 @@ public FactoryManager(Registry registry) { * @param constructor Instance supplier {@link Supplier} * @return The factory */ - public abstract F register(String id, Supplier constructor); + public abstract F register(Identifier id, Supplier constructor); /** * Register a new object construction factory. @@ -61,7 +62,7 @@ public F register(F factory) { * @param name Registered name * @return The object */ - public Optional get(String name) { + public Optional get(Identifier name) { return registry.get(name); } } diff --git a/src/main/java/nova/core/util/registry/Registry.java b/src/main/java/nova/core/util/registry/Registry.java index bf25553d9..7e0c7bb34 100644 --- a/src/main/java/nova/core/util/registry/Registry.java +++ b/src/main/java/nova/core/util/registry/Registry.java @@ -19,7 +19,8 @@ */package nova.core.util.registry; import com.google.common.collect.HashBiMap; -import nova.core.util.Identifiable; +import nova.core.util.id.Identifiable; +import nova.core.util.id.Identifier; import java.util.Iterator; import java.util.Optional; @@ -32,7 +33,7 @@ * @param The object type */ public class Registry implements Iterable { - private final HashBiMap objects = HashBiMap.create(); + private final HashBiMap objects = HashBiMap.create(); public Registry() { @@ -55,7 +56,7 @@ public T register(T object) { * @param ID the id to find. * @return true if the registry contains the object with the given ID. */ - public boolean contains(String ID) { + public boolean contains(Identifier ID) { return objects.containsKey(ID); } @@ -65,7 +66,7 @@ public boolean contains(String ID) { * @param ID the id to find. * @return the object found or empty Optional if not found. */ - public Optional get(String ID) { + public Optional get(Identifier ID) { return Optional.ofNullable(objects.get(ID)); } @@ -75,7 +76,7 @@ public Optional get(String ID) { * @param object the object to find. * @return the name of the object or empty Optional if not found. */ - public Optional getName(T object) { + public Optional getName(T object) { return Optional.ofNullable(objects.inverse().get(object)); } diff --git a/src/main/java/nova/core/world/World.java b/src/main/java/nova/core/world/World.java index d89565221..22832ac35 100644 --- a/src/main/java/nova/core/world/World.java +++ b/src/main/java/nova/core/world/World.java @@ -24,7 +24,7 @@ import nova.core.entity.EntityFactory; import nova.core.item.Item; import nova.core.sound.Sound; -import nova.core.util.Identifiable; +import nova.core.util.id.Identifiable; import nova.core.util.shape.Cuboid; import nova.internal.core.Game; import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; diff --git a/src/main/java/nova/core/world/WorldFactory.java b/src/main/java/nova/core/world/WorldFactory.java index cf53aaf80..2ede5b5fe 100644 --- a/src/main/java/nova/core/world/WorldFactory.java +++ b/src/main/java/nova/core/world/WorldFactory.java @@ -20,6 +20,7 @@ package nova.core.world; +import nova.core.util.id.Identifier; import nova.core.util.registry.Factory; import java.util.function.Function; @@ -30,16 +31,16 @@ * @author Calclavia */ public class WorldFactory extends Factory { - public WorldFactory(String id, Supplier constructor, Function processor) { + public WorldFactory(Identifier id, Supplier constructor, Function processor) { super(id, constructor, processor); } - public WorldFactory(String id, Supplier constructor) { + public WorldFactory(Identifier id, Supplier constructor) { super(id, constructor); } @Override - protected WorldFactory selfConstructor(String id, Supplier constructor, Function processor) { + protected WorldFactory selfConstructor(Identifier id, Supplier constructor, Function processor) { return new WorldFactory(id, constructor, processor); } } diff --git a/src/main/java/nova/core/world/WorldManager.java b/src/main/java/nova/core/world/WorldManager.java index 1f2c4bd82..c038e49a9 100644 --- a/src/main/java/nova/core/world/WorldManager.java +++ b/src/main/java/nova/core/world/WorldManager.java @@ -22,6 +22,7 @@ import nova.core.event.WorldEvent; import nova.core.event.bus.GlobalEvents; +import nova.core.util.id.Identifier; import nova.core.util.registry.FactoryManager; import nova.core.util.registry.Registry; import nova.internal.core.Game; @@ -48,7 +49,7 @@ public WorldManager(Registry registry, GlobalEvents events) { } @Override - public WorldFactory register(String id, Supplier constructor) { + public WorldFactory register(Identifier id, Supplier constructor) { return register(new WorldFactory(id, constructor)); } diff --git a/src/test/java/nova/core/retention/DataConvertibleTest.java b/src/test/java/nova/core/retention/DataConvertibleTest.java new file mode 100644 index 000000000..fca56a92f --- /dev/null +++ b/src/test/java/nova/core/retention/DataConvertibleTest.java @@ -0,0 +1,46 @@ +package nova.core.retention; + +import org.junit.Test; + +import static nova.testutils.NovaAssertions.assertThat; + +/** + * @author soniex2 + */ +public class DataConvertibleTest { + + @DataConvertible(AnImmutableObject.Converter.class) + public static class AnImmutableObject { + private final String data; + + public AnImmutableObject(String data) { + this.data = data; + } + + public String getData() { + return data; + } + + public static class Converter implements DataConverter { + @Override + public Object fromData(Data d) { + return new AnImmutableObject(d.get("data")); + } + + @Override + public void toData(Object o, Data data) { + data.put("data", ((AnImmutableObject) o).getData()); + } + } + } + + @Test + public void testDataConvertible() { + AnImmutableObject o = new AnImmutableObject("hello"); + Data d = new Data(); + d.put("anImmutableObject", o); + AnImmutableObject other = d.getDataConvertible("anImmutableObject"); + assertThat(o).isEqualToComparingFieldByField(other); + assertThat(o).isNotSameAs(other); + } +} diff --git a/src/test/java/nova/core/util/MockIdentifiable.java b/src/test/java/nova/core/util/MockIdentifiable.java index a69500bc8..33569e31c 100644 --- a/src/test/java/nova/core/util/MockIdentifiable.java +++ b/src/test/java/nova/core/util/MockIdentifiable.java @@ -20,6 +20,10 @@ package nova.core.util; +import nova.core.util.id.Identifiable; +import nova.core.util.id.Identifier; +import nova.core.util.id.StringIdentifier; + public class MockIdentifiable implements Identifiable { String ID; @@ -28,12 +32,12 @@ public MockIdentifiable(String ID) { } @Override - public String getID() { - return ID; + public Identifier getID() { + return new StringIdentifier(ID); } @Override public String toString() { - return getID(); + return getID().asString(); } } diff --git a/src/test/java/nova/core/util/RayTraceTest.java b/src/test/java/nova/core/util/RayTraceTest.java index 0815f904b..34d24771b 100755 --- a/src/test/java/nova/core/util/RayTraceTest.java +++ b/src/test/java/nova/core/util/RayTraceTest.java @@ -27,6 +27,7 @@ import nova.core.entity.EntityFactory; import nova.core.loader.Loadable; import nova.core.loader.Mod; +import nova.core.util.id.StringIdentifier; import nova.core.util.math.RotationUtil; import nova.internal.core.Game; import nova.internal.core.launch.NovaLauncher; @@ -145,7 +146,7 @@ public static class RayTraceMod implements Loadable { @Override public void preInit() { solid = Game.blocks().register( - "solid", + new StringIdentifier("solid"), () -> { Block solid = new Block(); solid.components.add(new Collider(solid)); @@ -153,7 +154,7 @@ public void preInit() { } ); - testEntity = Game.entities().register("test", Entity::new); + testEntity = Game.entities().register(new StringIdentifier("test"), Entity::new); } } } diff --git a/src/test/java/nova/core/util/RegistryTest.java b/src/test/java/nova/core/util/RegistryTest.java index 79afd10d8..edfb76017 100644 --- a/src/test/java/nova/core/util/RegistryTest.java +++ b/src/test/java/nova/core/util/RegistryTest.java @@ -20,6 +20,8 @@ package nova.core.util; +import nova.core.util.id.Identifiable; +import nova.core.util.id.StringIdentifier; import nova.core.util.registry.Registry; import org.junit.Test; @@ -38,18 +40,18 @@ public void testRegistry() throws Exception { registry.register(id1); registry.register(id2); - assertThat(registry.contains("ID1")).isTrue(); - assertThat(registry.contains("ID2")).isTrue(); + assertThat(registry.contains(new StringIdentifier("ID1"))).isTrue(); + assertThat(registry.contains(new StringIdentifier("ID2"))).isTrue(); - assertThat(registry.get("ID1").get().getID()).isEqualTo("ID1"); - assertThat(registry.get("ID2").get().getID()).isEqualTo("ID2"); + assertThat(registry.get(new StringIdentifier("ID1")).get().getID()).isEqualTo(new StringIdentifier("ID1")); + assertThat(registry.get(new StringIdentifier("ID2")).get().getID()).isEqualTo(new StringIdentifier("ID2")); - assertThat(registry.get("ID1").get()).isEqualTo(id1); - assertThat(registry.get("ID2").get()).isEqualTo(id2); + assertThat(registry.get(new StringIdentifier("ID1")).get()).isEqualTo(id1); + assertThat(registry.get(new StringIdentifier("ID2")).get()).isEqualTo(id2); assertThat(registry.iterator()).containsOnly(id1, id2); - assertThat(registry.get("None").isPresent()).isFalse(); + assertThat(registry.get(new StringIdentifier("None")).isPresent()).isFalse(); } } diff --git a/src/test/java/nova/core/util/id/IdentifierTest.java b/src/test/java/nova/core/util/id/IdentifierTest.java new file mode 100644 index 000000000..8d8ea3ce7 --- /dev/null +++ b/src/test/java/nova/core/util/id/IdentifierTest.java @@ -0,0 +1,64 @@ +package nova.core.util.id; + +import nova.testutils.NovaAssertions; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import static nova.testutils.NovaAssertions.assertThat; + +/** + * @author soniex2 + */ +public class IdentifierTest { + + @Test + public void testStringIdentifierComparison() { + StringIdentifier a1 = new StringIdentifier("a"); + StringIdentifier a2 = new StringIdentifier("a"); + StringIdentifier b = new StringIdentifier("b"); + assertThat(a1).isEqualTo(a2); + assertThat(a1).isNotEqualTo(b); + assertThat(a1.hashCode()).isEqualTo(a2.hashCode()); + assertThat(a1.asString()).isEqualTo(a2.asString()); + assertThat(a1.asString()).isNotEqualTo(b.asString()); + } + + @Test + public void testMixedIdentifierMap() { + Map map = new HashMap<>(); + + map.put(new StringIdentifier(StringIdentifier.class.getName()), "StringIdentifier class name"); + map.put(new ClassIdentifier(StringIdentifier.class), "StringIdentifier class"); + + assertThat(map.get(new StringIdentifier(StringIdentifier.class.getName()))).isEqualTo("StringIdentifier class name"); + assertThat(map.get(new StringIdentifier(StringIdentifier.class.getName()))).isNotEqualTo(map.get(new ClassIdentifier(StringIdentifier.class))); + assertThat(map.get(new ClassIdentifier(StringIdentifier.class))).isEqualTo("StringIdentifier class"); + } + + @Test(expected = IllegalArgumentException.class) + public void testInvalidNamespace() { + NamespacedStringIdentifier nsi = new NamespacedStringIdentifier("nova:nova", "nova"); + } + + @Test + public void testStringVsNamespace() { + NamespacedStringIdentifier nsi = new NamespacedStringIdentifier("", "a"); + StringIdentifier si = new StringIdentifier("a"); + assertThat(nsi).isNotEqualTo(si); + } + + @Test + public void testUUID() { + UUIDIdentifier a = new UUIDIdentifier(UUID.fromString("27b8a073-a6ed-4455-b144-92000c7394b7")); + UUIDIdentifier b = new UUIDIdentifier(UUID.fromString("27b8a073-a6ed-4455-b144-92000c7394b7")); + UUIDIdentifier c = new UUIDIdentifier(UUID.randomUUID()); + + assertThat(a).isEqualTo(b); + assertThat(a.hashCode()).isEqualTo(b.hashCode()); + assertThat(a.asUUID()).isEqualTo(UUID.fromString("27b8a073-a6ed-4455-b144-92000c7394b7")); + assertThat(a).isNotEqualTo(c); // this has a 1 in 2^122 chance of failing. it's *fine*. + } +} diff --git a/src/test/java/nova/testutils/FakeWorld.java b/src/test/java/nova/testutils/FakeWorld.java index c4443bdb5..522e878ab 100644 --- a/src/test/java/nova/testutils/FakeWorld.java +++ b/src/test/java/nova/testutils/FakeWorld.java @@ -28,6 +28,8 @@ import nova.core.entity.EntityFactory; import nova.core.item.Item; import nova.core.sound.Sound; +import nova.core.util.id.Identifier; +import nova.core.util.id.StringIdentifier; import nova.core.util.shape.Cuboid; import nova.core.world.World; import nova.internal.core.Game; @@ -131,7 +133,7 @@ public void playSoundAtPosition(Vector3D position, Sound sound) { } @Override - public String getID() { - return "fakeWorld"; + public Identifier getID() { + return new StringIdentifier("fakeWorld"); } } diff --git a/src/test/java/nova/wrappertests/NovaLauncherTestFactory.java b/src/test/java/nova/wrappertests/NovaLauncherTestFactory.java index 131897439..2b509a753 100644 --- a/src/test/java/nova/wrappertests/NovaLauncherTestFactory.java +++ b/src/test/java/nova/wrappertests/NovaLauncherTestFactory.java @@ -22,6 +22,7 @@ import nova.core.block.Block; import nova.core.block.BlockFactory; +import nova.core.util.id.StringIdentifier; import nova.internal.core.Game; import nova.internal.core.bootstrap.DependencyInjectionEntryPoint; import nova.internal.core.launch.NovaLauncher; @@ -82,7 +83,7 @@ public NovaLauncher createLauncher() { /** * Register fake air block */ - Game.blocks().register(new BlockFactory("air", Block::new, evt -> {})); + Game.blocks().register(new BlockFactory(new StringIdentifier("air"), Block::new, evt -> {})); launcher.generateDependencies(); launcher.load();