From 61b11a88bfdbfec10a649f4c26aaa1f532b33b13 Mon Sep 17 00:00:00 2001 From: WayofTime Date: Sun, 21 Aug 2016 13:17:04 -0400 Subject: [PATCH] Properly serialize and deserialize the Dungeon rooms --- .../WayofTime/bloodmagic/gson/Adapters.java | 6 ++ .../gson/EnumFacingTypeAdapter.java | 30 ++++++ .../bloodmagic/structures/Dungeon.java | 7 ++ .../bloodmagic/structures/DungeonRoom.java | 14 +-- .../structures/DungeonRoomLoader.java | 95 ++++++++++++++++++ .../structures/DungeonRoomRegistry.java | 12 ++- .../structures/DungeonStructure.java | 4 +- .../bloodmagic/structures/ModDungeons.java | 46 ++++----- .../schematics/building/buildings.zip | Bin 16996 -> 0 bytes 9 files changed, 176 insertions(+), 38 deletions(-) create mode 100644 src/main/java/WayofTime/bloodmagic/gson/Adapters.java create mode 100644 src/main/java/WayofTime/bloodmagic/gson/EnumFacingTypeAdapter.java create mode 100644 src/main/java/WayofTime/bloodmagic/structures/DungeonRoomLoader.java delete mode 100644 src/main/resources/assets/bloodmagic/schematics/building/buildings.zip diff --git a/src/main/java/WayofTime/bloodmagic/gson/Adapters.java b/src/main/java/WayofTime/bloodmagic/gson/Adapters.java new file mode 100644 index 00000000..bf250a83 --- /dev/null +++ b/src/main/java/WayofTime/bloodmagic/gson/Adapters.java @@ -0,0 +1,6 @@ +package WayofTime.bloodmagic.gson; + +public class Adapters +{ + public static EnumFacingTypeAdapter adapter = new EnumFacingTypeAdapter(); +} diff --git a/src/main/java/WayofTime/bloodmagic/gson/EnumFacingTypeAdapter.java b/src/main/java/WayofTime/bloodmagic/gson/EnumFacingTypeAdapter.java new file mode 100644 index 00000000..1201f458 --- /dev/null +++ b/src/main/java/WayofTime/bloodmagic/gson/EnumFacingTypeAdapter.java @@ -0,0 +1,30 @@ +package WayofTime.bloodmagic.gson; + +import java.lang.reflect.Type; + +import net.minecraft.util.EnumFacing; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; + +public class EnumFacingTypeAdapter implements JsonDeserializer, JsonSerializer +{ + @Override + public EnumFacing deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException + { + String str = json.getAsString(); + + return EnumFacing.byName(str); + } + + @Override + public JsonElement serialize(EnumFacing src, Type typeOfSrc, JsonSerializationContext context) + { + // Not necessary, since this is only used for deserialization. + return null; + } +} diff --git a/src/main/java/WayofTime/bloodmagic/structures/Dungeon.java b/src/main/java/WayofTime/bloodmagic/structures/Dungeon.java index 743b5f4a..0d640d3c 100644 --- a/src/main/java/WayofTime/bloodmagic/structures/Dungeon.java +++ b/src/main/java/WayofTime/bloodmagic/structures/Dungeon.java @@ -25,6 +25,8 @@ public class Dungeon { public static boolean placeStructureAtPosition(Random rand, WorldServer world, BlockPos pos) { + long startTime = System.nanoTime(); + Map> availableDoorMap = new HashMap>(); //Map of doors. The EnumFacing indicates what way this door faces. List descriptorList = new ArrayList(); Map> roomMap = new HashMap>(); // Placement positions in terms of actual positions @@ -158,6 +160,11 @@ public class Dungeon } } + long endTime = System.nanoTime(); + + long duration = (endTime - startTime); //divide by 1000000 to get milliseconds. + System.out.println("Duration: " + duration + "(ns), " + duration / 1000000 + "(ms)"); + //Building what I've got for (Entry> entry : roomMap.entrySet()) { diff --git a/src/main/java/WayofTime/bloodmagic/structures/DungeonRoom.java b/src/main/java/WayofTime/bloodmagic/structures/DungeonRoom.java index 5aebe083..f7d7a495 100644 --- a/src/main/java/WayofTime/bloodmagic/structures/DungeonRoom.java +++ b/src/main/java/WayofTime/bloodmagic/structures/DungeonRoom.java @@ -8,6 +8,7 @@ import java.util.Map.Entry; import java.util.Random; import net.minecraft.util.EnumFacing; +import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; import net.minecraft.world.WorldServer; import net.minecraft.world.gen.structure.template.PlacementSettings; @@ -16,12 +17,12 @@ import WayofTime.bloodmagic.api.ritual.AreaDescriptor; public class DungeonRoom { - protected Map structureMap = new HashMap(); + public Map structureMap = new HashMap(); - Map> doorMap = new HashMap>(); //Map of doors. The EnumFacing indicates what way this door faces. - List descriptorList = new ArrayList(); + public Map> doorMap = new HashMap>(); //Map of doors. The EnumFacing indicates what way this door faces. + public List descriptorList = new ArrayList(); - public DungeonRoom(Map structureMap, Map> doorMap, List descriptorList) + public DungeonRoom(Map structureMap, Map> doorMap, List descriptorList) { this.structureMap = structureMap; this.doorMap = doorMap; @@ -59,9 +60,10 @@ public class DungeonRoom public boolean placeStructureAtPosition(Random rand, PlacementSettings settings, WorldServer world, BlockPos pos) { - for (Entry entry : structureMap.entrySet()) + for (Entry entry : structureMap.entrySet()) { - DungeonStructure structure = entry.getKey(); + ResourceLocation location = new ResourceLocation(entry.getKey()); + DungeonStructure structure = new DungeonStructure(location); BlockPos offsetPos = Template.transformedBlockPos(settings, entry.getValue()); structure.placeStructureAtPosition(rand, settings, world, pos.add(offsetPos)); diff --git a/src/main/java/WayofTime/bloodmagic/structures/DungeonRoomLoader.java b/src/main/java/WayofTime/bloodmagic/structures/DungeonRoomLoader.java new file mode 100644 index 00000000..4145018f --- /dev/null +++ b/src/main/java/WayofTime/bloodmagic/structures/DungeonRoomLoader.java @@ -0,0 +1,95 @@ +package WayofTime.bloodmagic.structures; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.Writer; +import java.util.Random; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ResourceLocation; + +import org.apache.commons.io.IOUtils; + +import WayofTime.bloodmagic.api.Constants; +import WayofTime.bloodmagic.gson.Adapters; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +public class DungeonRoomLoader +{ + public static void saveDungeons() + { + for (DungeonRoom room : DungeonRoomRegistry.dungeonWeightMap.keySet()) + { + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + String json = gson.toJson(room); + + Writer writer; + try + { + File file = new File("config/BloodMagic/schematics"); + file.mkdirs(); + + writer = new FileWriter("config/BloodMagic/schematics/" + new Random().nextInt() + ".json"); + writer.write(json); + writer.close(); + } catch (IOException e) + { + e.printStackTrace(); + } + } + } + + public static void loadDungeons() + { + String folder = "config/BloodMagic/schematics"; + Gson gson = new GsonBuilder().setPrettyPrinting().registerTypeAdapter(EnumFacing.class, Adapters.adapter).create(); + + File file = new File(folder); + File[] files = file.listFiles(); + BufferedReader br; + + try + { + for (File f : files) + { + System.out.println("File: " + f); + br = new BufferedReader(new FileReader(f)); + + DungeonRoom room = gson.fromJson(br, DungeonRoom.class); + DungeonRoomRegistry.registerDungeonRoom(room, 1); + } + } catch (FileNotFoundException e) + { + e.printStackTrace(); + } + } + + public static void test() + { + ResourceLocation id = new ResourceLocation(Constants.Mod.MODID, "testGson"); + String s = id.getResourceDomain(); + String s1 = id.getResourcePath(); + InputStream inputstream = null; + + try + { + inputstream = MinecraftServer.class.getResourceAsStream("/assets/" + s + "/schematics/" + s1 + ".nbt"); +// this.readTemplateFromStream(s1, inputstream); + return; + } catch (Throwable var10) + { + + } finally + { + IOUtils.closeQuietly(inputstream); + } + } +} diff --git a/src/main/java/WayofTime/bloodmagic/structures/DungeonRoomRegistry.java b/src/main/java/WayofTime/bloodmagic/structures/DungeonRoomRegistry.java index 37f0c5c2..bfd47d8b 100644 --- a/src/main/java/WayofTime/bloodmagic/structures/DungeonRoomRegistry.java +++ b/src/main/java/WayofTime/bloodmagic/structures/DungeonRoomRegistry.java @@ -2,22 +2,30 @@ package WayofTime.bloodmagic.structures; import java.util.HashMap; import java.util.Map; +import java.util.Map.Entry; import java.util.Random; public class DungeonRoomRegistry { public static Map dungeonWeightMap = new HashMap(); + private static int totalWeight = 0; public static void registerDungeonRoom(DungeonRoom room, int weight) { dungeonWeightMap.put(room, weight); + totalWeight += weight; } public static DungeonRoom getRandomDungeonRoom(Random rand) { - for (DungeonRoom room : dungeonWeightMap.keySet()) + int wantedWeight = rand.nextInt(totalWeight); + for (Entry entry : dungeonWeightMap.entrySet()) { - return room; + wantedWeight -= entry.getValue(); + if (wantedWeight < 0) + { + return entry.getKey(); + } } return null; diff --git a/src/main/java/WayofTime/bloodmagic/structures/DungeonStructure.java b/src/main/java/WayofTime/bloodmagic/structures/DungeonStructure.java index 5e811bad..1aa9b655 100644 --- a/src/main/java/WayofTime/bloodmagic/structures/DungeonStructure.java +++ b/src/main/java/WayofTime/bloodmagic/structures/DungeonStructure.java @@ -9,11 +9,10 @@ import net.minecraft.world.WorldServer; import net.minecraft.world.gen.structure.template.PlacementSettings; import net.minecraft.world.gen.structure.template.Template; import net.minecraft.world.gen.structure.template.TemplateManager; -import WayofTime.bloodmagic.api.Constants; public class DungeonStructure { - final ResourceLocation resource; + public ResourceLocation resource; public DungeonStructure(ResourceLocation resource) { @@ -28,7 +27,6 @@ public class DungeonStructure MinecraftServer minecraftserver = world.getMinecraftServer(); TemplateManager templatemanager = world.getStructureTemplateManager(); - ResourceLocation resource = new ResourceLocation(Constants.Mod.MODID, "Corridor1"); Template template = templatemanager.func_189942_b(minecraftserver, resource); if (template == null) diff --git a/src/main/java/WayofTime/bloodmagic/structures/ModDungeons.java b/src/main/java/WayofTime/bloodmagic/structures/ModDungeons.java index f472d97c..021d9464 100644 --- a/src/main/java/WayofTime/bloodmagic/structures/ModDungeons.java +++ b/src/main/java/WayofTime/bloodmagic/structures/ModDungeons.java @@ -1,36 +1,28 @@ package WayofTime.bloodmagic.structures; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import net.minecraft.util.EnumFacing; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.BlockPos; -import WayofTime.bloodmagic.api.Constants; -import WayofTime.bloodmagic.api.ritual.AreaDescriptor; - public class ModDungeons { public static void init() { - ResourceLocation resource = new ResourceLocation(Constants.Mod.MODID, "Corridor1"); +// ResourceLocation resource = new ResourceLocation(Constants.Mod.MODID, "Corridor1"); +// +// Map structureMap = new HashMap(); +// structureMap.put(resource.toString(), new BlockPos(0, 0, 0)); +// +// Map> doorMap = new HashMap>(); +// List descriptorList = new ArrayList(); +// descriptorList.add(new AreaDescriptor.Rectangle(new BlockPos(0, 0, 0), 5, 3, 7)); +// +// DungeonUtil.addRoom(doorMap, EnumFacing.NORTH, new BlockPos(3, 0, 0)); +// DungeonUtil.addRoom(doorMap, EnumFacing.SOUTH, new BlockPos(3, 0, 6)); +// DungeonUtil.addRoom(doorMap, EnumFacing.WEST, new BlockPos(0, 0, 3)); +// +// DungeonRoom room = new DungeonRoom(structureMap, doorMap, descriptorList); +// +// DungeonRoomRegistry.registerDungeonRoom(room, 1); +// +// DungeonRoomLoader.saveDungeons(); - DungeonStructure structure = new DungeonStructure(resource); - Map structureMap = new HashMap(); - structureMap.put(structure, new BlockPos(0, 0, 0)); - - Map> doorMap = new HashMap>(); - List descriptorList = new ArrayList(); - descriptorList.add(new AreaDescriptor.Rectangle(new BlockPos(0, 0, 0), 5, 3, 7)); - - DungeonUtil.addRoom(doorMap, EnumFacing.NORTH, new BlockPos(3, 0, 0)); - DungeonUtil.addRoom(doorMap, EnumFacing.SOUTH, new BlockPos(3, 0, 6)); - DungeonUtil.addRoom(doorMap, EnumFacing.WEST, new BlockPos(0, 0, 3)); - - DungeonRoom room = new DungeonRoom(structureMap, doorMap, descriptorList); - - DungeonRoomRegistry.registerDungeonRoom(room, 1); + DungeonRoomLoader.loadDungeons(); } } diff --git a/src/main/resources/assets/bloodmagic/schematics/building/buildings.zip b/src/main/resources/assets/bloodmagic/schematics/building/buildings.zip deleted file mode 100644 index 8bd63a8594fefc1964a6ef31d6a58fabf1234082..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16996 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