From 82ad02fe13c87973daaa1dbe88cf38f7c495ca38 Mon Sep 17 00:00:00 2001 From: Bixilon Date: Sat, 25 Jul 2020 17:23:57 +0200 Subject: [PATCH 1/2] fix some mappings problems, improve performance --- .../java/de/bixilon/minosoft/Minosoft.java | 3 + .../datatypes/objectLoader/blocks/Block.java | 27 ++++--- .../datatypes/objectLoader/blocks/Blocks.java | 72 ++++--------------- .../enchantments/Enchantment.java | 3 +- .../enchantments/Enchantments.java | 7 +- .../objectLoader/entities/items/Item.java | 17 +++++ .../objectLoader/entities/items/Items.java | 19 ++--- .../objectLoader/statistics/Statistics.java | 5 -- .../de/bixilon/minosoft/util/ChunkUtil.java | 6 +- 9 files changed, 61 insertions(+), 98 deletions(-) diff --git a/src/main/java/de/bixilon/minosoft/Minosoft.java b/src/main/java/de/bixilon/minosoft/Minosoft.java index 6e85ce792..a7440b3ce 100644 --- a/src/main/java/de/bixilon/minosoft/Minosoft.java +++ b/src/main/java/de/bixilon/minosoft/Minosoft.java @@ -18,6 +18,7 @@ import de.bixilon.minosoft.config.Configuration; import de.bixilon.minosoft.config.GameConfiguration; import de.bixilon.minosoft.game.datatypes.Mappings; import de.bixilon.minosoft.game.datatypes.Player; +import de.bixilon.minosoft.game.datatypes.objectLoader.blocks.Block; import de.bixilon.minosoft.game.datatypes.objectLoader.blocks.Blocks; import de.bixilon.minosoft.game.datatypes.objectLoader.enchantments.Enchantments; import de.bixilon.minosoft.game.datatypes.objectLoader.entities.Entities; @@ -162,6 +163,8 @@ public class Minosoft { } Log.verbose(String.format("Loaded mappings for version %s in %dms (%s)", version, (System.currentTimeMillis() - startTime), version.getReleaseName())); } + // end, we must set the nullBlock + Blocks.nullBlock = new Block("minecraft", "air"); } catch (IOException e) { Log.fatal("Error occurred while loading version mapping: " + e.getLocalizedMessage()); System.exit(1); diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/blocks/Block.java b/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/blocks/Block.java index d6101b3eb..40dc361fa 100644 --- a/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/blocks/Block.java +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/blocks/Block.java @@ -13,20 +13,22 @@ package de.bixilon.minosoft.game.datatypes.objectLoader.blocks; +import java.util.HashSet; + public class Block { final String mod; final String identifier; final BlockRotation rotation; - final BlockProperties[] properties; + final HashSet properties; - public Block(String mod, String identifier, BlockProperties[] properties, BlockRotation rotation) { + public Block(String mod, String identifier, HashSet properties, BlockRotation rotation) { this.mod = mod; this.identifier = identifier; this.properties = properties; this.rotation = rotation; } - public Block(String mod, String identifier, BlockProperties[] properties) { + public Block(String mod, String identifier, HashSet properties) { this.mod = mod; this.identifier = identifier; this.properties = properties; @@ -36,14 +38,14 @@ public class Block { public Block(String mod, String identifier, BlockRotation rotation) { this.mod = mod; this.identifier = identifier; - this.properties = new BlockProperties[0]; + this.properties = new HashSet<>(); this.rotation = rotation; } public Block(String mod, String identifier) { this.mod = mod; this.identifier = identifier; - this.properties = new BlockProperties[0]; + this.properties = new HashSet<>(); this.rotation = BlockRotation.NONE; } @@ -59,7 +61,7 @@ public class Block { return rotation; } - public BlockProperties[] getProperties() { + public HashSet getProperties() { return properties; } @@ -71,7 +73,7 @@ public class Block { out.append("rotation="); out.append(getRotation()); } - if (properties.length > 0) { + if (properties.size() > 0) { if (out.length() > 0) { out.append(" ,"); } else { @@ -94,7 +96,11 @@ public class Block { @Override public int hashCode() { - return mod.hashCode() * identifier.hashCode(); + int ret = mod.hashCode() * identifier.hashCode() * rotation.hashCode(); + if (properties.size() > 0) { + ret *= properties.hashCode(); + } + return ret; } @Override @@ -102,7 +108,10 @@ public class Block { if (super.equals(obj)) { return true; } + if (hashCode() != obj.hashCode()) { + return false; + } Block their = (Block) obj; - return getMod().equals(their.getMod()) && getIdentifier().equals(their.getIdentifier()) && getRotation() == their.getRotation() && Blocks.propertiesEquals(getProperties(), their.getProperties()); + return getIdentifier().equals(their.getIdentifier()) && getRotation() == their.getRotation() && getProperties().equals(their.getProperties()) && getMod().equals(their.getMod()); } } diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/blocks/Blocks.java b/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/blocks/Blocks.java index cdbb28b15..6ade9ad61 100644 --- a/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/blocks/Blocks.java +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/blocks/Blocks.java @@ -17,12 +17,12 @@ import com.google.gson.JsonArray; import com.google.gson.JsonObject; import de.bixilon.minosoft.protocol.protocol.ProtocolVersion; -import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; public class Blocks { public static Block nullBlock; - static ArrayList blockList = new ArrayList<>(); + static HashSet blockList = new HashSet<>(); static HashMap> blockMap = new HashMap<>(); // version -> (protocolId > block) static HashMap> propertiesMapping = new HashMap<>(); static HashMap rotationMapping = new HashMap<>(); @@ -460,6 +460,7 @@ public class Blocks { JsonArray statesArray = identifierJSON.getAsJsonArray("states"); for (int i = 0; i < statesArray.size(); i++) { JsonObject statesJSON = statesArray.get(i).getAsJsonObject(); + Block block; if (statesJSON.has("properties")) { // properties are optional JsonObject propertiesJSON = statesJSON.getAsJsonObject("properties"); @@ -471,8 +472,7 @@ public class Blocks { rotation = rotationMapping.get(propertiesJSON.get("rotation").getAsString()); propertiesJSON.remove("rotation"); } - BlockProperties[] properties = new BlockProperties[propertiesJSON.size()]; - int ii = 0; + HashSet properties = new HashSet<>(); for (String propertyName : propertiesJSON.keySet()) { if (propertiesMapping.get(propertyName) == null) { throw new RuntimeException(String.format("Unknown block property: %s (identifier=%s)", propertyName, identifierName)); @@ -480,51 +480,24 @@ public class Blocks { if (propertiesMapping.get(propertyName).get(propertiesJSON.get(propertyName).getAsString()) == null) { throw new RuntimeException(String.format("Unknown block property: %s -> %s (identifier=%s)", propertyName, propertiesJSON.get(propertyName).getAsString(), identifierName)); } - properties[ii] = propertiesMapping.get(propertyName).get(propertiesJSON.get(propertyName).getAsString()); - ii++; + properties.add(propertiesMapping.get(propertyName).get(propertiesJSON.get(propertyName).getAsString())); } - Block block = new Block(mod, identifierName, properties, rotation); - if (blockList.contains(block)) { - block = blockList.get(blockList.indexOf(block)); - } - - if (block == null) { - // does not exist. create - block = new Block(mod, identifierName, properties, rotation); - blockList.add(block); - } - - // set nullBlock - if (block.getIdentifier().equals("air")) { - nullBlock = block; - } - - int blockId = getBlockId(statesJSON, version); - checkAndCrashIfBlockIsIn(blockId, identifierName, versionMapping, version); - versionMapping.put(blockId, block); + block = new Block(mod, identifierName, properties, rotation); } else { // no properties, directly add block - Block block = new Block(mod, identifierName); - if (blockList.contains(block)) { - block = blockList.get(blockList.indexOf(block)); - } - - if (block == null) { - // does not exist. create - block = new Block(mod, identifierName); - blockList.add(block); - } - - int blockId = getBlockId(statesJSON, version); - checkAndCrashIfBlockIsIn(blockId, identifierName, versionMapping, version); - versionMapping.put(blockId, block); + block = new Block(mod, identifierName); } + int blockId = getBlockId(statesJSON, version); + checkAndCrashIfBlockIsIn(blockId, identifierName, versionMapping, version); + versionMapping.put(blockId, block); + blockList.add(block); } } blockMap.put(version, versionMapping); } + private static int getBlockId(JsonObject json, ProtocolVersion version) { int blockId = json.get("id").getAsInt(); if (version.getVersionNumber() <= ProtocolVersion.VERSION_1_12_2.getVersionNumber()) { @@ -537,27 +510,6 @@ public class Blocks { return blockId; } - public static boolean propertiesEquals(BlockProperties[] one, BlockProperties[] two) { - if (one.length != two.length) { - return false; - } - for (BlockProperties property : one) { - if (!containsElement(two, property)) { - return false; - } - } - return true; - } - - public static boolean containsElement(BlockProperties[] arr, BlockProperties value) { - for (BlockProperties property : arr) { - if (property == value) { - return true; - } - } - return false; - } - public static void checkAndCrashIfBlockIsIn(int blockId, String identifierName, HashBiMap versionMapping, ProtocolVersion version) { if (versionMapping.containsKey(blockId)) { String blockIdString; diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/enchantments/Enchantment.java b/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/enchantments/Enchantment.java index 2e4982b72..1575b3aaf 100644 --- a/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/enchantments/Enchantment.java +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/enchantments/Enchantment.java @@ -40,6 +40,7 @@ public class Enchantment { if (super.equals(obj)) { return true; } - return toString().equals(obj.toString()); + Enchantment their = (Enchantment) obj; + return getIdentifier().equals(their.getIdentifier()) && getMod().equals(their.getMod()); } } diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/enchantments/Enchantments.java b/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/enchantments/Enchantments.java index 4f8176774..e6a9d5641 100644 --- a/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/enchantments/Enchantments.java +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/enchantments/Enchantments.java @@ -17,15 +17,13 @@ import com.google.common.collect.HashBiMap; import com.google.gson.JsonObject; import de.bixilon.minosoft.protocol.protocol.ProtocolVersion; -import java.util.ArrayList; import java.util.HashMap; public class Enchantments { - static ArrayList enchantmentList = new ArrayList<>(); static HashMap> enchantmentMap = new HashMap<>(); - public static Enchantment getEnchantmentBdyId(int protocolId, ProtocolVersion version) { + public static Enchantment getEnchantmentById(int protocolId, ProtocolVersion version) { if (version.getVersionNumber() < ProtocolVersion.VERSION_1_12_2.getVersionNumber()) { version = ProtocolVersion.VERSION_1_12_2; } @@ -36,9 +34,6 @@ public class Enchantments { HashBiMap versionMapping = HashBiMap.create(); for (String identifierName : json.keySet()) { Enchantment enchantment = new Enchantment(mod, identifierName); - if (enchantmentList.contains(enchantment)) { - enchantment = enchantmentList.get(enchantmentList.indexOf(enchantment)); - } versionMapping.put(json.getAsJsonObject(identifierName).get("id").getAsInt(), enchantment); } enchantmentMap.put(version, versionMapping); diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/entities/items/Item.java b/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/entities/items/Item.java index 76a5113fb..6f6269b3a 100644 --- a/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/entities/items/Item.java +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/entities/items/Item.java @@ -34,4 +34,21 @@ public class Item { public String toString() { return String.format("%s:%s", getMod(), getIdentifier()); } + + @Override + public int hashCode() { + return mod.hashCode() * identifier.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (super.equals(obj)) { + return true; + } + if (hashCode() != obj.hashCode()) { + return false; + } + Item their = (Item) obj; + return getIdentifier().equals(their.getIdentifier()) && getMod().equals(their.getMod()); + } } diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/entities/items/Items.java b/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/entities/items/Items.java index 23f592972..9e8ee4d52 100644 --- a/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/entities/items/Items.java +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/entities/items/Items.java @@ -17,12 +17,12 @@ import com.google.common.collect.HashBiMap; import com.google.gson.JsonObject; import de.bixilon.minosoft.protocol.protocol.ProtocolVersion; -import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; public class Items { - static ArrayList itemList = new ArrayList<>(); + static HashSet itemList = new HashSet<>(); static HashMap> itemMap = new HashMap<>(); // version -> (protocolId > Item) public static Item getItemByLegacy(int protocolId, int protocolMetaData) { @@ -45,12 +45,8 @@ public class Items { public static void load(String mod, JsonObject json, ProtocolVersion version) { HashBiMap versionMapping = HashBiMap.create(); for (String identifierName : json.keySet()) { - Item item = getItem(mod, identifierName); - if (item == null) { - // does not exist. create - item = new Item(mod, identifierName); - itemList.add(item); - } + Item item = new Item(mod, identifierName); + itemList.add(item); JsonObject identifierJSON = json.getAsJsonObject(identifierName); int itemId = identifierJSON.get("id").getAsInt(); if (version.getVersionNumber() <= ProtocolVersion.VERSION_1_12_2.getVersionNumber()) { @@ -66,12 +62,7 @@ public class Items { } public static Item getItem(String mod, String identifier) { - for (Item item : itemList) { - if (item.getMod().equals(mod) && item.getIdentifier().equals(identifier)) { - return item; - } - } - return null; + return new Item(mod, identifier); } public static int getItemId(Item item, ProtocolVersion version) { diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/statistics/Statistics.java b/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/statistics/Statistics.java index 40e19da96..bca1191d9 100644 --- a/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/statistics/Statistics.java +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/statistics/Statistics.java @@ -17,12 +17,10 @@ import com.google.common.collect.HashBiMap; import com.google.gson.JsonObject; import de.bixilon.minosoft.protocol.protocol.ProtocolVersion; -import java.util.ArrayList; import java.util.HashMap; public class Statistics { - static ArrayList statisticList = new ArrayList<>(); static HashMap> statisticsIdMap = new HashMap<>(); static HashMap> statisticsIdentifierMap = new HashMap<>(); @@ -45,9 +43,6 @@ public class Statistics { HashBiMap versionIdentifierMapping = HashBiMap.create(); for (String identifierName : json.keySet()) { Statistic statistic = new Statistic(mod, identifierName); - if (statisticList.contains(statistic)) { - statistic = statisticList.get(statisticList.indexOf(statistic)); - } if (json.getAsJsonObject(identifierName).has("id")) { versionIdMapping.put(json.getAsJsonObject(identifierName).get("id").getAsInt(), statistic); } else { diff --git a/src/main/java/de/bixilon/minosoft/util/ChunkUtil.java b/src/main/java/de/bixilon/minosoft/util/ChunkUtil.java index 097de64f3..cb5f28b47 100644 --- a/src/main/java/de/bixilon/minosoft/util/ChunkUtil.java +++ b/src/main/java/de/bixilon/minosoft/util/ChunkUtil.java @@ -82,7 +82,7 @@ public class ChunkUtil { // ToDo light, biome Block block = Blocks.getBlockByLegacy(singeBlockId, singleMeta); - if (block == Blocks.nullBlock) { + if (block.equals(Blocks.nullBlock)) { arrayPos++; continue; } @@ -130,7 +130,7 @@ public class ChunkUtil { for (int nibbleZ = 0; nibbleZ < 16; nibbleZ++) { for (int nibbleX = 0; nibbleX < 16; nibbleX++) { Block block = Blocks.getBlockByLegacy(blockData[arrayPos]); - if (block == Blocks.nullBlock) { + if (block.equals(Blocks.nullBlock)) { arrayPos++; continue; } @@ -186,7 +186,7 @@ public class ChunkUtil { blockId &= individualValueMask; Block block = palette.byId(blockId); - if (block == Blocks.nullBlock) { + if (block.equals(Blocks.nullBlock)) { continue; } blockMap.put(new ChunkNibbleLocation(nibbleX, nibbleY, nibbleZ), block); From 842bf9118b87073a36b4a46674819d21a0143c93 Mon Sep 17 00:00:00 2001 From: Bixilon Date: Sat, 25 Jul 2020 17:35:32 +0200 Subject: [PATCH 2/2] fix some problems with gson, use hashCode in Enchantment and Statistic --- src/main/java/de/bixilon/minosoft/ServerListPing.java | 3 +-- .../de/bixilon/minosoft/game/datatypes/TextComponent.java | 2 +- .../datatypes/objectLoader/enchantments/Enchantment.java | 8 ++++++++ .../game/datatypes/objectLoader/statistics/Statistic.java | 8 ++++++++ 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/main/java/de/bixilon/minosoft/ServerListPing.java b/src/main/java/de/bixilon/minosoft/ServerListPing.java index 75c9f2cae..82f27bece 100644 --- a/src/main/java/de/bixilon/minosoft/ServerListPing.java +++ b/src/main/java/de/bixilon/minosoft/ServerListPing.java @@ -14,7 +14,6 @@ package de.bixilon.minosoft; import com.google.gson.JsonObject; -import com.google.gson.JsonParseException; import de.bixilon.minosoft.game.datatypes.TextComponent; public class ServerListPing { final JsonObject raw; @@ -46,7 +45,7 @@ public class ServerListPing { public TextComponent getMotd() { try { return new TextComponent(raw.getAsJsonObject("description")); - } catch (JsonParseException ignored) { + } catch (Exception ignored) { } return new TextComponent(raw.get("description").getAsString()); } diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/TextComponent.java b/src/main/java/de/bixilon/minosoft/game/datatypes/TextComponent.java index edd1fc513..1189a5a3f 100644 --- a/src/main/java/de/bixilon/minosoft/game/datatypes/TextComponent.java +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/TextComponent.java @@ -30,7 +30,7 @@ public class TextComponent { } try { this.json = JsonParser.parseString(raw).getAsJsonObject(); - } catch (IllegalStateException e) { + } catch (Exception e) { // not a text component, is a legacy string this.json = new JsonObject(); JsonArray extra = new JsonArray(); diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/enchantments/Enchantment.java b/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/enchantments/Enchantment.java index 1575b3aaf..c8783b009 100644 --- a/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/enchantments/Enchantment.java +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/enchantments/Enchantment.java @@ -35,11 +35,19 @@ public class Enchantment { return String.format("%s:%s", getMod(), getIdentifier()); } + @Override + public int hashCode() { + return mod.hashCode() * identifier.hashCode(); + } + @Override public boolean equals(Object obj) { if (super.equals(obj)) { return true; } + if (hashCode() != obj.hashCode()) { + return false; + } Enchantment their = (Enchantment) obj; return getIdentifier().equals(their.getIdentifier()) && getMod().equals(their.getMod()); } diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/statistics/Statistic.java b/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/statistics/Statistic.java index 123a9887f..63a10ffd0 100644 --- a/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/statistics/Statistic.java +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/statistics/Statistic.java @@ -35,11 +35,19 @@ public class Statistic { return String.format("%s:%s", getMod(), getIdentifier()); } + @Override + public int hashCode() { + return mod.hashCode() * identifier.hashCode(); + } + @Override public boolean equals(Object obj) { if (super.equals(obj)) { return true; } + if (hashCode() != obj.hashCode()) { + return false; + } return toString().equals(obj.toString()); } }