Use .toml instead of .xml for config

This commit is contained in:
Stephen Seo 2018-10-20 17:54:32 +09:00
parent faf7a02619
commit 05b3dc90b0
10 changed files with 1352 additions and 1019 deletions

View file

@ -1,3 +1,11 @@
# Version 1.6
Fix bug where player can start battle with self.
Change config to use ".toml" instead of ".xml".
Change how battle info text is displayed.
# Version 1.5 # Version 1.5
Fix proper consumption of food/potion items in battle. Fix proper consumption of food/potion items in battle.

View file

@ -5,13 +5,14 @@ buildscript {
} }
dependencies { dependencies {
classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT' classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT'
classpath 'com.github.jengelman.gradle.plugins:shadow:4.0.1'
} }
} }
apply plugin: 'net.minecraftforge.gradle.forge' apply plugin: 'net.minecraftforge.gradle.forge'
//Only edit below this line, the above code adds and enables the necessary things for Forge to be setup. apply plugin: 'com.github.johnrengelman.shadow'
version = "1.5" version = "1.6"
group = "com.seodisparate.TurnBasedMinecraft" // http://maven.apache.org/guides/mini/guide-naming-conventions.html group = "com.seodisparate.TurnBasedMinecraft"
archivesBaseName = "TurnBasedMinecraft" archivesBaseName = "TurnBasedMinecraft"
sourceCompatibility = targetCompatibility = '1.8' // Need this here so eclipse task generates correctly. sourceCompatibility = targetCompatibility = '1.8' // Need this here so eclipse task generates correctly.
@ -37,6 +38,7 @@ dependencies {
// or you may define them like so.. // or you may define them like so..
//compile "some.group:artifact:version:classifier" //compile "some.group:artifact:version:classifier"
//compile "some.group:artifact:version" //compile "some.group:artifact:version"
compile "net.consensys.cava:cava-toml:0.3.1"
// real examples // real examples
//compile 'com.mod-buildcraft:buildcraft:6.0.8:dev' // adds buildcraft to the dev env //compile 'com.mod-buildcraft:buildcraft:6.0.8:dev' // adds buildcraft to the dev env
@ -74,3 +76,14 @@ processResources {
exclude 'mcmod.info' exclude 'mcmod.info'
} }
} }
shadowJar {
classifier ""
relocate 'net.consensys.cava', 'shadow.turnbasedmc.net.consensys.cava'
relocate 'org.antlr.v4', 'shadow.turnbasedmc.org.antlr.v4'
relocate 'javax.annotation', 'shadow.turnbasedmc.javax.annotation'
}
reobf { shadowJar { mappingType = "SEARGE" } }
tasks.reobfShadowJar.mustRunAfter shadowJar

View file

