diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..0c046ba --- /dev/null +++ b/build.gradle @@ -0,0 +1,117 @@ +buildscript { + repositories { + maven { url = 'https://maven.minecraftforge.net/' } + mavenCentral() + } + dependencies { + classpath 'net.minecraftforge.gradle:ForgeGradle:3.+' + } +} + +apply plugin: 'net.minecraftforge.gradle' +// Only edit below this line, the above code adds and enables the necessary things for Forge to be setup. +apply plugin: 'eclipse' +apply plugin: 'maven-publish' + +version = "${version}" +group = 'atomicstryker.battletowers' +archivesBaseName = 'battletowersfix' + +sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' // Need this here so eclipse task generates correctly. + +minecraft { + mappings channel: 'snapshot', version: '20171103-1.12' + runs { + client { + workingDirectory project.file('run') + + // Recommended logging data for a userdev environment + property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP' + + // Recommended logging level for the console + property 'forge.logging.console.level', 'debug' + + args '--username', 'wdcftgg' + } + + server { + + // Recommended logging data for a userdev environment + property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP' + + // Recommended logging level for the console + property 'forge.logging.console.level', 'debug' + } + } +} + + + +repositories { + +} + +dependencies { + + minecraft 'net.minecraftforge:forge:1.12.2-14.23.5.2860' + +} + +// Example for how to get properties into the manifest for reading by the runtime.. +jar { + manifest { + attributes([ + "Specification-Title": "battletowers", + "Specification-Vendor": "wdcftgg", + "Specification-Version": "1", // We are version 1 of ourselves + "Implementation-Title": project.name, + "Implementation-Version": "${version}", + "Implementation-Vendor" :"wdcftgg", + "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") + ]) + } +} + +processResources{ + // this will ensure that this task is redone when the versions change. + inputs.property "version", "${version}" + inputs.property "mcversion", "1.12.2" + + // replace stuff in mcmod.info, nothing else + from(sourceSets.main.resources.srcDirs) { + include 'mcmod.info' + + // replace version and mcversion + expand 'version':"${version}", 'mcversion':"1.12.2" + } + + // copy everything else, thats not the mcmod.info + from(sourceSets.main.resources.srcDirs) { + exclude 'mcmod.info' + } +} + +// Example configuration to allow publishing using the maven-publish task +// This is the preferred method to reobfuscate your jar file +jar.finalizedBy('reobfJar') +// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing +//publish.dependsOn('reobfJar') + +publishing { + publications { + mavenJava(MavenPublication) { + artifact jar + } + } + repositories { + maven { + url "file:///${project.projectDir}/mcmodsrepo" + } + } +} + +sourceSets { + main { + output.resourcesDir = output.classesDir + } +} \ No newline at end of file diff --git a/build/classes/java/main/assets/battletowers/lang/de_DE.lang b/build/classes/java/main/assets/battletowers/lang/de_DE.lang new file mode 100644 index 0000000..6a8713c --- /dev/null +++ b/build/classes/java/main/assets/battletowers/lang/de_DE.lang @@ -0,0 +1,2 @@ +entity.BattleTowers.Battletower Golem.name=Kampfturm-Golem +entity.Battletower Golem.name=Kampfturm-Golem \ No newline at end of file diff --git a/build/classes/java/main/assets/battletowers/lang/en_US.lang b/build/classes/java/main/assets/battletowers/lang/en_US.lang new file mode 100644 index 0000000..dc2c742 --- /dev/null +++ b/build/classes/java/main/assets/battletowers/lang/en_US.lang @@ -0,0 +1,3 @@ +entity.BattleTowers.Battletower Golem.name=Battletower Golem +entity.Battletower Golem.name=Battletower Golem +Battletowers.guardian=A Battletower's Guardian has fallen! Without it's power, the Tower will collapse... diff --git a/build/classes/java/main/assets/battletowers/lang/ru_RU.lang b/build/classes/java/main/assets/battletowers/lang/ru_RU.lang new file mode 100644 index 0000000..c12e56c --- /dev/null +++ b/build/classes/java/main/assets/battletowers/lang/ru_RU.lang @@ -0,0 +1,2 @@ +entity.BattleTowers.Battletower Golem.name=Голем боевой башни +entity.Battletower Golem.name=Голем боевой башни \ No newline at end of file diff --git a/build/classes/java/main/assets/battletowers/lang/tr_TR.lang b/build/classes/java/main/assets/battletowers/lang/tr_TR.lang new file mode 100644 index 0000000..b6d834d --- /dev/null +++ b/build/classes/java/main/assets/battletowers/lang/tr_TR.lang @@ -0,0 +1,2 @@ +entity.BattleTowers.Battletower Golem.name=Savaş Kulesi Golemi +entity.Battletower Golem.name=Savaş Kulesi Golemi \ No newline at end of file diff --git a/build/classes/java/main/assets/battletowers/pack.mcmeta b/build/classes/java/main/assets/battletowers/pack.mcmeta new file mode 100644 index 0000000..306e67b --- /dev/null +++ b/build/classes/java/main/assets/battletowers/pack.mcmeta @@ -0,0 +1,6 @@ +{ + "pack": { + "pack_format": 1, + "description": "Forge Mod Defaults" + } +} \ No newline at end of file diff --git a/build/classes/java/main/assets/battletowers/sounds.json b/build/classes/java/main/assets/battletowers/sounds.json new file mode 100644 index 0000000..7249148 --- /dev/null +++ b/build/classes/java/main/assets/battletowers/sounds.json @@ -0,0 +1,53 @@ +{ + "golem": { + "category": "hostile", + "sounds": [ + "battletowers:golem" + ] + }, + "golemawaken": { + "category": "hostile", + "sounds": [ + "battletowers:golemawaken" + ] + }, + "golemcharge": { + "category": "hostile", + "sounds": [ + "battletowers:golemcharge1", + "battletowers:golemcharge2" + ] + }, + "golemdeath": { + "category": "hostile", + "sounds": [ + "battletowers:golemdeath" + ] + }, + "golemhurt": { + "category": "hostile", + "sounds": [ + "battletowers:golemhurt1", + "battletowers:golemhurt2" + ] + }, + "golemspecial": { + "category": "hostile", + "sounds": [ + "battletowers:golemspecial1", + "battletowers:golemspecial2" + ] + }, + "towerbreakstart": { + "category": "hostile", + "sounds": [ + "battletowers:towerbreakstart" + ] + }, + "towercrumble": { + "category": "hostile", + "sounds": [ + "battletowers:towercrumble" + ] + } +} diff --git a/build/classes/java/main/assets/battletowers/sounds/golem.ogg b/build/classes/java/main/assets/battletowers/sounds/golem.ogg new file mode 100644 index 0000000..3f8e509 Binary files /dev/null and b/build/classes/java/main/assets/battletowers/sounds/golem.ogg differ diff --git a/build/classes/java/main/assets/battletowers/sounds/golemawaken.ogg b/build/classes/java/main/assets/battletowers/sounds/golemawaken.ogg new file mode 100644 index 0000000..222b6c6 Binary files /dev/null and b/build/classes/java/main/assets/battletowers/sounds/golemawaken.ogg differ diff --git a/build/classes/java/main/assets/battletowers/sounds/golemcharge1.ogg b/build/classes/java/main/assets/battletowers/sounds/golemcharge1.ogg new file mode 100644 index 0000000..ebad3bb Binary files /dev/null and b/build/classes/java/main/assets/battletowers/sounds/golemcharge1.ogg differ diff --git a/build/classes/java/main/assets/battletowers/sounds/golemcharge2.ogg b/build/classes/java/main/assets/battletowers/sounds/golemcharge2.ogg new file mode 100644 index 0000000..35bd61c Binary files /dev/null and b/build/classes/java/main/assets/battletowers/sounds/golemcharge2.ogg differ diff --git a/build/classes/java/main/assets/battletowers/sounds/golemdeath.ogg b/build/classes/java/main/assets/battletowers/sounds/golemdeath.ogg new file mode 100644 index 0000000..1aeb9ad Binary files /dev/null and b/build/classes/java/main/assets/battletowers/sounds/golemdeath.ogg differ diff --git a/build/classes/java/main/assets/battletowers/sounds/golemhurt1.ogg b/build/classes/java/main/assets/battletowers/sounds/golemhurt1.ogg new file mode 100644 index 0000000..b94a5c7 Binary files /dev/null and b/build/classes/java/main/assets/battletowers/sounds/golemhurt1.ogg differ diff --git a/build/classes/java/main/assets/battletowers/sounds/golemhurt2.ogg b/build/classes/java/main/assets/battletowers/sounds/golemhurt2.ogg new file mode 100644 index 0000000..7beb892 Binary files /dev/null and b/build/classes/java/main/assets/battletowers/sounds/golemhurt2.ogg differ diff --git a/build/classes/java/main/assets/battletowers/sounds/golemspecial1.ogg b/build/classes/java/main/assets/battletowers/sounds/golemspecial1.ogg new file mode 100644 index 0000000..7a147f4 Binary files /dev/null and b/build/classes/java/main/assets/battletowers/sounds/golemspecial1.ogg differ diff --git a/build/classes/java/main/assets/battletowers/sounds/golemspecial2.ogg b/build/classes/java/main/assets/battletowers/sounds/golemspecial2.ogg new file mode 100644 index 0000000..6a443ce Binary files /dev/null and b/build/classes/java/main/assets/battletowers/sounds/golemspecial2.ogg differ diff --git a/build/classes/java/main/assets/battletowers/sounds/towerbreakstart.ogg b/build/classes/java/main/assets/battletowers/sounds/towerbreakstart.ogg new file mode 100644 index 0000000..1c5a024 Binary files /dev/null and b/build/classes/java/main/assets/battletowers/sounds/towerbreakstart.ogg differ diff --git a/build/classes/java/main/assets/battletowers/sounds/towercrumble.ogg b/build/classes/java/main/assets/battletowers/sounds/towercrumble.ogg new file mode 100644 index 0000000..fceb44f Binary files /dev/null and b/build/classes/java/main/assets/battletowers/sounds/towercrumble.ogg differ diff --git a/build/classes/java/main/assets/battletowers/textures/gui/logo.png b/build/classes/java/main/assets/battletowers/textures/gui/logo.png new file mode 100644 index 0000000..54c3ae3 Binary files /dev/null and b/build/classes/java/main/assets/battletowers/textures/gui/logo.png differ diff --git a/build/classes/java/main/assets/battletowers/textures/model/golem.png b/build/classes/java/main/assets/battletowers/textures/model/golem.png new file mode 100644 index 0000000..3042001 Binary files /dev/null and b/build/classes/java/main/assets/battletowers/textures/model/golem.png differ diff --git a/build/classes/java/main/assets/battletowers/textures/model/golemdormant.png b/build/classes/java/main/assets/battletowers/textures/model/golemdormant.png new file mode 100644 index 0000000..2152c71 Binary files /dev/null and b/build/classes/java/main/assets/battletowers/textures/model/golemdormant.png differ diff --git a/build/classes/java/main/atomicstryker/battletowers/client/AS_RenderFireball.class b/build/classes/java/main/atomicstryker/battletowers/client/AS_RenderFireball.class new file mode 100644 index 0000000..f9f99dd Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/client/AS_RenderFireball.class differ diff --git a/build/classes/java/main/atomicstryker/battletowers/client/AS_RenderGolem.class b/build/classes/java/main/atomicstryker/battletowers/client/AS_RenderGolem.class new file mode 100644 index 0000000..6f69d42 Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/client/AS_RenderGolem.class differ diff --git a/build/classes/java/main/atomicstryker/battletowers/client/ClientProxy$1.class b/build/classes/java/main/atomicstryker/battletowers/client/ClientProxy$1.class new file mode 100644 index 0000000..9b8ad5c Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/client/ClientProxy$1.class differ diff --git a/build/classes/java/main/atomicstryker/battletowers/client/ClientProxy$2.class b/build/classes/java/main/atomicstryker/battletowers/client/ClientProxy$2.class new file mode 100644 index 0000000..9acecbf Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/client/ClientProxy$2.class differ diff --git a/build/classes/java/main/atomicstryker/battletowers/client/ClientProxy.class b/build/classes/java/main/atomicstryker/battletowers/client/ClientProxy.class new file mode 100644 index 0000000..c2d412c Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/client/ClientProxy.class differ diff --git a/build/classes/java/main/atomicstryker/battletowers/client/ClientTickHandler.class b/build/classes/java/main/atomicstryker/battletowers/client/ClientTickHandler.class new file mode 100644 index 0000000..15c2071 Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/client/ClientTickHandler.class differ diff --git a/build/classes/java/main/atomicstryker/battletowers/common/AS_BattleTowersCore$RegistrationHandler.class b/build/classes/java/main/atomicstryker/battletowers/common/AS_BattleTowersCore$RegistrationHandler.class new file mode 100644 index 0000000..7cf043e Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/common/AS_BattleTowersCore$RegistrationHandler.class differ diff --git a/build/classes/java/main/atomicstryker/battletowers/common/AS_BattleTowersCore.class b/build/classes/java/main/atomicstryker/battletowers/common/AS_BattleTowersCore.class new file mode 100644 index 0000000..3f9e4b7 Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/common/AS_BattleTowersCore.class differ diff --git a/build/classes/java/main/atomicstryker/battletowers/common/AS_EntityGolem.class b/build/classes/java/main/atomicstryker/battletowers/common/AS_EntityGolem.class new file mode 100644 index 0000000..12a8c9f Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/common/AS_EntityGolem.class differ diff --git a/build/classes/java/main/atomicstryker/battletowers/common/AS_EntityGolemFireball.class b/build/classes/java/main/atomicstryker/battletowers/common/AS_EntityGolemFireball.class new file mode 100644 index 0000000..becf996 Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/common/AS_EntityGolemFireball.class differ diff --git a/build/classes/java/main/atomicstryker/battletowers/common/AS_TowerDestroyer.class b/build/classes/java/main/atomicstryker/battletowers/common/AS_TowerDestroyer.class new file mode 100644 index 0000000..643c9de Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/common/AS_TowerDestroyer.class differ diff --git a/build/classes/java/main/atomicstryker/battletowers/common/AS_WorldGenTower$TowerTypes.class b/build/classes/java/main/atomicstryker/battletowers/common/AS_WorldGenTower$TowerTypes.class new file mode 100644 index 0000000..487acda Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/common/AS_WorldGenTower$TowerTypes.class differ diff --git a/build/classes/java/main/atomicstryker/battletowers/common/AS_WorldGenTower.class b/build/classes/java/main/atomicstryker/battletowers/common/AS_WorldGenTower.class new file mode 100644 index 0000000..62d6bfd Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/common/AS_WorldGenTower.class differ diff --git a/build/classes/java/main/atomicstryker/battletowers/common/CommandBattleTowers.class b/build/classes/java/main/atomicstryker/battletowers/common/CommandBattleTowers.class new file mode 100644 index 0000000..1d0102e Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/common/CommandBattleTowers.class differ diff --git a/build/classes/java/main/atomicstryker/battletowers/common/CommandDeleteAllBattleTowers.class b/build/classes/java/main/atomicstryker/battletowers/common/CommandDeleteAllBattleTowers.class new file mode 100644 index 0000000..c8d80e9 Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/common/CommandDeleteAllBattleTowers.class differ diff --git a/build/classes/java/main/atomicstryker/battletowers/common/CommandDeleteBattleTower.class b/build/classes/java/main/atomicstryker/battletowers/common/CommandDeleteBattleTower.class new file mode 100644 index 0000000..3c59720 Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/common/CommandDeleteBattleTower.class differ diff --git a/build/classes/java/main/atomicstryker/battletowers/common/CommandRegenerateAllBattleTowers.class b/build/classes/java/main/atomicstryker/battletowers/common/CommandRegenerateAllBattleTowers.class new file mode 100644 index 0000000..4290058 Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/common/CommandRegenerateAllBattleTowers.class differ diff --git a/build/classes/java/main/atomicstryker/battletowers/common/CommandRegenerateBattleTower.class b/build/classes/java/main/atomicstryker/battletowers/common/CommandRegenerateBattleTower.class new file mode 100644 index 0000000..3546ac2 Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/common/CommandRegenerateBattleTower.class differ diff --git a/build/classes/java/main/atomicstryker/battletowers/common/CommandSpawnBattleTower.class b/build/classes/java/main/atomicstryker/battletowers/common/CommandSpawnBattleTower.class new file mode 100644 index 0000000..54e2d16 Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/common/CommandSpawnBattleTower.class differ diff --git a/build/classes/java/main/atomicstryker/battletowers/common/CommonProxy.class b/build/classes/java/main/atomicstryker/battletowers/common/CommonProxy.class new file mode 100644 index 0000000..5438d35 Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/common/CommonProxy.class differ diff --git a/build/classes/java/main/atomicstryker/battletowers/common/DungeonTweaksCompat.class b/build/classes/java/main/atomicstryker/battletowers/common/DungeonTweaksCompat.class new file mode 100644 index 0000000..db21692 Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/common/DungeonTweaksCompat.class differ diff --git a/build/classes/java/main/atomicstryker/battletowers/common/ServerTickHandler.class b/build/classes/java/main/atomicstryker/battletowers/common/ServerTickHandler.class new file mode 100644 index 0000000..b431bd5 Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/common/ServerTickHandler.class differ diff --git a/build/classes/java/main/atomicstryker/battletowers/common/TowerStageItemManager.class b/build/classes/java/main/atomicstryker/battletowers/common/TowerStageItemManager.class new file mode 100644 index 0000000..c49e979 Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/common/TowerStageItemManager.class differ diff --git a/build/classes/java/main/atomicstryker/battletowers/common/WorldGenHandler$1.class b/build/classes/java/main/atomicstryker/battletowers/common/WorldGenHandler$1.class new file mode 100644 index 0000000..8d65760 Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/common/WorldGenHandler$1.class differ diff --git a/build/classes/java/main/atomicstryker/battletowers/common/WorldGenHandler$TowerPosition.class b/build/classes/java/main/atomicstryker/battletowers/common/WorldGenHandler$TowerPosition.class new file mode 100644 index 0000000..056a7cf Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/common/WorldGenHandler$TowerPosition.class differ diff --git a/build/classes/java/main/atomicstryker/battletowers/common/WorldGenHandler$WorldHandle.class b/build/classes/java/main/atomicstryker/battletowers/common/WorldGenHandler$WorldHandle.class new file mode 100644 index 0000000..cb91fc7 Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/common/WorldGenHandler$WorldHandle.class differ diff --git a/build/classes/java/main/atomicstryker/battletowers/common/WorldGenHandler.class b/build/classes/java/main/atomicstryker/battletowers/common/WorldGenHandler.class new file mode 100644 index 0000000..9bbe8fa Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/common/WorldGenHandler.class differ diff --git a/build/classes/java/main/atomicstryker/battletowers/common/network/ChestAttackedPacket.class b/build/classes/java/main/atomicstryker/battletowers/common/network/ChestAttackedPacket.class new file mode 100644 index 0000000..9267b98 Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/common/network/ChestAttackedPacket.class differ diff --git a/build/classes/java/main/atomicstryker/battletowers/common/network/LoginPacket.class b/build/classes/java/main/atomicstryker/battletowers/common/network/LoginPacket.class new file mode 100644 index 0000000..c656727 Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/common/network/LoginPacket.class differ diff --git a/build/classes/java/main/atomicstryker/battletowers/common/network/NetworkHelper$ChannelCodec.class b/build/classes/java/main/atomicstryker/battletowers/common/network/NetworkHelper$ChannelCodec.class new file mode 100644 index 0000000..817a0f3 Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/common/network/NetworkHelper$ChannelCodec.class differ diff --git a/build/classes/java/main/atomicstryker/battletowers/common/network/NetworkHelper$ChannelHandler.class b/build/classes/java/main/atomicstryker/battletowers/common/network/NetworkHelper$ChannelHandler.class new file mode 100644 index 0000000..71c3ffc Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/common/network/NetworkHelper$ChannelHandler.class differ diff --git a/build/classes/java/main/atomicstryker/battletowers/common/network/NetworkHelper$IPacket.class b/build/classes/java/main/atomicstryker/battletowers/common/network/NetworkHelper$IPacket.class new file mode 100644 index 0000000..4bd43e5 Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/common/network/NetworkHelper$IPacket.class differ diff --git a/build/classes/java/main/atomicstryker/battletowers/common/network/NetworkHelper.class b/build/classes/java/main/atomicstryker/battletowers/common/network/NetworkHelper.class new file mode 100644 index 0000000..144a9c2 Binary files /dev/null and b/build/classes/java/main/atomicstryker/battletowers/common/network/NetworkHelper.class differ diff --git a/build/classes/java/main/changelog.txt b/build/classes/java/main/changelog.txt new file mode 100644 index 0000000..090fa69 --- /dev/null +++ b/build/classes/java/main/changelog.txt @@ -0,0 +1,207 @@ +1.6.5 +- implement a world dimension handle system like Ruins has, as there might be more than one single dimension for Battletowers to work with + +1.6.4 +- make sure chest attacked packet does not cause off-thread controlflow (thanks Aaron1011) + +1.6.3 +- add a fix for dropping torches in generated towers (SandUhr32) + +1.6.2 +- add DungeonTweaks support (jredfox) + +1.6.1 +- reworked item generation in chests, chestgenhook now actually works + +1.6.0 +- fixed default chestgenhook resource to the 1.12 variant "chests/simple_dungeon" from "dungeonChest" + +1.5.9 +- fixed biome name issue on dedicated server + +1.5.8 +- tentative fix for golems falling through floor bug when hit by a reflected fireball + +1.5.7 +- stops listening to worldgen while performing manual tower generation or deletion, prevents side effect deadlocks + +1.5.6 +- fixed golem healing from death when "losing target" +- fixed various problems (such as infinite explosions) from above problem + +1.5.5 +- it actually made things much worse by duplicating all tower entries every world load +- fixed tower entries being duplicated on load + +1.5.4 +- properly synchronized tower list access, should stop too many towers spawning +- or will make everything much, much worse + +1.5.3 +- implemented the chestgenhook ruins has for battletower chests, by default the top 3 stages have 3, 5 and 7 dungeon loot items + +1.5.2 +- updated to mc 1.8 + +1.5.1 +- added Comparable Interface to Towerposition class (some java version demands it?) + +1.5.0 +- fixed issue with tower items being parsed before all mods *should* have finished loading + +1.4.9 +- moved config loading to preinit from modsloaded + +1.4.8 +- updated to mc 1.7.10 + +1.4.7 +- added Channel Handler which does nothing so FML would stop complaining about Packets + +1.4.6 +- removed sound loading as it is unneeded since 172 +- moved config parsing to postinit, fixes mod items not working for chests + +1.4.5 +- fixed stairs blocktypes +- fixed tower collapse message being sent for nonexploding underground towers + +1.4.4 +- fixed crash upon sending golem death chat packet + +1.4.3 +- update to mc 1.7.2 +- delete your config files, the new ones only take names + +1.4.2 +- added towerFallDestroysMobSpawners option in config + +1.4.1 +- now allows the use of unlocalized strings instead of item id's in config +- improved handling of invalid items in config + +1.4.0 +- fixed spawn coordinates errors by self-caused concurrent spawning +- fixed error with spawn coordinates being forgotten +- improved logging + +1.3.9 +- fixed nether towers to have netherbrick stairs, sandstone towers to sandstone stairs +- added configurable minimum Battletower distance from spawn +- added config setting noGolemExplosions to disable explosive "stomp", however damage still gets dealt when hiding below angry golem +- added autogenerating persistant Battletower Positions config file, located in World Save folder. See file content for info +- setting minDistanceBetweenTowers <= 0 in config will now completely disable the randomized automatic generation +- added console command /spawnbattletower, spawns a battletower with golem, arguments x,y,z,type,underground +- added console command /deletebattletower, deletes a battletower and removes Golem if present, arguments x,z +- added console command /regeneratebattletower, re-spawns a battletower and Golem if present, arguments x,z +- added console command /regenerateallbattletowers, re-spawns all logged Battletowers and present Golems +- added console command /deleteallbattletowers, de-spawns all logged Battletowers and all Golems +- note despawning towers will not remove side effect blocks (eg fillings under the tower socket) + +1.3.8 +- update to mc 1.6.4 + +1.3.7 +- added chunkprovider names to config (to exclude modded dimensions from getting towers) +- added battletower golem global entity id (configurable) and as spawnable egg +- fixed sleeping golems having the awake texture and vice versa +- buffed battletower golem melee attack to 7 (from 3), now equals enderman +- buffed battletower regeneration upon cowardism slightly (now heals 20 hp when executing frustration stomp) +- enabled minecrafts new pathing AI for battletowers (it failed last time i tried but i forgot the reason so here goes) +- fixed and reenabled golem death message + +1.3.6 +- fixed golem being attacked by non players not waking up +- update to mc 1.6.2 + +1.3.5 +- update to mc 1.6.1 + +1.3.4 +- fixed issue where first floor items were being overridden by second floor items + +1.3.3 +- update to mc 1.5.2 + +1.3.2 (rev2) +- improved config parsing, now skips and logs invalid entries instead of crashing + +1.3.2 +- found and fixed the chest item crash ... again + +1.3.1 +- update to mc 1.5.1 + +1.3.0 +- update to mc 1.5 + +1.2.9 +- found and fixed the chest item crash and disappearance issue +- buffed item spawn chances across the board + +1.2.8 +- added biome registration to config to allow blocking towers from biomes of choice +- you'll have to create a "dummy" world with your biomes to setup the config +- fixed spaces in config categories, causes bugs with Forge Configuration +- this unfortunately means old config categories are incompatible (remove the spaces from the categories!) + +1.2.7 (second revision) +- fixed loot Blocks being restricted to IDs below 256 + +1.2.7 +- update to Minecraft 1.4.6 + +1.2.6 +- fixed crash upon MC saving Golem Fireballs + +1.2.5 +- made sure underground towers dont start lower than 15 + +1.2.4 +- rewritten some parts of golem AI, found the hanging sounds and fixed them - REMOVE THE OLD SOUNDS FROM YOUR RESOURCES FOLDER +- added Cave Spiders to Battletowers Mobspawner List (MWAHAHAHA) +- made Item spawn attempts per floor configurable (was 3) +- improved floor/item spawning. Golem floor will always have the top notch loot +- added underground Battletowers, chance configurable +- made crumbling towers stop at y=70, that means underground towers shouldnt explode at all + +1.2.3 +- update to Minecraft 1.4.4 + +1.2.2 +- changed sounds yet again. Made a dormant Golem emit spooky sounds. + +1.2.1 +- fixed sounds crashing + +1.2.0 +- updated to Minecraft 1.4.2 and Forge 6 + +1.1.9 +- updated to Minecraft 1.4 and Forge 5 + +1.1.8B (hotfix) +- fixed NoSuchElement crash with Tower Destroyers tick + +1.1.8 +- synchronized Tower Destroyers for crash prevention +- fixed timer code derp in Server Ticks (ran every tick, not every second) +- updated Configuration code to have current FML compliant code +- Configuration file changed. To prevent incompatibility problems, i changed it's name to "Battletowers.cfg". You can delete the old one. + +1.1.7 +- fixed endless loop that could occur when trying to generate BattleTowers +- fixed BattleTowers trying to generate in Nether +- moved sounds back into the /resource/ folder. They didnt work inside the zip + +1.1.6 +- fixed NoSuchMethod Sound crash in Golems on Serverside + +1.1.5: +- synchronized WorldGen for BattleTowers, meaning there shouldnt be any next-to-each-other Towers, ever again. This also generally decreases their occurance. +- moved Sound files into the zip, away from /resources/ +- fixed Golem not reacting if you attacked him from far away +- fixed issue preventing BattleTowers from loading on a dedicated server + +1.1.4: +- fixed Battletowers spawning too close together (goddamnit Minecraft, i cant even depend on you to compute the distance between 2 points correctly?) \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..7f9908b --- /dev/null +++ b/gradle.properties @@ -0,0 +1,6 @@ + +mappings_channel=snapshot +mappings_version=20180814-1.12 +org.gradle.jvmargs=-Xmx3G +org.gradle.daemon=false +version=1.0.0 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..28861d2 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..115e6ac --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/resources/Installation & Credits.txt b/resources/Installation & Credits.txt new file mode 100644 index 0000000..d001b5a --- /dev/null +++ b/resources/Installation & Credits.txt @@ -0,0 +1,41 @@ +AtomicStryker's BattleTowers + +Source repository: +http://code.google.com/p/atomicstrykers-minecraft-mods/source/browse/#hg%2FBattleTowers + + +Changes from Kodaichi's original, maintained a while by freakstritch +http://www.minecraftforum.net/topic/139746-/ + + +- Completely rewritten Tower Spawning +- There is 7 Types of Towers now, also underground towers! +- 4 spawn depending on their underground (Sand, Ice, Water, Foliage) +- Battle Towers now have actual staircases +- Adjusted Items and Blocks in Chests +- rewritten Golem Combat: +- Golem is much slower, you can actually avoid him on the tower now +- Golem Apocalypse Stomp will trigger if you hide in the Staircase +- Golem also shoots Fireballs +- ported to Forge, SMP capable + +- You cannot open the 2 chests closest to a golem while the golem lives +- When a golem dies, the Tower will (by default setting) collapse quickly +- The Setting files allow full customization of Items found in BattleTower chests + + +Installation: + + +Required Stuff to have installed beforehand (client and server!!): + +Forge +http://minecraftforge.net + + + +Make sure you followed the Forge installation instructions. Make sure META-INF is deleted. +Best testlaunch minecraft once before installing this. + +Then... +Put everything in their respective folders in ./minecraft as the folder names inside the archive instruct you. mods to mods, config to config. \ No newline at end of file diff --git a/resources/config/BattleTowers_Config_Help.txt b/resources/config/BattleTowers_Config_Help.txt new file mode 100644 index 0000000..9ccda1e --- /dev/null +++ b/resources/config/BattleTowers_Config_Help.txt @@ -0,0 +1,7 @@ +A little info on how Items in the config work: + + /* + * Example setting string: redstone-0-50-1-4; pig_saddle-20-1-1 + * Spawns Redstone, Item Damage 0, with 50 percent chance, at least 1, max 4 + * Also Spawns Saddle, Item Damage 0, with 20 percent chance, at least 1, max 1 + */ \ No newline at end of file diff --git a/src/main/java/atomicstryker/battletowers/client/AS_RenderFireball.java b/src/main/java/atomicstryker/battletowers/client/AS_RenderFireball.java new file mode 100644 index 0000000..c529960 --- /dev/null +++ b/src/main/java/atomicstryker/battletowers/client/AS_RenderFireball.java @@ -0,0 +1,61 @@ +package atomicstryker.battletowers.client; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.entity.Render; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.entity.Entity; +import net.minecraft.init.Items; +import net.minecraft.util.ResourceLocation; + +public class AS_RenderFireball extends Render +{ + + private float scale; + + public AS_RenderFireball(RenderManager mgr, float par1) + { + super(mgr); + this.scale = par1; + } + + @Override + public void doRender(Entity entity, double x, double y, double z, float entityYaw, float partialTicks) + { + GlStateManager.pushMatrix(); + this.bindEntityTexture(entity); + GlStateManager.translate((float)x, (float)y, (float)z); + GlStateManager.enableRescaleNormal(); + GlStateManager.scale(this.scale, this.scale, this.scale); + TextureAtlasSprite textureatlassprite = Minecraft.getMinecraft().getRenderItem().getItemModelMesher().getParticleIcon(Items.FIRE_CHARGE); + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder worldrenderer = tessellator.getBuffer(); + float f = textureatlassprite.getMinU(); + float f1 = textureatlassprite.getMaxU(); + float f2 = textureatlassprite.getMinV(); + float f3 = textureatlassprite.getMaxV(); + GlStateManager.rotate(180.0F - this.renderManager.playerViewY, 0.0F, 1.0F, 0.0F); + GlStateManager.rotate(-this.renderManager.playerViewX, 1.0F, 0.0F, 0.0F); + worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX_NORMAL); + worldrenderer.pos(-0.5D, -0.25D, 0.0D).tex((double)f, (double)f3).normal(0.0F, 1.0F, 0.0F).endVertex(); + worldrenderer.pos(0.5D, -0.25D, 0.0D).tex((double)f1, (double)f3).normal(0.0F, 1.0F, 0.0F).endVertex(); + worldrenderer.pos(0.5D, 0.75D, 0.0D).tex((double)f1, (double)f2).normal(0.0F, 1.0F, 0.0F).endVertex(); + worldrenderer.pos(-0.5D, 0.75D, 0.0D).tex((double)f, (double)f2).normal(0.0F, 1.0F, 0.0F).endVertex(); + tessellator.draw(); + GlStateManager.disableRescaleNormal(); + GlStateManager.popMatrix(); + super.doRender(entity, x, y, z, entityYaw, partialTicks); + } + + @Override + protected ResourceLocation getEntityTexture(Entity entity) + { + return TextureMap.LOCATION_BLOCKS_TEXTURE; + } + +} diff --git a/src/main/java/atomicstryker/battletowers/client/AS_RenderGolem.java b/src/main/java/atomicstryker/battletowers/client/AS_RenderGolem.java new file mode 100644 index 0000000..16de164 --- /dev/null +++ b/src/main/java/atomicstryker/battletowers/client/AS_RenderGolem.java @@ -0,0 +1,39 @@ +package atomicstryker.battletowers.client; + +import org.lwjgl.opengl.GL11; + +import atomicstryker.battletowers.common.AS_EntityGolem; +import net.minecraft.client.model.ModelBiped; +import net.minecraft.client.renderer.entity.RenderBiped; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.util.ResourceLocation; + + +public class AS_RenderGolem extends RenderBiped +{ + private static ResourceLocation texSleep = new ResourceLocation("battletowers", "textures/model/golemdormant.png"); + private static ResourceLocation texAwake = new ResourceLocation("battletowers", "textures/model/golem.png"); + + public AS_RenderGolem(RenderManager rm) + { + super(rm, new ModelBiped(), 1.0F); + } + + protected void rescaleGolem() + { + GL11.glScalef(2.0F, 2.0F, 2.0F); + } + + @Override + protected void preRenderCallback(AS_EntityGolem entityliving, float f) + { + rescaleGolem(); + } + + @Override + protected ResourceLocation getEntityTexture(AS_EntityGolem par1EntityLiving) + { + boolean awake = !((AS_EntityGolem)par1EntityLiving).getIsDormant(); + return awake ? texAwake : texSleep; + } +} diff --git a/src/main/java/atomicstryker/battletowers/client/ClientProxy.java b/src/main/java/atomicstryker/battletowers/client/ClientProxy.java new file mode 100644 index 0000000..4fd214d --- /dev/null +++ b/src/main/java/atomicstryker/battletowers/client/ClientProxy.java @@ -0,0 +1,42 @@ +package atomicstryker.battletowers.client; + +import atomicstryker.battletowers.common.AS_EntityGolem; +import atomicstryker.battletowers.common.AS_EntityGolemFireball; +import atomicstryker.battletowers.common.CommonProxy; +import net.minecraft.client.renderer.entity.Render; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.client.registry.IRenderFactory; +import net.minecraftforge.fml.client.registry.RenderingRegistry; + +public class ClientProxy extends CommonProxy +{ + @Override + public void preInit() + { + MinecraftForge.EVENT_BUS.register(new ClientTickHandler()); + + RenderingRegistry.registerEntityRenderingHandler(AS_EntityGolem.class, new IRenderFactory() + { + @Override + public Render createRenderFor(RenderManager manager) + { + return new AS_RenderGolem(manager); + } + }); + RenderingRegistry.registerEntityRenderingHandler(AS_EntityGolemFireball.class, new IRenderFactory() + { + @Override + public Render createRenderFor(RenderManager manager) + { + return new AS_RenderFireball(manager, 0.5f); + } + }); + } + + @Override + public void load() + { + + } +} diff --git a/src/main/java/atomicstryker/battletowers/client/ClientTickHandler.java b/src/main/java/atomicstryker/battletowers/client/ClientTickHandler.java new file mode 100644 index 0000000..d6fb9d8 --- /dev/null +++ b/src/main/java/atomicstryker/battletowers/client/ClientTickHandler.java @@ -0,0 +1,112 @@ +package atomicstryker.battletowers.client; + +import java.util.List; + +import atomicstryker.battletowers.common.AS_BattleTowersCore; +import atomicstryker.battletowers.common.AS_EntityGolem; +import atomicstryker.battletowers.common.network.ChestAttackedPacket; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.inventory.GuiChest; +import net.minecraft.client.multiplayer.PlayerControllerMP; +import net.minecraft.init.Blocks; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.RayTraceResult.Type; +import net.minecraftforge.fml.client.FMLClientHandler; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; +import net.minecraftforge.fml.relauncher.ReflectionHelper; + +public class ClientTickHandler +{ + + private RayTraceResult playerTarget; + private boolean hackFailed; + + @SubscribeEvent + public void onTick(TickEvent.RenderTickEvent tick) + { + Minecraft mc = FMLClientHandler.instance().getClient(); + + if (mc.currentScreen != null + && mc.currentScreen instanceof GuiChest) + { + List ents = mc.world.getEntitiesWithinAABBExcludingEntity(mc.player, new AxisAlignedBB(mc.player.posX - 8D, mc.player.posY - 8D, mc.player.posZ - 8D, mc.player.posX + 8D, mc.player.posY + 8D, mc.player.posZ + 8D)); + if (!ents.isEmpty()) + { + for (int i = ents.size() - 1; i >= 0; i--) + { + if (ents.get(i) instanceof AS_EntityGolem) + { + AS_EntityGolem golem = (AS_EntityGolem) ents.get(i); + ChestAttackedPacket packet = new ChestAttackedPacket(mc.player.getGameProfile().getName(), golem.getEntityId()); + AS_BattleTowersCore.instance.networkHelper.sendPacketToServer(packet); + mc.displayGuiScreen(null); + break; + } + } + } + } + + if (!hackFailed + && mc.world != null + && mc.objectMouseOver != null + && mc.objectMouseOver.typeOfHit == Type.BLOCK + && mc.objectMouseOver != playerTarget) + { + playerTarget = mc.objectMouseOver; + + int x = playerTarget.getBlockPos().getX(); + int y = playerTarget.getBlockPos().getY(); + int z = playerTarget.getBlockPos().getZ(); + + if (mc.world.getBlockState(new BlockPos(x, y, z)).getBlock() == Blocks.CHEST) + { + List ents = mc.world.getEntitiesWithinAABBExcludingEntity(mc.player, new AxisAlignedBB(x - 7D, y - 7D, z - 7D, x + 7D, y + 7D, z + 7D)); + if (!ents.isEmpty()) + { + for (int i = ents.size() - 1; i >= 0; i--) + { + if (ents.get(i) instanceof AS_EntityGolem) + { + boolean multiplayer = mc.world.isRemote; + + AS_EntityGolem golem = (AS_EntityGolem) ents.get(i); + Object progressHack; + float progress = 0; + try + { + progressHack = ReflectionHelper.getPrivateValue(PlayerControllerMP.class, mc.playerController, 4); + progress = (Float) progressHack; + } + catch (Exception e) + { + System.err.println("Tell AtomicStryker to update his BattleTowers Block Break Progress Hack because: " + e); + hackFailed = true; + e.printStackTrace(); + } + + if (progress > 0) + { + if (multiplayer) + { + ChestAttackedPacket packet = new ChestAttackedPacket(mc.player.getGameProfile().getName(), golem.getEntityId()); + AS_BattleTowersCore.instance.networkHelper.sendPacketToServer(packet); + } + else + { + golem.setAwake(); + golem.setAttackTarget(mc.player); + } + } + + break; + } + } + } + } + } + } + +} diff --git a/src/main/java/atomicstryker/battletowers/common/AS_BattleTowersCore.java b/src/main/java/atomicstryker/battletowers/common/AS_BattleTowersCore.java new file mode 100644 index 0000000..a0dd2d7 --- /dev/null +++ b/src/main/java/atomicstryker/battletowers/common/AS_BattleTowersCore.java @@ -0,0 +1,288 @@ +package atomicstryker.battletowers.common; + +import java.util.HashSet; +import java.util.Set; + +import org.apache.logging.log4j.Logger; + +import atomicstryker.battletowers.common.network.ChestAttackedPacket; +import atomicstryker.battletowers.common.network.LoginPacket; +import atomicstryker.battletowers.common.network.NetworkHelper; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.network.play.server.SPacketChat; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.text.TextComponentTranslation; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.config.Configuration; +import net.minecraftforge.event.RegistryEvent; +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.Mod.EventHandler; +import net.minecraftforge.fml.common.Mod.Instance; +import net.minecraftforge.fml.common.SidedProxy; +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.common.event.FMLServerStartingEvent; +import net.minecraftforge.fml.common.event.FMLServerStoppedEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.PlayerEvent.PlayerLoggedInEvent; +import net.minecraftforge.fml.common.network.FMLNetworkEvent.ClientConnectedToServerEvent; +import net.minecraftforge.fml.common.network.FMLNetworkEvent.ClientDisconnectionFromServerEvent; +import net.minecraftforge.fml.common.registry.EntityRegistry; +import net.minecraftforge.fml.common.registry.GameRegistry; +import net.minecraftforge.fml.common.registry.GameRegistry.ObjectHolder; + +@ObjectHolder("battletowers") +@Mod(modid = "battletowers", name = "Battle Towers", version = "1.6.5") +public class AS_BattleTowersCore +{ + + private Set towerDestroyers; + public int minDistanceFromSpawn; + public int minDistanceBetweenTowers; + public int towerDestroyerEnabled; + public int itemGenerateAttemptsPerFloor; + public int chanceTowerIsUnderGround; + public boolean noGolemExplosions; + public boolean towerFallDestroysMobSpawners; + // private int golemEntityID; + + @Instance(value = "battletowers") + public static AS_BattleTowersCore instance; + + @SidedProxy(clientSide = "atomicstryker.battletowers.client.ClientProxy", serverSide = "atomicstryker.battletowers.common.CommonProxy") + public static CommonProxy proxy; + + public static Logger LOGGER; + + public TowerStageItemManager[] floorItemManagers = new TowerStageItemManager[10]; + public Configuration configuration; + + public NetworkHelper networkHelper; + + @ObjectHolder("towerbreakstart") + public static final SoundEvent soundTowerBreakStart = createSoundEvent("towerbreakstart"); + + @ObjectHolder("towercrumble") + public static final SoundEvent soundTowerCrumble = createSoundEvent("towercrumble"); + + @ObjectHolder("golemawaken") + public static final SoundEvent soundGolemAwaken = createSoundEvent("golemawaken"); + + @ObjectHolder("golemspecial") + public static final SoundEvent soundGolemSpecial = createSoundEvent("golemspecial"); + + @ObjectHolder("golemcharge") + public static final SoundEvent soundGolemCharge = createSoundEvent("golemcharge"); + + @ObjectHolder("golem") + public static final SoundEvent soundGolem = createSoundEvent("golem"); + + @ObjectHolder("golemhurt") + public static final SoundEvent soundGolemHurt = createSoundEvent("golemhurt"); + + @ObjectHolder("golemdeath") + public static final SoundEvent soundGolemDeath = createSoundEvent("golemdeath"); + + @EventHandler + public void preInit(FMLPreInitializationEvent event) + { + DungeonTweaksCompat.legacyCheck(); + DungeonTweaksCompat.registerDungeons(); + + configuration = new Configuration(event.getSuggestedConfigurationFile(), false); + loadForgeConfig(); + + proxy.preInit(); + + networkHelper = new NetworkHelper("AS_BT", LoginPacket.class, ChestAttackedPacket.class); + + MinecraftForge.EVENT_BUS.register(this); + MinecraftForge.EVENT_BUS.register(new ServerTickHandler()); + + LOGGER = event.getModLog(); + } + + @SubscribeEvent + public void onClientConnected(ClientConnectedToServerEvent event) + { + System.out.println(FMLCommonHandler.instance().getEffectiveSide() + " registered ClientConnectedToServerEvent, sending packet to server"); + networkHelper.sendPacketToServer(new LoginPacket()); + } + + @SubscribeEvent + public void onClientDisconnected(ClientDisconnectionFromServerEvent event) + { + //Tell the client's WorldGenHandler to clear the world map on the next world load + WorldGenHandler.shouldClearWorldMap = true; + } + + @SubscribeEvent + public void onPlayerLogin(PlayerLoggedInEvent event) + { + networkHelper.sendPacketToPlayer(new LoginPacket(), (EntityPlayerMP) event.player); + } + + @EventHandler + public void load(FMLInitializationEvent evt) + { + proxy.load(); + + // EntityRegistry.registerGlobalEntityID(AS_EntityGolem.class, + // "Battletower Golem", golemEntityID, 0xA0A0A0, 0x808080); + EntityRegistry.registerModEntity(new ResourceLocation("battletowers", "golem"), AS_EntityGolem.class, "Battletower Golem", 1, this, 32, 3, false); + + EntityRegistry.registerModEntity(new ResourceLocation("battletowers", "golemfireball"), AS_EntityGolemFireball.class, "Golem Fireball", 2, this, 32, 3, false); + + towerDestroyers = new HashSet(); + + GameRegistry.registerWorldGenerator(new WorldGenHandler(), 0); + } + + /** + * Create a {@link SoundEvent}. + * + * @param soundName + * The SoundEvent's name without the modid prefix + * @return The SoundEvent + */ + private static SoundEvent createSoundEvent(String soundName) + { + final ResourceLocation soundID = new ResourceLocation("battletowers", soundName); + return new SoundEvent(soundID).setRegistryName(soundID); + } + + @Mod.EventBusSubscriber + public static class RegistrationHandler + { + @SubscribeEvent + public static void registerSoundEvents(RegistryEvent.Register event) + { + event.getRegistry().registerAll(soundTowerBreakStart, soundTowerCrumble, soundGolemAwaken, soundGolemSpecial, soundGolemCharge, soundGolem, soundGolemHurt, soundGolemDeath); + } + } + + @EventHandler + public void modsLoaded(FMLPostInitializationEvent evt) + { + configuration.load(); + configuration.addCustomCategoryComment("BattleTowerChestItems", "Syntax for each Item entry is 'Name-Meta-Spawnchance-minAmount-maxAmount', entries are seperated by ';'"); + + // stick-0-50-5-6 sticks + // wheat_seeds-0-50-3-5 seeds + // planks-0-50-5-6 planks + // reeds-0-50-3-5 sugarcane + floorItemManagers[0] = new TowerStageItemManager(configuration.get("BattleTowerChestItems", "Floor 1", "stick-0-75-5-6;wheat_seeds-0-75-3-5;planks-0-75-5-6;reeds-0-75-3-5").getString()); + + // stone_pickaxe-0-25-1-1 stone pick + // stone_axe-0-25-1-1 stone axe + // torch-0-75-3-3 torches + // stone_button-0-50-2-2 stone button + floorItemManagers[1] = new TowerStageItemManager( + configuration.get("BattleTowerChestItems", "Floor 2", "stone_pickaxe-0-50-1-1;stone_axe-0-50-1-1;torch-0-80-3-3;stone_button-0-50-2-2").getString()); + + // bowl-0-50-2-4 wooden bowl + // coal-0-75-4-4 coal + // string-0-50-5-5 string + // wool-0-25-2-2 wool + floorItemManagers[2] = new TowerStageItemManager(configuration.get("BattleTowerChestItems", "Floor 3", "bowl-0-75-2-4;coal-0-90-4-4;string-0-80-5-5;wool-0-75-2-2").getString()); + + // glass-0-50-3-3 glass + // feather-0-25-4-4 feather + // bread-0-50-2-2 bread + // apple-0-75-2-2 apple + floorItemManagers[3] = new TowerStageItemManager(configuration.get("BattleTowerChestItems", "Floor 4", "glass-0-75-3-3;feather-0-75-4-4;bread-0-75-2-2;apple-0-75-2-2").getString()); + + // brown_mushroom-0-50-2-2 brown mushroom + // red_mushroom-0-50-2-2 red mushroom + // sapling-0-75-3-3 saplings + // wheat-0-25-4-4 wheat + floorItemManagers[4] = new TowerStageItemManager( + configuration.get("BattleTowerChestItems", "Floor 5", "brown_mushroom-0-75-2-2;red_mushroom-0-75-2-2;sapling-0-90-3-3;wheat-0-75-4-4").getString()); + + // sign-0-50-1-2 sign + // fishing_rod-0-75-1-1 fishing rod + // pumpkin_seeds-0-25-2-2 pumpkin seeds + // melon_seeds-0-25-3-3 Melon Seeds + floorItemManagers[5] = new TowerStageItemManager( + configuration.get("BattleTowerChestItems", "Floor 6", "sign-0-50-1-2;fishing_rod-0-75-1-1;pumpkin_seeds-0-60-2-2;melon_seeds-0-60-3-3").getString()); + + // iron_sword-0-25-1-1 iron sword + // gunpowder-0-25-3-3 gunpowder + // leather-0-50-4-4 leather + // fish-0-75-3-3 raw fish + // dye-0-50-1-2 dye + floorItemManagers[6] = new TowerStageItemManager( + configuration.get("BattleTowerChestItems", "Floor 7", "iron_sword-0-60-1-1;gunpowder-0-75-3-3;leather-0-75-4-4;fish-0-75-3-3;dye-0-60-1-2").getString()); + + // chainmail_helmet-0-25-1-1 chain helmet + // chainmail_chestplate-0-25-1-1 chain chestplate + // chainmail_leggings-0-25-1-1 chain leggings + // chainmail_boots-0-25-1-1 chain boots + floorItemManagers[7] = new TowerStageItemManager(configuration + .get("BattleTowerChestItems", "Floor 8", "chainmail_helmet-0-40-1-1;chainmail_chestplate-0-40-1-1;chainmail_leggings-0-40-1-1;chainmail_boots-0-40-1-1;ChestGenHook:chests/simple_dungeon:3") + .getString()); + + // bookshelf-0-50-1-3 bookshelf + // redstone_lamp-0-25-2-2 redstone lamp + // waterlily-0-75-3-3 Lily Plants + // brewing_stand-0-25-1-1 brewing stand + floorItemManagers[8] = new TowerStageItemManager( + configuration.get("BattleTowerChestItems", "Floor 9", "bookshelf-0-70-1-3;redstone_lamp-0-60-2-2;waterlily-0-75-3-3;brewing_stand-0-50-1-1;ChestGenHook:chests/simple_dungeon:5").getString()); + + // ender_pearl-0-50-2-2 ender pearl + // diamond-0-50-2-2 diamond + // redstone-0-75-5-5 redstone dust + // gold_ingot-0-75-8-8 gold ingot + floorItemManagers[9] = new TowerStageItemManager( + configuration.get("BattleTowerChestItems", "Top Floor", "ender_pearl-0-50-2-2;diamond-0-70-2-2;redstone-0-75-5-5;gold_ingot-0-90-8-8;ChestGenHook:chests/simple_dungeon:7").getString()); + configuration.save(); + } + + @EventHandler + public void serverStarted(FMLServerStartingEvent evt) + { + evt.registerServerCommand(new CommandSpawnBattleTower()); + evt.registerServerCommand(new CommandDeleteBattleTower()); + evt.registerServerCommand(new CommandRegenerateBattleTower()); + evt.registerServerCommand(new CommandRegenerateAllBattleTowers()); + evt.registerServerCommand(new CommandDeleteAllBattleTowers()); + } + + @EventHandler + public void serverStopped(FMLServerStoppedEvent evt) + { + //Wipe world handles to avoid save folder conflicts + WorldGenHandler.wipeWorldHandles(); + } + + public void loadForgeConfig() + { + configuration.load(); + minDistanceFromSpawn = configuration.get("MainOptions", "Minimum Distance of Battletowers from Spawn", 96).getInt(); + minDistanceBetweenTowers = Integer.parseInt(configuration.get("MainOptions", "Minimum Distance between 2 BattleTowers", 196).getString()); + towerDestroyerEnabled = Integer.parseInt(configuration.get("MainOptions", "Tower Destroying Enabled", 1).getString()); + itemGenerateAttemptsPerFloor = configuration.get("BattleTowerChestItems", "Item Generations per Floor", "7").getInt(); + chanceTowerIsUnderGround = configuration.get("MainOptions", "chanceTowerIsUnderGround", 15).getInt(); + noGolemExplosions = configuration.get("MainOptions", "noGolemExplosions", false).getBoolean(false); + towerFallDestroysMobSpawners = configuration.get("MainOptions", "towerFallDestroysMobSpawners", false, "Destroy all Mob Spawners in Tower Area upon Tower Fall?").getBoolean(false); + // golemEntityID = configuration.get(Configuration.CATEGORY_GENERAL, + // "Golem Entity ID", 186).getInt(); + configuration.save(); + } + + public static synchronized void onBattleTowerDestroyed(AS_TowerDestroyer td) + { + FMLCommonHandler.instance().getMinecraftServerInstance().getPlayerList() + .sendPacketToAllPlayers(new SPacketChat(new TextComponentTranslation("Battletowers.guardian"))); + instance.towerDestroyers.add(td); + } + + public static synchronized Set getTowerDestroyers() + { + return instance.towerDestroyers; + } + +} diff --git a/src/main/java/atomicstryker/battletowers/common/AS_EntityGolem.java b/src/main/java/atomicstryker/battletowers/common/AS_EntityGolem.java new file mode 100644 index 0000000..f85df58 --- /dev/null +++ b/src/main/java/atomicstryker/battletowers/common/AS_EntityGolem.java @@ -0,0 +1,453 @@ +package atomicstryker.battletowers.common; + +import javax.annotation.Nullable; + +import io.netty.buffer.ByteBuf; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.EntityAIAttackMelee; +import net.minecraft.entity.ai.EntityAIHurtByTarget; +import net.minecraft.entity.ai.EntityAINearestAttackableTarget; +import net.minecraft.entity.ai.EntityAISwimming; +import net.minecraft.entity.ai.EntityAIWatchClosest; +import net.minecraft.entity.monster.EntityMob; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.init.Items; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.datasync.DataParameter; +import net.minecraft.network.datasync.DataSerializers; +import net.minecraft.network.datasync.EntityDataManager; +import net.minecraft.util.DamageSource; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData; + +public class AS_EntityGolem extends EntityMob implements IEntityAdditionalSpawnData +{ + + private final static DataParameter AWAKE = EntityDataManager. createKey(AS_EntityGolem.class, DataSerializers.BOOLEAN); + + private int rageCounter; + private int explosionAttack; + private int towerID; + private int drops; + private int attackCounter; + private int noTargetCountdown; + + private int towerX = -1; + private int towerY = -1; + private int towerZ = -1; + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public AS_EntityGolem(World world) + { + super(world); + this.setSize(1.1F, 4.0F); + rotationYaw = 0.0F; + rageCounter = 0; + explosionAttack = 0; + isImmuneToFire = true; + drops = 1; + setLocationAndAngles(posX, posY, posZ, 0.0F, 0.0F); + attackCounter = 0; + + getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(300.0d); // max + // health + setHealth(getMaxHealth()); + + getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(7.0d); // attack + // damage + getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.3d); // movespeed + + tasks.addTask(0, new EntityAISwimming(this)); + tasks.addTask(1, new EntityAIAttackMelee(this, 1.0d, true)); + tasks.addTask(2, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F)); + targetTasks.addTask(1, new EntityAIHurtByTarget(this, false)); + targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityPlayer.class, true, true)); + } + + public AS_EntityGolem(World world, int i) + { + this(world); + towerID = i; + this.updateGolemType(); + } + + @Override + protected void updateAITasks() + { + if (!this.getIsDormant()) + { + super.updateAITasks(); + } + } + + @Override + public void onLivingUpdate() + { + if (!this.getIsDormant()) + { + super.onLivingUpdate(); + } + } + + @Override + public void writeSpawnData(ByteBuf data) + { + data.writeInt(this.towerID); + } + + @Override + public void readSpawnData(ByteBuf data) + { + towerID = data.readInt(); + this.updateGolemType(); + } + + private void updateGolemType() + { + drops = 5 + towerID; + getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(7.0f + towerID); + getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(150f + 50f * towerID); + setHealth(getMaxHealth()); + } + + @Override + protected void entityInit() + { + super.entityInit(); + dataManager.register(AWAKE, false); // dormant dataManager + } + + public void setDormant() + { + if (!world.isRemote && !isDead && getHealth() > 0F) + { + dataManager.set(AWAKE, false); + } + } + + public void setAwake() + { + if (!world.isRemote) + { + if (getIsDormant()) + { + noTargetCountdown = 90; + world.playSound(null, getPosition(), AS_BattleTowersCore.soundGolemAwaken, SoundCategory.HOSTILE, getSoundVolume() * 2.0F, + ((rand.nextFloat() - rand.nextFloat()) * 0.2F + 1.0F) * 1.8F); + } + + dataManager.set(AWAKE, true); + } + } + + public boolean getIsDormant() + { + return dataManager.get(AWAKE) == false; + } + + @Override + public boolean attackEntityFrom(DamageSource damageSource, float amount) + { + if (damageSource.getTrueSource() != null && damageSource.getTrueSource() instanceof EntityLivingBase) + { + setAwake(); + setAttackTarget((EntityLivingBase) damageSource.getTrueSource()); + } + + return super.attackEntityFrom(damageSource, amount); + } + + @Override + public void setDead() + { + super.setDead(); + } + + @Override + public void onDeath(DamageSource var1) + { + super.onDeath(var1); + setDormant(); + Entity entity = var1.getTrueSource(); + + if (scoreValue > 0 && entity != null) + { + entity.awardKillScore(this, scoreValue, var1); + } + if (!world.isRemote) + { + int i = drops; + for (int j = 0; j < i; j++) + { + entityDropItem(new ItemStack(Items.DIAMOND, 1), 0f); + entityDropItem(new ItemStack(Items.REDSTONE, 1), 0f); + } + + i = rand.nextInt(4) + 8; + for (int k = 0; k < i; k++) + { + entityDropItem(new ItemStack(Blocks.CLAY, 1), 0f); + } + if (getAttackTarget() != null && (AS_BattleTowersCore.instance.towerDestroyerEnabled != 0) && towerY > 50 && posY > 0) + { + AS_BattleTowersCore.onBattleTowerDestroyed(new AS_TowerDestroyer(world, new BlockPos(towerX, towerY, towerZ), System.currentTimeMillis(), getAttackTarget())); + } + } + world.setEntityState(this, (byte) 3); + } + + @Override + public void knockBack(Entity entity, float i, double d, double d1) + { + // moveSpeed = 0.25F + (float)((double)(450 - health) / 1750D); + if (rand.nextInt(5) == 0) + { + motionX *= 1.5D; + motionZ *= 1.5D; + motionY += 0.60000002384185791D; + } + // rageCounter = 150; + } + + @Override + public void onUpdate() + { + if ((this.isDead || this.getHealth() <= 0F || this.posY < 0)) + { + this.setDead(); + this.setDormant(); + super.onUpdate(); + return; + } + + if (!this.getIsDormant()) + { + if (getAttackTarget() == null || !getAttackTarget().isEntityAlive()) + { + noTargetCountdown--; + if (noTargetCountdown < 1) + { + setHealth(getMaxHealth()); + rageCounter = 125; + explosionAttack = 0; + + if (this.onGround) + { + this.setDormant(); + } + } + } + else if (rageCounter <= 0 && explosionAttack == 0) + { + world.playSound(null, getPosition(), AS_BattleTowersCore.soundGolemSpecial, SoundCategory.HOSTILE, getSoundVolume() * 2.0F, + ((rand.nextFloat() - rand.nextFloat()) * 0.2F + 1.0F) * 1.8F); + motionY += 0.9D; + explosionAttack = 1; + } + else if ((rageCounter <= -30 || onGround) && explosionAttack == 1) + { + if (getHealth() <= getMaxHealth() / 2) // getEntityHealth + { + setHealth(getHealth() + 20); + } + + if (!world.isRemote && (this.posY - getAttackTarget().posY) > 0.3D) + { + if (AS_BattleTowersCore.instance.noGolemExplosions) + { + getAttackTarget().attackEntityFrom(DamageSource.causeMobDamage(this), 3.5f); + } + else + { + world.createExplosion(this, posX, posY - 0.3D, posZ, 4F, true); + } + } + rageCounter = 125; + explosionAttack = 0; + } + noTargetCountdown = 90; + } + + checkForVictim(); + super.onUpdate(); + } + + private void checkForVictim() + { + if (this.getIsDormant()) + { + if (!world.isRemote) + { + EntityPlayer entityplayer = world.getClosestPlayerToEntity(this, 6D); + if (entityplayer != null && canEntityBeSeen(entityplayer)) + { + setAwake(); + setAttackTarget(entityplayer); + rageCounter = 175; + } + } + } + else if (getAttackTarget() != null) + { + if (towerY == -1) + { + towerX = (int) posX; + towerY = (int) posY; + towerZ = (int) posZ; + } + + boolean targetNearby = (getAttackTarget().getDistanceSq(this) < 6F * 6F); + + if (!targetNearby || explosionAttack == 1 || (((this.posY - getAttackTarget().posY) > 0.3D))) + { + rageCounter -= 2; + // System.out.println("Golem losing patience: "+rageCounter); + } + else + { + rageCounter = 175; + } + + if (attackCounter == 10) + { + world.playSound(null, getPosition(), AS_BattleTowersCore.soundGolemCharge, SoundCategory.HOSTILE, getSoundVolume(), (rand.nextFloat() - rand.nextFloat()) * 0.2F + 1.0F); + } + attackCounter++; + if (attackCounter >= 20) + { + conjureFireBall(); + attackCounter = -40; + } + } + else if (attackCounter > 0) + { + attackCounter--; + } + } + + private void conjureFireBall() + { + if (!world.isRemote) + { + double diffX = getAttackTarget().posX - posX; + double diffY = (getAttackTarget().getEntityBoundingBox().minY + (double) (getAttackTarget().height / 2.0F)) - (posY + height * 0.8D); + double diffZ = getAttackTarget().posZ - posZ; + + renderYawOffset = rotationYaw = (-(float) Math.atan2(diffX, diffZ) * 180F) / (float) Math.PI; + + world.playSound(null, getPosition(), SoundEvents.ENTITY_GHAST_SHOOT, SoundCategory.HOSTILE, getSoundVolume(), (rand.nextFloat() - rand.nextFloat()) * 0.2F + 1.0F); + AS_EntityGolemFireball entityfireball = new AS_EntityGolemFireball(world, this, diffX, diffY, diffZ); + Vec3d vec3d = getLook(1.0F); + entityfireball.posX = posX + vec3d.x * 2D; + entityfireball.posY = posY + (height * 0.8) + vec3d.y * 0.5D; + entityfireball.posZ = posZ + vec3d.z * 2D; + world.spawnEntity(entityfireball); + } + } + + @Override + protected boolean canDespawn() + { + return this.isDead; + } + + @Override + public void writeEntityToNBT(NBTTagCompound nbttagcompound) + { + if (towerY == -1) + { + towerX = (int) posX; + towerY = (int) posY; + towerZ = (int) posZ; + } + + super.writeEntityToNBT(nbttagcompound); + nbttagcompound.setByte("isDormant", (byte) (this.getIsDormant() ? 1 : 0)); + nbttagcompound.setByte("hasexplosionAttacked", (byte) explosionAttack); + nbttagcompound.setByte("rageCounter", (byte) rageCounter); + nbttagcompound.setByte("Drops", (byte) drops); + nbttagcompound.setInteger("towerX", towerX); + nbttagcompound.setInteger("towerY", towerY); + nbttagcompound.setInteger("towerZ", towerZ); + } + + @Override + public void readEntityFromNBT(NBTTagCompound nbttagcompound) + { + super.readEntityFromNBT(nbttagcompound); + if ((nbttagcompound.getByte("isDormant") & 0xff) == 1) + { + this.setDormant(); + } + else + { + this.setAwake(); + } + explosionAttack = nbttagcompound.getByte("hasexplosionAttacked") & 0xff; + rageCounter = nbttagcompound.getByte("rageCounter") & 0xff; + drops = nbttagcompound.getByte("Drops") & 0xff; + + towerX = nbttagcompound.getInteger("towerX"); + towerY = nbttagcompound.getInteger("towerY"); + towerZ = nbttagcompound.getInteger("towerZ"); + } + + @Override + public boolean attackEntityAsMob(Entity entity) + { + if (onGround) + { + double d = entity.posX - posX; + double d1 = entity.posZ - posZ; + float f1 = MathHelper.sqrt(d * d + d1 * d1); + motionX = (d / (double) f1) * 0.5D * 0.20000000192092895D + motionX * 0.20000000098023224D; + motionZ = (d1 / (double) f1) * 0.5D * 0.10000000192092896D + motionZ * 0.20000000098023224D; + } + + return super.attackEntityAsMob(entity); + } + + @Override + protected SoundEvent getAmbientSound() + { + if (!this.getIsDormant()) + { + return AS_BattleTowersCore.soundGolem; + } + else + { + return SoundEvents.AMBIENT_CAVE; + } + } + + @Override + @Nullable + protected SoundEvent getHurtSound(DamageSource damageSource) + { + return AS_BattleTowersCore.soundGolemHurt; + } + + @Override + protected SoundEvent getDeathSound() + { + return AS_BattleTowersCore.soundGolemDeath; + } + + @Override + protected Item getDropItem() + { + return Items.PAPER; + } + +} diff --git a/src/main/java/atomicstryker/battletowers/common/AS_EntityGolemFireball.java b/src/main/java/atomicstryker/battletowers/common/AS_EntityGolemFireball.java new file mode 100644 index 0000000..2c34aff --- /dev/null +++ b/src/main/java/atomicstryker/battletowers/common/AS_EntityGolemFireball.java @@ -0,0 +1,198 @@ +package atomicstryker.battletowers.common; + +import java.util.List; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLiving; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.DamageSource; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public class AS_EntityGolemFireball extends Entity +{ + private boolean wasDeflected; + public EntityLiving shooterEntity; + public double accelerationX; + public double accelerationY; + public double accelerationZ; + + public AS_EntityGolemFireball(World world) + { + super(world); + setSize(0.3F, 0.3F); + wasDeflected = false; + } + + @Override + protected void entityInit() + { + } + + public AS_EntityGolemFireball(World world, EntityLiving entityliving, double diffX, double diffY, double diffZ) + { + this(world); + + shooterEntity = entityliving; + motionX = motionY = motionZ = 0.0D; + diffX += rand.nextGaussian() * 0.4D; + diffY += rand.nextGaussian() * 0.4D; + diffZ += rand.nextGaussian() * 0.4D; + double targetDistance = MathHelper.sqrt(diffX * diffX + diffY * diffY + diffZ * diffZ); + accelerationX = (diffX / targetDistance) * 0.1D; + accelerationY = (diffY / targetDistance) * 0.1D; + accelerationZ = (diffZ / targetDistance) * 0.1D; + } + + @SuppressWarnings("rawtypes") + @Override + public void onUpdate() + { + super.onUpdate(); + this.setFire(1); + + Vec3d curVec = new Vec3d(posX, posY, posZ); + Vec3d nextVec = new Vec3d(posX + motionX, posY + motionY, posZ + motionZ); + RayTraceResult collisionPosition = world.rayTraceBlocks(curVec, nextVec); + curVec = new Vec3d(posX, posY, posZ); + nextVec = new Vec3d(posX + motionX, posY + motionY, posZ + motionZ); + if (collisionPosition != null) + { + nextVec = new Vec3d(collisionPosition.hitVec.x, collisionPosition.hitVec.y, collisionPosition.hitVec.z); + } + Entity hitEntity = null; + List list = world.getEntitiesWithinAABBExcludingEntity(this, getEntityBoundingBox().offset(motionX, motionY, motionZ).grow(1.0D, 1.0D, 1.0D)); + double minDist = 0.0D; + for (Object aList : list) + { + Entity ent = (Entity) aList; + if (!ent.canBeCollidedWith() || (ent == shooterEntity && ticksExisted < 25 && !wasDeflected)) + { + continue; + } + AxisAlignedBB axisalignedbb = ent.getEntityBoundingBox().grow(0.3F, 0.3F, 0.3F); + RayTraceResult entCollision = axisalignedbb.calculateIntercept(curVec, nextVec); + if (entCollision == null) + { + continue; + } + double distToCollision = curVec.distanceTo(entCollision.hitVec); + if (distToCollision < minDist || minDist == 0.0D) + { + hitEntity = ent; + minDist = distToCollision; + } + } + + if (hitEntity != null) + { + collisionPosition = new RayTraceResult(hitEntity); + } + if (collisionPosition != null) + { + if (!world.isRemote) + { + if (collisionPosition.entityHit != null) + { + // this causes the fall through floor bug?!?!?! + // collisionPosition.entityHit.attackEntityFrom(DamageSource.causeMobDamage(shooterEntity), + // 0); + } + world.newExplosion(null, posX, posY, posZ, 1.0F, true, true); + } + setDead(); + } + posX += motionX; + posY += motionY; + posZ += motionZ; + float f = MathHelper.sqrt(motionX * motionX + motionZ * motionZ); + rotationYaw = (float) ((Math.atan2(motionX, motionZ) * 180D) / 3.1415927410125732D); + for (rotationPitch = (float) ((Math.atan2(motionY, f) * 180D) / 3.1415927410125732D); rotationPitch - prevRotationPitch < -180F; prevRotationPitch -= 360F) + { + } + for (; rotationPitch - prevRotationPitch >= 180F; prevRotationPitch += 360F) + { + } + for (; rotationYaw - prevRotationYaw < -180F; prevRotationYaw -= 360F) + { + } + for (; rotationYaw - prevRotationYaw >= 180F; prevRotationYaw += 360F) + { + } + rotationPitch = prevRotationPitch + (rotationPitch - prevRotationPitch) * 0.2F; + rotationYaw = prevRotationYaw + (rotationYaw - prevRotationYaw) * 0.2F; + float f1 = 0.95F; + if (isInWater()) + { + for (int k = 0; k < 4; k++) + { + float f3 = 0.25F; + world.spawnParticle(EnumParticleTypes.WATER_BUBBLE, posX - motionX * (double) f3, posY - motionY * (double) f3, posZ - motionZ * (double) f3, motionX, motionY, motionZ); + } + + f1 = 0.8F; + } + motionX += accelerationX; + motionY += accelerationY; + motionZ += accelerationZ; + motionX *= f1; + motionY *= f1; + motionZ *= f1; + world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, posX, posY + 0.5D, posZ, 0.0D, 0.0D, 0.0D); + setPosition(posX, posY, posZ); + } + + @Override + public boolean canBeCollidedWith() + { + return true; + } + + @Override + public float getCollisionBorderSize() + { + return 1.0F; + } + + @Override + public boolean attackEntityFrom(DamageSource damage, float i) + { + markVelocityChanged(); + Entity entity = damage.getTrueSource(); + if (entity != null) + { + Vec3d vec3d = entity.getLookVec(); + if (vec3d != null) + { + motionX = vec3d.x; + motionY = vec3d.y; + motionZ = vec3d.z; + accelerationX = motionX * 0.1D; + accelerationY = motionY * 0.1D; + accelerationZ = motionZ * 0.1D; + + wasDeflected = true; + } + return true; + } + else + { + return false; + } + } + + @Override + public void readEntityFromNBT(NBTTagCompound nbttagcompound) + { + } + + @Override + public void writeEntityToNBT(NBTTagCompound nbttagcompound) + { + } + +} diff --git a/src/main/java/atomicstryker/battletowers/common/AS_TowerDestroyer.java b/src/main/java/atomicstryker/battletowers/common/AS_TowerDestroyer.java new file mode 100644 index 0000000..2f798b8 --- /dev/null +++ b/src/main/java/atomicstryker/battletowers/common/AS_TowerDestroyer.java @@ -0,0 +1,229 @@ +package atomicstryker.battletowers.common; + +import net.minecraft.block.Block; +import net.minecraft.entity.Entity; +import net.minecraft.init.Blocks; +import net.minecraft.init.SoundEvents; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.World; + +public class AS_TowerDestroyer +{ + public Entity player; + private int xGolem; + private int yGolem; + private int zGolem; + private World world; + private long triggerTime; + private long lastExplosionSoundTime; + private final int maxfloor = 6; + private int floor = maxfloor; + private final int floorDistance = 7; + private final float explosionPower = 10F; + + private final long initialExplosionDelay = 15000L; + private final long perFloorExplosionDelay = 5000L; + private boolean deleteMe = false; + + public AS_TowerDestroyer(World worldObj, BlockPos coords, long time, Entity golemkiller) + { + this.world = worldObj; + this.player = golemkiller; + this.xGolem = coords.getX(); + this.yGolem = coords.getY(); + this.zGolem = coords.getZ(); + this.triggerTime = time; + this.lastExplosionSoundTime = time; + + world.playSound(null, new BlockPos(xGolem, yGolem, zGolem), AS_BattleTowersCore.soundTowerBreakStart, SoundCategory.HOSTILE, 4F, 1.0F); + } + + public void update() + { + if (deleteMe) + { + return; + } + else if (yCoord() < 70) + { + finishByDeletingSpawners(); + return; + } + + if (floor == maxfloor && System.currentTimeMillis() > triggerTime + initialExplosionDelay) + { + triggerTime = System.currentTimeMillis(); + + // kaboom baby + if (!world.isRemote) + { + world.createExplosion(player, xGolem, yCoord(), zGolem, explosionPower, true); + cleanUpStragglerBlocks(); + } + + floor--; + } + else if (floor < maxfloor && System.currentTimeMillis() > triggerTime + perFloorExplosionDelay) // each + // floor + // bursts + // 10 + // seconds + // after + // that + { + if (floor < 1) + { + finishByDeletingSpawners(); + return; + } + triggerTime = System.currentTimeMillis(); + + // kaboom baby + if (!world.isRemote) + { + world.createExplosion(player, xGolem, yCoord(), zGolem, explosionPower, true); + cleanUpStragglerBlocks(); + } + + floor--; + } + else + { + createSFX(randomTowerCoord(xGolem), (int) yCoord(), randomTowerCoord(zGolem)); + } + } + + private void finishByDeletingSpawners() + { + deleteMe = true; + + if (AS_BattleTowersCore.instance.towerFallDestroysMobSpawners) + { + Block spawnerid = Blocks.MOB_SPAWNER; + int minYdeletion = Math.max(yGolem - 80, 8); + for (int xIterator = xGolem - 8; xIterator < xGolem + 8; xIterator++) // do + // each + // X + { + for (int zIterator = zGolem - 8; zIterator < zGolem + 8; zIterator++) // do + // each + // Z + { + for (int yIterator = yGolem; yIterator >= minYdeletion; yIterator--) // go + // down + // the + // tower + { + if (world.getBlockState(new BlockPos(xIterator, yIterator, zIterator)).getBlock() == spawnerid) + { + // destroy all present mobspawners + world.setBlockToAir(new BlockPos(xIterator, yIterator, zIterator)); + } + } + } + } + } + } + + public boolean isFinished() + { + return deleteMe; + } + + private double yCoord() + { + return yGolem - (floorDistance * Math.abs(maxfloor - floor)); + } + + private int randomTowerCoord(int i) + { + return i - 7 + world.rand.nextInt(15); + } + + private void cleanUpStragglerBlocks() + { + int ytemp = (int) yCoord(); + for (int xIterator = -8; xIterator < 8; xIterator++) // do each X + { + for (int zIterator = -8; zIterator < 8; zIterator++) // do each Z + { + for (int yIterator = 1; yIterator < 9; yIterator++) // do Y 8 + // blocks + // high + { + if (world.getBlockState(new BlockPos(xGolem + xIterator, ytemp + yIterator, zGolem + zIterator)).getBlock() != Blocks.AIR) + { + world.setBlockToAir(new BlockPos(xGolem + xIterator, ytemp + yIterator, zGolem + zIterator)); + } + } + } + } + } + + private void createSFX(int i, int j, int k) + { + if (System.currentTimeMillis() > lastExplosionSoundTime + 4000L) + { + switch (world.rand.nextInt(4)) + { + case 0: + { + // world.playSound(i, j, k, "random.fizz", 4F, (1.0F + + // (world.rand.nextFloat() - world.rand.nextFloat()) * 0.2F) * + // 0.7F); + world.playSound(null, new BlockPos(xGolem, yGolem, zGolem), SoundEvents.BLOCK_LAVA_AMBIENT, SoundCategory.HOSTILE, 4F, 1.0F); + break; + } + case 1: + { + world.playSound(null, new BlockPos(xGolem, yGolem, zGolem), AS_BattleTowersCore.soundTowerCrumble, SoundCategory.HOSTILE, 4F, 1.0F); + break; + } + } + lastExplosionSoundTime = System.currentTimeMillis(); + } + + double d = (float) i + world.rand.nextFloat(); + double d1 = (float) j + world.rand.nextFloat(); + double d2 = (float) k + world.rand.nextFloat(); + double d3 = d - i; + double d4 = d1 - j; + double d5 = d2 - k; + double d6 = MathHelper.sqrt(d3 * d3 + d4 * d4 + d5 * d5); + d3 /= d6; + d4 /= d6; + d5 /= d6; + double d7 = 0.5D / (d6 / 1D + 0.10000000000000001D); + d7 *= world.rand.nextFloat() * world.rand.nextFloat() + 0.3F; + d3 *= d7; + d4 *= d7; + d5 *= d7; + + switch (world.rand.nextInt(4)) + { + case 0: + { + world.spawnParticle(EnumParticleTypes.EXPLOSION_NORMAL, (d + i * 1.0D) / 2D, (d1 + j * 1.0D) / 2D, (d2 + k * 1.0D) / 2D, d3, d4, d5); + break; + } + case 1: + { + world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, d, d1, d2, d3, d4, d5); + break; + } + case 2: + { + world.spawnParticle(EnumParticleTypes.LAVA, d, d1, d2, 0.0D, 0.0D, 0.0D); + break; + } + case 4: + { + world.spawnParticle(EnumParticleTypes.SMOKE_LARGE, (double) i + Math.random(), (double) j + 1.2D, (double) k + Math.random(), 0.0D, 0.0D, 0.0D); + break; + } + } + } +} diff --git a/src/main/java/atomicstryker/battletowers/common/AS_WorldGenTower.java b/src/main/java/atomicstryker/battletowers/common/AS_WorldGenTower.java new file mode 100644 index 0000000..f538ae9 --- /dev/null +++ b/src/main/java/atomicstryker/battletowers/common/AS_WorldGenTower.java @@ -0,0 +1,695 @@ +package atomicstryker.battletowers.common; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Random; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockTorch; +import net.minecraft.entity.EntityList; +import net.minecraft.entity.monster.EntityCaveSpider; +import net.minecraft.entity.monster.EntitySkeleton; +import net.minecraft.entity.monster.EntitySpider; +import net.minecraft.entity.monster.EntityZombie; +import net.minecraft.init.Blocks; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntityChest; +import net.minecraft.tileentity.TileEntityMobSpawner; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class AS_WorldGenTower +{ + + public String failState; + + private static int candidates[][] = { { 4, -5 }, { 4, 0 }, { 4, 5, }, { 0, -5 }, { 0, 0 }, { 0, 5, }, { -4, -5 }, { -4, 0, }, { -4, 5 } }; + + private static int candidatecount = candidates.length; + private final static int maxHoleDepthInBase = 22; + + /** + * @param world + * instance + * @param random + * gen + * @param ix + * coordinate + * @param jy + * coordinate + * @param kz + * coordinate + * @return -1 when no tower should be able to spawn, else Towerchosen enum + * ordinal + */ + public int getChosenTowerOrdinal(World world, Random random, int ix, int jy, int kz) + { + TowerTypes towerChosen; + int countWater = 0; + int countSand = 0; + int countSnow = 0; + int countFoliage = 0; + int countElse = 0; + + for (int ccounter = 0; ccounter < candidatecount; ccounter++) + { + int pair[] = candidates[ccounter]; + int checkBlockY = getSurfaceBlockHeight(world, ix + pair[0], kz + pair[1]); + + Block ID = world.getBlockState(new BlockPos(ix + pair[0], checkBlockY, kz + pair[1])).getBlock(); + + if (world.getBlockState(new BlockPos(ix + pair[0], checkBlockY + 1, kz + pair[1])).getBlock() == Blocks.SNOW || ID == Blocks.ICE) + { + countSnow++; + } + else if (ID == Blocks.SAND || ID == Blocks.SANDSTONE) + { + countSand++; + } + else if (ID == Blocks.WATER) + { + countWater++; + } + else if (ID == Blocks.LEAVES || ID == Blocks.WATERLILY || ID == Blocks.LOG || ID == Blocks.LOG2) + { + countFoliage++; + } + else + countElse++; + + if (Math.abs(checkBlockY - jy) > maxHoleDepthInBase) + { + failState = "Uneven Surface, diff value: " + Math.abs(checkBlockY - jy); + return -1; + } + + for (int ycounter2 = 1; ycounter2 <= 3; ycounter2++) + { + ID = world.getBlockState(new BlockPos(ix + pair[0], (checkBlockY + ycounter2), kz + pair[1])).getBlock(); + if (isBannedBlockID(ID)) + { + failState = "Surface banned Block of ID: " + ID + " at height: " + ycounter2; + return -1; + } + } + + for (int ycounter = 1; ycounter <= 5; ycounter++) + { + ID = world.getBlockState(new BlockPos(ix + pair[0], checkBlockY - ycounter, kz + pair[1])).getBlock(); + + if (ID == Blocks.AIR || isBannedBlockID(ID)) + { + failState = "Depth check - Banned Block or hole, Depth: " + ycounter + " ID: " + ID; + return -1; + } + } + } + + // System.err.println("Snow: "+countSnow+" Sand: "+countSand+" Water: + // "+countWater+" else: "+countElse); + + int[] nums = { countWater, countSnow, countSand, countFoliage, countElse }; + Arrays.sort(nums); + int result = nums[nums.length - 1]; + + // System.err.println("Picked max value of "+result); + + if (countSand == result) + { + towerChosen = TowerTypes.SandStone; + } + else if (countSnow == result) + { + towerChosen = TowerTypes.Ice; + } + else if (countWater == result) + { + towerChosen = TowerTypes.CobbleStoneMossy; + } + else if (countFoliage == result) + { + towerChosen = TowerTypes.CobbleStoneMossy; + } + else // standard is cobblestone, really rare should be nether + { + if (random.nextInt(10) == 0) + { + towerChosen = TowerTypes.Netherrack; + } + else + { + towerChosen = (random.nextInt(5) == 0) ? TowerTypes.SmoothStone : TowerTypes.CobbleStone; + } + } + + return towerChosen.ordinal(); + } + + @SuppressWarnings("deprecation") // is needed because getDefaultState on + // stairs does not work + public void generate(World world, Random random, int ix, int jy, int kz, int towerchoice, boolean underground) + { + TowerTypes towerChosen = TowerTypes.values()[towerchoice]; + + Block towerWallBlockID = towerChosen.getWallBlockID(); + Block towerLightBlockID = towerChosen.getLightBlockID(); + Block towerFloorBlockID = towerChosen.getFloorBlockID(); + int towerFloorMeta = towerChosen.getFloorBlockMetaData(); + + int startingHeight = underground ? Math.max(jy - 70, 15) : jy - 6; + int maximumHeight = underground ? jy + 7 : 120; + + int floor = 1; + boolean topFloor = false; + int builderHeight = startingHeight; + for (; builderHeight < maximumHeight; builderHeight += 7) // builderHeight + // jumps + // floors + { + if (builderHeight + 7 >= maximumHeight) + { + topFloor = true; + } + + for (int floorIterator = 0; floorIterator < 7; floorIterator++) // build + // each + // floor + // height + // block + // till + // next + // floor + { + if (floor == 1 && floorIterator < 4) // initial floor + { + floorIterator = 4; + } + for (int xIterator = -7; xIterator < 7; xIterator++) // do each + // X + { + for (int zIterator = -7; zIterator < 7; zIterator++) // do + // each + // Z + { + int iCurrent = xIterator + ix; + int jCurrent = floorIterator + builderHeight; + int zCurrent = zIterator + kz; + + if (zIterator == -7) // last row, 14 + { + if (xIterator > -5 && xIterator < 4) // rear outer + // wall + { + buildWallPiece(world, iCurrent, jCurrent, zCurrent, towerWallBlockID, floor, floorIterator); + } + continue; + } + if (zIterator == -6 || zIterator == -5) // rows 12 and + // 13 + { + if (xIterator == -5 || xIterator == 4) // outer wall + // parts + { + buildWallPiece(world, iCurrent, jCurrent, zCurrent, towerWallBlockID, floor, floorIterator); + continue; + } + if (zIterator == -6) // row 13 extra + { + if (xIterator == (floorIterator + 1) % 7 - 3) // stairwell!! + { + if (!(underground && floor == 1)) + { + world.setBlockState(new BlockPos(iCurrent, jCurrent, zCurrent), towerChosen.getStairBlockID().getStateFromMeta(0)); + } + if (floorIterator == 5) + { + world.setBlockState(new BlockPos(iCurrent - 7, jCurrent, zCurrent), towerFloorBlockID.getDefaultState()); + } + if (floorIterator == 6 && topFloor) // top + // ledge + // part + { + buildWallPiece(world, iCurrent, jCurrent, zCurrent, towerWallBlockID, floor, floorIterator); + } + continue; + } + if (xIterator < 4 && xIterator > -5) // tower + // insides + { + world.setBlockState(new BlockPos(iCurrent, jCurrent, zCurrent), Blocks.AIR.getDefaultState()); + } + continue; + } + if (zIterator != -5 || xIterator <= -5 || xIterator >= 5) // outside + // tower + { + continue; + } + if (floorIterator != 0 && floorIterator != 6 || xIterator != -4 && xIterator != 3) + { + if (floorIterator == 5 && (xIterator == 3 || xIterator == -4)) + { + buildFloorPiece(world, iCurrent, jCurrent, zCurrent, towerFloorBlockID, towerFloorMeta); + } + else + { + buildWallPiece(world, iCurrent, jCurrent, zCurrent, towerWallBlockID, floor, floorIterator); // under + // stairwell + } + } + else + { + world.setBlockState(new BlockPos(iCurrent, jCurrent, zCurrent), Blocks.AIR.getDefaultState()); // stairwell + // space + } + continue; + } + if (zIterator == -4 || zIterator == -3 || zIterator == 2 || zIterator == 3) // rows + // 11, + // 10, + // 5, + // 4 + { + if (xIterator == -6 || xIterator == 5) // outer wall + // parts + { + buildWallPiece(world, iCurrent, jCurrent, zCurrent, towerWallBlockID, floor, floorIterator); + continue; + } + if (xIterator <= -6 || xIterator >= 5) // outside + // tower + { + continue; + } + if (floorIterator == 5) + { + buildFloorPiece(world, iCurrent, jCurrent, zCurrent, towerFloorBlockID, towerFloorMeta); + continue; + } + if (world.getBlockState(new BlockPos(iCurrent, jCurrent, zCurrent)).getBlock() != Blocks.CHEST) // tower + // inside + // space + { + world.setBlockState(new BlockPos(iCurrent, jCurrent, zCurrent), Blocks.AIR.getDefaultState()); + } + continue; + } + if (zIterator > -3 && zIterator < 2) // rows 10 to 5 + { + if (xIterator == -7 || xIterator == 6) + { + if (floorIterator < 0 || floorIterator > 3 || ((xIterator != -7 && xIterator != 6) || underground) || zIterator != -1 && zIterator != 0) // wall, + // short + // of + // window + { + buildWallPiece(world, iCurrent, jCurrent, zCurrent, towerWallBlockID, floor, floorIterator); + } + else + { + world.setBlockState(new BlockPos(iCurrent, jCurrent, zCurrent), Blocks.AIR.getDefaultState()); + } + continue; + } + if (xIterator <= -7 || xIterator >= 6) + { + continue; + } + if (floorIterator == 5) + { + buildFloorPiece(world, iCurrent, jCurrent, zCurrent, towerFloorBlockID, towerFloorMeta); + } + else + { + world.setBlockState(new BlockPos(iCurrent, jCurrent, zCurrent), Blocks.AIR.getDefaultState()); + } + continue; + } + if (zIterator == 4) // row 3 + { + if (xIterator == -5 || xIterator == 4) + { + buildWallPiece(world, iCurrent, jCurrent, zCurrent, towerWallBlockID, floor, floorIterator); + continue; + } + if (xIterator <= -5 || xIterator >= 4) + { + continue; + } + if (floorIterator == 5) + { + buildFloorPiece(world, iCurrent, jCurrent, zCurrent, towerFloorBlockID, towerFloorMeta); + } + else + { + world.setBlockState(new BlockPos(iCurrent, jCurrent, zCurrent), Blocks.AIR.getDefaultState()); + } + continue; + } + if (zIterator == 5) // row 2 + { + if (xIterator == -4 || xIterator == -3 || xIterator == 2 || xIterator == 3) + { + buildWallPiece(world, iCurrent, jCurrent, zCurrent, towerWallBlockID, floor, floorIterator); + continue; + } + if (xIterator <= -3 || xIterator >= 2) + { + continue; + } + if (floorIterator == 5) + { + buildFloorPiece(world, iCurrent, jCurrent, zCurrent, towerFloorBlockID, towerFloorMeta); + } + else + { + buildWallPiece(world, iCurrent, jCurrent, zCurrent, towerWallBlockID, floor, floorIterator); + } + continue; + } + if (zIterator != 6 || xIterator <= -3 || xIterator >= 2) + { + continue; + } + if (floorIterator < 0 || floorIterator > 3 || xIterator != -1 && xIterator != 0) + { + buildWallPiece(world, iCurrent, jCurrent, zCurrent, towerWallBlockID, floor, floorIterator); + } + else + { + buildWallPiece(world, iCurrent, jCurrent, zCurrent, towerWallBlockID, floor, floorIterator); + } + } + + } + } + + if (floor == 2) + { + world.setBlockState(new BlockPos(ix + 3, builderHeight, kz - 5), towerWallBlockID.getDefaultState()); + world.setBlockState(new BlockPos(ix + 3, builderHeight - 1, kz - 5), towerWallBlockID.getDefaultState()); + } + if ((!underground && topFloor) || (underground && floor == 1)) + { + if (towerChosen != TowerTypes.Null) + { + AS_EntityGolem entitygolem = new AS_EntityGolem(world, towerChosen.ordinal()); + entitygolem.setLocationAndAngles(ix + 0.5D, builderHeight + 6, kz + 0.5D, world.rand.nextFloat() * 360F, 0.0F); + world.spawnEntity(entitygolem); + } + } + else + { + if (towerChosen != TowerTypes.Null) + { + world.setBlockState(new BlockPos(ix + 2, builderHeight + 6, kz + 2), Blocks.MOB_SPAWNER.getDefaultState()); + TileEntityMobSpawner tileentitymobspawner = (TileEntityMobSpawner) world.getTileEntity(new BlockPos(ix + 2, builderHeight + 6, kz + 2)); + if (tileentitymobspawner != null) + { + if (!DungeonTweaksCompat.isLoaded) + { + tileentitymobspawner.getSpawnerBaseLogic().setEntityId(getMobType(world.rand)); + } + else + { + DungeonTweaksCompat.fireDungeonSpawn(tileentitymobspawner, world, random, towerChosen); + } + } + + world.setBlockState(new BlockPos(ix - 3, builderHeight + 6, kz + 2), Blocks.MOB_SPAWNER.getDefaultState()); + tileentitymobspawner = (TileEntityMobSpawner) world.getTileEntity(new BlockPos(ix - 3, builderHeight + 6, kz + 2)); + if (tileentitymobspawner != null) + { + if (!DungeonTweaksCompat.isLoaded) + { + tileentitymobspawner.getSpawnerBaseLogic().setEntityId(getMobType(world.rand)); + } + else + { + DungeonTweaksCompat.fireDungeonSpawn(tileentitymobspawner, world, random, towerChosen); + } + } + } + else + { + world.setBlockState(new BlockPos(ix + 2, builderHeight + 6, kz + 2), Blocks.AIR.getDefaultState()); + world.setBlockState(new BlockPos(ix - 3, builderHeight + 6, kz + 2), Blocks.AIR.getDefaultState()); + } + } + // chest pedestal + world.setBlockState(new BlockPos(ix, builderHeight + 6, kz + 3), towerFloorBlockID.getDefaultState()); + world.setBlockState(new BlockPos(ix - 1, builderHeight + 6, kz + 3), towerFloorBlockID.getDefaultState()); + + if (builderHeight + 56 >= 120 && floor == 1) + { + floor = 2; + } + + if (towerChosen != TowerTypes.Null) + { + // chest + TowerStageItemManager floorChestManager; + if (!underground) + { + floorChestManager = topFloor ? WorldGenHandler.getTowerStageManagerForFloor(10) : WorldGenHandler.getTowerStageManagerForFloor(floor); + } + else + { + floorChestManager = floor == 1 ? WorldGenHandler.getTowerStageManagerForFloor(10) : WorldGenHandler.getTowerStageManagerForFloor(Math.abs(11 - floor)); + } + + for (int chestlength = 0; chestlength < 2; chestlength++) + { + world.setBlockState(new BlockPos(ix - chestlength, builderHeight + 7, kz + 3), Blocks.CHEST.getStateFromMeta(2)); + TileEntityChest tileentitychest = (TileEntityChest) world.getTileEntity(new BlockPos(ix - chestlength, builderHeight + 7, kz + 3)); + if (tileentitychest != null) + { + int count = underground ? AS_BattleTowersCore.instance.itemGenerateAttemptsPerFloor * 2 : AS_BattleTowersCore.instance.itemGenerateAttemptsPerFloor; + List generatedStacks = floorChestManager.getStageItemStacks(world, world.rand, tileentitychest, count); + List freeSlots = new ArrayList<>(tileentitychest.getSizeInventory()); + for (int i = 0; i < tileentitychest.getSizeInventory(); i++) + { + freeSlots.add(i); + } + Iterator iterator = generatedStacks.iterator(); + while (iterator.hasNext() && !freeSlots.isEmpty()) + { + Integer slot = freeSlots.get(world.rand.nextInt(freeSlots.size())); + freeSlots.remove(slot); + tileentitychest.setInventorySlotContents(slot, iterator.next()); + } + } + } + } + else + { + for (int chestlength = 0; chestlength < 2; chestlength++) + { + world.setBlockState(new BlockPos(ix - chestlength, builderHeight + 7, kz + 3), Blocks.CHEST.getStateFromMeta(2)); + } + } + + // move lights builder a bit higher, to support non-opaque lights + // such as lamps + if (towerLightBlockID == Blocks.TORCH) + { + world.setBlockState(new BlockPos(ix + 3, builderHeight + 2, kz - 6), towerLightBlockID.getStateFromMeta(0).withProperty(BlockTorch.FACING, EnumFacing.SOUTH), 2); + world.setBlockState(new BlockPos(ix - 4, builderHeight + 2, kz - 6), towerLightBlockID.getStateFromMeta(0).withProperty(BlockTorch.FACING, EnumFacing.SOUTH), 2); + world.setBlockState(new BlockPos(ix + 1, builderHeight + 2, kz - 4), towerLightBlockID.getStateFromMeta(0).withProperty(BlockTorch.FACING, EnumFacing.SOUTH), 2); + world.setBlockState(new BlockPos(ix - 2, builderHeight + 2, kz - 4), towerLightBlockID.getStateFromMeta(0).withProperty(BlockTorch.FACING, EnumFacing.SOUTH), 2); + } + else + { + world.setBlockState(new BlockPos(ix + 3, builderHeight + 2, kz - 6), towerLightBlockID.getStateFromMeta(0)); + world.setBlockState(new BlockPos(ix - 4, builderHeight + 2, kz - 6), towerLightBlockID.getStateFromMeta(0)); + world.setBlockState(new BlockPos(ix + 1, builderHeight + 2, kz - 4), towerLightBlockID.getStateFromMeta(0)); + world.setBlockState(new BlockPos(ix - 2, builderHeight + 2, kz - 4), towerLightBlockID.getStateFromMeta(0)); + } + + if (towerChosen != TowerTypes.Null) + { + for (int l3 = 0; l3 < (floor * 4 + towerChosen.ordinal()) - 8 && !topFloor; l3++) // random + // hole + // poker + { + int k4 = 5 - world.rand.nextInt(12); + int k5 = builderHeight + 5; + int j6 = 5 - world.rand.nextInt(10); + if (j6 < -2 && k4 < 4 && k4 > -5 && k4 != 1 && k4 != -2) + { + continue; + } + k4 += ix; + j6 += kz; + if (world.getBlockState(new BlockPos(k4, k5, j6)).getBlock() == towerFloorBlockID && world.getBlockState(new BlockPos(k4, k5 + 1, j6)).getBlock() != Blocks.MOB_SPAWNER) + { + world.setBlockState(new BlockPos(k4, k5, j6), Blocks.AIR.getDefaultState()); + } + } + } + + floor++; + } + + System.out.println("Dimension " + world.provider.getDimension() + " Battle Tower type " + towerChosen + " spawned at [ " + ix + " | " + kz + " ], underground: " + underground); + } + + @SuppressWarnings("deprecation") + private void buildFloorPiece(World world, int i, int j, int k, Block towerFloorBlockID, int towerFloorMeta) + { + world.setBlockState(new BlockPos(i, j, k), towerFloorBlockID.getStateFromMeta(towerFloorMeta)); + } + + private void buildWallPiece(World world, int i, int j, int k, Block towerWallBlockID, int floor, int floorIterator) + { + world.setBlockState(new BlockPos(i, j, k), towerWallBlockID.getDefaultState()); + if (floor == 1 && floorIterator == 4) + { + fillTowerBaseToGround(world, i, j, k, towerWallBlockID); + } + } + + private void fillTowerBaseToGround(World world, int i, int j, int k, Block blocktype) + { + int y = j - 1; + while (y > 0 && !isBuildableBlockID(world.getBlockState(new BlockPos(i, y, k)).getBlock())) + { + world.setBlockState(new BlockPos(i, y, k), blocktype.getDefaultState()); + y--; + } + } + + private int getSurfaceBlockHeight(World world, int x, int z) + { + int h = 50; + + do + { + h++; + } + while (world.getBlockState(new BlockPos(x, h, z)).getBlock() != Blocks.AIR && !isFoliageBlockID(world.getBlockState(new BlockPos(x, h, z)).getBlock())); + + return h - 1; + } + + private boolean isFoliageBlockID(Block ID) + { + return (ID == Blocks.SNOW || ID == Blocks.TALLGRASS || ID == Blocks.DEADBUSH || ID == Blocks.LOG || ID == Blocks.LOG2 || ID == Blocks.LEAVES); + } + + private boolean isBuildableBlockID(Block ID) + { + return (ID == Blocks.STONE || ID == Blocks.GRASS || ID == Blocks.SAND || ID == Blocks.SANDSTONE || ID == Blocks.GRAVEL || ID == Blocks.DIRT); + } + + private boolean isBannedBlockID(Block iD) + { + return (iD == Blocks.YELLOW_FLOWER || iD == Blocks.RED_FLOWER || iD == Blocks.BROWN_MUSHROOM_BLOCK || iD == Blocks.RED_MUSHROOM_BLOCK || iD == Blocks.CACTUS || iD == Blocks.PUMPKIN + || iD == Blocks.LAVA); + } + + private ResourceLocation getMobType(Random random) + { + switch (random.nextInt(10)) + { + case 0: + case 1: + case 2: + { + return EntityList.getKey(EntitySkeleton.class); + } + case 3: + case 4: + case 5: + case 6: + { + return EntityList.getKey(EntityZombie.class); + } + case 7: + case 8: + { + EntityList.getKey(EntitySpider.class); + } + case 9: + { + return EntityList.getKey(EntityCaveSpider.class); + } + default: + return EntityList.getKey(EntityZombie.class); + } + } + + public enum TowerTypes + { + Null("null", Blocks.AIR, Blocks.AIR, Blocks.AIR, 0, Blocks.AIR), + CobbleStone("cobblestone", Blocks.COBBLESTONE, Blocks.TORCH, Blocks.DOUBLE_STONE_SLAB, 0, Blocks.STONE_STAIRS), + CobbleStoneMossy("cobblestonemossy", Blocks.MOSSY_COBBLESTONE, Blocks.TORCH, Blocks.DOUBLE_STONE_SLAB, 0, Blocks.STONE_STAIRS), + SandStone("sandstone", Blocks.SANDSTONE, Blocks.TORCH, Blocks.DOUBLE_STONE_SLAB, 1, Blocks.SANDSTONE_STAIRS), + Ice("ice", Blocks.ICE, Blocks.AIR /* Blocks.GLOWSTONE */, Blocks.CLAY, 2, Blocks.OAK_STAIRS), // since + // when + // does + // glowstone + // melt + // ice + SmoothStone("smoothstone", Blocks.STONE, Blocks.TORCH, Blocks.DOUBLE_STONE_SLAB, 3, Blocks.STONE_STAIRS), + Netherrack("netherrack", Blocks.NETHERRACK, Blocks.GLOWSTONE, Blocks.SOUL_SAND, 0, Blocks.NETHER_BRICK_STAIRS), + Jungle("jungle", Blocks.MOSSY_COBBLESTONE, Blocks.WEB, Blocks.DIRT, 0, Blocks.JUNGLE_STAIRS); + + private Block wallBlockID; + private Block lightBlockID; + private Block floorBlockID; + private int floorBlockMetaData; + private Block stairBlockID; + private String typeName; + + TowerTypes(String t, Block a, Block b, Block c, int d, Block e) + { + this.wallBlockID = a; + this.lightBlockID = b; + this.floorBlockID = c; + this.floorBlockMetaData = d; + this.stairBlockID = e; + this.typeName = t; + } + + Block getWallBlockID() + { + return wallBlockID; + } + + Block getLightBlockID() + { + return lightBlockID; + } + + Block getFloorBlockID() + { + return floorBlockID; + } + + int getFloorBlockMetaData() + { + return floorBlockMetaData; + } + + Block getStairBlockID() + { + return stairBlockID; + } + + public String getName() + { + return this.typeName; + } + + public ResourceLocation getId() + { + return new ResourceLocation("battletowers:" + this.typeName); + } + } + +} diff --git a/src/main/java/atomicstryker/battletowers/common/CommandBattleTowers.java b/src/main/java/atomicstryker/battletowers/common/CommandBattleTowers.java new file mode 100644 index 0000000..a172fd2 --- /dev/null +++ b/src/main/java/atomicstryker/battletowers/common/CommandBattleTowers.java @@ -0,0 +1,14 @@ +package atomicstryker.battletowers.common; + +import net.minecraft.command.CommandBase; + +public abstract class CommandBattleTowers extends CommandBase +{ + + @Override + public int getRequiredPermissionLevel() + { + return 2; + } + +} diff --git a/src/main/java/atomicstryker/battletowers/common/CommandDeleteAllBattleTowers.java b/src/main/java/atomicstryker/battletowers/common/CommandDeleteAllBattleTowers.java new file mode 100644 index 0000000..aa78363 --- /dev/null +++ b/src/main/java/atomicstryker/battletowers/common/CommandDeleteAllBattleTowers.java @@ -0,0 +1,30 @@ +package atomicstryker.battletowers.common; + +import org.apache.logging.log4j.Level; + +import net.minecraft.command.ICommandSender; +import net.minecraft.server.MinecraftServer; + +public class CommandDeleteAllBattleTowers extends CommandBattleTowers +{ + + @Override + public String getName() + { + return "deleteallbattletowers"; + } + + @Override + public String getUsage(ICommandSender icommandsender) + { + return "/deleteallbattletowers deletes all existing Battletowers, as logged in save file"; + } + + @Override + public void execute(MinecraftServer server, ICommandSender icommandsender, String[] astring) + { + WorldGenHandler.deleteAllTowers(icommandsender.getEntityWorld(), false); + AS_BattleTowersCore.LOGGER.log(Level.INFO, icommandsender.getName() + ": All Battletowers deleted"); + } + +} diff --git a/src/main/java/atomicstryker/battletowers/common/CommandDeleteBattleTower.java b/src/main/java/atomicstryker/battletowers/common/CommandDeleteBattleTower.java new file mode 100644 index 0000000..ba28634 --- /dev/null +++ b/src/main/java/atomicstryker/battletowers/common/CommandDeleteBattleTower.java @@ -0,0 +1,63 @@ +package atomicstryker.battletowers.common; + +import org.apache.logging.log4j.Level; + +import atomicstryker.battletowers.common.WorldGenHandler.TowerPosition; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.command.WrongUsageException; +import net.minecraft.entity.Entity; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.math.AxisAlignedBB; + +public class CommandDeleteBattleTower extends CommandBattleTowers +{ + + @Override + public String getName() + { + return "deletebattletower"; + } + + @Override + public String getUsage(ICommandSender icommandsender) + { + return "/deletebattletower deletes the nearest existing Battletower, given x,z coordinates"; + } + + @Override + public void execute(MinecraftServer server, ICommandSender icommandsender, String[] astring) throws CommandException + { + if (astring.length < 2) + { + throw new WrongUsageException("Invalid Usage of Battletower delete command, must provide x,z coordinates", (Object) astring); + } + else + { + try + { + int x = Integer.valueOf(astring[0]); + int z = Integer.valueOf(astring[1]); + TowerPosition tp = WorldGenHandler.deleteNearestTower(icommandsender.getEntityWorld(), x, z); + if (tp != null) + { + AS_BattleTowersCore.LOGGER.log(Level.INFO, icommandsender.getName() + ": Battletower deleted: " + tp.toString()); + for (Object o : icommandsender.getEntityWorld().getEntitiesWithinAABB(AS_EntityGolem.class, new AxisAlignedBB(tp.x - 10, 0.0D, tp.z - 10, tp.x + 10, 255, tp.z + 10))) + { + ((Entity) o).setDead(); + break; + } + } + else + { + AS_BattleTowersCore.LOGGER.log(Level.INFO, icommandsender.getName() + ": no Battletower deleted, no valid target"); + } + } + catch (Exception e) + { + throw new WrongUsageException("Invalid Usage of Battletower delete command, must provide x,z coordinates", (Object) astring); + } + } + } + +} diff --git a/src/main/java/atomicstryker/battletowers/common/CommandRegenerateAllBattleTowers.java b/src/main/java/atomicstryker/battletowers/common/CommandRegenerateAllBattleTowers.java new file mode 100644 index 0000000..deee313 --- /dev/null +++ b/src/main/java/atomicstryker/battletowers/common/CommandRegenerateAllBattleTowers.java @@ -0,0 +1,30 @@ +package atomicstryker.battletowers.common; + +import org.apache.logging.log4j.Level; + +import net.minecraft.command.ICommandSender; +import net.minecraft.server.MinecraftServer; + +public class CommandRegenerateAllBattleTowers extends CommandBattleTowers +{ + + @Override + public String getName() + { + return "regenerateallbattletowers"; + } + + @Override + public String getUsage(ICommandSender icommandsender) + { + return "/regenerateallbattletowers re-spawns all Battletowers and their golems"; + } + + @Override + public void execute(MinecraftServer server, ICommandSender icommandsender, String[] astring) + { + WorldGenHandler.deleteAllTowers(icommandsender.getEntityWorld(), true); + AS_BattleTowersCore.LOGGER.log(Level.INFO, icommandsender.getName() + ": Battletowers regenerated"); + } + +} diff --git a/src/main/java/atomicstryker/battletowers/common/CommandRegenerateBattleTower.java b/src/main/java/atomicstryker/battletowers/common/CommandRegenerateBattleTower.java new file mode 100644 index 0000000..08a83b6 --- /dev/null +++ b/src/main/java/atomicstryker/battletowers/common/CommandRegenerateBattleTower.java @@ -0,0 +1,65 @@ +package atomicstryker.battletowers.common; + +import org.apache.logging.log4j.Level; + +import atomicstryker.battletowers.common.WorldGenHandler.TowerPosition; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.command.WrongUsageException; +import net.minecraft.entity.Entity; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.math.AxisAlignedBB; + +public class CommandRegenerateBattleTower extends CommandBattleTowers +{ + + @Override + public String getName() + { + return "regeneratebattletower"; + } + + @Override + public String getUsage(ICommandSender icommandsender) + { + return "/regeneratebattletower re-spawns the nearest existing Battletower, given x,z coordinates"; + } + + @Override + public void execute(MinecraftServer server, ICommandSender icommandsender, String[] astring) throws CommandException + { + if (astring.length < 2) + { + throw new WrongUsageException("Invalid Usage of Battletower regenerate command, must provide x,z coordinates", (Object) astring); + } + else + { + try + { + int x = Integer.valueOf(astring[0]); + int z = Integer.valueOf(astring[1]); + TowerPosition tp = WorldGenHandler.deleteNearestTower(icommandsender.getEntityWorld(), x, z); + if (tp != null) + { + AS_BattleTowersCore.LOGGER.log(Level.INFO, icommandsender.getName() + ": Battletower regenerated: " + tp.toString()); + for (Object o : icommandsender.getEntityWorld().getEntitiesWithinAABB(AS_EntityGolem.class, new AxisAlignedBB(tp.x - 10, 0.0D, tp.z - 10, tp.x + 10, 255, tp.z + 10))) + { + ((Entity) o).setDead(); + break; + } + + WorldGenHandler.generateTower(icommandsender.getEntityWorld(), tp.x, tp.y, tp.z, tp.type, tp.underground); + } + else + { + AS_BattleTowersCore.LOGGER.log(Level.INFO, icommandsender.getName() + ": no Battletower regenerated, no valid target"); + } + } + catch (Exception e) + { + throw new WrongUsageException("Invalid Usage of Battletower regenerate command, must provide x,z coordinates", (Object) astring); + } + } + } + +} diff --git a/src/main/java/atomicstryker/battletowers/common/CommandSpawnBattleTower.java b/src/main/java/atomicstryker/battletowers/common/CommandSpawnBattleTower.java new file mode 100644 index 0000000..7948ef6 --- /dev/null +++ b/src/main/java/atomicstryker/battletowers/common/CommandSpawnBattleTower.java @@ -0,0 +1,51 @@ +package atomicstryker.battletowers.common; + +import org.apache.logging.log4j.Level; + +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.command.WrongUsageException; +import net.minecraft.server.MinecraftServer; + +public class CommandSpawnBattleTower extends CommandBattleTowers +{ + + @Override + public String getName() + { + return "spawnbattletower"; + } + + @Override + public String getUsage(ICommandSender icommandsender) + { + return "/spawnbattletower spawns a Battletower with supplied data x,y,z,type,underground"; + } + + @Override + public void execute(MinecraftServer server, ICommandSender icommandsender, String[] astring) throws CommandException + { + if (astring.length < 5) + { + throw new WrongUsageException("Invalid Usage of Battletower spawn command", (Object) astring); + } + else + { + try + { + int x = Integer.valueOf(astring[0]); + int y = Integer.valueOf(astring[1]); + int z = Integer.valueOf(astring[2]); + int type = Integer.valueOf(astring[3]); + boolean underground = Boolean.valueOf(astring[4]); + WorldGenHandler.generateTower(icommandsender.getEntityWorld(), x, y, z, type, underground); + AS_BattleTowersCore.LOGGER.log(Level.INFO, icommandsender.getName() + ": Battletower spawned"); + } + catch (Exception e) + { + throw new WrongUsageException("Invalid Usage of Battletower spawn command", (Object) astring); + } + } + } + +} diff --git a/src/main/java/atomicstryker/battletowers/common/CommonProxy.java b/src/main/java/atomicstryker/battletowers/common/CommonProxy.java new file mode 100644 index 0000000..eaf174f --- /dev/null +++ b/src/main/java/atomicstryker/battletowers/common/CommonProxy.java @@ -0,0 +1,14 @@ +package atomicstryker.battletowers.common; + +public class CommonProxy +{ + public void preInit() + { + // NOOP + } + + public void load() + { + // NOOP + } +} diff --git a/src/main/java/atomicstryker/battletowers/common/DungeonTweaksCompat.java b/src/main/java/atomicstryker/battletowers/common/DungeonTweaksCompat.java new file mode 100644 index 0000000..85238ef --- /dev/null +++ b/src/main/java/atomicstryker/battletowers/common/DungeonTweaksCompat.java @@ -0,0 +1,122 @@ +package atomicstryker.battletowers.common; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.util.Random; + +import atomicstryker.battletowers.common.AS_WorldGenTower.TowerTypes; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.tileentity.TileEntityMobSpawner; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.Loader; +import net.minecraftforge.fml.common.eventhandler.Event; + +/** + * this is backwards and modern dungeon tweaks compatible + * + * @author jredfox + * + */ +public class DungeonTweaksCompat +{ + + public static boolean isLegacy = false; + public static boolean isLoaded = false; + + /** + * make backwards compatability when isLegacy becomes true + */ + public static void legacyCheck() + { + isLoaded = Loader.isModLoaded("dungeontweaks"); + + if(!isLoaded) + { + return; + } + + try + { + Class c = Class.forName("com.EvilNotch.dungeontweeks.main.Events.EventDungeon$Post"); + isLegacy = true; + } + catch (Throwable t) + { + + } + } + + /** + * register all dungeon tweaks mobs to anydim towers + */ + public static void registerDungeons() + { + if (!isLoaded || isLegacy) + { + return;// I supported this mod in older versions + } + + try + { + Method addDungeonMob = Class.forName("com.evilnotch.dungeontweeks.main.world.worldgen.mobs.DungeonMobs").getMethod("addDungeonMob", ResourceLocation.class, ResourceLocation.class, + int.class); + for (AS_WorldGenTower.TowerTypes tower : AS_WorldGenTower.TowerTypes.values()) + { + boolean nether = tower == TowerTypes.Netherrack; + addDungeonMob.invoke(null, tower.getId(), new ResourceLocation("cave_spider"), 100); + addDungeonMob.invoke(null, tower.getId(), new ResourceLocation("spider"), 90); + addDungeonMob.invoke(null, tower.getId(), nether ? new ResourceLocation("wither_skeleton") : new ResourceLocation("skeleton"), 120); + addDungeonMob.invoke(null, tower.getId(), new ResourceLocation("zombie"), 120); + + if (nether) + { + addDungeonMob.invoke(null, tower.getId(), new ResourceLocation("blaze"), 20); + } + } + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + /** + * fire the event based upon tower definitions + */ + public static void fireDungeonSpawn(TileEntityMobSpawner spawner, World world, Random random, TowerTypes towerChosen) + { + ResourceLocation towerId = towerChosen.getId(); + if (isLegacy) + { + try + { + @SuppressWarnings("unchecked") + Constructor constructor = (Constructor) Class.forName("com.EvilNotch.dungeontweeks.main.Events.EventDungeon$Post").getConstructor(TileEntity.class, + BlockPos.class, Random.class, ResourceLocation.class, World.class); + Event event = constructor.newInstance(spawner, spawner.getPos(), world.rand, towerId, world); + MinecraftForge.EVENT_BUS.post(event); + } + catch (Throwable t) + { + t.printStackTrace(); + } + } + else + { + try + { + Method fireDungeonTweaks = Class.forName("com.evilnotch.dungeontweeks.main.world.worldgen.mobs.DungeonMobs").getMethod("fireDungeonTweaks", ResourceLocation.class, TileEntity.class, + Random.class, World.class); + fireDungeonTweaks.invoke(null, towerId, spawner, random, world); + } + catch (Throwable t) + { + t.printStackTrace(); + } + } + } + +} diff --git a/src/main/java/atomicstryker/battletowers/common/ServerTickHandler.java b/src/main/java/atomicstryker/battletowers/common/ServerTickHandler.java new file mode 100644 index 0000000..08b1f41 --- /dev/null +++ b/src/main/java/atomicstryker/battletowers/common/ServerTickHandler.java @@ -0,0 +1,39 @@ +package atomicstryker.battletowers.common; + +import java.util.Iterator; + +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +public class ServerTickHandler +{ + private long time; + + public ServerTickHandler() + { + time = System.currentTimeMillis(); + } + + @SubscribeEvent + public void onTick(TickEvent.WorldTickEvent tick) + { + if (System.currentTimeMillis() > time + 1000L) // its a one second timer OMFG + { + time = System.currentTimeMillis(); + Iterator iter = AS_BattleTowersCore.getTowerDestroyers().iterator(); + while(iter.hasNext()) + { + AS_TowerDestroyer td = iter.next(); + if (td.isFinished()) + { + iter.remove(); + } + else + { + td.update(); + } + } + } + } + +} diff --git a/src/main/java/atomicstryker/battletowers/common/TowerStageItemManager.java b/src/main/java/atomicstryker/battletowers/common/TowerStageItemManager.java new file mode 100644 index 0000000..777255b --- /dev/null +++ b/src/main/java/atomicstryker/battletowers/common/TowerStageItemManager.java @@ -0,0 +1,186 @@ +package atomicstryker.battletowers.common; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Random; + +import net.minecraft.block.Block; +import net.minecraft.init.Blocks; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntityChest; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; +import net.minecraft.world.storage.loot.LootContext; +import net.minecraft.world.storage.loot.LootTable; +import net.minecraftforge.fml.common.registry.ForgeRegistries; + +public class TowerStageItemManager +{ + + private Object[] itemID; + private int[] itemDamage; + private int[] chanceToSpawn; + private int[] minAmount; + private int[] maxAmount; + + /** + * @param configString + * see TowerStageItemManager in AS_BattleTowersCore for example + * String + */ + public TowerStageItemManager(String configString) + { + String[] elements = configString.split(";"); + itemID = new Object[elements.length]; + itemDamage = new int[elements.length]; + chanceToSpawn = new int[elements.length]; + minAmount = new int[elements.length]; + maxAmount = new int[elements.length]; + + ArrayList validItemIndexes = new ArrayList(); + for (int i = 0; i < elements.length; i++) + { + String[] settings = elements[i].trim().split("-"); + + if (settings.length < 5 && !settings[0].startsWith("ChestGenHook:")) + { + System.err.println("Battletowers skipping invalid entry [" + elements[i].trim() + "], fix config file!"); + } + else + { + itemID[i] = tryFindingObject(settings[0]); + if (itemID[i] != null) + { + validItemIndexes.add(i); + itemDamage[i] = Integer.parseInt(settings[1]); + chanceToSpawn[i] = Integer.parseInt(settings[2]); + minAmount[i] = Integer.parseInt(settings[3]); + maxAmount[i] = Integer.parseInt(settings[4]); + } + else if (settings[0].startsWith("ChestGenHook:")) + { + validItemIndexes.add(i); + itemID[i] = settings[0]; + chanceToSpawn[i] = 100; + } + + if (itemID[i] != null) + { + System.out.println("Battletowers parsed Item/Block/ChestGenHook " + itemID[i]); + } + else + { + System.out.println("Battletowers failed parsing or finding Item/Block " + settings[0]); + } + // System.out.println("Name of that Item: + // "+Item.itemsList[itemID[i]].getItemName()); + } + } + + final Object[] itemIDf = new Object[validItemIndexes.size()]; + final int[] itemDamagef = new int[validItemIndexes.size()]; + final int[] chanceToSpawnf = new int[validItemIndexes.size()]; + final int[] minAmountf = new int[validItemIndexes.size()]; + final int[] maxAmountf = new int[validItemIndexes.size()]; + int assigned; + for (int i = 0; i < validItemIndexes.size(); i++) + { + assigned = validItemIndexes.get(i); + itemIDf[i] = itemID[assigned]; + itemDamagef[i] = itemDamage[assigned]; + chanceToSpawnf[i] = chanceToSpawn[assigned]; + minAmountf[i] = minAmount[assigned]; + maxAmountf[i] = maxAmount[assigned]; + } + + itemID = itemIDf; + itemDamage = itemDamagef; + chanceToSpawn = chanceToSpawnf; + minAmount = minAmountf; + maxAmount = maxAmountf; + } + + private Object tryFindingObject(String s) + { + ResourceLocation rl = new ResourceLocation(s); + Item item = ForgeRegistries.ITEMS.getValue(rl); + if (item != null) + { + return item; + } + + Block block = ForgeRegistries.BLOCKS.getValue(rl); + if (block != Blocks.AIR) + { + return block; + } + return null; + } + + /** + * @param toCopy + * TowerStageItemManager you need an image of + */ + public TowerStageItemManager(TowerStageItemManager toCopy) + { + itemID = toCopy.itemID.clone(); + itemDamage = toCopy.itemDamage.clone(); + chanceToSpawn = toCopy.chanceToSpawn.clone(); + minAmount = toCopy.minAmount.clone(); + maxAmount = toCopy.maxAmount.clone(); + } + + /** + * @param rand + * your WorldGen Random + * @param teChest + * chest tileentity to fill with loot + * @param count + * how many slots worth of itemstacks are supposed to be + * generated + * @return ItemStack instance of the configured Block or Item with amount, + * or null + */ + public List getStageItemStacks(World world, Random rand, TileEntityChest teChest, int count) + { + List result = new ArrayList<>(); + int index = 0; + while (result.size() < count && index < itemID.length) + { + if (itemID[index] instanceof Item && rand.nextInt(100) < chanceToSpawn[index]) + { + result.add(new ItemStack((Item) itemID[index], minAmount[index] + rand.nextInt(maxAmount[index]), itemDamage[index])); + } + else if (itemID[index] instanceof Block && rand.nextInt(100) < chanceToSpawn[index]) + { + result.add(new ItemStack((Block) itemID[index], minAmount[index] + rand.nextInt(maxAmount[index]), itemDamage[index])); + } + else if (itemID[index] instanceof String) // ChestGenHook:strongholdLibrary:5 + { + String[] split = ((String) itemID[index]).split(":"); + LootTable loottable = world.getLootTableManager().getLootTableFromLocation(new ResourceLocation(split[1])); + List generatedItems = loottable.generateLootForPools(rand, new LootContext.Builder((WorldServer) world).build()); + + if (split.length > 2) + { + int number = Integer.valueOf(split[2]); + if (number > 0) + { + while (generatedItems.size() > number) + { + Collections.shuffle(generatedItems); + generatedItems.remove(generatedItems.size() - 1); + } + result.addAll(generatedItems); + } + } + } + + index++; + } + return result; + } +} diff --git a/src/main/java/atomicstryker/battletowers/common/WorldGenHandler.java b/src/main/java/atomicstryker/battletowers/common/WorldGenHandler.java new file mode 100644 index 0000000..0a03a3a --- /dev/null +++ b/src/main/java/atomicstryker/battletowers/common/WorldGenHandler.java @@ -0,0 +1,535 @@ +package atomicstryker.battletowers.common; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +import net.minecraft.entity.Entity; +import net.minecraft.init.Blocks; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.chunk.IChunkProvider; +import net.minecraft.world.gen.IChunkGenerator; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.config.Configuration; +import net.minecraftforge.event.world.WorldEvent; +import net.minecraftforge.fml.common.IWorldGenerator; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +public class WorldGenHandler implements IWorldGenerator +{ + + private final static String fileName = "BattletowerPositionsFile.txt"; + + private final static WorldGenHandler instance = new WorldGenHandler(); + private HashMap biomesMap; + private HashMap dimensionsMap; + private HashMap providerMap; + private final static Map worldMap = new HashMap<>(); + public static boolean shouldClearWorldMap = false; + + private final AS_WorldGenTower generator; + + public WorldGenHandler() + { + biomesMap = new HashMap(); + providerMap = new HashMap(); + dimensionsMap = new HashMap(); + generator = new AS_WorldGenTower(); + + MinecraftForge.EVENT_BUS.register(this); + } + + private class WorldHandle + { + boolean posFileLoaded; + File worldSaveDirectory; + final ArrayList towerPositions = new ArrayList(); + boolean towerPositionsAccessLock; + int disableGenerationHook; + } + + public static void wipeWorldHandles() + { + worldMap.clear(); + } + + @SubscribeEvent + public void eventWorldLoad(WorldEvent.Load evt) + { + if(shouldClearWorldMap) + { + wipeWorldHandles(); + shouldClearWorldMap = false; + } + + WorldHandle wh = getWorldHandle(evt.getWorld()); + if (!wh.posFileLoaded) + { + wh.posFileLoaded = true; + loadPosFile(wh, new File(wh.worldSaveDirectory, fileName), evt.getWorld()); + } + } + + private WorldHandle getWorldHandle(World world) + { + Integer dimension = world.provider.getDimension(); + WorldHandle result = worldMap.get(dimension); + if (result == null) + { + result = new WorldHandle(); + result.worldSaveDirectory = world.getSaveHandler().getWorldDirectory(); + if (result.worldSaveDirectory != null) + { + String dim_folder = ""; + if (dimension != 0) + dim_folder = File.separator + world.provider.getSaveFolder(); + try + { + result.worldSaveDirectory = new File(world.getSaveHandler().getWorldDirectory().getCanonicalPath() + dim_folder); + } + catch (IOException e) + { + // Failed, revert to old handling for safety + result.worldSaveDirectory = world.getSaveHandler().getWorldDirectory(); + e.printStackTrace(); + } + } + result.posFileLoaded = false; + result.towerPositionsAccessLock = false; + result.disableGenerationHook = 0; + worldMap.put(dimension, result); + } + return result; + } + + @SubscribeEvent + public void eventWorldSave(WorldEvent.Save evt) + { + WorldHandle wh = getWorldHandle(evt.getWorld()); + flushCurrentPosListToFile(wh, wh.worldSaveDirectory); + } + + @Override + public void generate(Random random, int chunkX, int chunkZ, World world, IChunkGenerator chunkGenerator, IChunkProvider chunkProvider) + { + WorldHandle wh = getWorldHandle(world); + if (wh.disableGenerationHook > 0) + { + return; + } + Biome target = world.getBiome(new BlockPos(chunkX, 0, chunkZ)); + if (target != Biome.getBiome(8) && getIsBiomeAllowed(target) && getIsChunkProviderAllowed(chunkProvider) && getIsDimensionAllowed(world)) + { + generateSurface(wh, world, random, chunkX * 16, chunkZ * 16); + } + } + + private boolean getIsChunkProviderAllowed(IChunkProvider chunkProvider) + { + String name = chunkProvider.getClass().getSimpleName(); + if (providerMap.containsKey(name)) + { + return providerMap.get(name); + } + + Configuration config = AS_BattleTowersCore.instance.configuration; + config.load(); + boolean result = config.get("ChunkProviderAllowed", name, true).getBoolean(true); + config.save(); + providerMap.put(name, result); + return result; + } + + private boolean getIsBiomeAllowed(Biome target) + { + if (biomesMap.containsKey(target.getRegistryName().getResourcePath())) + { + return biomesMap.get(target.getRegistryName().getResourcePath()); + } + + Configuration config = AS_BattleTowersCore.instance.configuration; + config.load(); + boolean result = config.get("BiomeSpawnAllowed", target.getRegistryName().getResourcePath(), true).getBoolean(true); + config.save(); + biomesMap.put(target.getRegistryName().getResourcePath(), result); + return result; + } + + private boolean getIsDimensionAllowed(World world) + { + if (dimensionsMap.containsKey(world.provider.getDimensionType().getName())) + { + return dimensionsMap.get(world.provider.getDimensionType().getName()); + } + + Configuration config = AS_BattleTowersCore.instance.configuration; + config.load(); + boolean result = config.get("DimensionSpawnAllowed", world.provider.getDimensionType().getName(), true).getBoolean(true); + config.save(); + dimensionsMap.put(world.provider.getDimensionType().getName(), result); + return result; + } + + private void generateSurface(WorldHandle wh, World world, Random random, int xActual, int zActual) + { + TowerPosition pos = canTowerSpawnAt(wh, world, xActual, zActual); + if (pos != null) + { + obtainTowerPosListAccess(wh); + wh.towerPositions.add(pos); + releaseTowerPosListAccess(wh); + int y = getSurfaceBlockHeight(world, xActual, zActual); + if (y > 49) + { + pos.y = y; + if (!attemptToSpawnTower(world, pos, random, xActual, y, zActual)) + { + System.out.printf("Tower Site [%d|%d] rejected: %s\n", pos.x, pos.z, generator.failState); + obtainTowerPosListAccess(wh); + wh.towerPositions.remove(pos); + releaseTowerPosListAccess(wh); + } + } + } + } + + private boolean attemptToSpawnTower(World world, TowerPosition pos, Random random, int x, int y, int z) + { + int choice = generator.getChosenTowerOrdinal(world, random, x, y, z); + pos.type = choice; + + if (choice >= 0) + { + pos.underground = world.rand.nextInt(100) + 1 < AS_BattleTowersCore.instance.chanceTowerIsUnderGround; + generator.generate(world, random, x, y, z, choice, pos.underground); + return true; + } + + return false; + } + + public static void generateTower(World world, int x, int y, int z, int type, boolean underground) + { + WorldHandle wh = instance.getWorldHandle(world); + wh.disableGenerationHook++; + instance.generator.generate(world, world.rand, x, y, z, type, underground); + obtainTowerPosListAccess(wh); + wh.towerPositions.add(instance.new TowerPosition(x, y, z, type, underground)); + releaseTowerPosListAccess(wh); + wh.disableGenerationHook--; + } + + private int getSurfaceBlockHeight(World world, int x, int z) + { + int h = 50; + + do + { + h++; + } + while (world.getBlockState(new BlockPos(x, h, z)).getBlock() != Blocks.AIR); + + return h - 1; + } + + public static TowerStageItemManager getTowerStageManagerForFloor(int floor) + { + // wait for load if it hasnt happened yet + while (AS_BattleTowersCore.instance.floorItemManagers == null) + { + Thread.yield(); + } + + floor--; // subtract 1 to match the floors to the array + + if (floor >= AS_BattleTowersCore.instance.floorItemManagers.length) + { + floor = AS_BattleTowersCore.instance.floorItemManagers.length - 1; + } + if (floor < 0) + { + floor = 0; + } + + return new TowerStageItemManager(AS_BattleTowersCore.instance.floorItemManagers[floor]); + } + + private synchronized static void obtainTowerPosListAccess(WorldHandle worldHandle) + { + int counter = 0; + while (worldHandle.towerPositionsAccessLock) + { + if (counter >= 0) + counter++; + if (counter > 100000) + { + new Exception().printStackTrace(System.out); + counter = -1; + } + Thread.yield(); + } + worldHandle.towerPositionsAccessLock = true; + } + + private static void releaseTowerPosListAccess(WorldHandle worldHandle) + { + worldHandle.towerPositionsAccessLock = false; + } + + private TowerPosition canTowerSpawnAt(WorldHandle worldHandle, World world, int xActual, int zActual) + { + BlockPos spawn = world.getSpawnPoint(); + if (Math.sqrt((spawn.getX() - xActual) * (spawn.getX() - xActual) + (spawn.getZ() - zActual) * (spawn.getZ() - zActual)) < AS_BattleTowersCore.instance.minDistanceFromSpawn) + { + return null; + } + + if (AS_BattleTowersCore.instance.minDistanceBetweenTowers > 0) + { + double mindist = 9999f; + obtainTowerPosListAccess(worldHandle); + for (TowerPosition temp : worldHandle.towerPositions) + { + int diffX = temp.x - xActual; + int diffZ = temp.z - zActual; + double dist = Math.sqrt(diffX * diffX + diffZ * diffZ); + mindist = Math.min(mindist, dist); + if (dist < AS_BattleTowersCore.instance.minDistanceBetweenTowers) + { + // System.out.printf("refusing site coords [%d,%d], mindist + // %f\n", xActual, zActual, mindist); + releaseTowerPosListAccess(worldHandle); + return null; + } + } + System.out.printf("Logged %d towers so far for world %s, accepted new site coords [%d,%d], mindist %f\n", worldHandle.towerPositions.size(), worldHandle.worldSaveDirectory, xActual, + zActual, mindist); + releaseTowerPosListAccess(worldHandle); + } + + return new TowerPosition(xActual, 0, zActual, 0, false); + } + + public class TowerPosition implements Comparable + { + int x; + int y; + int z; + int type; + boolean underground; + + public TowerPosition(int ix, int iy, int iz, int itype, boolean under) + { + x = ix; + y = iy; + z = iz; + type = itype; + underground = under; + } + + @Override + public String toString() + { + return x + " " + y + " " + z + " " + type + " " + underground; + } + + public TowerPosition fromString(String s) + { + String[] data = s.split(" "); + return new TowerPosition(Integer.valueOf(data[0]), Integer.valueOf(data[1]), Integer.valueOf(data[2]), Integer.valueOf(data[3]), Boolean.valueOf(data[4])); + } + + @Override + public boolean equals(Object o) + { + if (o instanceof TowerPosition) + { + TowerPosition t = (TowerPosition) o; + return t.x == x && t.y == y && t.z == z; + } + return false; + } + + @Override + public int hashCode() + { + return x + z << 8 + y << 16; + } + + @Override + public int compareTo(TowerPosition o) + { + return o.x < x ? 1 : o.x > x ? -1 : o.z < z ? 1 : o.z > z ? -1 : 0; + } + } + + private static void loadPosFile(WorldHandle worldHandle, File file, World world) + { + if (!file.getAbsolutePath().contains(world.getWorldInfo().getWorldName())) + { + return; + } + + obtainTowerPosListAccess(worldHandle); + try + { + if (!file.exists()) + { + if (!file.createNewFile()) + { + throw new RuntimeException("Battletowers mod crashed trying to create pos file " + file); + } + } + int lineNumber = 1; + BufferedReader br = new BufferedReader(new FileReader(file)); + String line = br.readLine(); + TowerPosition tp = instance.new TowerPosition(0, 0, 0, 0, false); + while (line != null) + { + line = line.trim(); + if (!line.startsWith("#")) + { + try + { + TowerPosition newtp = tp.fromString(line); + if (!worldHandle.towerPositions.contains(newtp)) + { + worldHandle.towerPositions.add(tp.fromString(line)); + } + } + catch (Exception e) + { + System.err.println("Battletowers positions file is invalid in line " + lineNumber + ", skipping..."); + } + } + + lineNumber++; + line = br.readLine(); + } + br.close(); + System.out.println("Battletower Positions reloaded. Lines " + lineNumber + ", entries " + worldHandle.towerPositions.size()); + } + catch (Exception e) + { + e.printStackTrace(); + } + releaseTowerPosListAccess(worldHandle); + } + + private static void flushCurrentPosListToFile(WorldHandle worldHandle, File worldSaveFile) + { + if (worldHandle.towerPositions.isEmpty()) + { + return; + } + + obtainTowerPosListAccess(worldHandle); + File file = new File(worldSaveFile, fileName); + if (file.exists()) + { + if (!file.delete()) + { + throw new RuntimeException("Battletowers mod crashed because it was denied file write access to " + file); + } + } + + try + { + PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(file))); + pw.println("# Behold! The Battletower position management file. Below, you see all data accumulated by AtomicStrykers Battletowers during the last run of this World."); + pw.println("# Data is noted as follows: Each line stands for one successfull Battletower spawn. Data syntax is:"); + pw.println("# xCoordinate yCoordinate zCoordinate towerType towerUnderground"); + pw.println("# everything but the last value is an integer value. Towertypes values are:"); + pw.println("# 0: Null, 1: Cobblestone, 2: Mossy Cobblestone, 3: Sandstone, 4: Ice, 5: Smoothstone, 6: Nether, 7: Jungle"); + pw.println("#"); + pw.println("# DO NOT EDIT THIS FILE UNLESS YOU ARE SURE OF WHAT YOU ARE DOING"); + pw.println("#"); + pw.println("# the primary function of this file is to enable regeneration or removal of spawned Battletowers."); + pw.println("# that is possible via commands /regenerateallbattletowers and /deleteallbattletowers."); + pw.println("# do not change values once towers have spawned! Either do that before creating a World (put this file in a world named folder)..."); + pw.println("# ... or use /deletebattletowers, exit the game, modify this file any way you want, load the world, then use /regeneratebattletowers!"); + + for (TowerPosition t : worldHandle.towerPositions) + { + pw.println(t.toString()); + } + + pw.flush(); + pw.close(); + } + catch (IOException e) + { + e.printStackTrace(); + } + releaseTowerPosListAccess(worldHandle); + } + + public static TowerPosition deleteNearestTower(World world, int x, int z) + { + double lowestDist = 9999d; + TowerPosition chosen = null; + WorldHandle worldHandle = instance.getWorldHandle(world); + + worldHandle.disableGenerationHook++; + obtainTowerPosListAccess(worldHandle); + for (TowerPosition tp : worldHandle.towerPositions) + { + double dist = Math.sqrt((tp.x - x) * (tp.x - x) + (tp.z - z) * (tp.z - z)); + if (dist < lowestDist) + { + lowestDist = dist; + chosen = tp; + } + } + releaseTowerPosListAccess(worldHandle); + worldHandle.disableGenerationHook--; + + if (chosen != null) + { + instance.generator.generate(world, world.rand, chosen.x, chosen.y, chosen.z, AS_WorldGenTower.TowerTypes.Null.ordinal(), chosen.underground); + obtainTowerPosListAccess(worldHandle); + worldHandle.towerPositions.remove(chosen); + releaseTowerPosListAccess(worldHandle); + } + + return chosen; + } + + public static void deleteAllTowers(World world, boolean regenerate) + { + WorldHandle wh = instance.getWorldHandle(world); + + for (Object o : world.loadedEntityList) + { + if (o instanceof AS_EntityGolem) + { + ((Entity) o).setDead(); + } + } + + wh.disableGenerationHook++; + obtainTowerPosListAccess(wh); + for (TowerPosition tp : wh.towerPositions) + { + instance.generator.generate(world, world.rand, tp.x, tp.y, tp.z, regenerate ? tp.type : AS_WorldGenTower.TowerTypes.Null.ordinal(), tp.underground); + } + + if (!regenerate) + { + wh.towerPositions.clear(); + } + releaseTowerPosListAccess(wh); + wh.disableGenerationHook--; + } + +} diff --git a/src/main/java/atomicstryker/battletowers/common/network/ChestAttackedPacket.java b/src/main/java/atomicstryker/battletowers/common/network/ChestAttackedPacket.java new file mode 100644 index 0000000..18f698c --- /dev/null +++ b/src/main/java/atomicstryker/battletowers/common/network/ChestAttackedPacket.java @@ -0,0 +1,65 @@ +package atomicstryker.battletowers.common.network; + +import atomicstryker.battletowers.common.AS_EntityGolem; +import atomicstryker.battletowers.common.network.NetworkHelper.IPacket; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraftforge.fml.common.FMLCommonHandler; + +public class ChestAttackedPacket implements IPacket +{ + + private String playerName; + private int golemEntityID; + + // if there is a constructor with >0 args, we MUST supply another with no args + public ChestAttackedPacket() + { + playerName = ""; + golemEntityID = 0; + } + + public ChestAttackedPacket(String player, int id) + { + playerName = player; + golemEntityID = id; + } + + @Override + public void writeBytes(ChannelHandlerContext ctx, ByteBuf bytes) + { + bytes.writeShort(playerName.length()); + for (char c : playerName.toCharArray()) + bytes.writeChar(c); + bytes.writeInt(golemEntityID); + } + + @Override + public void readBytes(ChannelHandlerContext ctx, ByteBuf bytes) + { + short len = bytes.readShort(); + char[] chars = new char[len]; + for (int i = 0; i < len; i++) + { + chars[i] = bytes.readChar(); + } + playerName = String.valueOf(chars); + golemEntityID = bytes.readInt(); + + FMLCommonHandler.instance().getMinecraftServerInstance().addScheduledTask(() -> { + EntityPlayerMP p = FMLCommonHandler.instance().getMinecraftServerInstance().getPlayerList().getPlayerByUsername(playerName); + if (p != null) + { + Entity e = p.world.getEntityByID(golemEntityID); + if (e instanceof AS_EntityGolem) + { + AS_EntityGolem golem = (AS_EntityGolem) e; + golem.setAwake(); + golem.setAttackTarget(p); + } + } + }); + } +} \ No newline at end of file diff --git a/src/main/java/atomicstryker/battletowers/common/network/LoginPacket.java b/src/main/java/atomicstryker/battletowers/common/network/LoginPacket.java new file mode 100644 index 0000000..7ae40ab --- /dev/null +++ b/src/main/java/atomicstryker/battletowers/common/network/LoginPacket.java @@ -0,0 +1,23 @@ +package atomicstryker.battletowers.common.network; + +import atomicstryker.battletowers.common.AS_BattleTowersCore; +import atomicstryker.battletowers.common.network.NetworkHelper.IPacket; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; + +public class LoginPacket implements IPacket +{ + + @Override + public void writeBytes(ChannelHandlerContext ctx, ByteBuf bytes) + { + bytes.writeByte(AS_BattleTowersCore.instance.towerDestroyerEnabled); + } + + @Override + public void readBytes(ChannelHandlerContext ctx, ByteBuf bytes) + { + AS_BattleTowersCore.instance.towerDestroyerEnabled = bytes.readByte(); + } + +} \ No newline at end of file diff --git a/src/main/java/atomicstryker/battletowers/common/network/NetworkHelper.java b/src/main/java/atomicstryker/battletowers/common/network/NetworkHelper.java new file mode 100644 index 0000000..8f6f27d --- /dev/null +++ b/src/main/java/atomicstryker/battletowers/common/network/NetworkHelper.java @@ -0,0 +1,211 @@ +package atomicstryker.battletowers.common.network; + +import java.util.Collections; +import java.util.EnumMap; +import java.util.HashSet; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandler.Sharable; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraftforge.fml.common.network.FMLEmbeddedChannel; +import net.minecraftforge.fml.common.network.FMLIndexedMessageToMessageCodec; +import net.minecraftforge.fml.common.network.FMLOutboundHandler; +import net.minecraftforge.fml.common.network.NetworkRegistry; +import net.minecraftforge.fml.common.network.NetworkRegistry.TargetPoint; +import net.minecraftforge.fml.relauncher.Side; + +/** + * + * Helper class to wrap the new 1.7 Netty channels and packets into something + * resembling the older packet system. Create one instance of this for a Mod, + * then use the helper methods to send Packets. Packet Handling is done inside + * the packet classes themselves. + * + * @author AtomicStryker + * + */ +public class NetworkHelper +{ + + private final FMLEmbeddedChannel clientOutboundChannel; + private final FMLEmbeddedChannel serverOutboundChannel; + + private final HashSet> registeredClasses; + + /** + * Set true when helper is about to send a packet, remains true until packet is out + */ + private boolean isCurrentlySendingSemaphor; + + /** + * Creates an instance of the NetworkHelper with included channels for client and server communication. + * Automatically registers the necessary channels and discriminators for the supplied Packet classes. + * @param channelName channel name to use, anything but already taken designations goes + * @param handledPacketClasses provide the IPacket classes you want to use for communication here + */ + @SafeVarargs + public NetworkHelper(String channelName, Class ... handledPacketClasses) + { + EnumMap channelPair = NetworkRegistry.INSTANCE.newChannel(channelName, new ChannelCodec(handledPacketClasses), new ChannelHandler()); + clientOutboundChannel = channelPair.get(Side.CLIENT); + serverOutboundChannel = channelPair.get(Side.SERVER); + + registeredClasses = new HashSet>(handledPacketClasses.length); + Collections.addAll(registeredClasses, handledPacketClasses); + } + + /** + * Packets only need to implement this and offer a constructor with no args, + * unless you don't have constructors with >0 args. The class MUST also be + * statically accessible, else you will suffer an InstantiationException! + * Note Packets don't distinguish between being sent from client to server or + * the other way around, so be careful using them bidirectional or avoid + * doing that altogether. + */ + public interface IPacket + { + + /** + * Executed upon sending a Packet away. Put your arbitrary data into the ByteBuffer, + * and retrieve it on the receiving side when readBytes is executed. + * @param ctx channel context + * @param bytes data being sent + */ + void writeBytes(ChannelHandlerContext ctx, ByteBuf bytes); + + /** + * Executed upon arrival of a Packet at a recipient. Byte order matches writeBytes exactly. + * @param ctx channel context, you can send answers through here directly + * @param bytes data being received + */ + void readBytes(ChannelHandlerContext ctx, ByteBuf bytes); + } + + /** + * Sends the supplied Packet from a client to the server + * @param packet to send + */ + public void sendPacketToServer(IPacket packet) + { + checkClassAndSync(packet.getClass()); + clientOutboundChannel.attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.TOSERVER); + clientOutboundChannel.writeOutbound(packet); + isCurrentlySendingSemaphor = false; + } + + /** + * Sends the supplied Packet from the server to the chosen Player + * @param packet to send + * @param player to send to + */ + public void sendPacketToPlayer(IPacket packet, EntityPlayerMP player) + { + checkClassAndSync(packet.getClass()); + serverOutboundChannel.attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.PLAYER); + serverOutboundChannel.attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(player); + serverOutboundChannel.writeOutbound(packet); + isCurrentlySendingSemaphor = false; + } + + /** + * Sends a packet from the server to all currently connected players + * @param packet to send + */ + public void sendPacketToAllPlayers(IPacket packet) + { + checkClassAndSync(packet.getClass()); + serverOutboundChannel.attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.ALL); + serverOutboundChannel.writeOutbound(packet); + isCurrentlySendingSemaphor = false; + } + + /** + * Sends a packet from the server to all players in a dimension around a location + * @param packet to send + * @param tp targetpoint instance to pass, cannot be null + */ + public void sendPacketToAllAroundPoint(IPacket packet, TargetPoint tp) + { + checkClassAndSync(packet.getClass()); + serverOutboundChannel.attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.ALLAROUNDPOINT); + serverOutboundChannel.attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(tp); + serverOutboundChannel.writeOutbound(packet); + isCurrentlySendingSemaphor = false; + } + + /** + * Sends a packet from the server to all players in a dimension + * @param packet to send + * @param dimension serverside dim id to use + */ + public void sendPacketToAllInDimension(IPacket packet, int dimension) + { + checkClassAndSync(packet.getClass()); + serverOutboundChannel.attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.DIMENSION); + serverOutboundChannel.attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(dimension); + serverOutboundChannel.writeOutbound(packet); + isCurrentlySendingSemaphor = false; + } + + /** + * Since the crash that happens if we dont do this is complete garbage + */ + private void checkClassAndSync(Class clazz) + { + if (!registeredClasses.contains(clazz)) + { + throw new RuntimeException("NetworkHelper got unknown Packet type "+clazz+" to send, critical error"); + } + + // prevent concurrent packet sending + while (isCurrentlySendingSemaphor) + { + Thread.yield(); + } + isCurrentlySendingSemaphor = true; + } + + /** + * Internal Channel Codec, automatic discrimination and data forwarding + */ + private class ChannelCodec extends FMLIndexedMessageToMessageCodec + { + + @SafeVarargs + public ChannelCodec(Class ... handledPacketClasses) + { + for (int i = 0; i < handledPacketClasses.length; i++) + { + addDiscriminator(i, handledPacketClasses[i]); + } + } + + @Override + public void encodeInto(ChannelHandlerContext ctx, IPacket msg, ByteBuf bytes) throws Exception + { + msg.writeBytes(ctx, bytes); + } + + @Override + public void decodeInto(ChannelHandlerContext ctx, ByteBuf bytes, IPacket msg) + { + msg.readBytes(ctx, bytes); + } + + } + + @Sharable + public class ChannelHandler extends SimpleChannelInboundHandler + { + public ChannelHandler() {} + + @Override + protected void channelRead0(ChannelHandlerContext ctx, IPacket msg) throws Exception + { + // NOOP, just to prevent memory leaks + } + } + +} diff --git a/src/main/resources/assets/battletowers/lang/de_DE.lang b/src/main/resources/assets/battletowers/lang/de_DE.lang new file mode 100644 index 0000000..6a8713c --- /dev/null +++ b/src/main/resources/assets/battletowers/lang/de_DE.lang @@ -0,0 +1,2 @@ +entity.BattleTowers.Battletower Golem.name=Kampfturm-Golem +entity.Battletower Golem.name=Kampfturm-Golem \ No newline at end of file diff --git a/src/main/resources/assets/battletowers/lang/en_US.lang b/src/main/resources/assets/battletowers/lang/en_US.lang new file mode 100644 index 0000000..dc2c742 --- /dev/null +++ b/src/main/resources/assets/battletowers/lang/en_US.lang @@ -0,0 +1,3 @@ +entity.BattleTowers.Battletower Golem.name=Battletower Golem +entity.Battletower Golem.name=Battletower Golem +Battletowers.guardian=A Battletower's Guardian has fallen! Without it's power, the Tower will collapse... diff --git a/src/main/resources/assets/battletowers/lang/ru_RU.lang b/src/main/resources/assets/battletowers/lang/ru_RU.lang new file mode 100644 index 0000000..c12e56c --- /dev/null +++ b/src/main/resources/assets/battletowers/lang/ru_RU.lang @@ -0,0 +1,2 @@ +entity.BattleTowers.Battletower Golem.name=Голем боевой башни +entity.Battletower Golem.name=Голем боевой башни \ No newline at end of file diff --git a/src/main/resources/assets/battletowers/lang/tr_TR.lang b/src/main/resources/assets/battletowers/lang/tr_TR.lang new file mode 100644 index 0000000..b6d834d --- /dev/null +++ b/src/main/resources/assets/battletowers/lang/tr_TR.lang @@ -0,0 +1,2 @@ +entity.BattleTowers.Battletower Golem.name=Savaş Kulesi Golemi +entity.Battletower Golem.name=Savaş Kulesi Golemi \ No newline at end of file diff --git a/src/main/resources/assets/battletowers/pack.mcmeta b/src/main/resources/assets/battletowers/pack.mcmeta new file mode 100644 index 0000000..306e67b --- /dev/null +++ b/src/main/resources/assets/battletowers/pack.mcmeta @@ -0,0 +1,6 @@ +{ + "pack": { + "pack_format": 1, + "description": "Forge Mod Defaults" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/battletowers/sounds.json b/src/main/resources/assets/battletowers/sounds.json new file mode 100644 index 0000000..7249148 --- /dev/null +++ b/src/main/resources/assets/battletowers/sounds.json @@ -0,0 +1,53 @@ +{ + "golem": { + "category": "hostile", + "sounds": [ + "battletowers:golem" + ] + }, + "golemawaken": { + "category": "hostile", + "sounds": [ + "battletowers:golemawaken" + ] + }, + "golemcharge": { + "category": "hostile", + "sounds": [ + "battletowers:golemcharge1", + "battletowers:golemcharge2" + ] + }, + "golemdeath": { + "category": "hostile", + "sounds": [ + "battletowers:golemdeath" + ] + }, + "golemhurt": { + "category": "hostile", + "sounds": [ + "battletowers:golemhurt1", + "battletowers:golemhurt2" + ] + }, + "golemspecial": { + "category": "hostile", + "sounds": [ + "battletowers:golemspecial1", + "battletowers:golemspecial2" + ] + }, + "towerbreakstart": { + "category": "hostile", + "sounds": [ + "battletowers:towerbreakstart" + ] + }, + "towercrumble": { + "category": "hostile", + "sounds": [ + "battletowers:towercrumble" + ] + } +} diff --git a/src/main/resources/assets/battletowers/sounds/golem.ogg b/src/main/resources/assets/battletowers/sounds/golem.ogg new file mode 100644 index 0000000..3f8e509 Binary files /dev/null and b/src/main/resources/assets/battletowers/sounds/golem.ogg differ diff --git a/src/main/resources/assets/battletowers/sounds/golemawaken.ogg b/src/main/resources/assets/battletowers/sounds/golemawaken.ogg new file mode 100644 index 0000000..222b6c6 Binary files /dev/null and b/src/main/resources/assets/battletowers/sounds/golemawaken.ogg differ diff --git a/src/main/resources/assets/battletowers/sounds/golemcharge1.ogg b/src/main/resources/assets/battletowers/sounds/golemcharge1.ogg new file mode 100644 index 0000000..ebad3bb Binary files /dev/null and b/src/main/resources/assets/battletowers/sounds/golemcharge1.ogg differ diff --git a/src/main/resources/assets/battletowers/sounds/golemcharge2.ogg b/src/main/resources/assets/battletowers/sounds/golemcharge2.ogg new file mode 100644 index 0000000..35bd61c Binary files /dev/null and b/src/main/resources/assets/battletowers/sounds/golemcharge2.ogg differ diff --git a/src/main/resources/assets/battletowers/sounds/golemdeath.ogg b/src/main/resources/assets/battletowers/sounds/golemdeath.ogg new file mode 100644 index 0000000..1aeb9ad Binary files /dev/null and b/src/main/resources/assets/battletowers/sounds/golemdeath.ogg differ diff --git a/src/main/resources/assets/battletowers/sounds/golemhurt1.ogg b/src/main/resources/assets/battletowers/sounds/golemhurt1.ogg new file mode 100644 index 0000000..b94a5c7 Binary files /dev/null and b/src/main/resources/assets/battletowers/sounds/golemhurt1.ogg differ diff --git a/src/main/resources/assets/battletowers/sounds/golemhurt2.ogg b/src/main/resources/assets/battletowers/sounds/golemhurt2.ogg new file mode 100644 index 0000000..7beb892 Binary files /dev/null and b/src/main/resources/assets/battletowers/sounds/golemhurt2.ogg differ diff --git a/src/main/resources/assets/battletowers/sounds/golemspecial1.ogg b/src/main/resources/assets/battletowers/sounds/golemspecial1.ogg new file mode 100644 index 0000000..7a147f4 Binary files /dev/null and b/src/main/resources/assets/battletowers/sounds/golemspecial1.ogg differ diff --git a/src/main/resources/assets/battletowers/sounds/golemspecial2.ogg b/src/main/resources/assets/battletowers/sounds/golemspecial2.ogg new file mode 100644 index 0000000..6a443ce Binary files /dev/null and b/src/main/resources/assets/battletowers/sounds/golemspecial2.ogg differ diff --git a/src/main/resources/assets/battletowers/sounds/towerbreakstart.ogg b/src/main/resources/assets/battletowers/sounds/towerbreakstart.ogg new file mode 100644 index 0000000..1c5a024 Binary files /dev/null and b/src/main/resources/assets/battletowers/sounds/towerbreakstart.ogg differ diff --git a/src/main/resources/assets/battletowers/sounds/towercrumble.ogg b/src/main/resources/assets/battletowers/sounds/towercrumble.ogg new file mode 100644 index 0000000..fceb44f Binary files /dev/null and b/src/main/resources/assets/battletowers/sounds/towercrumble.ogg differ