diff --git a/src/com/massivecraft/massivecore/MassiveCore.java b/src/com/massivecraft/massivecore/MassiveCore.java index f09fefb3..e643a6f4 100644 --- a/src/com/massivecraft/massivecore/MassiveCore.java +++ b/src/com/massivecraft/massivecore/MassiveCore.java @@ -31,6 +31,7 @@ import com.massivecraft.massivecore.collections.MassiveTreeSet; import com.massivecraft.massivecore.collections.MassiveTreeSetDef; import com.massivecraft.massivecore.command.type.RegistryType; import com.massivecraft.massivecore.item.DataBannerPattern; +import com.massivecraft.massivecore.item.DataItemStack; import com.massivecraft.massivecore.item.WriterItemStack; import com.massivecraft.massivecore.mixin.MixinEvent; import com.massivecraft.massivecore.mson.Mson; @@ -43,6 +44,7 @@ import com.massivecraft.massivecore.store.Coll; import com.massivecraft.massivecore.store.EntityInternalMap; import com.massivecraft.massivecore.store.ModificationPollerLocal; import com.massivecraft.massivecore.store.ModificationPollerRemote; +import com.massivecraft.massivecore.store.migrator.MigratorUtil; import com.massivecraft.massivecore.util.BoardUtil; import com.massivecraft.massivecore.util.ContainerUtil; import com.massivecraft.massivecore.util.EventUtil; @@ -231,6 +233,10 @@ public class MassiveCore extends MassivePlugin // Setup RegistryType RegistryType.registerAll(); + MigratorUtil.addJsonRepresentation(ItemStack.class, DataItemStack.class); + MigratorUtil.addJsonRepresentation(Inventory.class, null); + MigratorUtil.setTargetVersion(Inventory.class, MigratorUtil.getTargetVersion(DataItemStack.class)); + // Activate this.activateAuto(); diff --git a/src/com/massivecraft/massivecore/adapter/AdapterInventory.java b/src/com/massivecraft/massivecore/adapter/AdapterInventory.java index 7f4e2a8c..8faa847e 100644 --- a/src/com/massivecraft/massivecore/adapter/AdapterInventory.java +++ b/src/com/massivecraft/massivecore/adapter/AdapterInventory.java @@ -3,6 +3,7 @@ package com.massivecraft.massivecore.adapter; import com.massivecraft.massivecore.MassiveCore; import com.massivecraft.massivecore.item.DataItemStack; import com.massivecraft.massivecore.mixin.MixinInventory; +import com.massivecraft.massivecore.store.migrator.MigratorUtil; import com.massivecraft.massivecore.xlib.gson.JsonDeserializationContext; import com.massivecraft.massivecore.xlib.gson.JsonDeserializer; import com.massivecraft.massivecore.xlib.gson.JsonElement; @@ -156,6 +157,10 @@ public class AdapterInventory implements JsonDeserializer, JsonSerial jsonInventory.add(index, jsonItemStack); } + // Add version + int version = MigratorUtil.getTargetVersion(DataItemStack.class); + jsonInventory.addProperty(MigratorUtil.VERSION_FIELD_NAME, version); + return jsonInventory; } @@ -191,16 +196,14 @@ public class AdapterInventory implements JsonDeserializer, JsonSerial // Helmet if (jsonInventory.has(HELMET)) { - jsonItemStack = jsonInventory.get(HELMET); - itemStack = MassiveCore.gson.fromJson(jsonItemStack, ItemStack.class); + itemStack = getItemStack(jsonInventory, HELMET); pret.setHelmet(itemStack); } // Chestplate if (jsonInventory.has(CHESTPLATE)) { - jsonItemStack = jsonInventory.get(CHESTPLATE); - itemStack = MassiveCore.gson.fromJson(jsonItemStack, ItemStack.class); + itemStack = getItemStack(jsonInventory, CHESTPLATE); pret.setChestplate(itemStack); } @@ -215,16 +218,14 @@ public class AdapterInventory implements JsonDeserializer, JsonSerial // Boots if (jsonInventory.has(BOOTS)) { - jsonItemStack = jsonInventory.get(BOOTS); - itemStack = MassiveCore.gson.fromJson(jsonItemStack, ItemStack.class); + itemStack = getItemStack(jsonInventory, BOOTS); pret.setBoots(itemStack); } // Shield (Minecraft 1.9) if (jsonInventory.has(SHIELD) && INDEX_PLAYER_SHIELD < pret.getSize()) { - jsonItemStack = jsonInventory.get(SHIELD); - itemStack = MassiveCore.gson.fromJson(jsonItemStack, ItemStack.class); + itemStack = getItemStack(jsonInventory, SHIELD); pret.setItem(INDEX_PLAYER_SHIELD, itemStack); } } @@ -241,9 +242,7 @@ public class AdapterInventory implements JsonDeserializer, JsonSerial for (int i = 0; i < size; i++) { String stackIdx = String.valueOf(i); - jsonItemStack = jsonInventory.get(stackIdx); - if (jsonItemStack == null) continue; - itemStack = MassiveCore.gson.fromJson(jsonItemStack, ItemStack.class); + itemStack = getItemStack(jsonInventory, stackIdx); if (itemStack == null) continue; ret.setItem(i, itemStack); } @@ -251,6 +250,16 @@ public class AdapterInventory implements JsonDeserializer, JsonSerial return ret; } + private static ItemStack getItemStack(JsonObject jsonInventory, String idx) + { + // Get jsonItemStack + JsonElement jsonItemStack = jsonInventory.get(idx); + if (jsonItemStack == null) return null; + + ItemStack ret = MassiveCore.gson.fromJson(jsonItemStack, ItemStack.class); + return ret; + } + // -------------------------------------------- // // UTIL // -------------------------------------------- // diff --git a/src/com/massivecraft/massivecore/adapter/AdapterItemStack.java b/src/com/massivecraft/massivecore/adapter/AdapterItemStack.java index 638d847c..2ab9b78a 100644 --- a/src/com/massivecraft/massivecore/adapter/AdapterItemStack.java +++ b/src/com/massivecraft/massivecore/adapter/AdapterItemStack.java @@ -1,6 +1,7 @@ package com.massivecraft.massivecore.adapter; import com.massivecraft.massivecore.item.DataItemStack; +import com.massivecraft.massivecore.store.migrator.MigratorUtil; import com.massivecraft.massivecore.xlib.gson.JsonDeserializationContext; import com.massivecraft.massivecore.xlib.gson.JsonDeserializer; import com.massivecraft.massivecore.xlib.gson.JsonElement; diff --git a/src/com/massivecraft/massivecore/entity/migrator/MigratorDataItemStack001StringId.java b/src/com/massivecraft/massivecore/entity/migrator/MigratorDataItemStack001StringId.java new file mode 100644 index 00000000..7b73b6df --- /dev/null +++ b/src/com/massivecraft/massivecore/entity/migrator/MigratorDataItemStack001StringId.java @@ -0,0 +1,522 @@ +package com.massivecraft.massivecore.entity.migrator; + +import com.google.common.collect.ImmutableMap; +import com.massivecraft.massivecore.collections.MassiveMap; +import com.massivecraft.massivecore.item.DataItemStack; +import com.massivecraft.massivecore.store.migrator.MigratorRoot; +import com.massivecraft.massivecore.xlib.gson.JsonElement; +import com.massivecraft.massivecore.xlib.gson.JsonObject; +import com.massivecraft.massivecore.xlib.gson.JsonPrimitive; + +import java.util.Map; + +public class MigratorDataItemStack001StringId extends MigratorRoot +{ + // -------------------------------------------- // + // INSTANCE & CONSTRUCT + // -------------------------------------------- // + + private static MigratorDataItemStack001StringId i = new MigratorDataItemStack001StringId(); + public static MigratorDataItemStack001StringId get() { return i; } + private MigratorDataItemStack001StringId() + { + super(DataItemStack.class); + } + + // -------------------------------------------- // + // CONVERSION + // -------------------------------------------- // + + @Override + public void migrateInner(JsonObject json) + { + // Get the id + JsonElement id = json.get("id"); + if (id == null || id.isJsonNull()) return; + + // The id is either a number or string, always a JsonPrimitive + JsonPrimitive primitive = id.getAsJsonPrimitive(); + + // Only convert if number + if (!primitive.isNumber()) return; + int typeId = primitive.getAsInt(); + String name = id2name.get(typeId); + if (name == null) throw new RuntimeException(String.valueOf(typeId)); + JsonElement newValue = new JsonPrimitive(name); + json.add("id", newValue); + } + + private static final Map id2name; + + static + { + Map map = new MassiveMap<>(); + + map.put(0, "AIR"); + map.put(1, "STONE"); + map.put(2, "GRASS"); + map.put(3, "DIRT"); + map.put(4, "COBBLESTONE"); + map.put(5, "WOOD"); + map.put(6, "SAPLING"); + map.put(7, "BEDROCK"); + map.put(8, "WATER"); + map.put(9, "STATIONARY_WATER"); + map.put(10, "LAVA"); + map.put(11, "STATIONARY_LAVA"); + map.put(12, "SAND"); + map.put(13, "GRAVEL"); + map.put(14, "GOLD_ORE"); + map.put(15, "IRON_ORE"); + map.put(16, "COAL_ORE"); + map.put(17, "LOG"); + map.put(18, "LEAVES"); + map.put(19, "SPONGE"); + map.put(20, "GLASS"); + map.put(21, "LAPIS_ORE"); + map.put(22, "LAPIS_BLOCK"); + map.put(23, "DISPENSER"); + map.put(24, "SANDSTONE"); + map.put(25, "NOTE_BLOCK"); + map.put(26, "BED_BLOCK"); + map.put(27, "POWERED_RAIL"); + map.put(28, "DETECTOR_RAIL"); + map.put(29, "PISTON_STICKY_BASE"); + map.put(30, "WEB"); + map.put(31, "LONG_GRASS"); + map.put(32, "DEAD_BUSH"); + map.put(33, "PISTON_BASE"); + map.put(34, "PISTON_EXTENSION"); + map.put(35, "WOOL"); + map.put(36, "PISTON_MOVING_PIECE"); + map.put(37, "YELLOW_FLOWER"); + map.put(38, "RED_ROSE"); + map.put(39, "BROWN_MUSHROOM"); + map.put(40, "RED_MUSHROOM"); + map.put(41, "GOLD_BLOCK"); + map.put(42, "IRON_BLOCK"); + map.put(43, "DOUBLE_STEP"); + map.put(44, "STEP"); + map.put(45, "BRICK"); + map.put(46, "TNT"); + map.put(47, "BOOKSHELF"); + map.put(48, "MOSSY_COBBLESTONE"); + map.put(49, "OBSIDIAN"); + map.put(50, "TORCH"); + map.put(51, "FIRE"); + map.put(52, "MOB_SPAWNER"); + map.put(53, "WOOD_STAIRS"); + map.put(54, "CHEST"); + map.put(55, "REDSTONE_WIRE"); + map.put(56, "DIAMOND_ORE"); + map.put(57, "DIAMOND_BLOCK"); + map.put(58, "WORKBENCH"); + map.put(59, "CROPS"); + map.put(60, "SOIL"); + map.put(61, "FURNACE"); + map.put(62, "BURNING_FURNACE"); + map.put(63, "SIGN_POST"); + map.put(64, "WOODEN_DOOR"); + map.put(65, "LADDER"); + map.put(66, "RAILS"); + map.put(67, "COBBLESTONE_STAIRS"); + map.put(68, "WALL_SIGN"); + map.put(69, "LEVER"); + map.put(70, "STONE_PLATE"); + map.put(71, "IRON_DOOR_BLOCK"); + map.put(72, "WOOD_PLATE"); + map.put(73, "REDSTONE_ORE"); + map.put(74, "GLOWING_REDSTONE_ORE"); + map.put(75, "REDSTONE_TORCH_OFF"); + map.put(76, "REDSTONE_TORCH_ON"); + map.put(77, "STONE_BUTTON"); + map.put(78, "SNOW"); + map.put(79, "ICE"); + map.put(80, "SNOW_BLOCK"); + map.put(81, "CACTUS"); + map.put(82, "CLAY"); + map.put(83, "SUGAR_CANE_BLOCK"); + map.put(84, "JUKEBOX"); + map.put(85, "FENCE"); + map.put(86, "PUMPKIN"); + map.put(87, "NETHERRACK"); + map.put(88, "SOUL_SAND"); + map.put(89, "GLOWSTONE"); + map.put(90, "PORTAL"); + map.put(91, "JACK_O_LANTERN"); + map.put(92, "CAKE_BLOCK"); + map.put(93, "DIODE_BLOCK_OFF"); + map.put(94, "DIODE_BLOCK_ON"); + map.put(95, "STAINED_GLASS"); + map.put(96, "TRAP_DOOR"); + map.put(97, "MONSTER_EGGS"); + map.put(98, "SMOOTH_BRICK"); + map.put(99, "HUGE_MUSHROOM_1"); + map.put(100, "HUGE_MUSHROOM_2"); + map.put(101, "IRON_FENCE"); + map.put(102, "THIN_GLASS"); + map.put(103, "MELON_BLOCK"); + map.put(104, "PUMPKIN_STEM"); + map.put(105, "MELON_STEM"); + map.put(106, "VINE"); + map.put(107, "FENCE_GATE"); + map.put(108, "BRICK_STAIRS"); + map.put(109, "SMOOTH_STAIRS"); + map.put(110, "MYCEL"); + map.put(111, "WATER_LILY"); + map.put(112, "NETHER_BRICK"); + map.put(113, "NETHER_FENCE"); + map.put(114, "NETHER_BRICK_STAIRS"); + map.put(115, "NETHER_WARTS"); + map.put(116, "ENCHANTMENT_TABLE"); + map.put(117, "BREWING_STAND"); + map.put(118, "CAULDRON"); + map.put(119, "ENDER_PORTAL"); + map.put(120, "ENDER_PORTAL_FRAME"); + map.put(121, "ENDER_STONE"); + map.put(122, "DRAGON_EGG"); + map.put(123, "REDSTONE_LAMP_OFF"); + map.put(124, "REDSTONE_LAMP_ON"); + map.put(125, "WOOD_DOUBLE_STEP"); + map.put(126, "WOOD_STEP"); + map.put(127, "COCOA"); + map.put(128, "SANDSTONE_STAIRS"); + map.put(129, "EMERALD_ORE"); + map.put(130, "ENDER_CHEST"); + map.put(131, "TRIPWIRE_HOOK"); + map.put(132, "TRIPWIRE"); + map.put(133, "EMERALD_BLOCK"); + map.put(134, "SPRUCE_WOOD_STAIRS"); + map.put(135, "BIRCH_WOOD_STAIRS"); + map.put(136, "JUNGLE_WOOD_STAIRS"); + map.put(137, "COMMAND"); + map.put(138, "BEACON"); + map.put(139, "COBBLE_WALL"); + map.put(140, "FLOWER_POT"); + map.put(141, "CARROT"); + map.put(142, "POTATO"); + map.put(143, "WOOD_BUTTON"); + map.put(144, "SKULL"); + map.put(145, "ANVIL"); + map.put(146, "TRAPPED_CHEST"); + map.put(147, "GOLD_PLATE"); + map.put(148, "IRON_PLATE"); + map.put(149, "REDSTONE_COMPARATOR_OFF"); + map.put(150, "REDSTONE_COMPARATOR_ON"); + map.put(151, "DAYLIGHT_DETECTOR"); + map.put(152, "REDSTONE_BLOCK"); + map.put(153, "QUARTZ_ORE"); + map.put(154, "HOPPER"); + map.put(155, "QUARTZ_BLOCK"); + map.put(156, "QUARTZ_STAIRS"); + map.put(157, "ACTIVATOR_RAIL"); + map.put(158, "DROPPER"); + map.put(159, "STAINED_CLAY"); + map.put(160, "STAINED_GLASS_PANE"); + map.put(161, "LEAVES_2"); + map.put(162, "LOG_2"); + map.put(163, "ACACIA_STAIRS"); + map.put(164, "DARK_OAK_STAIRS"); + map.put(165, "SLIME_BLOCK"); + map.put(166, "BARRIER"); + map.put(167, "IRON_TRAPDOOR"); + map.put(168, "PRISMARINE"); + map.put(169, "SEA_LANTERN"); + map.put(170, "HAY_BLOCK"); + map.put(171, "CARPET"); + map.put(172, "HARD_CLAY"); + map.put(173, "COAL_BLOCK"); + map.put(174, "PACKED_ICE"); + map.put(175, "DOUBLE_PLANT"); + map.put(176, "STANDING_BANNER"); + map.put(177, "WALL_BANNER"); + map.put(178, "DAYLIGHT_DETECTOR_INVERTED"); + map.put(179, "RED_SANDSTONE"); + map.put(180, "RED_SANDSTONE_STAIRS"); + map.put(181, "DOUBLE_STONE_SLAB2"); + map.put(182, "STONE_SLAB2"); + map.put(183, "SPRUCE_FENCE_GATE"); + map.put(184, "BIRCH_FENCE_GATE"); + map.put(185, "JUNGLE_FENCE_GATE"); + map.put(186, "DARK_OAK_FENCE_GATE"); + map.put(187, "ACACIA_FENCE_GATE"); + map.put(188, "SPRUCE_FENCE"); + map.put(189, "BIRCH_FENCE"); + map.put(190, "JUNGLE_FENCE"); + map.put(191, "DARK_OAK_FENCE"); + map.put(192, "ACACIA_FENCE"); + map.put(193, "SPRUCE_DOOR"); + map.put(194, "BIRCH_DOOR"); + map.put(195, "JUNGLE_DOOR"); + map.put(196, "ACACIA_DOOR"); + map.put(197, "DARK_OAK_DOOR"); + map.put(198, "END_ROD"); + map.put(199, "CHORUS_PLANT"); + map.put(200, "CHORUS_FLOWER"); + map.put(201, "PURPUR_BLOCK"); + map.put(202, "PURPUR_PILLAR"); + map.put(203, "PURPUR_STAIRS"); + map.put(204, "PURPUR_DOUBLE_SLAB"); + map.put(205, "PURPUR_SLAB"); + map.put(206, "END_BRICKS"); + map.put(207, "BEETROOT_BLOCK"); + map.put(208, "GRASS_PATH"); + map.put(209, "END_GATEWAY"); + map.put(210, "COMMAND_REPEATING"); + map.put(211, "COMMAND_CHAIN"); + map.put(212, "FROSTED_ICE"); + map.put(213, "MAGMA"); + map.put(214, "NETHER_WART_BLOCK"); + map.put(215, "RED_NETHER_BRICK"); + map.put(216, "BONE_BLOCK"); + map.put(217, "STRUCTURE_VOID"); + map.put(218, "OBSERVER"); + map.put(219, "WHITE_SHULKER_BOX"); + map.put(220, "ORANGE_SHULKER_BOX"); + map.put(221, "MAGENTA_SHULKER_BOX"); + map.put(222, "LIGHT_BLUE_SHULKER_BOX"); + map.put(223, "YELLOW_SHULKER_BOX"); + map.put(224, "LIME_SHULKER_BOX"); + map.put(225, "PINK_SHULKER_BOX"); + map.put(226, "GRAY_SHULKER_BOX"); + map.put(227, "SILVER_SHULKER_BOX"); + map.put(228, "CYAN_SHULKER_BOX"); + map.put(229, "PURPLE_SHULKER_BOX"); + map.put(230, "BLUE_SHULKER_BOX"); + map.put(231, "BROWN_SHULKER_BOX"); + map.put(232, "GREEN_SHULKER_BOX"); + map.put(233, "RED_SHULKER_BOX"); + map.put(234, "BLACK_SHULKER_BOX"); + map.put(235, "WHITE_GLAZED_TERRACOTTA"); + map.put(236, "ORANGE_GLAZED_TERRACOTTA"); + map.put(237, "MAGENTA_GLAZED_TERRACOTTA"); + map.put(238, "LIGHT_BLUE_GLAZED_TERRACOTTA"); + map.put(239, "YELLOW_GLAZED_TERRACOTTA"); + map.put(240, "LIME_GLAZED_TERRACOTTA"); + map.put(241, "PINK_GLAZED_TERRACOTTA"); + map.put(242, "GRAY_GLAZED_TERRACOTTA"); + map.put(243, "SILVER_GLAZED_TERRACOTTA"); + map.put(244, "CYAN_GLAZED_TERRACOTTA"); + map.put(245, "PURPLE_GLAZED_TERRACOTTA"); + map.put(246, "BLUE_GLAZED_TERRACOTTA"); + map.put(247, "BROWN_GLAZED_TERRACOTTA"); + map.put(248, "GREEN_GLAZED_TERRACOTTA"); + map.put(249, "RED_GLAZED_TERRACOTTA"); + map.put(250, "BLACK_GLAZED_TERRACOTTA"); + map.put(251, "CONCRETE"); + map.put(252, "CONCRETE_POWDER"); + map.put(255, "STRUCTURE_BLOCK"); + map.put(256, "IRON_SPADE"); + map.put(257, "IRON_PICKAXE"); + map.put(258, "IRON_AXE"); + map.put(259, "FLINT_AND_STEEL"); + map.put(260, "APPLE"); + map.put(261, "BOW"); + map.put(262, "ARROW"); + map.put(263, "COAL"); + map.put(264, "DIAMOND"); + map.put(265, "IRON_INGOT"); + map.put(266, "GOLD_INGOT"); + map.put(267, "IRON_SWORD"); + map.put(268, "WOOD_SWORD"); + map.put(269, "WOOD_SPADE"); + map.put(270, "WOOD_PICKAXE"); + map.put(271, "WOOD_AXE"); + map.put(272, "STONE_SWORD"); + map.put(273, "STONE_SPADE"); + map.put(274, "STONE_PICKAXE"); + map.put(275, "STONE_AXE"); + map.put(276, "DIAMOND_SWORD"); + map.put(277, "DIAMOND_SPADE"); + map.put(278, "DIAMOND_PICKAXE"); + map.put(279, "DIAMOND_AXE"); + map.put(280, "STICK"); + map.put(281, "BOWL"); + map.put(282, "MUSHROOM_SOUP"); + map.put(283, "GOLD_SWORD"); + map.put(284, "GOLD_SPADE"); + map.put(285, "GOLD_PICKAXE"); + map.put(286, "GOLD_AXE"); + map.put(287, "STRING"); + map.put(288, "FEATHER"); + map.put(289, "SULPHUR"); + map.put(290, "WOOD_HOE"); + map.put(291, "STONE_HOE"); + map.put(292, "IRON_HOE"); + map.put(293, "DIAMOND_HOE"); + map.put(294, "GOLD_HOE"); + map.put(295, "SEEDS"); + map.put(296, "WHEAT"); + map.put(297, "BREAD"); + map.put(298, "LEATHER_HELMET"); + map.put(299, "LEATHER_CHESTPLATE"); + map.put(300, "LEATHER_LEGGINGS"); + map.put(301, "LEATHER_BOOTS"); + map.put(302, "CHAINMAIL_HELMET"); + map.put(303, "CHAINMAIL_CHESTPLATE"); + map.put(304, "CHAINMAIL_LEGGINGS"); + map.put(305, "CHAINMAIL_BOOTS"); + map.put(306, "IRON_HELMET"); + map.put(307, "IRON_CHESTPLATE"); + map.put(308, "IRON_LEGGINGS"); + map.put(309, "IRON_BOOTS"); + map.put(310, "DIAMOND_HELMET"); + map.put(311, "DIAMOND_CHESTPLATE"); + map.put(312, "DIAMOND_LEGGINGS"); + map.put(313, "DIAMOND_BOOTS"); + map.put(314, "GOLD_HELMET"); + map.put(315, "GOLD_CHESTPLATE"); + map.put(316, "GOLD_LEGGINGS"); + map.put(317, "GOLD_BOOTS"); + map.put(318, "FLINT"); + map.put(319, "PORK"); + map.put(320, "GRILLED_PORK"); + map.put(321, "PAINTING"); + map.put(322, "GOLDEN_APPLE"); + map.put(323, "SIGN"); + map.put(324, "WOOD_DOOR"); + map.put(325, "BUCKET"); + map.put(326, "WATER_BUCKET"); + map.put(327, "LAVA_BUCKET"); + map.put(328, "MINECART"); + map.put(329, "SADDLE"); + map.put(330, "IRON_DOOR"); + map.put(331, "REDSTONE"); + map.put(332, "SNOW_BALL"); + map.put(333, "BOAT"); + map.put(334, "LEATHER"); + map.put(335, "MILK_BUCKET"); + map.put(336, "CLAY_BRICK"); + map.put(337, "CLAY_BALL"); + map.put(338, "SUGAR_CANE"); + map.put(339, "PAPER"); + map.put(340, "BOOK"); + map.put(341, "SLIME_BALL"); + map.put(342, "STORAGE_MINECART"); + map.put(343, "POWERED_MINECART"); + map.put(344, "EGG"); + map.put(345, "COMPASS"); + map.put(346, "FISHING_ROD"); + map.put(347, "WATCH"); + map.put(348, "GLOWSTONE_DUST"); + map.put(349, "RAW_FISH"); + map.put(350, "COOKED_FISH"); + map.put(351, "INK_SACK"); + map.put(352, "BONE"); + map.put(353, "SUGAR"); + map.put(354, "CAKE"); + map.put(355, "BED"); + map.put(356, "DIODE"); + map.put(357, "COOKIE"); + map.put(358, "MAP"); + map.put(359, "SHEARS"); + map.put(360, "MELON"); + map.put(361, "PUMPKIN_SEEDS"); + map.put(362, "MELON_SEEDS"); + map.put(363, "RAW_BEEF"); + map.put(364, "COOKED_BEEF"); + map.put(365, "RAW_CHICKEN"); + map.put(366, "COOKED_CHICKEN"); + map.put(367, "ROTTEN_FLESH"); + map.put(368, "ENDER_PEARL"); + map.put(369, "BLAZE_ROD"); + map.put(370, "GHAST_TEAR"); + map.put(371, "GOLD_NUGGET"); + map.put(372, "NETHER_STALK"); + map.put(373, "POTION"); + map.put(374, "GLASS_BOTTLE"); + map.put(375, "SPIDER_EYE"); + map.put(376, "FERMENTED_SPIDER_EYE"); + map.put(377, "BLAZE_POWDER"); + map.put(378, "MAGMA_CREAM"); + map.put(379, "BREWING_STAND_ITEM"); + map.put(380, "CAULDRON_ITEM"); + map.put(381, "EYE_OF_ENDER"); + map.put(382, "SPECKLED_MELON"); + map.put(383, "MONSTER_EGG"); + map.put(384, "EXP_BOTTLE"); + map.put(385, "FIREBALL"); + map.put(386, "BOOK_AND_QUILL"); + map.put(387, "WRITTEN_BOOK"); + map.put(388, "EMERALD"); + map.put(389, "ITEM_FRAME"); + map.put(390, "FLOWER_POT_ITEM"); + map.put(391, "CARROT_ITEM"); + map.put(392, "POTATO_ITEM"); + map.put(393, "BAKED_POTATO"); + map.put(394, "POISONOUS_POTATO"); + map.put(395, "EMPTY_MAP"); + map.put(396, "GOLDEN_CARROT"); + map.put(397, "SKULL_ITEM"); + map.put(398, "CARROT_STICK"); + map.put(399, "NETHER_STAR"); + map.put(400, "PUMPKIN_PIE"); + map.put(401, "FIREWORK"); + map.put(402, "FIREWORK_CHARGE"); + map.put(403, "ENCHANTED_BOOK"); + map.put(404, "REDSTONE_COMPARATOR"); + map.put(405, "NETHER_BRICK_ITEM"); + map.put(406, "QUARTZ"); + map.put(407, "EXPLOSIVE_MINECART"); + map.put(408, "HOPPER_MINECART"); + map.put(409, "PRISMARINE_SHARD"); + map.put(410, "PRISMARINE_CRYSTALS"); + map.put(411, "RABBIT"); + map.put(412, "COOKED_RABBIT"); + map.put(413, "RABBIT_STEW"); + map.put(414, "RABBIT_FOOT"); + map.put(415, "RABBIT_HIDE"); + map.put(416, "ARMOR_STAND"); + map.put(417, "IRON_BARDING"); + map.put(418, "GOLD_BARDING"); + map.put(419, "DIAMOND_BARDING"); + map.put(420, "LEASH"); + map.put(421, "NAME_TAG"); + map.put(422, "COMMAND_MINECART"); + map.put(423, "MUTTON"); + map.put(424, "COOKED_MUTTON"); + map.put(425, "BANNER"); + map.put(426, "END_CRYSTAL"); + map.put(427, "SPRUCE_DOOR_ITEM"); + map.put(428, "BIRCH_DOOR_ITEM"); + map.put(429, "JUNGLE_DOOR_ITEM"); + map.put(430, "ACACIA_DOOR_ITEM"); + map.put(431, "DARK_OAK_DOOR_ITEM"); + map.put(432, "CHORUS_FRUIT"); + map.put(433, "CHORUS_FRUIT_POPPED"); + map.put(434, "BEETROOT"); + map.put(435, "BEETROOT_SEEDS"); + map.put(436, "BEETROOT_SOUP"); + map.put(437, "DRAGONS_BREATH"); + map.put(438, "SPLASH_POTION"); + map.put(439, "SPECTRAL_ARROW"); + map.put(440, "TIPPED_ARROW"); + map.put(441, "LINGERING_POTION"); + map.put(442, "SHIELD"); + map.put(443, "ELYTRA"); + map.put(444, "BOAT_SPRUCE"); + map.put(445, "BOAT_BIRCH"); + map.put(446, "BOAT_JUNGLE"); + map.put(447, "BOAT_ACACIA"); + map.put(448, "BOAT_DARK_OAK"); + map.put(449, "TOTEM"); + map.put(450, "SHULKER_SHELL"); + map.put(452, "IRON_NUGGET"); + map.put(453, "KNOWLEDGE_BOOK"); + map.put(2256, "GOLD_RECORD"); + map.put(2257, "GREEN_RECORD"); + map.put(2258, "RECORD_3"); + map.put(2259, "RECORD_4"); + map.put(2260, "RECORD_5"); + map.put(2261, "RECORD_6"); + map.put(2262, "RECORD_7"); + map.put(2263, "RECORD_8"); + map.put(2264, "RECORD_9"); + map.put(2265, "RECORD_10"); + map.put(2266, "RECORD_11"); + map.put(2267, "RECORD_12"); + + id2name = ImmutableMap.copyOf(map); + } + +} diff --git a/src/com/massivecraft/massivecore/entity/migrator/MigratorInventory001StringId.java b/src/com/massivecraft/massivecore/entity/migrator/MigratorInventory001StringId.java new file mode 100644 index 00000000..7789d6d1 --- /dev/null +++ b/src/com/massivecraft/massivecore/entity/migrator/MigratorInventory001StringId.java @@ -0,0 +1,69 @@ +package com.massivecraft.massivecore.entity.migrator; + +import com.massivecraft.massivecore.adapter.AdapterInventory; +import com.massivecraft.massivecore.item.DataItemStack; +import com.massivecraft.massivecore.store.migrator.MigratorRoot; +import com.massivecraft.massivecore.store.migrator.MigratorUtil; +import com.massivecraft.massivecore.util.MUtil; +import com.massivecraft.massivecore.xlib.gson.JsonElement; +import com.massivecraft.massivecore.xlib.gson.JsonObject; +import com.massivecraft.massivecore.xlib.gson.JsonPrimitive; +import org.apache.commons.lang.StringUtils; +import org.bukkit.inventory.Inventory; + +import java.util.Map.Entry; +import java.util.Set; + +public class MigratorInventory001StringId extends MigratorRoot +{ + // -------------------------------------------- // + // CONSTANTS + // -------------------------------------------- // + + public static final Set NAMES_EXTRA_FIELDS = MUtil.set( + AdapterInventory.HELMET, + AdapterInventory.CHESTPLATE, + AdapterInventory.LEGGINGS, + AdapterInventory.BOOTS, + AdapterInventory.SHIELD + ); + + // -------------------------------------------- // + // INSTANCE & CONSTRUCT + // -------------------------------------------- // + + private static MigratorInventory001StringId i = new MigratorInventory001StringId(); + public static MigratorInventory001StringId get() { return i; } + private MigratorInventory001StringId() + { + super(Inventory.class); + } + + // -------------------------------------------- // + // CONVERSION + // -------------------------------------------- // + + @Override + public void migrateInner(JsonObject json) + { + for (Entry entry : json.entrySet()) + { + String name = entry.getKey(); + boolean updateable = NAMES_EXTRA_FIELDS.contains(name) || StringUtils.isNumeric(name); + + if (!updateable) continue; + + updateField(json, name); + } + } + + public void updateField(JsonObject json, String name) + { + JsonElement element = json.get(name); + if (element == null) return; + if (!element.isJsonObject()) return; + JsonObject object = element.getAsJsonObject(); + MigratorUtil.migrate(DataItemStack.class, object); + } + +} diff --git a/src/com/massivecraft/massivecore/item/ConverterFromMaterial.java b/src/com/massivecraft/massivecore/item/ConverterFromMaterial.java new file mode 100644 index 00000000..7cfce8ec --- /dev/null +++ b/src/com/massivecraft/massivecore/item/ConverterFromMaterial.java @@ -0,0 +1,25 @@ +package com.massivecraft.massivecore.item; + +import org.bukkit.Material; + +public class ConverterFromMaterial extends Converter +{ + // -------------------------------------------- // + // INSTANCE & CONSTRUCT + // -------------------------------------------- // + + private static final ConverterFromMaterial i = new ConverterFromMaterial(); + public static ConverterFromMaterial get() { return i; } + + // -------------------------------------------- // + // OVERRIDE + // -------------------------------------------- // + + @Override + public String convert(Material x) + { + if (x == null) return null; + return x.name(); + } + +} diff --git a/src/com/massivecraft/massivecore/item/ConverterToMaterial.java b/src/com/massivecraft/massivecore/item/ConverterToMaterial.java new file mode 100644 index 00000000..e4e098fa --- /dev/null +++ b/src/com/massivecraft/massivecore/item/ConverterToMaterial.java @@ -0,0 +1,27 @@ +package com.massivecraft.massivecore.item; + +import org.bukkit.Material; + +public class ConverterToMaterial extends Converter +{ + // -------------------------------------------- // + // INSTANCE & CONSTRUCT + // -------------------------------------------- // + + private static final ConverterToMaterial i = new ConverterToMaterial(); + public static ConverterToMaterial get() { return i; } + + // -------------------------------------------- // + // OVERRIDE + // -------------------------------------------- // + + @Override + public Material convert(String x) + { + if (x == null) return null; + Material ret = Material.getMaterial(x); + if (ret == null) throw new NullPointerException(x); + return ret; + } + +} diff --git a/src/com/massivecraft/massivecore/item/DataItemStack.java b/src/com/massivecraft/massivecore/item/DataItemStack.java index 97a06e7f..ffcbb504 100644 --- a/src/com/massivecraft/massivecore/item/DataItemStack.java +++ b/src/com/massivecraft/massivecore/item/DataItemStack.java @@ -5,6 +5,7 @@ import com.massivecraft.massivecore.collections.MassiveListDef; import com.massivecraft.massivecore.collections.MassiveMap; import com.massivecraft.massivecore.collections.MassiveTreeMapDef; import com.massivecraft.massivecore.collections.MassiveTreeSetDef; +import com.massivecraft.massivecore.command.editor.annotation.EditorEditable; import com.massivecraft.massivecore.command.editor.annotation.EditorMethods; import com.massivecraft.massivecore.command.editor.annotation.EditorType; import com.massivecraft.massivecore.command.editor.annotation.EditorTypeInner; @@ -21,6 +22,7 @@ import com.massivecraft.massivecore.util.InventoryUtil; import com.massivecraft.massivecore.util.MUtil; import com.massivecraft.massivecore.xlib.gson.annotations.SerializedName; import org.bukkit.Bukkit; +import org.bukkit.Material; import org.bukkit.inventory.ItemStack; import java.util.Collection; @@ -56,7 +58,7 @@ public class DataItemStack implements Comparable // Since Bukkit doesn't NPE evade much we save ourselves a lot of trouble that way. // Especially note how all collections default to empty immutables instead of null. - public static final transient Integer DEFAULT_ID = 0; + public static final transient String DEFAULT_ID = Material.AIR.name(); public static final transient Integer DEFAULT_COUNT = 1; public static final transient Integer DEFAULT_DAMAGE = 0; public static final transient String DEFAULT_NAME = null; @@ -83,14 +85,22 @@ public class DataItemStack implements Comparable public static final transient Integer DEFAULT_POTION_COLOR = null; public static final transient Integer DEFAULT_MAP_COLOR = null; + // -------------------------------------------- // + // FIELDS > VERSION + // -------------------------------------------- // + + @EditorEditable(false) + @EditorVisible(false) + private int version = 1; + // -------------------------------------------- // // FIELDS > BASIC // -------------------------------------------- // @EditorType(value = TypeMaterialId.class) - private Integer id = null; - public int getId() { return get(this.id, DEFAULT_ID); } - public DataItemStack setId(int id) { this.id = set(id, DEFAULT_ID); return this; } + private String id = null; + public String getId() { return get(this.id, DEFAULT_ID); } + public DataItemStack setId(String id) { this.id = set(id, DEFAULT_ID); return this; } private Integer count = null; public int getCount() { return get(this.count, DEFAULT_COUNT); } @@ -461,7 +471,7 @@ public class DataItemStack implements Comparable public static boolean isSomething(DataItemStack dataItemStack) { if (dataItemStack == null) return false; - if (dataItemStack.getId() == 0) return false; + if (dataItemStack.getId().equals(DEFAULT_ID)) return false; // In Minecraft 1.9 zero quantity is a thing. return true; } diff --git a/src/com/massivecraft/massivecore/item/WriterItemStackId.java b/src/com/massivecraft/massivecore/item/WriterItemStackId.java index e1ec2c58..129c049d 100644 --- a/src/com/massivecraft/massivecore/item/WriterItemStackId.java +++ b/src/com/massivecraft/massivecore/item/WriterItemStackId.java @@ -1,8 +1,9 @@ package com.massivecraft.massivecore.item; +import org.bukkit.Material; import org.bukkit.inventory.ItemStack; -public class WriterItemStackId extends WriterAbstractItemStackField +public class WriterItemStackId extends WriterAbstractItemStackField { // -------------------------------------------- // // INSTANCE & CONSTRUCT @@ -10,35 +11,38 @@ public class WriterItemStackId extends WriterAbstractItemStackField> extends CollAbstract // BEHAVIOR // -------------------------------------------- // - // What entity version do we want? - protected final int entityTargetVersion; - @Override public int getEntityTargetVersion() { return this.entityTargetVersion; } - // This should be false under most circumstances. // In some cases such as Factions we want it though. // Especially so we don't change the years old way Factions does it. @@ -290,15 +286,15 @@ public class Coll> extends CollAbstract Long mtime = remoteEntry.getValue(); int version = MigratorUtil.getVersion(raw); - if (version > this.getEntityTargetVersion()) + if (version > MigratorUtil.getTargetVersion(this.getEntityClass())) { logLoadError(id, String.format("Cannot load entity of entity version %d", version)); return; } // Migrate if another version is wanted - boolean migrated = MigratorUtil.migrate(this.getEntityClass(), raw, this.getEntityTargetVersion()); - + boolean migrated = MigratorUtil.migrate(this.getEntityClass(), raw); + // Calculate temp but handle raw cases. E temp; @@ -320,9 +316,14 @@ public class Coll> extends CollAbstract } else { - // Create first - entity = this.createNewInstance(); - + // Create first (or load from registry) + // The registry is used by MassiveMagic + Map tempRegistry = this.getTempRegistry(); + if(tempRegistry != null) entity = tempRegistry.get(id); + if (entity == null) entity = this.createNewInstance(); + + if (tempRegistry != null) tempRegistry.remove(id); + // Copy over data first this.copy(temp, entity); @@ -773,18 +774,6 @@ public class Coll> extends CollAbstract // Collections this.idToEntity = new ConcurrentHashMap<>(); this.identifiedModifications = new ConcurrentHashMap<>(); - - // Migration - int version = 0; - try - { - version = ReflectionUtil.getField(this.getEntityClass(), MigratorUtil.VERSION_FIELD_NAME, this.createNewInstance()); - } - catch (Exception ex) - { - // The field was not there - } - this.entityTargetVersion = version; // Tasks this.tickTask = new Runnable() @@ -877,7 +866,7 @@ public class Coll> extends CollAbstract // TODO: Clean up this stuff below. It branches too late. if (active) { - MigratorUtil.validateMigratorsPresent(entityClass, 0, this.getEntityTargetVersion()); + MigratorUtil.validateMigratorsPresent(entityClass, 0, MigratorUtil.getTargetVersion(entityClass)); if (this.supportsPusher()) { diff --git a/src/com/massivecraft/massivecore/store/CollAbstract.java b/src/com/massivecraft/massivecore/store/CollAbstract.java index caa7daba..3a5066af 100644 --- a/src/com/massivecraft/massivecore/store/CollAbstract.java +++ b/src/com/massivecraft/massivecore/store/CollAbstract.java @@ -2,6 +2,7 @@ package com.massivecraft.massivecore.store; import com.massivecraft.massivecore.xlib.gson.JsonObject; +import java.util.Map; import java.util.Map.Entry; @@ -46,6 +47,11 @@ public abstract class CollAbstract> extends EntityContainerA if (oid == null) throw new NullPointerException("oid"); this.saveToRemoteFixed(this.fixIdOrThrow(oid)); } + + @Override public Map getTempRegistry() + { + return null; + } @Override public void loadFromRemote(Object oid, Entry remoteEntry) diff --git a/src/com/massivecraft/massivecore/store/CollInterface.java b/src/com/massivecraft/massivecore/store/CollInterface.java index efad2284..79d46c59 100644 --- a/src/com/massivecraft/massivecore/store/CollInterface.java +++ b/src/com/massivecraft/massivecore/store/CollInterface.java @@ -40,12 +40,6 @@ public interface CollInterface> extends Named, Active, Ident // -------------------------------------------- // Collection getIdsRemote(); - - // -------------------------------------------- // - // BEHAVIOR - // -------------------------------------------- // - - int getEntityTargetVersion(); // -------------------------------------------- // // SYNC LOG @@ -68,7 +62,9 @@ public interface CollInterface> extends Named, Active, Ident void removeAtRemoteFixed(String id); void saveToRemoteFixed(String id); void loadFromRemoteFixed(String id, Entry remoteEntry); - + + Map getTempRegistry(); + // -------------------------------------------- // // SYNC EXAMINE AND DO // -------------------------------------------- // diff --git a/src/com/massivecraft/massivecore/store/Entity.java b/src/com/massivecraft/massivecore/store/Entity.java index 2bab9ca0..e125658c 100644 --- a/src/com/massivecraft/massivecore/store/Entity.java +++ b/src/com/massivecraft/massivecore/store/Entity.java @@ -2,12 +2,6 @@ package com.massivecraft.massivecore.store; import com.massivecraft.massivecore.xlib.gson.JsonObject; -/** - * Usage of this class is highly optional. You may persist anything. If you are - * creating the class to be persisted yourself, it might be handy to extend this - * Entity class. It just contains a set of shortcut methods. - */ - // Self referencing generic. // http://www.angelikalanger.com/GenericsFAQ/FAQSections/ProgrammingIdioms.html#FAQ206 public class Entity> extends EntityInternal diff --git a/src/com/massivecraft/massivecore/store/GsonEqualsChecker.java b/src/com/massivecraft/massivecore/store/GsonEqualsChecker.java index 8da0f0ad..3c3b4a57 100644 --- a/src/com/massivecraft/massivecore/store/GsonEqualsChecker.java +++ b/src/com/massivecraft/massivecore/store/GsonEqualsChecker.java @@ -124,12 +124,14 @@ public class GsonEqualsChecker // Boolean check if (one.isBoolean()) { + if (!two.isBoolean()) return false; return one.getAsBoolean() == two.getAsBoolean(); } // Number check if (one.isNumber()) { + if (!two.isNumber()) return false; Number oneNumber = one.getAsNumber(); Number twoNumber = two.getAsNumber(); @@ -149,6 +151,7 @@ public class GsonEqualsChecker // String check if (one.isString()) { + if (!two.isString()) return false; return one.getAsString().equals(two.getAsString()); } diff --git a/src/com/massivecraft/massivecore/store/migrator/MigratorRoot.java b/src/com/massivecraft/massivecore/store/migrator/MigratorRoot.java index d860fa51..61b46fbc 100644 --- a/src/com/massivecraft/massivecore/store/migrator/MigratorRoot.java +++ b/src/com/massivecraft/massivecore/store/migrator/MigratorRoot.java @@ -24,16 +24,16 @@ public class MigratorRoot implements Migrator, Active this.innerMigrators.add(innerMigrator); } - private final Class> entityClass; - public Class> getEntityClass() { return entityClass; } + private final Class clazz; + public Class getClazz() { return clazz; } // -------------------------------------------- // // CONSTRUCT // -------------------------------------------- // - public MigratorRoot(Class> entityClass) + public MigratorRoot(Class clazz) { - this.entityClass = entityClass; + this.clazz = clazz; } // -------------------------------------------- // diff --git a/src/com/massivecraft/massivecore/store/migrator/MigratorUtil.java b/src/com/massivecraft/massivecore/store/migrator/MigratorUtil.java index 32101328..d8f7a72c 100644 --- a/src/com/massivecraft/massivecore/store/migrator/MigratorUtil.java +++ b/src/com/massivecraft/massivecore/store/migrator/MigratorUtil.java @@ -2,15 +2,22 @@ package com.massivecraft.massivecore.store.migrator; import com.massivecraft.massivecore.collections.MassiveList; import com.massivecraft.massivecore.collections.MassiveMap; -import com.massivecraft.massivecore.store.Entity; +import com.massivecraft.massivecore.util.ReflectionUtil; import com.massivecraft.massivecore.util.Txt; import com.massivecraft.massivecore.xlib.gson.JsonElement; import com.massivecraft.massivecore.xlib.gson.JsonObject; +import com.massivecraft.massivecore.xlib.gson.annotations.SerializedName; +import org.bukkit.inventory.Inventory; +import java.lang.reflect.Field; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Map.Entry; public class MigratorUtil { @@ -21,10 +28,10 @@ public class MigratorUtil public static final String VERSION_FIELD_NAME = "version"; // -------------------------------------------- // - // REGISTRY + // MIGRATOR REGISTRY // -------------------------------------------- // - private static Map>, Map> migrators = new HashMap<>(); + private static Map, Map> migrators = new HashMap<>(); public static boolean isActive(MigratorRoot migrator) { @@ -50,7 +57,7 @@ public class MigratorUtil } // GET - public static MigratorRoot getMigrator(Class> entityClass, int version) + public static MigratorRoot getMigrator(Class entityClass, int version) { Map migratorMap = getMigratorMap(entityClass); @@ -66,10 +73,10 @@ public class MigratorUtil // GET MAP private static Map getMigratorMap(MigratorRoot migrator) { - return getMigratorMap(migrator.getEntityClass()); + return getMigratorMap(migrator.getClazz()); } - private static Map getMigratorMap(Class> entityClass) + private static Map getMigratorMap(Class entityClass) { Map ret = migrators.get(entityClass); if (ret == null) @@ -79,39 +86,213 @@ public class MigratorUtil } return ret; } - + + // -------------------------------------------- // + // TARGET VERSION + // -------------------------------------------- // + + private static Map, Integer> targetVersions = new HashMap<>(); + + // ADD + public static void setTargetVersion(Class clazz, int targetVersion) + { + targetVersions.put(clazz, targetVersion); + } + + // GET + public static int getTargetVersion(Class entityClass) + { + if (!targetVersions.containsKey(entityClass)) + { + targetVersions.put(entityClass, computeTargetVersion(entityClass)); + } + return targetVersions.get(entityClass); + } + + public static int computeTargetVersion(Class clazz) + { + int version = 0; + try + { + version = ReflectionUtil.getField(clazz, VERSION_FIELD_NAME, ReflectionUtil.newInstance(clazz)); + } + catch (Exception ex) + { + // The field was not there + } + return version; + } + + // -------------------------------------------- // + // JSON REPRESENTATION + // -------------------------------------------- // + + private static Map, Type> jsonRepresentation = new HashMap<>(); + + // ADD + public static void addJsonRepresentation(Class clazz, Type representation) + { + jsonRepresentation.put(clazz, representation); + } + + // GET + public static Type getJsonRepresentation(Type actualType) + { + if (!jsonRepresentation.containsKey(actualType)) + { + return actualType; + } + return jsonRepresentation.get(actualType); + } + + // -------------------------------------------- // // MIGRATE // -------------------------------------------- // - - public static boolean migrate(Class> entityClass, JsonObject entity, int targetVersion) + + public static boolean migrate(Type realType, JsonElement jsonElement) { - if (entityClass == null) throw new NullPointerException("entityClass"); - if (entity == null) throw new NullPointerException("entity"); + if (jsonElement == null) throw new NullPointerException("element"); + + if (jsonElement.isJsonNull()) return false; + if (jsonElement.isJsonPrimitive()) return false; + + Type jsonType = getJsonRepresentation(realType); + + if (jsonElement.isJsonObject()) + { + if (jsonType != null && Map.class.isAssignableFrom(getClassType(jsonType))) + { + ParameterizedType parameterizedType = (ParameterizedType) jsonType; + Type keyType = parameterizedType.getActualTypeArguments()[0]; + Type valueType = parameterizedType.getActualTypeArguments()[1]; + + JsonObject object = jsonElement.getAsJsonObject(); + + boolean migrated = false; + for (Entry entry : object.entrySet()) + { + migrated = migrate(valueType, entry.getValue()) | migrated; + } + return migrated; + } + + boolean migrated = false; + JsonObject object = jsonElement.getAsJsonObject(); + Type classType = jsonType != null ? jsonType : realType; + migrated = migrateClass(classType, object) | migrated; + if (jsonType != null) migrated = migrateFields(jsonType, object) | migrated; + return migrated; + + } + if (jsonElement.isJsonArray()) + { + Class clazz = getClassType(jsonType); + + Type elementType = null; + + if (clazz.isArray()) + { + elementType = clazz.getComponentType(); + } + else if (Collection.class.isAssignableFrom(clazz)) + { + ParameterizedType parameterizedType = (ParameterizedType) jsonType; + elementType = parameterizedType.getActualTypeArguments()[0]; + } + + boolean migrated = false; + for (JsonElement element1 : jsonElement.getAsJsonArray()) + { + migrated = migrate(elementType, element1) | migrated; + } + return migrated; + } + + throw new RuntimeException(); + } + public static boolean migrateClass(Type type, JsonObject entity) + { + if (type == null) throw new NullPointerException("entityClass"); + if (entity == null) throw new NullPointerException("entity"); + + Class entityClass = getClassType(type); + + int targetVersion = getTargetVersion(entityClass); int entityVersion = getVersion(entity); if (entityVersion == targetVersion) return false; - + validateMigratorsPresent(entityClass, entityVersion, targetVersion); for (; entityVersion < targetVersion; entityVersion++) { // When upgrading we need the migrator we are updating to. - // When downgrading we need the migrator we are downgrading from. - // This is done to preserve the same logic within the same class. - // That is why when updating we don't use entityVersion and when downgrading we do. Migrator migrator = getMigrator(entityClass, entityVersion+1); migrator.migrate(entity); } return true; } + + public static boolean migrateFields(Type type, JsonObject object) + { + if (type == null) throw new NullPointerException("entityClass"); + if (object == null) throw new NullPointerException("object"); + + Class entityClass = getClassType(type); + + // We can't lookup the generic type of a map, so trying to convert the fields is useless + // Furthermore maps are stored as jsopnobjects, and we can't treat them like other objects + // because their "fields" are dynamically made and can't be looked up with reflection + if (Map.class.isAssignableFrom(entityClass)) return false; + + boolean migrated = false; + for (Entry entry : object.entrySet()) + { + String name = entry.getKey(); + JsonElement element = entry.getValue(); + // It might be defined in a superclass, so find the defining class + Class superClass = ReflectionUtil.getSuperclassDeclaringField(entityClass, true, name); + + // Try find field if it has a different serialisation name + if (superClass == null) + { + Field field = tryFindField(entityClass, name); + if (field != null) + { + name = field.getName(); + superClass = entityClass; + } + } + Type elementType = ReflectionUtil.getField(superClass, name).getGenericType(); + migrated = migrate(elementType, element) | migrated; + } + + return migrated; + } + + private static Field tryFindField(Class clazz, String name) + { + for (Field field : clazz.getDeclaredFields()) + { + SerializedName serializedName = field.getAnnotation(SerializedName.class); + if (serializedName == null) continue; + + if (serializedName.value().equals(name)) + { + return field; + } + } + return null; + } + // -------------------------------------------- // // MISSING MIGRATORS // -------------------------------------------- // - public static void validateMigratorsPresent(Class> entityClass, int from, int to) + public static void validateMigratorsPresent(Class entityClass, int from, int to) { List missingMigrators = MigratorUtil.getMissingMigratorVersions(entityClass, from, to); if (missingMigrators.isEmpty()) return; @@ -121,7 +302,7 @@ public class MigratorUtil throw new IllegalStateException(String.format("Could not find migrators for %s for versions: %s", name, versions)); } - public static List getMissingMigratorVersions(Class> entityClass, int from, int to) + public static List getMissingMigratorVersions(Class entityClass, int from, int to) { if (from == to) return Collections.emptyList(); if (from > to) throw new IllegalArgumentException(String.format("from: %d to: %d", from, to)); @@ -139,11 +320,11 @@ public class MigratorUtil } return ret; } - + // -------------------------------------------- // // UTIL // -------------------------------------------- // - + public static int getVersion(JsonObject entity) { if (entity == null) throw new NullPointerException("entity"); @@ -151,5 +332,22 @@ public class MigratorUtil if (element == null) return 0; return element.getAsInt(); } + + public static Class getClassType(Type type) + { + if (type == null) return null; + if (type instanceof Class) + { + return (Class) type; + } + else if (type instanceof ParameterizedType) + { + return (Class) ((ParameterizedType) type).getRawType(); + } + else + { + throw new RuntimeException(type.getTypeName()); + } + } } diff --git a/src/com/massivecraft/massivecore/util/RecipeUtil.java b/src/com/massivecraft/massivecore/util/RecipeUtil.java index 9ce6453a..d4d5e948 100644 --- a/src/com/massivecraft/massivecore/util/RecipeUtil.java +++ b/src/com/massivecraft/massivecore/util/RecipeUtil.java @@ -1,21 +1,14 @@ package com.massivecraft.massivecore.util; -import com.massivecraft.massivecore.collections.MassiveList; -import com.massivecraft.massivecore.predicate.Predicate; import org.bukkit.Bukkit; import org.bukkit.Material; +import org.bukkit.NamespacedKey; import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.Recipe; import org.bukkit.inventory.ShapelessRecipe; import org.bukkit.inventory.meta.PotionMeta; import org.bukkit.potion.PotionData; import org.bukkit.potion.PotionType; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Objects; - // NOTE: This utility targets 1.9 and will crash on older servers. public class RecipeUtil { @@ -79,7 +72,7 @@ public class RecipeUtil @SuppressWarnings("deprecation") public static ShapelessRecipe createShapeless(ItemStack result, Object... objects) { - ShapelessRecipe recipe = new ShapelessRecipe(result); + ShapelessRecipe recipe = new ShapelessRecipe(NamespacedKey.randomKey(), result); int quantity = 1; int data = 0;