@ -7,7 +7,9 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.settings.GameSettings; import net.minecraft.client.settings.GameSettings;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundCategory;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentString; import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextFormatting;
public class ClientProxy extends CommonProxy public class ClientProxy extends CommonProxy
{ {
@ -158,7 +160,12 @@ public class ClientProxy extends CommonProxy
@Override @Override
public void displayString(String message) public void displayString(String message)
{ {
Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString(message)); ITextComponent prefix = new TextComponentString("TBM: ");
prefix.getStyle().setColor(TextFormatting.GREEN).setBold(true);
ITextComponent text = new TextComponentString(message);
prefix.appendSibling(text);
text.getStyle().setColor(TextFormatting.WHITE).setBold(false);
Minecraft.getMinecraft().player.sendMessage(prefix);
} }
@Override @Override

View file

@ -1,23 +1,16 @@
package com.seodisparate.TurnBasedMinecraft.common; package com.seodisparate.TurnBasedMinecraft.common;
import java.io.File; import java.io.*;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.stream.FactoryConfigurationError; import net.consensys.cava.toml.*;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
public class Config public class Config
@ -36,8 +29,8 @@ public class Config
private int playerEvasion = 10; private int playerEvasion = 10;
private int defenseDuration = 1; private int defenseDuration = 1;
private int fleeGoodProbability = 90; private int fleeGoodProbability = 90;
private int fleeBadProbability = 40; private int fleeBadProbability = 35;
private int minimumHitPercentage = 1; private int minimumHitPercentage = 4;
private int maxInBattle = 8; private int maxInBattle = 8;
private Set<String> musicBattleTypes; private Set<String> musicBattleTypes;
private Set<String> musicSillyTypes; private Set<String> musicSillyTypes;
@ -60,19 +53,7 @@ public class Config
musicSillyTypes = new HashSet<String>(); musicSillyTypes = new HashSet<String>();
battleIgnoringPlayers = new HashSet<Integer>(); battleIgnoringPlayers = new HashSet<Integer>();
int internalVersion = 0; int internalVersion = getConfigFileVersion(getClass().getResourceAsStream(TurnBasedMinecraftMod.CONFIG_INTERNAL_PATH));
try
{
InputStream is = getClass().getResourceAsStream(TurnBasedMinecraftMod.CONFIG_INTERNAL_PATH);
if(is == null)
{
logger.error("Internal resource is null");
}
else
{
internalVersion = getConfigFileVersion(is);
}
} catch (Throwable t) {}
if(internalVersion == 0) if(internalVersion == 0)
{ {
@ -96,7 +77,7 @@ public class Config
logger.error("Failed to check/create-new config file"); logger.error("Failed to check/create-new config file");
} }
// parse xml // parse config
File configFile = new File(TurnBasedMinecraftMod.CONFIG_FILE_PATH); File configFile = new File(TurnBasedMinecraftMod.CONFIG_FILE_PATH);
if(!configFile.exists() || !configFile.canRead()) if(!configFile.exists() || !configFile.canRead())
{ {
@ -155,316 +136,604 @@ public class Config
configFile.renameTo(new File(TurnBasedMinecraftMod.CONFIG_DIRECTORY configFile.renameTo(new File(TurnBasedMinecraftMod.CONFIG_DIRECTORY
+ "TBM_Config_" + "TBM_Config_"
+ DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(LocalDateTime.now()) + DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(LocalDateTime.now())
+ ".xml")); + ".toml"));
} }
} }
private boolean parseConfig(File configFile) throws XMLStreamException, FactoryConfigurationError, IOException private boolean parseConfig(File configFile) throws IOException
{ {
FileInputStream fis = new FileInputStream(configFile); TomlParseResult parseResult = Toml.parse(configFile.toPath(), TomlVersion.V0_5_0);
XMLStreamReader xmlReader = XMLInputFactory.newInstance().createXMLStreamReader(fis);
while(xmlReader.hasNext()) // client_config
{ {
xmlReader.next(); TomlArray battleMusicCategories = parseResult.getArray("client_config.battle_music");
if(xmlReader.isStartElement()) if(battleMusicCategories != null)
{ {
if(xmlReader.getLocalName().equals("TurnBasedMinecraftConfig")) for (int i = 0; i < battleMusicCategories.size(); ++i)
{ {
continue; musicBattleTypes.add(battleMusicCategories.getString(i));
} }
else if(xmlReader.getLocalName().equals("Version"))
{
continue;
} }
else if(xmlReader.getLocalName().equals("LeaveBattleCooldown")) else
{ {
leaveBattleCooldownSeconds = Integer.parseInt(xmlReader.getElementText()); musicBattleTypes.add("monster");
if(leaveBattleCooldownSeconds <= 0) musicBattleTypes.add("animal");
musicBattleTypes.add("boss");
musicBattleTypes.add("player");
logNotFound("client_config.battle_music");
}
}
{
TomlArray sillyMusicCategories = parseResult.getArray("client_config.silly_music");
if(sillyMusicCategories != null)
{
for (int i = 0; i < sillyMusicCategories.size(); ++i)
{
musicSillyTypes.add(sillyMusicCategories.getString(i));
}
}
else
{
musicSillyTypes.add("passive");
logNotFound("client_config.silly_music");
}
}
try
{
sillyMusicThreshold = parseResult.getLong("client_config.silly_music_threshold").intValue();
}
catch (NullPointerException e)
{
sillyMusicThreshold = 40;
logNotFound("client_config.silly_music_threshold", "40");
}
// server_config
try
{
leaveBattleCooldownSeconds = parseResult.getLong("server_config.leave_battle_cooldown").intValue();
if (leaveBattleCooldownSeconds < 1)
{ {
leaveBattleCooldownSeconds = 1; leaveBattleCooldownSeconds = 1;
} } else if (leaveBattleCooldownSeconds > 10)
else if(leaveBattleCooldownSeconds > 10)
{ {
leaveBattleCooldownSeconds = 10; leaveBattleCooldownSeconds = 10;
} }
} }
else if(xmlReader.getLocalName().equals("AggroStartBattleDistance")) catch (NullPointerException e)
{ {
aggroStartBattleDistance = Integer.parseInt(xmlReader.getElementText()); leaveBattleCooldownSeconds = 5;
logNotFound("server_config.leave_battle_cooldown", "5");
}
try
{
aggroStartBattleDistance = parseResult.getLong("server_config.aggro_start_battle_max_distance").intValue();
if (aggroStartBattleDistance < 5) if (aggroStartBattleDistance < 5)
{ {
aggroStartBattleDistance = 5; aggroStartBattleDistance = 5;
} } else if (aggroStartBattleDistance > 50)
else if(aggroStartBattleDistance > 50)
{ {
aggroStartBattleDistance = 50; aggroStartBattleDistance = 50;
} }
} }
else if(xmlReader.getLocalName().equals("OldBattleBehavior")) catch (NullPointerException e)
{ {
if(xmlReader.getElementText().toLowerCase().equals("false")) aggroStartBattleDistance = 8;
logNotFound("server_config.aggro_start_battle_max_distance", "8");
}
try
{
oldBattleBehaviorEnabled = parseResult.getBoolean("server_config.old_battle_behavior");
}
catch (NullPointerException e)
{ {
oldBattleBehaviorEnabled = false; oldBattleBehaviorEnabled = false;
logNotFound("server_config.old_battle_behavior", "false");
} }
else
try
{ {
oldBattleBehaviorEnabled = true; onlyOPsSelfDisableTB = !parseResult.getBoolean("server_config.anyone_can_disable_tbm_for_self");
} }
} catch (NullPointerException e)
else if(xmlReader.getLocalName().equals("WhoCanDisableTurnBasedForSelf"))
{
if(xmlReader.getElementText().toLowerCase().equals("any"))
{
onlyOPsSelfDisableTB = false;
}
else
{ {
onlyOPsSelfDisableTB = true; onlyOPsSelfDisableTB = true;
logNotFound("server_config.anyone_can_disable_tbm_for_self", "false");
}
try
{
maxInBattle = parseResult.getLong("server_config.max_in_battle").intValue();
if (maxInBattle < 2)
{
maxInBattle = 2;
} }
} }
else if(xmlReader.getLocalName().equals("MaxInBattle")) catch (NullPointerException e)
{ {
maxInBattle = Integer.parseInt(xmlReader.getElementText()); maxInBattle = 8;
logNotFound("server_config.max_in_battle", "8");
} }
else if(xmlReader.getLocalName().equals("FreezeBattleCombatants"))
try
{ {
freezeCombatantsInBattle = !xmlReader.getElementText().toLowerCase().equals("false"); freezeCombatantsInBattle = parseResult.getBoolean("server_config.freeze_battle_combatants");
} }
else if(xmlReader.getLocalName().equals("IgnoreBattleTypes")) catch (NullPointerException e)
{ {
do freezeCombatantsInBattle = false;
{ logNotFound("server_config.freeze_battle_combatants", "false");
xmlReader.next();
if(xmlReader.isStartElement())
{
ignoreBattleTypes.add(xmlReader.getLocalName().toLowerCase());
} }
} while(!(xmlReader.isEndElement() && xmlReader.getLocalName().equals("IgnoreBattleTypes")));
} try
else if(xmlReader.getLocalName().equals("BattleMusic"))
{ {
do TomlArray ignoreTypes = parseResult.getArray("server_config.ignore_battle_types");
for(int i = 0; i < ignoreTypes.size(); ++i)
{ {
xmlReader.next(); ignoreBattleTypes.add(ignoreTypes.getString(i));
if(xmlReader.isStartElement())
{
if(xmlReader.getLocalName().equals("Normal"))
{
do
{
xmlReader.next();
if(xmlReader.isStartElement())
{
musicBattleTypes.add(xmlReader.getLocalName().toLowerCase());
}
} while(!(xmlReader.isEndElement() && xmlReader.getLocalName().equals("Normal")));
}
else if(xmlReader.getLocalName().equals("Silly"))
{
do
{
xmlReader.next();
if(xmlReader.isStartElement())
{
musicSillyTypes.add(xmlReader.getLocalName().toLowerCase());
}
} while(!(xmlReader.isEndElement() && xmlReader.getLocalName().equals("Silly")));
} }
} }
} while(!(xmlReader.isEndElement() && xmlReader.getLocalName().equals("BattleMusic"))); catch (NullPointerException e)
{
ignoreBattleTypes.add("passive");
ignoreBattleTypes.add("boss");
logNotFound("server_config.ignore_battle_types");
} }
else if(xmlReader.getLocalName().equals("PlayerStats"))
try
{ {
do playerSpeed = parseResult.getLong("server_config.player_speed").intValue();
{
xmlReader.next();
if(xmlReader.isStartElement())
{
if(xmlReader.getLocalName().equals("Speed"))
{
playerSpeed = Integer.parseInt(xmlReader.getElementText());
} }
else if(xmlReader.getLocalName().equals("HasteSpeed")) catch (NullPointerException e)
{ {
playerHasteSpeed = Integer.parseInt(xmlReader.getElementText()); playerSpeed = 50;
logNotFound("server_config.player_speed", "50");
} }
else if(xmlReader.getLocalName().equals("SlowSpeed")) try
{ {
playerSlowSpeed = Integer.parseInt(xmlReader.getElementText()); playerHasteSpeed = parseResult.getLong("server_config.player_haste_speed").intValue();
} }
else if(xmlReader.getLocalName().equals("AttackProbability")) catch (NullPointerException e)
{ {
playerAttackProbability = Integer.parseInt(xmlReader.getElementText()); playerHasteSpeed = 80;
logNotFound("server_config.player_haste_speed", "80");
} }
else if(xmlReader.getLocalName().equals("Evasion")) try
{ {
playerEvasion = Integer.parseInt(xmlReader.getElementText()); playerSlowSpeed = parseResult.getLong("server_config.player_slow_speed").intValue();
} }
} catch (NullPointerException e)
} while(!(xmlReader.isEndElement() && xmlReader.getLocalName().equals("PlayerStats")));
}
else if(xmlReader.getLocalName().equals("DefenseDuration"))
{ {
defenseDuration = Integer.parseInt(xmlReader.getElementText()); playerSlowSpeed = 20;
logNotFound("server_config.player_slow_speed", "20");
} }
else if(xmlReader.getLocalName().equals("FleeGoodProbability")) try
{ {
fleeGoodProbability = Integer.parseInt(xmlReader.getElementText()); playerAttackProbability = parseResult.getLong("server_config.player_attack_probability").intValue();
} }
else if(xmlReader.getLocalName().equals("FleeBadProbability")) catch (NullPointerException e)
{ {
fleeBadProbability = Integer.parseInt(xmlReader.getElementText()); playerAttackProbability = 90;
logNotFound("server_config.player_attack_probability", "90");
} }
else if(xmlReader.getLocalName().equals("MinimumHitPercentage")) try
{ {
minimumHitPercentage = Integer.parseInt(xmlReader.getElementText()); playerEvasion = parseResult.getLong("server_config.player_evasion").intValue();
}
catch (NullPointerException e)
{
playerEvasion = 10;
logNotFound("server_config.player_evasion", "10");
}
try
{
defenseDuration = parseResult.getLong("server_config.defense_duration").intValue();
}
catch (NullPointerException e)
{
defenseDuration = 1;
logNotFound("server_config.defense_duration", "1");
}
try
{
fleeGoodProbability = parseResult.getLong("server_config.flee_good_probability").intValue();
}
catch (NullPointerException e)
{
fleeGoodProbability = 90;
logNotFound("server_config.flee_good_probability", "90");
}
try
{
fleeBadProbability = parseResult.getLong("server_config.flee_bad_probability").intValue();
}
catch (NullPointerException e)
{
fleeBadProbability = 35;
logNotFound("server_config.flee_bad_probability", "35");
}
try
{
minimumHitPercentage = parseResult.getLong("server_config.minimum_hit_percentage").intValue();
if (minimumHitPercentage < 1) if (minimumHitPercentage < 1)
{ {
minimumHitPercentage = 1; minimumHitPercentage = 1;
} }
} }
else if(xmlReader.getLocalName().equals("BattleTurnTimeSeconds")) catch (NullPointerException e)
{ {
minimumHitPercentage = 4;
logNotFound("server_config.minimum_hit_percentage", "4");
}
try try
{ {
int seconds = Integer.parseInt(xmlReader.getElementText()); battleDecisionDurationNanos = parseResult.getLong("server_config.battle_turn_time_seconds") * 1000000000L;
battleDecisionDurationNanos = (long)(seconds) * 1000000000L;
if(battleDecisionDurationNanos < BATTLE_DECISION_DURATION_NANO_MIN) if(battleDecisionDurationNanos < BATTLE_DECISION_DURATION_NANO_MIN)
{ {
battleDecisionDurationNanos = BATTLE_DECISION_DURATION_NANO_MIN; battleDecisionDurationNanos = BATTLE_DECISION_DURATION_NANO_MIN;
logger.warn("Config \"server_config.battle_turn_time_seconds\" too low, defaulting to minimum \"5\"");
} }
else if(battleDecisionDurationNanos > BATTLE_DECISION_DURATION_NANO_MAX) else if(battleDecisionDurationNanos > BATTLE_DECISION_DURATION_NANO_MAX)
{ {
battleDecisionDurationNanos = BATTLE_DECISION_DURATION_NANO_MAX; battleDecisionDurationNanos = BATTLE_DECISION_DURATION_NANO_MAX;
logger.warn("Config \"server_config.battle_turn_time_seconds\" too high, defaulting to maximum \"60\"");
} }
} catch (Throwable t) }
catch (NullPointerException e)
{ {
logger.warn("Unable to get value for \"BattleTurnTimeSeconds\" from config, using default");
battleDecisionDurationNanos = BATTLE_DECISION_DURATION_NANO_DEFAULT; battleDecisionDurationNanos = BATTLE_DECISION_DURATION_NANO_DEFAULT;
logNotFound("server_config.battle_turn_time_seconds", "15");
} }
}
else if(xmlReader.getLocalName().equals("SillyMusicThreshold")) // entities
TomlArray entityArray = parseResult.getArray("server_config.entity");
if(entityArray != null)
{ {
sillyMusicThreshold = Integer.parseInt(xmlReader.getElementText()); for(int i = 0; i < entityArray.size(); ++i)
if(sillyMusicThreshold < 0)
{
sillyMusicThreshold = 0;
}
else if(sillyMusicThreshold > 100)
{
sillyMusicThreshold = 100;
}
}
else if(xmlReader.getLocalName().equals("EntityEntry"))
{ {
TomlTable entity = entityArray.getTable(i);
EntityInfo eInfo = new EntityInfo(); EntityInfo eInfo = new EntityInfo();
do
{
xmlReader.next();
if(xmlReader.isStartElement())
{
if(xmlReader.getLocalName().equals("Name"))
{
try try
{ {
eInfo.classType = Class.forName(xmlReader.getElementText()); eInfo.classType = Class.forName(entity.getString("name"));
} catch (ClassNotFoundException e) }
catch (ClassNotFoundException e)
{ {
logger.error("Failed to get class of name " + xmlReader.getElementText()); logger.error("Entity with class name \"" + entity.getString("name") + "\" not found, skipping...");
continue;
}
catch (NullPointerException e)
{
logger.error("Entity does not have \"name\", skipping...");
continue;
}
try
{
eInfo.attackPower = entity.getLong("attack_power").intValue();
if(eInfo.attackPower < 0)
{
eInfo.attackPower = 0;
logEntityInvalidValue("attack_power", eInfo.classType.getName(), "0");
} }
} }
else if(xmlReader.getLocalName().equals("AttackPower")) catch (NullPointerException e)
{ {
for(int i = 0; i < xmlReader.getAttributeCount(); ++i) logEntityMissingRequiredValue("attack_power", eInfo.classType.getName());
{ continue;
if(xmlReader.getAttributeLocalName(i).equals("Probability"))
{
eInfo.attackProbability = Integer.parseInt(xmlReader.getAttributeValue(i));
} }
else if(xmlReader.getAttributeLocalName(i).equals("Variance"))
try
{ {
eInfo.attackVariance = Integer.parseInt(xmlReader.getAttributeValue(i)); eInfo.attackProbability = entity.getLong("attack_probability").intValue();
if(eInfo.attackProbability < 0 || eInfo.attackProbability > 100)
{
eInfo.attackProbability = 35;
logEntityInvalidValue("attack_probability", eInfo.classType.getName(), "35");
} }
} }
eInfo.attackPower = Integer.parseInt(xmlReader.getElementText()); catch (NullPointerException e)
{
logEntityMissingRequiredValue("attack_probability", eInfo.classType.getName());
continue;
} }
else if(xmlReader.getLocalName().equals("AttackEffect"))
try
{ {
for(int i = 0; i < xmlReader.getAttributeCount(); ++i) eInfo.attackEffect = EntityInfo.Effect.fromString(entity.getString("attack_effect"));
if(eInfo.attackEffect != EntityInfo.Effect.UNKNOWN)
{ {
if(xmlReader.getAttributeLocalName(i).equals("Probability")) eInfo.attackEffectProbability = entity.getLong("attack_effect_probability").intValue();
if(eInfo.attackEffectProbability < 0 || eInfo.attackEffectProbability > 100)
{ {
eInfo.attackEffectProbability = Integer.parseInt(xmlReader.getAttributeValue(i)); eInfo.attackEffectProbability = 35;
logEntityInvalidValue("attack_effect", eInfo.classType.getName(), "35");
} }
} }
eInfo.attackEffect = EntityInfo.Effect.fromString(xmlReader.getElementText());
} }
else if(xmlReader.getLocalName().equals("Evasion")) catch (NullPointerException e)
{ {
eInfo.evasion = Integer.parseInt(xmlReader.getElementText()); eInfo.attackEffect = EntityInfo.Effect.UNKNOWN;
} }
else if(xmlReader.getLocalName().equals("DefenseDamage"))
try
{ {
for(int i = 0; i < xmlReader.getAttributeCount(); ++i) eInfo.attackVariance = entity.getLong("attack_variance").intValue();
if(eInfo.attackVariance < 0)
{ {
if(xmlReader.getAttributeLocalName(i).equals("Probability")) eInfo.attackVariance = 0;
{ logEntityInvalidValue("attack_variance", eInfo.classType.getName(), "0");
eInfo.defenseDamageProbability = Integer.parseInt(xmlReader.getAttributeValue(i));
} }
} }
eInfo.defenseDamage = Integer.parseInt(xmlReader.getElementText()); catch (NullPointerException e)
{
eInfo.attackVariance = 0;
} }
else if(xmlReader.getLocalName().equals("Category"))
try
{ {
eInfo.category = xmlReader.getElementText().toLowerCase(); eInfo.defenseDamage = entity.getLong("defense_damage").intValue();
if(eInfo.defenseDamage < 0)
{
eInfo.defenseDamage = 0;
logEntityInvalidValue("defense_damage", eInfo.classType.getName(), "0");
} }
else if(xmlReader.getLocalName().equals("IgnoreBattle")) else
{ {
if(xmlReader.getElementText().toLowerCase().equals("true")) eInfo.defenseDamageProbability = entity.getLong("defense_damage_probability").intValue();
if(eInfo.defenseDamageProbability < 0 || eInfo.defenseDamageProbability > 100)
{ {
eInfo.ignoreBattle = true; eInfo.defenseDamageProbability = 35;
logEntityInvalidValue("defense_damage_probability", eInfo.classType.getName(), "35");
} }
} }
else if(xmlReader.getLocalName().equals("Speed"))
{
eInfo.speed = Integer.parseInt(xmlReader.getElementText());
} }
else if(xmlReader.getLocalName().equals("Decision")) catch (NullPointerException e)
{ {
do eInfo.defenseDamage = 0;
{
xmlReader.next();
if(xmlReader.isStartElement())
{
if(xmlReader.getLocalName().equals("Attack"))
{
eInfo.decisionAttack = Integer.parseInt(xmlReader.getElementText());
} }
else if(xmlReader.getLocalName().equals("Defend"))
try
{ {
eInfo.decisionDefend = Integer.parseInt(xmlReader.getElementText()); eInfo.evasion = entity.getLong("evasion").intValue();
} if(eInfo.evasion < 0 || eInfo.evasion > 100)
else if(xmlReader.getLocalName().equals("Flee"))
{ {
eInfo.decisionFlee = Integer.parseInt(xmlReader.getElementText()); eInfo.evasion = 20;
logEntityInvalidValue("evasion", eInfo.classType.getName(), "20");
} }
} }
} while(!(xmlReader.isEndElement() && xmlReader.getLocalName().equals("Decision"))); catch (NullPointerException e)
}
}
} while(!(xmlReader.isEndElement() && xmlReader.getLocalName().equals("EntityEntry")));
if(eInfo.classType != null)
{ {
logEntityMissingRequiredValue("evasion", eInfo.classType.getName());
continue;
}
try
{
eInfo.speed = entity.getLong("speed").intValue();
}
catch (NullPointerException e)
{
logEntityMissingRequiredValue("speed", eInfo.classType.getName());
}
try
{
eInfo.ignoreBattle = entity.getBoolean("ignore_battle");
}
catch (NullPointerException e)
{
eInfo.ignoreBattle = false;
}
eInfo.category = entity.getString("category");
if(eInfo.category == null)
{
logEntityMissingRequiredValue("category", eInfo.classType.getName());
continue;
}
try
{
eInfo.decisionAttack = entity.getLong("decision_attack_probability").intValue();
}
catch (NullPointerException e)
{
logEntityMissingRequiredValue("decision_attack_probability", eInfo.classType.getName());
continue;
}
try
{
eInfo.decisionDefend = entity.getLong("decision_defend_probability").intValue();
}
catch (NullPointerException e)
{
logEntityMissingRequiredValue("decision_defend_probability", eInfo.classType.getName());
continue;
}
try
{
eInfo.decisionFlee = entity.getLong("decision_flee_probability").intValue();
}
catch (NullPointerException e)
{
logEntityMissingRequiredValue("decision_flee_probability", eInfo.classType.getName());
continue;
}
entityInfoMap.put(eInfo.classType.getName(), eInfo); entityInfoMap.put(eInfo.classType.getName(), eInfo);
} }
} }
}
}
xmlReader.close();
fis.close();
return true; return true;
} }
private void logNotFound(String option)
{
logger.warn("Config option \"" + option + "\" not found, setting defaults");
}
private void logNotFound(String option, String defaultValue)
{
logger.warn("Config option \"" + option + "\" not found, defaulting to \"" + defaultValue + "\"");
}
private void logEntityInvalidValue(String option, String name, String defaultValue)
{
logger.warn("Invalid \"" + option + "\" for \"" + name + "\", defaulting to " + defaultValue);
}
private void logEntityMissingRequiredValue(String option, String name)
{
logger.error("Entity \"" + name + "\" does not have option \"" + option + "\", skipping...");
}
private String getRegexEntityName(String name)
{
String regex = "^\\s*name\\s*=\\s*";
regex += "(\"" + name + "\"";
regex += "|'" + name + "')";
return regex;
}
private boolean addEntityEntry(EntityInfo eInfo)
{
try
{
File config = new File(TurnBasedMinecraftMod.CONFIG_FILE_PATH);
FileWriter fw = new FileWriter(config, true);
fw.write("[[server_config.entity]]\n");
fw.write("name = \"" + eInfo.classType.getName() + "\"\n");
fw.write("attack_power = " + eInfo.attackPower + "\n");
fw.write("attack_probability = " + eInfo.attackProbability + "\n");
if(eInfo.attackVariance > 0)
{
fw.write("attack_variance = " + eInfo.attackVariance + "\n");
}
if(eInfo.attackEffect != EntityInfo.Effect.UNKNOWN && eInfo.attackEffectProbability > 0)
{
fw.write("attack_effect = \"" + eInfo.attackEffect.toString() + "\"\n");
fw.write("attack_effect_probability = " + eInfo.attackEffectProbability + "\n");
}
if(eInfo.defenseDamage > 0 && eInfo.defenseDamageProbability > 0)
{
fw.write("defense_damage = " + eInfo.defenseDamage + "\n");
fw.write("defense_damage_probability = " + eInfo.defenseDamageProbability + "\n");
}
fw.write("evasion = " + eInfo.evasion + "\n");
fw.write("speed = " + eInfo.speed + "\n");
if(eInfo.ignoreBattle)
{
fw.write("ignoreBattle = true\n");
}
fw.write("category = \"" + eInfo.category + "\"\n");
fw.write("decision_attack_probability = " + eInfo.decisionAttack + "\n");
fw.write("decision_defend_probability = " + eInfo.decisionDefend + "\n");
fw.write("decision_flee_probability = " + eInfo.decisionFlee + "\n");
fw.close();
entityInfoMap.put(eInfo.classType.getName(), eInfo);
}
catch (Throwable t)
{
logger.error("Failed to add entity entry (name = \"" + eInfo.classType.getName() + "\")");
return false;
}
return true;
}
protected boolean editEntityEntry(EntityInfo eInfo)
{
try
{
String cached = new String();
char buf[] = new char[1024];
int read = 0;
File config = new File(TurnBasedMinecraftMod.CONFIG_FILE_PATH);
{
FileReader fr = new FileReader(config);
read = fr.read(buf);
while (read != -1)
{
cached += String.valueOf(buf, 0, read);
read = fr.read(buf);
}
fr.close();
}
int nameIndex = -1;
{
Pattern p = Pattern.compile(getRegexEntityName(eInfo.classType.getName()), Pattern.MULTILINE);
Matcher m = p.matcher(cached);
if(m.find())
{
nameIndex = m.start();
}
}
int entryIndex = -1;
int nextIndex = -1;
if(nameIndex != -1)
{
{
Pattern p = Pattern.compile("^\\s*\\[\\[\\s*server_config\\s*\\.\\s*entity\\s*]]", Pattern.MULTILINE);
Matcher m = p.matcher(cached.substring(0, nameIndex));
while(m.find())
{
entryIndex = m.start();
}
if(entryIndex == -1)
{
logger.warn("editEntityEntry: could not find header for entry \"" + eInfo.classType.getName() + "\", skipping to adding it...");
return addEntityEntry(eInfo);
}
}
{
Pattern p = Pattern.compile("^\\s*\\[", Pattern.MULTILINE);
Matcher m = p.matcher(cached.substring(nameIndex));
if(m.find())
{
nextIndex = m.start() + nameIndex;
}
}
}
else
{
logger.warn("editEntityEntry: could not find entry for \"" + eInfo.classType.getName() + "\", skipping to adding it...");
return addEntityEntry(eInfo);
}
String cut = null;
if(nextIndex != -1)
{
cut = cached.substring(0, entryIndex) + cached.substring(nextIndex);
}
else
{
cut = cached.substring(0, entryIndex);
}
{
FileWriter fw = new FileWriter(config);
fw.write(cut);
fw.close();
}
return addEntityEntry(eInfo);
}
catch (Throwable t)
{
return false;
}
}
public int getPlayerSpeed() public int getPlayerSpeed()
{ {
return playerSpeed; return playerSpeed;
@ -534,40 +803,34 @@ public class Config
return null; return null;
} }
private int getConfigFileVersion(InputStream io)
{
int version = 0;
try
{
TomlParseResult result = Toml.parse(io, TomlVersion.V0_5_0);
version = result.getLong("version").intValue();
}
catch (Throwable t)
{
// ignored
}
return version;
}
private int getConfigFileVersion(File configFile) private int getConfigFileVersion(File configFile)
{ {
int version = 0;
try try
{ {
return getConfigFileVersion(new FileInputStream(configFile)); TomlParseResult result = Toml.parse(configFile.toPath(), TomlVersion.V0_5_0);
} catch(FileNotFoundException e) version = result.getLong("version").intValue();
{
return 0;
} }
catch (Throwable t)
{
// ignored
} }
return version;
private int getConfigFileVersion(InputStream configStream)
{
int configVersion = 1;
try
{
XMLStreamReader xmlReader = XMLInputFactory.newInstance().createXMLStreamReader(configStream);
while(xmlReader.hasNext())
{
xmlReader.next();
if(xmlReader.isStartElement() && xmlReader.getLocalName().equals("Version"))
{
configVersion = Integer.parseInt(xmlReader.getElementText());
break;
}
}
xmlReader.close();
} catch (Throwable t)
{
return 0;
}
return configVersion;
} }
public boolean isIgnoreBattleType(String type) public boolean isIgnoreBattleType(String type)

