From 26c3356147100b8ffcc6b2dd635686548939d5de Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Mon, 3 Sep 2018 15:19:33 +0900 Subject: [PATCH] WIP Add Config.java for setup/loading config --- .../TurnBasedMinecraftMod.java | 13 +- .../TurnBasedMinecraft/common/Battle.java | 1 - .../TurnBasedMinecraft/common/Config.java | 245 ++++++++++++++++++ .../TurnBasedMinecraft/common/EntityInfo.java | 225 ++++++++++++++++ src/main/resources/TBM_Config.xml | 110 +++++--- 5 files changed, 550 insertions(+), 44 deletions(-) create mode 100644 src/main/java/com/seodisparate/TurnBasedMinecraft/common/Config.java create mode 100644 src/main/java/com/seodisparate/TurnBasedMinecraft/common/EntityInfo.java diff --git a/src/main/java/com/seodisparate/TurnBasedMinecraft/TurnBasedMinecraftMod.java b/src/main/java/com/seodisparate/TurnBasedMinecraft/TurnBasedMinecraftMod.java index 0ae12db..e4a3a04 100644 --- a/src/main/java/com/seodisparate/TurnBasedMinecraft/TurnBasedMinecraftMod.java +++ b/src/main/java/com/seodisparate/TurnBasedMinecraft/TurnBasedMinecraftMod.java @@ -6,6 +6,7 @@ import org.apache.logging.log4j.Logger; import com.seodisparate.TurnBasedMinecraft.common.Battle; import com.seodisparate.TurnBasedMinecraft.common.BattleManager; +import com.seodisparate.TurnBasedMinecraft.common.Config; import com.seodisparate.TurnBasedMinecraft.common.networking.PacketBattleDecision; import com.seodisparate.TurnBasedMinecraft.common.networking.PacketBattleEntered; import com.seodisparate.TurnBasedMinecraft.common.networking.PacketBattleExited; @@ -18,6 +19,7 @@ import net.minecraftforge.event.entity.living.LivingAttackEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventHandler; import net.minecraftforge.fml.common.event.FMLInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import net.minecraftforge.fml.relauncher.Side; @@ -28,11 +30,16 @@ public class TurnBasedMinecraftMod public static final String NAME = "Turn Based Minecraft Mod"; public static final String VERSION = "1.0"; public static final Duration BattleDecisionTime = Duration.ofSeconds(15); + public static final String CONFIG_FILENAME = "TBM_Config.xml"; + public static final String CONFIG_DIRECTORY = "config/TurnBasedMinecraft/"; + public static final String CONFIG_FILE_PATH = CONFIG_DIRECTORY + CONFIG_FILENAME; + public static final int CONFIG_FILE_VERSION = 1; // TODO derive this from internal config private static Logger logger; private static BattleManager battleManager; private static int packetHandlerID = 0; public static Entity attackingEntity; + private static Config config; public static Battle currentBattle; @@ -83,12 +90,14 @@ public class TurnBasedMinecraftMod Side.SERVER); } - /* @EventHandler public void postInit(FMLPostInitializationEvent event) { + if(battleManager != null) + { + config = new Config(logger); + } } - */ @EventHandler public void entityAttacked(LivingAttackEvent event) diff --git a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/Battle.java b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/Battle.java index 2395d7c..78cf6e8 100644 --- a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/Battle.java +++ b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/Battle.java @@ -6,7 +6,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Hashtable; -import java.util.List; import java.util.Map; import com.seodisparate.TurnBasedMinecraft.TurnBasedMinecraftMod; diff --git a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/Config.java b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/Config.java new file mode 100644 index 0000000..1d8897f --- /dev/null +++ b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/Config.java @@ -0,0 +1,245 @@ +package com.seodisparate.TurnBasedMinecraft.common; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.time.Instant; +import java.time.format.DateTimeFormatter; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.xml.stream.FactoryConfigurationError; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.logging.log4j.Logger; + +import com.seodisparate.TurnBasedMinecraft.TurnBasedMinecraftMod; +import com.seodisparate.TurnBasedMinecraft.common.EntityInfo.Category; + +public class Config +{ + private Map entityInfoMap; + private Set ignoreBattleTypes; + private Logger logger; + + private enum ConfigParseResult + { + IS_OLD, + SUCCESS + } + + public Config(Logger logger) + { + entityInfoMap = new HashMap(); + ignoreBattleTypes = new HashSet(); + this.logger = logger; + + try + { + File testLoad = new File(TurnBasedMinecraftMod.CONFIG_FILE_PATH); + if(!testLoad.exists()) + { + writeConfig(); + } + } + catch (Exception e) + { + logger.error("Failed to check/create-new config file"); + } + + // parse xml + File configFile = new File(TurnBasedMinecraftMod.CONFIG_FILE_PATH); + if(!configFile.exists() || !configFile.canRead()) + { + logger.error("Failed to read/parse config file " + TurnBasedMinecraftMod.CONFIG_FILE_PATH); + return; + } + try + { + ConfigParseResult result = parseConfig(configFile); + if(result == ConfigParseResult.IS_OLD) + { + moveOldConfig(); + writeConfig(); + ConfigParseResult resultSecond = parseConfig(configFile); + if(resultSecond != ConfigParseResult.SUCCESS) + { + logger.error("Failed to parse config file " + TurnBasedMinecraftMod.CONFIG_FILE_PATH); + } + } + else if(result != ConfigParseResult.SUCCESS) + { + logger.error("Failed to parse config file " + TurnBasedMinecraftMod.CONFIG_FILE_PATH); + } + } catch (Exception e) + { + logger.error("Failed to parse config file " + TurnBasedMinecraftMod.CONFIG_FILE_PATH); + } + } + + private void writeConfig() throws IOException + { + File configFile = new File(TurnBasedMinecraftMod.CONFIG_FILE_PATH); + File dirs = configFile.getParentFile(); + dirs.mkdirs(); + InputStream configStream = this.getClass().getResourceAsStream(TurnBasedMinecraftMod.CONFIG_FILENAME); + FileOutputStream configOutput = new FileOutputStream(configFile); + byte[] buf = new byte[4096]; + int read = 0; + while(read != -1) + { + read = configStream.read(buf); + if(read > 0) + { + configOutput.write(buf, 0, read); + } + } + configStream.close(); + configOutput.close(); + } + + private void moveOldConfig() + { + File configFile = new File(TurnBasedMinecraftMod.CONFIG_FILE_PATH); + if(configFile.exists()) + { + configFile.renameTo(new File(TurnBasedMinecraftMod.CONFIG_DIRECTORY + "_" + + DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(Instant.now()))); + } + } + + private ConfigParseResult parseConfig(File configFile) throws XMLStreamException, FactoryConfigurationError, IOException + { + FileInputStream fis = new FileInputStream(configFile); + XMLStreamReader xmlReader = XMLInputFactory.newInstance().createXMLStreamReader(fis); + while(xmlReader.hasNext()) + { + xmlReader.next(); + if(xmlReader.isStartElement()) + { + if(xmlReader.getLocalName().equals("TurnBasedMinecraftConfig")) + { + continue; + } + else if(xmlReader.getLocalName().equals("Version")) + { + if(Integer.parseInt(xmlReader.getElementText()) < TurnBasedMinecraftMod.CONFIG_FILE_VERSION) + { + logger.info("Config file is older version, moving it and writing a new one in its place"); + xmlReader.close(); + fis.close(); + return ConfigParseResult.IS_OLD; + } + continue; + } + else if(xmlReader.getLocalName().equals("IgnoreBattleTypes")) + { + do + { + xmlReader.next(); + if(xmlReader.isStartElement()) + { + ignoreBattleTypes.add(Category.fromString(xmlReader.getLocalName())); + } + } while(!(xmlReader.isEndElement() && xmlReader.getLocalName().equals("IgnoreBattleTypes"))); + } + else if(xmlReader.getLocalName().equals("EntityStats")) + { + do + { + xmlReader.next(); + if(xmlReader.isStartElement()) + { + String classType = xmlReader.getLocalName(); + EntityInfo eInfo = new EntityInfo(); + try + { + eInfo.classType = Class.forName(classType); + } catch (ClassNotFoundException e) + { + logger.error("Failed to get class of name " + classType); + continue; + } + do + { + xmlReader.next(); + if(xmlReader.isStartElement()) + { + if(xmlReader.getLocalName().equals("AttackPower")) + { + for(int i = 0; i < xmlReader.getAttributeCount(); ++i) + { + if(xmlReader.getAttributeLocalName(i).equals("Probability")) + { + eInfo.attackProbability = Integer.parseInt(xmlReader.getAttributeValue(i)); + } + } + eInfo.attackPower = Integer.parseInt(xmlReader.getElementText()); + } + else if(xmlReader.getLocalName().equals("AttackEffect")) + { + for(int i = 0; i < xmlReader.getAttributeCount(); ++i) + { + if(xmlReader.getAttributeLocalName(i).equals("Probability")) + { + eInfo.attackEffectProbability = Integer.parseInt(xmlReader.getAttributeValue(i)); + } + } + eInfo.attackEffect = EntityInfo.Effect.fromString(xmlReader.getElementText()); + } + else if(xmlReader.getLocalName().equals("Evasion")) + { + eInfo.evasion = Integer.parseInt(xmlReader.getElementText()); + } + else if(xmlReader.getLocalName().equals("DefenseDamage")) + { + for(int i = 0; i < xmlReader.getAttributeCount(); ++i) + { + if(xmlReader.getAttributeLocalName(i).equals("Probability")) + { + eInfo.defenseDamageProbability = Integer.parseInt(xmlReader.getAttributeValue(i)); + } + } + eInfo.defenseDamage = Integer.parseInt(xmlReader.getElementText()); + } + else if(xmlReader.getLocalName().equals("Category")) + { + eInfo.category = Category.fromString(xmlReader.getElementText()); + } + else if(xmlReader.getLocalName().equals("Conflicts")) + { + do + { + xmlReader.next(); + if(xmlReader.isStartElement()) + { + try + { + Class conflictingType = Class.forName(xmlReader.getLocalName()); + eInfo.conflictingTypes.add(conflictingType); + } catch(ClassNotFoundException e) + { + logger.warn("Invalid conflicting type for entity " + eInfo.classType.getName()); + } + } + } while(!(xmlReader.isEndElement() && xmlReader.getLocalName().equals("Conflicts"))); + } + } + } while(!(xmlReader.isEndElement() && xmlReader.getLocalName().equals(classType))); + entityInfoMap.put(eInfo.classType, eInfo); + } + } while(!(xmlReader.isEndElement() && xmlReader.getLocalName().equals("EntityStats"))); + } + } + } + xmlReader.close(); + fis.close(); + return ConfigParseResult.SUCCESS; + } +} diff --git a/src/main/java/com/seodisparate/TurnBasedMinecraft/common/EntityInfo.java b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/EntityInfo.java new file mode 100644 index 0000000..a068575 --- /dev/null +++ b/src/main/java/com/seodisparate/TurnBasedMinecraft/common/EntityInfo.java @@ -0,0 +1,225 @@ +package com.seodisparate.TurnBasedMinecraft.common; + +import java.util.ArrayList; +import java.util.List; + +public class EntityInfo +{ + public Class classType; + public List conflictingTypes; + public int attackPower; + public int attackProbability; + public Effect attackEffect; + public int attackEffectProbability; + public int defenseDamage; + public int defenseDamageProbability; + public int evasion; + public Category category; + + public enum Category + { + MONSTER, + PASSIVE, + ANIMAL, + BOSS, + UNKNOWN; + + public static Category fromString(String c) + { + c = c.toLowerCase(); + if(c.equals("monster")) + { + return MONSTER; + } + else if(c.equals("passive")) + { + return PASSIVE; + } + else if(c.equals("animal")) + { + return ANIMAL; + } + else if(c.equals("boss")) + { + return BOSS; + } + else + { + return UNKNOWN; + } + } + } + + public enum Effect + { + SPEED, + SLOW, + HASTE, + MINING_FATIGUE, + STRENGTH, + JUMP_BOOST, + NAUSEA, + REGENERATION, + RESISTANCE, + FIRE_RESISTANCE, + WATER_BREATHING, + INVISIBILITY, + BLINDNESS, + NIGHT_VISION, + HUNGER, + WEAKNESS, + POISON, + WITHER, + ABSORPTION, + SATURATION, + GLOWING, + LEVITATION, + LUCK, + UNLUCK, + FIRE, + UNKNOWN; + + public static Effect fromString(String c) + { + c = c.toLowerCase(); + if(c.equals("speed")) + { + return SPEED; + } + else if(c.equals("slow")) + { + return SLOW; + } + else if(c.equals("haste")) + { + return HASTE; + } + else if(c.equals("mining_fatigue") || c.equals("fatigue")) + { + return MINING_FATIGUE; + } + else if(c.equals("strength")) + { + return STRENGTH; + } + else if(c.equals("jump_boost")) + { + return JUMP_BOOST; + } + else if(c.equals("nausea")) + { + return NAUSEA; + } + else if(c.equals("regeneration")) + { + return REGENERATION; + } + else if(c.equals("resistance")) + { + return RESISTANCE; + } + else if(c.equals("fire_resistance")) + { + return FIRE_RESISTANCE; + } + else if(c.equals("water_breathing")) + { + return WATER_BREATHING; + } + else if(c.equals("invisibility")) + { + return INVISIBILITY; + } + else if(c.equals("blindness") || c.equals("blind")) + { + return BLINDNESS; + } + else if(c.equals("night_vision")) + { + return NIGHT_VISION; + } + else if(c.equals("hunger")) + { + return HUNGER; + } + else if(c.equals("weakness")) + { + return WEAKNESS; + } + else if(c.equals("poison")) + { + return POISON; + } + else if(c.equals("wither")) + { + return WITHER; + } + else if(c.equals("absorption")) + { + return ABSORPTION; + } + else if(c.equals("saturation")) + { + return SATURATION; + } + else if(c.equals("glowing")) + { + return GLOWING; + } + else if(c.equals("levitation")) + { + return LEVITATION; + } + else if(c.equals("luck")) + { + return LUCK; + } + else if(c.equals("unluck")) + { + return UNLUCK; + } + else if(c.equals("fire")) + { + return FIRE; + } + else + { + return UNKNOWN; + } + } + } + + public EntityInfo() + { + classType = null; + conflictingTypes = new ArrayList(); + attackPower = 0; + attackProbability = 70; + attackEffect = Effect.UNKNOWN; + attackEffectProbability = 50; + defenseDamage = 0; + defenseDamageProbability = 0; + evasion = 15; + category = Category.UNKNOWN; + } + + public EntityInfo clone() + { + EntityInfo newEntityInfo = new EntityInfo(); + newEntityInfo.classType = classType; + newEntityInfo.conflictingTypes = new ArrayList(); + for(Class c : conflictingTypes) + { + newEntityInfo.conflictingTypes.add(c); + } + newEntityInfo.attackPower = attackPower; + newEntityInfo.attackProbability = attackProbability; + newEntityInfo.attackEffect = attackEffect; + newEntityInfo.attackEffectProbability = attackEffectProbability; + newEntityInfo.defenseDamage = defenseDamage; + newEntityInfo.defenseDamageProbability = defenseDamageProbability; + newEntityInfo.evasion = evasion; + newEntityInfo.category = category; + return newEntityInfo; + } +} diff --git a/src/main/resources/TBM_Config.xml b/src/main/resources/TBM_Config.xml index a897bd9..937660f 100644 --- a/src/main/resources/TBM_Config.xml +++ b/src/main/resources/TBM_Config.xml @@ -9,89 +9,108 @@ 5 fire 5 + monster 2 poison 35 + monster true 15 5 + monster 8 2 25 + monster 7 40 + monster 2 40 + monster 6 35 + monster true 13 35 + monster 11 2 + monster 6 2 25 + monster 3 hunger 5 + monster 14 5 + monster 3 12 + monster 8 10 + monster 6 5 + animal 4 15 + monster 1 37 + monster 3 13 + monster 2 10 + monster - + 0 5 + passive 2 @@ -99,28 +118,34 @@ + monster 3 - slowness + slow 13 + monster 9 30 + monster 13 10 + monster 5 8 + monster 8 wither 7 + monster 3 @@ -129,113 +154,116 @@ 5 + monster 3 5 + monster - + 0 35 + passive - + 0 10 + passive - + 0 1 + passive - + 0 10 + passive - + 0 10 + passive - + 1 10 + passive - + 0 1 + passive - + 0 10 + passive - + 1 10 + passive - + 0 35 + passive - + 0 10 + passive - + 0 40 + passive - + 0 5 + passive - + 0 5 + passive - + 0 15 + passive - + 0 5 + passive 4 20 + animal - + 0 8 + passive - + 10 27 + boss - + 8 20 wither + boss \ No newline at end of file