View file

@ -160,6 +160,65 @@ public class EntityInfo
} }
} }
public String toString()
{
switch(this)
{
case SPEED:
return "speed";
case SLOW:
return "slow";
case HASTE:
return "haste";
case MINING_FATIGUE:
return "mining_fatigue";
case STRENGTH:
return "strength";
case JUMP_BOOST:
return "jump_boost";
case NAUSEA:
return "nausea";
case REGENERATION:
return "regeneration";
case RESISTANCE:
return "resistance";
case FIRE_RESISTANCE:
return "fire_resistance";
case WATER_BREATHING:
return "water_breathing";
case INVISIBILITY:
return "invisibility";
case BLINDNESS:
return "blindness";
case NIGHT_VISION:
return "night_vision";
case HUNGER:
return "hunger";
case WEAKNESS:
return "weakness";
case POISON:
return "poison";
case WITHER:
return "wither";
case ABSORPTION:
return "absorption";
case SATURATION:
return "saturation";
case GLOWING:
return "glowing";
case LEVITATION:
return "levitation";
case LUCK:
return "luck";
case UNLUCK:
return "unluck";
case FIRE:
return "fire";
default:
return "unknown";
}
}
public PotionEffect getPotionEffect() public PotionEffect getPotionEffect()
{ {
return getPotionEffect(20 * 7, 0); return getPotionEffect(20 * 7, 0);

View file

@ -9,7 +9,7 @@ public class PlayerJoinEventHandler
@SubscribeEvent @SubscribeEvent
public void entityJoinHandler(EntityJoinWorldEvent event) public void entityJoinHandler(EntityJoinWorldEvent event)
{ {
if(event.getEntity().world.isRemote) if(event.getWorld().isRemote)
{ {
return; return;
} }

View file

@ -26,8 +26,8 @@ public class TurnBasedMinecraftMod
{ {
public static final String MODID = "com.seodisparate.turnbasedminecraft"; public static final String MODID = "com.seodisparate.turnbasedminecraft";
public static final String NAME = "Turn Based Minecraft Mod"; public static final String NAME = "Turn Based Minecraft Mod";
public static final String VERSION = "1.5"; public static final String VERSION = "1.6";
public static final String CONFIG_FILENAME = "TBM_Config.xml"; public static final String CONFIG_FILENAME = "TBM_Config.toml";
public static final String CONFIG_DIRECTORY = "config/TurnBasedMinecraft/"; public static final String CONFIG_DIRECTORY = "config/TurnBasedMinecraft/";
public static final String CONFIG_FILE_PATH = CONFIG_DIRECTORY + CONFIG_FILENAME; public static final String CONFIG_FILE_PATH = CONFIG_DIRECTORY + CONFIG_FILENAME;
public static final String CONFIG_INTERNAL_PATH = "/assets/TurnBasedMinecraft/" + CONFIG_FILENAME; public static final String CONFIG_INTERNAL_PATH = "/assets/TurnBasedMinecraft/" + CONFIG_FILENAME;

View file

@ -0,0 +1,636 @@
# Please do not change this option, the mod uses this to keep track of what new
# changes to add to the config.
version = 1
[client_config]
# determines what categories use what type of music.
# Unknown categories sent by the server will default to "battle_music".
battle_music = ["monster", "animal", "boss", "player"]
silly_music = ["passive"]
# Minimum percentage of silly entities in battle to use silly music.
silly_music_threshold = 40
[server_config]
# Number of seconds that an entity cannot enter battle after having just left
# one. Minimum 1, maximum 10.
leave_battle_cooldown = 5
# Maximum distance for a monster to start battle by targeting a player or other
# entity in turn-based-battle. Minimum 5, maximum 50.
aggro_start_battle_max_distance = 8
# If true, only initiate battle on attack. If false, monsters targeting players
# also trigger battle.
old_battle_behavior = false
# If true, any player can disable/enable turn-based-battle for themselves with
# the commands "/tbm-enable" and "/tbm-disable".
anyone_can_disable_tbm_for_self = false
# Maximum amount of entities in one battle. If max is reached, no more entities
# will be added to battle until there are less than max entities.
max_in_battle = 8
# If true, all entities in battle will be frozen in place
freeze_battle_combatants = false
# Entity categories that will not initiate battle.
ignore_battle_types = ["passive", "boss"]
# Stats that apply to all players
player_speed = 50
player_haste_speed = 80
player_slow_speed = 20
player_attack_probability = 90
player_evasion = 10
# Number of attacks that a "defend" move will block
defense_duration = 1
# If speed is greater than fastest speed of entity on opposing side, good
# probability is used.
flee_good_probability = 90
flee_bad_probability = 40
# Minimum hit percentage for everyone. If option is set to less than 1,
# config will assume option of "1" anyway.
minimum_hit_percentage = 4
# Number of seconds to wait in battle for all players to make a decision.
# Minimum 5, maximum 60.
battle_turn_time_seconds = 15
# Each "server_config.entity" entry uses the following options:
# name: full class name of the entity
# attack_power: how much damage an entity does on successful attack
# attack_probability: percentage of attack success. (Usually calculated with enemy's evasion to determine actual percentage)
# attack_variance (optional): determines how much a successful attack's damage varies.
# attack_effect (optional): applies effect on hit success
# attack_effect_probability (optional): percentage of attack_effect being applied on hit success.
# defense_damage (optional): damage dealt to attacker when hit.
# defense_damage_probability (optional): percentage of defense_damage being applied on received hit.
# evasion: percentage of evading hit.
# speed: used to determine turn-order, and flee success rates.
# ignore_battle (optional): per-entity setting that causes that entity to not enter turn-based-battle.
# category: Determines type of entity. Used for server config for what groups do not enter turn-based-battle, and for client config for determining what type of battle music to play.
# decision_attack_probability: Percentage of entity choosing to attack on turn.
# decision_defend_probability: Percentage of entity choosing to defend on turn.
# decision_flee_probability: Percentage of entity choosing to flee on turn.
[[server_config.entity]]
name = "net.minecraft.entity.monster.EntityBlaze"
attack_power = 5
attack_probability = 50
attack_effect = "fire"
attack_effect_probability = 75
evasion = 5
category = "monster"
speed = 45
decision_attack_probability = 100
decision_defend_probability = 0
decision_flee_probability = 0
[[server_config.entity]]
name = "net.minecraft.entity.monster.EntityCaveSpider"
attack_power = 2
attack_probability = 75
attack_effect = "poison"
attack_effect_probability = 90
evasion = 35
category = "monster"
speed = 75
decision_attack_probability = 100
decision_defend_probability = 0
decision_flee_probability = 0
[[server_config.entity]]
name = "net.minecraft.entity.monster.EntityCreeper"
ignore_battle = true
attack_power = 15
attack_probability = 17
attack_variance = 7
evasion = 5
category = "monster"
speed = 25
decision_attack_probability = 100
decision_defend_probability = 0
decision_flee_probability = 0
[[server_config.entity]]
name = "net.minecraft.entity.monster.EntityElderGuardian"
attack_power = 8
attack_probability = 65
defense_damage = 2
defense_damage_probability = 35
evasion = 25
category = "monster"
speed = 45
decision_attack_probability = 80
decision_defend_probability = 20
decision_flee_probability = 0
[[server_config.entity]]
name = "net.minecraft.entity.monster.EntityEnderman"
attack_power = 7
attack_probability = 80
evasion = 40
category = "monster"
speed = 70
decision_attack_probability = 100
decision_defend_probability = 0
decision_flee_probability = 0
[[server_config.entity]]
name = "net.minecraft.entity.monster.EntityEndermite"
attack_power = 2
attack_probability = 80
evasion = 40
category = "monster"
speed = 35
decision_attack_probability = 100
decision_defend_probability = 0
decision_flee_probability = 0
[[server_config.entity]]
name = "net.minecraft.entity.monster.EntityEvoker"
attack_power = 6
attack_probability = 60
evasion = 35
category = "monster"
speed = 35
decision_attack_probability = 100
decision_defend_probability = 0
decision_flee_probability = 0
[[server_config.entity]]
name = "net.minecraft.entity.monster.EntityGhast"
ignore_battle = true
attack_power = 13
attack_probability = 20
evasion = 35
category = "monster"
speed = 60
decision_attack_probability = 75
decision_defend_probability = 0
decision_flee_probability = 25
[[server_config.entity]]
name = "net.minecraft.entity.monster.EntityGiantZombie"
attack_power = 11
attack_probability = 35
evasion = 2
category = "monster"
speed = 45
decision_attack_probability = 100
decision_defend_probability = 0
decision_flee_probability = 0
[[server_config.entity]]
name = "net.minecraft.entity.monster.EntityGuardian"
attack_power = 6
attack_probability = 55
defense_damage = 2
defense_damage_probability = 30
evasion = 25
category = "monster"
speed = 50
decision_attack_probability = 80
decision_defend_probability = 20
decision_flee_probability = 0
[[server_config.entity]]
name = "net.minecraft.entity.monster.EntityHusk"
attack_power = 3
attack_probability = 70
attack_effect = "hunger"
attack_effect_probability = 95
evasion = 5
category = "monster"
speed = 25
decision_attack_probability = 100
decision_defend_probability = 0
decision_flee_probability = 0
[[server_config.entity]]
name = "net.minecraft.entity.monster.EntityIronGolem"
attack_power = 14
attack_probability = 85
attack_variance = 7
evasion = 5
category = "monster"
speed = 45
decision_attack_probability = 100
decision_defend_probability = 0
decision_flee_probability = 0
[[server_config.entity]]
name = "net.minecraft.entity.monster.EntityMagmaCube"
attack_power = 3
attack_probability = 35
evasion = 12
category = "monster"
speed = 35
decision_attack_probability = 100
decision_defend_probability = 0
decision_flee_probability = 0
[[server_config.entity]]
name = "net.minecraft.entity.monster.EntityPigZombie"
attack_power = 8
attack_probability = 70
evasion = 10
category = "monster"
speed = 50
decision_attack_probability = 100
decision_defend_probability = 0
decision_flee_probability = 0
[[server_config.entity]]
name = "net.minecraft.entity.monster.EntityPolarBear"
attack_power = 6
attack_probability = 67
evasion = 5
category = "animal"
speed = 35
decision_attack_probability = 100
decision_defend_probability = 0
decision_flee_probability = 0
[[server_config.entity]]
name = "net.minecraft.entity.monster.EntityShulker"
attack_power = 4
attack_probability = 80
evasion = 15
category = "monster"
speed = 10
decision_attack_probability = 100
decision_defend_probability = 0
decision_flee_probability = 0
[[server_config.entity]]
name = "net.minecraft.entity.monster.EntitySilverfish"
attack_power = 1
attack_probability = 85
evasion = 37
category = "monster"
speed = 35
decision_attack_probability = 100
decision_defend_probability = 0
decision_flee_probability = 0
[[server_config.entity]]
name = "net.minecraft.entity.monster.EntitySkeleton"
attack_power = 3
attack_probability = 75
attack_variance = 1
evasion = 13
category = "monster"
speed = 30
decision_attack_probability = 100
decision_defend_probability = 0
decision_flee_probability = 0
[[server_config.entity]]
name = "net.minecraft.entity.monster.EntitySlime"
attack_power = 2
attack_probability = 35
evasion = 10
category = "monster"
speed = 30
decision_attack_probability = 100
decision_defend_probability = 0
decision_flee_probability = 0
[[server_config.entity]]
name = "net.minecraft.entity.monster.EntitySnowman"
attack_power = 0
attack_probability = 80
evasion = 5
category = "passive"
speed = 60
decision_attack_probability = 100
decision_defend_probability = 0
decision_flee_probability = 0
[[server_config.entity]]
name = "net.minecraft.entity.monster.EntitySpider"
attack_power = 2
attack_probability = 70
evasion = 25
category = "monster"
speed = 70
decision_attack_probability = 100
decision_defend_probability = 0
decision_flee_probability = 0
[[server_config.entity]]
name = "net.minecraft.entity.monster.EntityStray"
attack_power = 3
attack_probability = 75
attack_variance = 1
attack_effect = "slow"
attack_effect_probability = 90
evasion = 13
category = "monster"
speed = 30
decision_attack_probability = 100
decision_defend_probability = 0
decision_flee_probability = 0
[[server_config.entity]]
name = "net.minecraft.entity.monster.EntityVex"
attack_power = 9
attack_probability = 65
evasion = 30
category = "monster"
speed = 80
decision_attack_probability = 100
decision_defend_probability = 0
decision_flee_probability = 0
[[server_config.entity]]
name = "net.minecraft.entity.monster.EntityVindicator"
attack_power = 13
attack_probability = 70
evasion = 10
category = "monster"
speed = 35
decision_attack_probability = 100
decision_defend_probability = 0
decision_flee_probability = 0
[[server_config.entity]]
name = "net.minecraft.entity.monster.EntityWitch"
attack_power = 5
attack_probability = 75
attack_variance = 1
evasion = 8
category = "monster"
speed = 35
decision_attack_probability = 100
decision_defend_probability = 0
decision_flee_probability = 0
[[server_config.entity]]
name = "net.minecraft.entity.monster.EntityWitherSkeleton"
attack_power = 8
attack_probability = 70
attack_effect = "wither"
attack_effect_probability = 90
evasion = 7
category = "monster"
speed = 65
decision_attack_probability = 100
decision_defend_probability = 0
decision_flee_probability = 0
[[server_config.entity]]
name = "net.minecraft.entity.monster.EntityZombie"
attack_power = 3
attack_probability = 70
evasion = 5
category = "monster"
speed = 25
decision_attack_probability = 100
decision_defend_probability = 0
decision_flee_probability = 0
[[server_config.entity]]
name = "net.minecraft.entity.monster.EntityZombieVillager"
attack_power = 3
attack_probability = 70
evasion = 5
category = "monster"
speed = 25
decision_attack_probability = 100
decision_defend_probability = 0
decision_flee_probability = 0
[[server_config.entity]]
name = "net.minecraft.entity.passive.EntityBat"
attack_power = 0
attack_probability = 70
evasion = 35
category = "passive"
speed = 75
decision_attack_probability = 0
decision_defend_probability = 0
decision_flee_probability = 90
[[server_config.entity]]
name = "net.minecraft.entity.passive.EntityChicken"
attack_power = 0
attack_probability = 70
evasion = 10
category = "passive"
speed = 35
decision_attack_probability = 0
decision_defend_probability = 0
decision_flee_probability = 90
[[server_config.entity]]
name = "net.minecraft.entity.passive.EntityCow"
attack_power = 0
attack_probability = 50
evasion = 1
category = "passive"
speed = 20
decision_attack_probability = 0
decision_defend_probability = 10
decision_flee_probability = 80
[[server_config.entity]]
name = "net.minecraft.entity.passive.EntityDonkey"
attack_power = 0
attack_probability = 70
evasion = 10
category = "passive"
speed = 65
decision_attack_probability = 0
decision_defend_probability = 0
decision_flee_probability = 90
[[server_config.entity]]
name = "net.minecraft.entity.passive.EntityHorse"
attack_power = 0
attack_probability = 70
evasion = 10
category = "passive"
speed = 65
decision_attack_probability = 0
decision_defend_probability = 0
decision_flee_probability = 90
[[server_config.entity]]
name = "net.minecraft.entity.passive.EntityLlama"
attack_power = 1
attack_probability = 70
evasion = 10
category = "passive"
speed = 50
decision_attack_probability = 65
decision_defend_probability = 0
decision_flee_probability = 25
[[server_config.entity]]
name = "net.minecraft.entity.passive.EntityMooshroom"
attack_power = 0
attack_probability = 70
evasion = 1
category = "passive"
speed = 20
decision_attack_probability = 0
decision_defend_probability = 10
decision_flee_probability = 80
[[server_config.entity]]
name = "net.minecraft.entity.passive.EntityMule"
attack_power = 0
attack_probability = 70
evasion = 10
category = "passive"
speed = 50
decision_attack_probability = 0
decision_defend_probability = 0
decision_flee_probability = 90
[[server_config.entity]]
name = "net.minecraft.entity.passive.EntityOcelot"
attack_power = 1
attack_probability = 70
attack_variance = 1
evasion = 10
category = "passive"
speed = 75
decision_attack_probability = 0
decision_defend_probability = 0
decision_flee_probability = 90
[[server_config.entity]]
name = "net.minecraft.entity.passive.EntityParrot"
attack_power = 0
attack_probability = 70
evasion = 35
category = "passive"
speed = 70
decision_attack_probability = 0
decision_defend_probability = 0
decision_flee_probability = 90
[[server_config.entity]]
name = "net.minecraft.entity.passive.EntityPig"
attack_power = 0
attack_probability = 70
evasion = 10
category = "passive"
speed = 30
decision_attack_probability = 0
decision_defend_probability = 5
decision_flee_probability = 85
[[server_config.entity]]
name = "net.minecraft.entity.passive.EntityRabbit"
attack_power = 0
attack_probability = 70
evasion = 40
category = "passive"
speed = 75
decision_attack_probability = 0
decision_defend_probability = 0
decision_flee_probability = 100
[[server_config.entity]]
name = "net.minecraft.entity.passive.EntitySheep"
attack_power = 0
attack_probability = 70
evasion = 5
category = "passive"
speed = 30
decision_attack_probability = 0
decision_defend_probability = 0
decision_flee_probability = 90
[[server_config.entity]]
name = "net.minecraft.entity.passive.EntitySkeletonHorse"
attack_power = 0
attack_probability = 70
evasion = 5
category = "passive"
speed = 65
decision_attack_probability = 0
decision_defend_probability = 0
decision_flee_probability = 90
[[server_config.entity]]
name = "net.minecraft.entity.passive.EntitySquid"
attack_power = 0
attack_probability = 70
evasion = 15
category = "passive"
speed = 40
decision_attack_probability = 0
decision_defend_probability = 0
decision_flee_probability = 90
[[server_config.entity]]
name = "net.minecraft.entity.passive.EntityVillager"
attack_power = 0
attack_probability = 70
evasion = 5
category = "passive"
speed = 35
decision_attack_probability = 0
decision_defend_probability = 10
decision_flee_probability = 80
[[server_config.entity]]
name = "net.minecraft.entity.passive.EntityWolf"
attack_power = 4
attack_probability = 70
evasion = 20
category = "animal"
speed = 70
decision_attack_probability = 80
decision_defend_probability = 15
decision_flee_probability = 5
[[server_config.entity]]
name = "net.minecraft.entity.passive.EntityZombieHorse"
attack_power = 0
attack_probability = 70
evasion = 8
category = "passive"
speed = 65
decision_attack_probability = 0
decision_defend_probability = 0
decision_flee_probability = 90
[[server_config.entity]]
name = "net.minecraft.entity.boss.EntityDragon"
attack_power = 10
attack_probability = 70
attack_variance = 2
evasion = 27
category = "boss"
speed = 63
decision_attack_probability = 100
decision_defend_probability = 0
decision_flee_probability = 0
[[server_config.entity]]
name = "net.minecraft.entity.boss.EntityWither"
attack_power = 8
attack_probability = 70
attack_effect = "wither"
attack_effect_probability = 90
evasion = 20
category = "boss"
speed = 68
decision_attack_probability = 100
decision_defend_probability = 0
decision_flee_probability = 0

View file

@ -1,653 +0,0 @@
<TurnBasedMinecraftConfig>
<!-- If the mod has a newer version config, it will rename the existing config and place the new config -->
<Version>6</Version>
<!-- Number of seconds that an entity cannot enter battle after having just left one. Minimum 1, maximum 10-->
<LeaveBattleCooldown>5</LeaveBattleCooldown>
<!-- Maximum distance for a monster to start battle by targeting a player or other entity in turn-based-battle.
Minimum 5, maximum 50. -->
<AggroStartBattleDistance>8</AggroStartBattleDistance>
<!-- If not "false", uses old battle behavior where battles only start on attack/hit. Otherwise, battles can
start when a hostile mob targets a player or another entity in battle. -->
<OldBattleBehavior>false</OldBattleBehavior>
<!-- Determines who can disable turn-based-battle for themselves via command. Must be "op" or "any". If neither, defaults to "op"-->
<WhoCanDisableTurnBasedForSelf>op</WhoCanDisableTurnBasedForSelf>
<!-- If there are "MaxInBattle" amount of entities in battle, other entities cannot join until combatants leave battle. -->
<MaxInBattle>8</MaxInBattle>
<!-- If not set to "false", then when battle starts all combatants will remain in their starting position. -->
<FreezeBattleCombatants>false</FreezeBattleCombatants>
<!-- Types that will not initiate battle with player. They are listed as "Category" per EntiytStats entity.
Note that items listed in "IgnoreBattleTypes" and "Category" are converted to lowercase before being compared. -->
<IgnoreBattleTypes>
<passive></passive>
<boss></boss>
</IgnoreBattleTypes>
<!-- BattleMusic determines what categories a type will play music for. -->
<!-- Music is placed in "config/TurnBasedMinecraft/Music/battle/" and "config/TurnBasedMinecraft/Music/silly/" -->
<BattleMusic>
<Normal>
<monster></monster>
<animal></animal>
<boss></boss>
<player></player>
</Normal>
<Silly>
<passive></passive>
</Silly>
</BattleMusic>
<PlayerStats>
<Speed>50</Speed>
<HasteSpeed>80</HasteSpeed> <!-- Speed used if the player entity has "speed" or "haste" effects -->
<SlowSpeed>20</SlowSpeed> <!-- Speed used if the player entity has "slow" effect -->
<AttackProbability>90</AttackProbability>
<Evasion>10</Evasion>
</PlayerStats>
<!-- Determines how many attacks a "defense" move can block before that entity's next turn. -->
<DefenseDuration>1</DefenseDuration>
<!-- Probability of escaping battle. If entity's speed is greater than the enemy team's speediest entity, then good probability is used. -->
<FleeGoodProbability>90</FleeGoodProbability>
<FleeBadProbability>40</FleeBadProbability>
<!-- Minimum hit percentage for every entity. If less than 1, it will be stored as 1 anyways. -->
<MinimumHitPercentage>4</MinimumHitPercentage>
<!-- Number of seconds to wait in battle for all players to make a decision. Minimum of 5 and maximum of 60. -->
<BattleTurnTimeSeconds>15</BattleTurnTimeSeconds>
<!-- Minimum percentage of silly entities in battle to use silly music -->
<SillyMusicThreshold>40</SillyMusicThreshold>
<!-- Battle stats for entities should be specified here. If an entity is not listed it cannot enter battle. -->
<!-- Name: The full class name of an entity. -->
<!-- AttackPower: How much damage an entity does per attack. Usually has a "Probability" attribute between 0 and 100. Also may have a "Variance" attribute that varies the attack power by the specified amount randomly. -->
<!-- AttackEffect: (Optional) Applies effect to target entity with "Probability" success rate. -->
<!-- DefenseDamage: (Optional) Applies damage to an attacker when attacked with "Probability" success rate. -->
<!-- Evasion: Determines the percentage of evading attacks between 0 and 100. -->
<!-- Note that if the hit probability and evasion result in a percentage less than 1%, the hit chance will be changed ti 1% -->
<!-- Speed: Value in range of 0 to 100 that determines the order entities act in battle. Higher is sooner. Entities with same speed will take their turn as a group in random order (not at the same time). -->
<!-- IgnoreBattle: (Optional) Per entity setting to not enter turn-based-battle if value is "true". If "true" these stats will not apply to the entity as they are only used in turn-based-battle. -->
<!-- Category: Sets the type of the entity, used by "IgnoreBattleTypes" to determine what types ignore battle. -->
<!-- Decision: Lists percentages of what action taken by the entity, one of Attack, Defend, or Flee. If the sum is less than 100, the mob has a chance to do nothing with the remaining percentage -->
<EntityEntry>
<Name>net.minecraft.entity.monster.EntityBlaze</Name>
<AttackPower Probability="50">5</AttackPower>
<AttackEffect Probability="75">fire</AttackEffect>
<Evasion>5</Evasion>
<Category>monster</Category>
<Speed>45</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.monster.EntityCaveSpider</Name>
<AttackPower Probability="75">2</AttackPower>
<AttackEffect Probability="90">poison</AttackEffect>
<Evasion>35</Evasion>
<Category>monster</Category>
<Speed>75</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.monster.EntityCreeper</Name>
<IgnoreBattle>true</IgnoreBattle>
<AttackPower Probability="17" Variance="7">15</AttackPower>
<Evasion>5</Evasion>
<Category>monster</Category>
<Speed>25</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.monster.EntityElderGuardian</Name>
<AttackPower Probability="65">8</AttackPower>
<DefenseDamage Probability="35">2</DefenseDamage>
<Evasion>25</Evasion>
<Category>monster</Category>
<Speed>45</Speed>
<Decision>
<Attack>80</Attack>
<Defend>20</Defend>
<Flee>0</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.monster.EntityEnderman</Name>
<AttackPower Probability="80">7</AttackPower>
<Evasion>40</Evasion>
<Category>monster</Category>
<Speed>70</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.monster.EntityEndermite</Name>
<AttackPower Probability="80">2</AttackPower>
<Evasion>40</Evasion>
<Category>monster</Category>
<Speed>35</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.monster.EntityEvoker</Name>
<AttackPower Probability="60">6</AttackPower>
<Evasion>35</Evasion>
<Category>monster</Category>
<Speed>35</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.monster.EntityGhast</Name>
<IgnoreBattle>true</IgnoreBattle>
<AttackPower Probability="20">13</AttackPower>
<Evasion>35</Evasion>
<Category>monster</Category>
<Speed>60</Speed>
<Decision>
<Attack>75</Attack>
<Defend>0</Defend>
<Flee>25</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.monster.EntityGiantZombie</Name>
<AttackPower Probability="35">11</AttackPower>
<Evasion>2</Evasion>
<Category>monster</Category>
<Speed>45</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.monster.EntityGuardian</Name>
<AttackPower Probability="55">6</AttackPower>
<DefenseDamage Probability="30">2</DefenseDamage>
<Evasion>25</Evasion>
<Category>monster</Category>
<Speed>50</Speed>
<Decision>
<Attack>80</Attack>
<Defend>20</Defend>
<Flee>0</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.monster.EntityHusk</Name>
<AttackPower Probability="70">3</AttackPower>
<AttackEffect Probability="95">hunger</AttackEffect>
<Evasion>5</Evasion>
<Category>monster</Category>
<Speed>25</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.monster.EntityIronGolem</Name>
<AttackPower Probability="85" Variance="7">14</AttackPower>
<Evasion>5</Evasion>
<Category>monster</Category>
<Speed>45</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.monster.EntityMagmaCube</Name>
<AttackPower Probability="35">3</AttackPower>
<Evasion>12</Evasion>
<Category>monster</Category>
<Speed>35</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.monster.EntityPigZombie</Name>
<AttackPower Probability="70">8</AttackPower>
<Evasion>10</Evasion>
<Category>monster</Category>
<Speed>50</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.monster.EntityPolarBear</Name>
<AttackPower Probability="67">6</AttackPower>
<Evasion>5</Evasion>
<Category>animal</Category>
<Speed>35</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.monster.EntityShulker</Name>
<AttackPower Probability="80">4</AttackPower>
<Evasion>15</Evasion>
<Category>monster</Category>
<Speed>10</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.monster.EntitySilverfish</Name>
<AttackPower Probability="85">1</AttackPower>
<Evasion>37</Evasion>
<Category>monster</Category>
<Speed>35</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.monster.EntitySkeleton</Name>
<AttackPower Probability="75" Variance="1">3</AttackPower>
<Evasion>13</Evasion>
<Category>monster</Category>
<Speed>30</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.monster.EntitySlime</Name>
<AttackPower Probability="35">2</AttackPower>
<Evasion>10</Evasion>
<Category>monster</Category>
<Speed>30</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.monster.EntitySnowman</Name>
<AttackPower Probability="80">0</AttackPower>
<Evasion>5</Evasion>
<Category>passive</Category>
<Speed>60</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.monster.EntitySpider</Name>
<AttackPower Probability="70">2</AttackPower>
<Evasion>25</Evasion>
<Category>monster</Category>
<Speed>70</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.monster.EntityStray</Name>
<AttackPower Probability="75" Variance="1">3</AttackPower>
<AttackEffect Probability="90">slow</AttackEffect>
<Evasion>13</Evasion>
<Category>monster</Category>
<Speed>30</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.monster.EntityVex</Name>
<AttackPower Probability="65">9</AttackPower>
<Evasion>30</Evasion>
<Category>monster</Category>
<Speed>80</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.monster.EntityVindicator</Name>
<AttackPower Probability="70">13</AttackPower>
<Evasion>10</Evasion>
<Category>monster</Category>
<Speed>35</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.monster.EntityWitch</Name>
<AttackPower Probability="75" Variance="1">5</AttackPower>
<Evasion>8</Evasion>
<Category>monster</Category>
<Speed>35</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.monster.EntityWitherSkeleton</Name>
<AttackPower Probability="70">8</AttackPower>
<AttackEffect Probability="90">wither</AttackEffect>
<Evasion>7</Evasion>
<Category>monster</Category>
<Speed>65</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.monster.EntityZombie</Name>
<AttackPower Probability="70">3</AttackPower>
<Evasion>5</Evasion>
<Category>monster</Category>
<Speed>25</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.monster.EntityZombieVillager</Name>
<AttackPower Probability="70">3</AttackPower>
<Evasion>5</Evasion>
<Category>monster</Category>
<Speed>25</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.passive.EntityBat</Name>
<AttackPower Probability="70">0</AttackPower>
<Evasion>35</Evasion>
<Category>passive</Category>
<Speed>75</Speed>
<Decision>
<Attack>0</Attack>
<Defend>0</Defend>
<Flee>90</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.passive.EntityChicken</Name>
<AttackPower Probability="70">0</AttackPower>
<Evasion>10</Evasion>
<Category>passive</Category>
<Speed>35</Speed>
<Decision>
<Attack>0</Attack>
<Defend>0</Defend>
<Flee>90</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.passive.EntityCow</Name>
<AttackPower Probability="50">0</AttackPower>
<Evasion>1</Evasion>
<Category>passive</Category>
<Speed>20</Speed>
<Decision>
<Attack>0</Attack>
<Defend>10</Defend>
<Flee>80</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.passive.EntityDonkey</Name>
<AttackPower Probability="70">0</AttackPower>
<Evasion>10</Evasion>
<Category>passive</Category>
<Speed>65</Speed>
<Decision>
<Attack>0</Attack>
<Defend>0</Defend>
<Flee>90</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.passive.EntityHorse</Name>
<AttackPower Probability="70">0</AttackPower>
<Evasion>10</Evasion>
<Category>passive</Category>
<Speed>65</Speed>
<Decision>
<Attack>0</Attack>
<Defend>0</Defend>
<Flee>90</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.passive.EntityLlama</Name>
<AttackPower Probability="70">1</AttackPower>
<Evasion>10</Evasion>
<Category>passive</Category>
<Speed>50</Speed>
<Decision>
<Attack>65</Attack>
<Defend>0</Defend>
<Flee>25</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.passive.EntityMooshroom</Name>
<AttackPower Probability="70">0</AttackPower>
<Evasion>1</Evasion>
<Category>passive</Category>
<Speed>20</Speed>
<Decision>
<Attack>0</Attack>
<Defend>10</Defend>
<Flee>80</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.passive.EntityMule</Name>
<AttackPower Probability="70">0</AttackPower>
<Evasion>10</Evasion>
<Category>passive</Category>
<Speed>50</Speed>
<Decision>
<Attack>0</Attack>
<Defend>0</Defend>
<Flee>90</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.passive.EntityOcelot</Name>
<AttackPower Probability="70" Variance="1">1</AttackPower>
<Evasion>10</Evasion>
<Category>passive</Category>
<Speed>75</Speed>
<Decision>
<Attack>0</Attack>
<Defend>0</Defend>
<Flee>90</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.passive.EntityParrot</Name>
<AttackPower Probability="70">0</AttackPower>
<Evasion>35</Evasion>
<Category>passive</Category>
<Speed>70</Speed>
<Decision>
<Attack>0</Attack>
<Defend>0</Defend>
<Flee>90</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.passive.EntityPig</Name>
<AttackPower Probability="70">0</AttackPower>
<Evasion>10</Evasion>
<Category>passive</Category>
<Speed>30</Speed>
<Decision>
<Attack>0</Attack>
<Defend>5</Defend>
<Flee>85</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.passive.EntityRabbit</Name>
<AttackPower Probability="70">0</AttackPower>
<Evasion>40</Evasion>
<Category>passive</Category>
<Speed>75</Speed>
<Decision>
<Attack>0</Attack>
<Defend>0</Defend>
<Flee>100</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.passive.EntitySheep</Name>
<AttackPower Probability="70">0</AttackPower>
<Evasion>5</Evasion>
<Category>passive</Category>
<Speed>30</Speed>
<Decision>
<Attack>0</Attack>
<Defend>0</Defend>
<Flee>90</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.passive.EntitySkeletonHorse</Name>
<AttackPower Probability="70">0</AttackPower>
<Evasion>5</Evasion>
<Category>passive</Category>
<Speed>65</Speed>
<Decision>
<Attack>0</Attack>
<Defend>0</Defend>
<Flee>90</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.passive.EntitySquid</Name>
<AttackPower Probability="70">0</AttackPower>
<Evasion>15</Evasion>
<Category>passive</Category>
<Speed>40</Speed>
<Decision>
<Attack>0</Attack>
<Defend>0</Defend>
<Flee>90</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.passive.EntityVillager</Name>
<AttackPower Probability="70">0</AttackPower>
<Evasion>5</Evasion>
<Category>passive</Category>
<Speed>35</Speed>
<Decision>
<Attack>0</Attack>
<Defend>10</Defend>
<Flee>80</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.passive.EntityWolf</Name>
<AttackPower Probability="70">4</AttackPower>
<Evasion>20</Evasion>
<Category>animal</Category>
<Speed>70</Speed>
<Decision>
<Attack>80</Attack>
<Defend>15</Defend>
<Flee>5</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.passive.EntityZombieHorse</Name>
<AttackPower Probability="70">0</AttackPower>
<Evasion>8</Evasion>
<Category>passive</Category>
<Speed>65</Speed>
<Decision>
<Attack>0</Attack>
<Defend>0</Defend>
<Flee>90</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.boss.EntityDragon</Name>
<AttackPower Probability="70" Variance="2">10</AttackPower>
<Evasion>27</Evasion>
<Category>boss</Category>
<Speed>63</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</EntityEntry>
<EntityEntry>
<Name>net.minecraft.entity.boss.EntityWither</Name>
<AttackPower Probability="70">8</AttackPower>
<Evasion>20</Evasion>
<AttackEffect Probability="90">wither</AttackEffect>
<Category>boss</Category>
<Speed>68</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</EntityEntry>
</TurnBasedMinecraftConfig>