diff --git a/.gitignore b/.gitignore index fe12f1e41..5836788f8 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ output # other eclipse run +run-server refresh.bat AdvancedRocketry.txt changelog.html diff --git a/LICENSE b/LICENSE index a0bf476a7..c13f99117 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2017 +Copyright (c) 2024 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file +SOFTWARE. diff --git a/README.md b/README.md index c6a5f0f9c..2a577e6e7 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Advanced Rocketry - Reworked -This is a fork of Advanced Rocketry where we fix all the bugs of the mod because the devs don't do it. +This is a fork of Advanced Rocketry. You can download the new mod from curseforge: https://www.curseforge.com/minecraft/mc-mods/advanced-rocketry-2 @@ -10,23 +10,6 @@ original github repo: https://github.com/Advanced-Rocketry/AdvancedRocketry old documentation: http://arwiki.dmodoomsirius.me/ - -## Current bugfixes: -- satellites disconnect on server restart fixed -- biome remote crash fixed -- warp fuel displays incorrect fixed -- rocket stuck in orbit 25 secs (fixed) -- biome changer energy consumption system fixed -- asteroid field available as custom Icon: customIcon="asteroid" -- improved planetary map -- space elevator fixed -- void miner fixed (void miner does not actually break blocks on planet) -- gas mining: gas selection not updating fixed -- solar panels crash near stars fixed -- #### AR had over 200 open issues. I fixed so many of them that I stopped writing them all down because it would be a very long list. Just look at the commit history and you can see all that changed. - - -## Improvements: -- There are many improvements but same as with bugs, I stopped writing them all down because it would be a very long list +You can see all bugfixes / improvements in the commit history diff --git a/build.gradle.kts b/build.gradle.kts index e4daa9b23..1aa545d72 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -32,6 +32,10 @@ val startGitRev: String by project group = "zmaster587.advancedRocketry" setProperty("archivesBaseName", archiveBase) +legacy { + fixClasspath = true +} + val buildNumber: String by lazy { System.getenv("BUILD_NUMBER") ?: getDate() } fun getDate(): String { @@ -41,7 +45,7 @@ fun getDate(): String { return format.format(Date()) } -version = "$modVersion-$buildNumber" +version = "$modVersion" println("$archiveBase v$mcVersion-$version") @@ -51,10 +55,26 @@ java { } } -configurations.configureEach { - exclude(group = "net.minecraftforge", module = "mergetool") +tasks { + javadoc { + options.encoding = "UTF-8" + } + compileJava { + options.encoding = "UTF-8" + } + compileTestJava { + options.encoding = "UTF-8" + } + +// withType(JavaCompile) { +// options.encoding = "UTF-8" +// } } +//configurations.configureEach { +// exclude(group = "net.minecraftforge", module = "mergetool") +//} + //sourceCompatibility = targetCompatibility = '1.8' // Need this here so eclipse task generates correctly. tasks.compileJava { sourceCompatibility = "1.8" @@ -63,7 +83,7 @@ tasks.compileJava { minecraft { - mappings("snapshot", "20170624-1.12") + mappings("snapshot", "20171003-1.12") accessTransformer(file("src/main/resources/META-INF/accessTransformer.cfg")) @@ -131,10 +151,10 @@ repositories { name = "ModMaven" url = uri("https://modmaven.k-4u.nl") } - maven { - name = "Galacticraft" - url = uri("https://maven.galacticraft.dev/repository/legacy-releases/") - } + //maven { + // name = "Galacticraft" + // url = uri("https://maven.galacticraft.dev/repository/legacy-releases/") + //} // maven { // name = "LibVulpes" // url = uri("http://maven.dmodoomsirius.me/") @@ -152,15 +172,17 @@ dependencies { //compileOnly("net.industrial-craft:industrialcraft-2:$icVersion:dev") //implementation("zmaster587.libVulpes:LibVulpes:$mcVersion-$libVulpesVersion-$libVulpesBuildNum-deobf") - compileOnly(fg.deobf("dev.galacticraft:galacticraft-legacy:$gcVersion")) - + //compileOnly(fg.deobf("dev.galacticraft:galacticraft-legacy:$gcVersion")) + compileOnly(fg.deobf("curse.maven:galacticraft-legacy-564236:4671122")) compileOnly(fg.deobf("mezz.jei:jei_${mcVersion}:${jeiVersion}:api")) - runtimeOnly(fg.deobf("mezz.jei:jei_${mcVersion}:${jeiVersion}")) + implementation(fg.deobf("mezz.jei:jei_${mcVersion}:${jeiVersion}")) // Sorry but it won't start wihout jei... + //runtimeOnly(fg.deobf("mezz.jei:jei_${mcVersion}:${jeiVersion}")) // I think this crashes the game for me when running from IntelliJ implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar")))) + compileOnly(fileTree(mapOf("dir" to "libs/compileOnly", "include" to listOf("*.jar")))) - implementation ("net.minecraftforge:mergetool:0.2.3.3") - // implementation ("zmaster587.libVulpes:libVulpes:1.12.2-0.4.2+:deobf") +// implementation ("net.minecraftforge:mergetool:0.2.3.3") + implementation ("net.minecraftforge:mergetool") { version { strictly("0.2.3.3") } } } tasks.processResources { @@ -206,6 +228,7 @@ tasks.withType(Jar::class) { "Implementation-Title" to archiveBase, "Implementation-Version" to project.version, "Git-Hash" to gitHash, + "FMLAT" to "accessTransformer.cfg", "FMLCorePlugin" to "zmaster587.advancedRocketry.asm.AdvancedRocketryPlugin", "FMLCorePluginContainsFMLMod" to "true" ) @@ -308,4 +331,4 @@ idea { module { inheritOutputDirs = true } -} \ No newline at end of file +} diff --git a/gradle.properties b/gradle.properties index 9135f44e4..e38cfe1d5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,12 +4,10 @@ org.gradle.daemon=false # Project mcVersion=1.12.2 forgeVersion=14.23.5.2860 -modVersion=2.0.11 +modVersion=2.1.7 archiveBase=AdvancedRocketry startGitRev=8e676bd # Dependencies -libVulpesVersion=0.4.3 +libVulpesVersion=0.5.0 jeiVersion=4.16.1.301 -icVersion=2.7.39-ex111 -gcVersion=4.0.6 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index fc6f9a390..cea70190a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ +#Sun Jul 07 14:46:24 CEST 2024 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip -networkTimeout=10000 +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/libs/LibVulpes-deobf.jar b/libs/LibVulpes-deobf.jar index e47687576..737822448 100644 Binary files a/libs/LibVulpes-deobf.jar and b/libs/LibVulpes-deobf.jar differ diff --git a/libs/compileOnly/MatterOverdrive-1.12.2-0.8.6-universal.jar b/libs/compileOnly/MatterOverdrive-1.12.2-0.8.6-universal.jar new file mode 100644 index 000000000..a15dac16d Binary files /dev/null and b/libs/compileOnly/MatterOverdrive-1.12.2-0.8.6-universal.jar differ diff --git a/settings.gradle.kts b/settings.gradle.kts index fe5385aca..8c3d444bb 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,6 +1,7 @@ pluginManagement { repositories { gradlePluginPortal() + mavenCentral() maven { name = "MinecraftForge" url = uri("https://maven.minecraftforge.net/") @@ -9,6 +10,10 @@ pluginManagement { name = "FancyGradle" url = uri("https://maven.gofancy.wtf/releases") } + maven { url = uri("https://plugins.gradle.org/m2/") } + maven { + url = uri("https://oss.sonatype.org/content/repositories/snapshots/") + } } } diff --git a/src/main/java/zmaster587/advancedRocketry/ARHookLoader.java b/src/main/java/zmaster587/advancedRocketry/ARHookLoader.java new file mode 100644 index 000000000..80986c48d --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/ARHookLoader.java @@ -0,0 +1,18 @@ +package zmaster587.advancedRocketry; + + +import zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.minecraft.HookLoader; +import zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.minecraft.PrimaryClassTransformer; + +public class ARHookLoader extends HookLoader { + + @Override + public String[] getASMTransformerClass() { + return new String[]{PrimaryClassTransformer.class.getName()}; + } + + @Override + public void registerHooks() { + registerHookContainer("zmaster587.advancedRocketry.ARHooks"); + } +} diff --git a/src/main/java/zmaster587/advancedRocketry/ARHooks.java b/src/main/java/zmaster587/advancedRocketry/ARHooks.java new file mode 100644 index 000000000..9030c4c16 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/ARHooks.java @@ -0,0 +1,211 @@ +package zmaster587.advancedRocketry; + +import net.minecraft.command.*; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.integrated.IntegratedServer; +import net.minecraft.world.*; +import net.minecraft.world.storage.ISaveHandler; +import net.minecraft.world.storage.WorldInfo; +import net.minecraftforge.common.DimensionManager; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.world.WorldEvent; +import net.minecraftforge.fml.common.FMLLog; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import zmaster587.advancedRocketry.dimension.DimensionProperties; +import zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.asm.Hook; +import zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.asm.ReturnCondition; +import zmaster587.advancedRocketry.world.WorldServerNotMulti; +import zmaster587.advancedRocketry.world.provider.WorldProviderPlanet; + +import java.util.Random; + +import static net.minecraftforge.common.DimensionManager.getWorld; + +public class ARHooks { + +// @Hook(returnCondition = ReturnCondition.ON_TRUE, booleanReturnConstant = true) +// public static boolean bindEntityTexture(Render instance, Entity entity) { +//// if (Minecraft.getMinecraft().isSingleplayer()) { +//// return false; +//// } +// if (entity instanceof EntityPlayer) { +// ITextureObject t = Skin.forPlayer(entity.getName()).getSkin(); +// if (t == null) { +// return false; +// } +// GlStateManager.bindTexture(t.getGlTextureId()); +// return true; +// } else { +// return false; +// } +// } + + + @Hook(returnCondition = ReturnCondition.ALWAYS) + public static void initDimension(DimensionManager mgr, int dim) { + WorldServer overworld = getWorld(0); + if (overworld == null) { + throw new RuntimeException("Cannot Hotload Dim: Overworld is not Loaded!"); + } + try { + DimensionManager.getProviderType(dim); + } catch (Exception e) { + FMLLog.log.error("Cannot Hotload Dim: {}", dim, e); + return; // If a provider hasn't been registered then we can't hotload the dim + } + MinecraftServer mcServer = overworld.getMinecraftServer(); + ISaveHandler savehandler = overworld.getSaveHandler(); + //WorldSettings worldSettings = new WorldSettings(overworld.getWorldInfo()); + + WorldServer world = (dim == 0 ? overworld : (WorldServer) (new WorldServerNotMulti(mcServer, savehandler, dim, overworld, mcServer.profiler).init())); + world.addEventListener(new ServerWorldEventHandler(mcServer, world)); + MinecraftForge.EVENT_BUS.post(new WorldEvent.Load(world)); + if (!mcServer.isSinglePlayer()) { + world.getWorldInfo().setGameType(mcServer.getGameType()); + } + + mcServer.setDifficultyForAllWorlds(mcServer.getDifficulty()); + } + + @Hook(returnCondition = ReturnCondition.ALWAYS) + public static void loadAllWorlds(MinecraftServer server, String saveName, String worldNameIn, long seed, WorldType type, String generatorOptions) { + server.convertMapIfNeeded(saveName); + server.setUserMessage("menu.loadingLevel"); + ISaveHandler isavehandler = server.anvilConverterForAnvilFile.getSaveLoader(saveName, true); + server.setResourcePackFromWorld(server.getFolderName(), isavehandler); + WorldInfo worldinfo = isavehandler.loadWorldInfo(); + WorldSettings worldsettings; + + if (worldinfo == null) { + if (server.isDemo()) { + worldsettings = WorldServerDemo.DEMO_WORLD_SETTINGS; + } else { + worldsettings = new WorldSettings(seed, server.getGameType(), server.canStructuresSpawn(), server.isHardcore(), type); + worldsettings.setGeneratorOptions(generatorOptions); + + if (server.enableBonusChest) { + worldsettings.enableBonusChest(); + } + } + + worldinfo = new WorldInfo(worldsettings, worldNameIn); + } else { + worldinfo.setWorldName(worldNameIn); + worldsettings = new WorldSettings(worldinfo); + } + + WorldServer overWorld = (WorldServer) (server.isDemo() ? new WorldServerDemo(server, isavehandler, worldinfo, 0, server.profiler).init() : new WorldServer(server, isavehandler, worldinfo, 0, server.profiler).init()); + overWorld.initialize(worldsettings); + for (int dim : net.minecraftforge.common.DimensionManager.getStaticDimensionIDs()) { + WorldServer world = (dim == 0 ? overWorld : (WorldServer) new WorldServerNotMulti(server, isavehandler, dim, overWorld, server.profiler).init()); + world.addEventListener(new ServerWorldEventHandler(server, world)); + + if (!server.isSinglePlayer()) { + world.getWorldInfo().setGameType(server.getGameType()); + } + net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.world.WorldEvent.Load(world)); + } + + server.playerList.setPlayerManager(new WorldServer[]{overWorld}); + server.setDifficultyForAllWorlds(server.getDifficulty()); + server.initialWorldChunkLoad(); + } + + @SideOnly(Side.CLIENT) + @Hook(returnCondition = ReturnCondition.ALWAYS) + public static void loadAllWorlds(IntegratedServer server, String saveName, String worldNameIn, long seed, WorldType type, String generatorOptions) { + server.convertMapIfNeeded(saveName); + ISaveHandler isavehandler = server.getActiveAnvilConverter().getSaveLoader(saveName, true); + server.setResourcePackFromWorld(server.getFolderName(), isavehandler); + WorldInfo worldinfo = isavehandler.loadWorldInfo(); + + if (worldinfo == null) { + worldinfo = new WorldInfo(server.worldSettings, worldNameIn); + } else { + worldinfo.setWorldName(worldNameIn); + } + + WorldServer overWorld = (server.isDemo() ? (WorldServer) (new WorldServerDemo(server, isavehandler, worldinfo, 0, server.profiler)).init() : + (WorldServer) (new WorldServer(server, isavehandler, worldinfo, 0, server.profiler)).init()); + overWorld.initialize(server.worldSettings); + for (int dim : net.minecraftforge.common.DimensionManager.getStaticDimensionIDs()) { + WorldServer world = (dim == 0 ? overWorld : (WorldServer) new WorldServerNotMulti(server, isavehandler, dim, overWorld, server.profiler).init()); + world.addEventListener(new ServerWorldEventHandler(server, world)); + if (!server.isSinglePlayer()) { + world.getWorldInfo().setGameType(server.getGameType()); + } + net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.world.WorldEvent.Load(world)); + } + + server.getPlayerList().setPlayerManager(new WorldServer[]{overWorld}); + + if (overWorld.getWorldInfo().getDifficulty() == null) { + server.setDifficultyForAllWorlds(server.mc.gameSettings.difficulty); + } + + server.initialWorldChunkLoad(); + } + + @Hook(returnCondition = ReturnCondition.ALWAYS) + public static void execute(CommandWeather command, MinecraftServer server, ICommandSender sender, String[] args) throws CommandException { + if (args.length >= 1 && args.length <= 2) { + int i = (300 + (new Random()).nextInt(600)) * 20; + + if (args.length >= 2) { + i = CommandBase.parseInt(args[1], 1, 1000000) * 20; + } + + World world = sender.getEntityWorld(); + WorldInfo worldinfo = world.getWorldInfo(); + WorldProvider provider = world.provider; + DimensionProperties props = null; + if (provider instanceof WorldProviderPlanet) { + props = ((WorldProviderPlanet) provider).getDimensionProperties(); + } + + if ("clear".equalsIgnoreCase(args[0])) { + if (props != null && (props.getRainMarker() == 1 || props.getThunderMarker() == 1)) { + CommandBase.notifyCommandListener(sender, command, "commands.weather.always_not_clear", new Object[0]); + return; + } + + worldinfo.setCleanWeatherTime(i); + worldinfo.setRainTime(0); + worldinfo.setThunderTime(0); + worldinfo.setRaining(false); + worldinfo.setThundering(false); + CommandBase.notifyCommandListener(sender, command, "commands.weather.clear", new Object[0]); + } else if ("rain".equalsIgnoreCase(args[0])) { + if (props != null && props.getRainMarker() == -1) { + CommandBase.notifyCommandListener(sender, command, "commands.weather.cannot_rain", new Object[0]); + return; + } + + worldinfo.setCleanWeatherTime(0); + worldinfo.setRainTime(i); + worldinfo.setThunderTime(i); + worldinfo.setRaining(true); + worldinfo.setThundering(false); + CommandBase.notifyCommandListener(sender, command, "commands.weather.rain", new Object[0]); + } else { + if (!"thunder".equalsIgnoreCase(args[0])) { + throw new WrongUsageException("commands.weather.usage", new Object[0]); + } + if (props != null && props.getThunderMarker() == -1) { + CommandBase.notifyCommandListener(sender, command, "commands.weather.cannot_thunder", new Object[0]); + return; + } + + worldinfo.setCleanWeatherTime(0); + worldinfo.setRainTime(i); + worldinfo.setThunderTime(i); + worldinfo.setRaining(true); + worldinfo.setThundering(true); + CommandBase.notifyCommandListener(sender, command, "commands.weather.thunder", new Object[0]); + } + } else { + throw new WrongUsageException("commands.weather.usage", new Object[0]); + } + } +} diff --git a/src/main/java/zmaster587/advancedRocketry/AdvancedRocketry.java b/src/main/java/zmaster587/advancedRocketry/AdvancedRocketry.java index cbe6b6827..0865bd4c2 100644 --- a/src/main/java/zmaster587/advancedRocketry/AdvancedRocketry.java +++ b/src/main/java/zmaster587/advancedRocketry/AdvancedRocketry.java @@ -6,6 +6,7 @@ import net.minecraft.block.material.MaterialLiquid; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.enchantment.Enchantment; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.init.Biomes; import net.minecraft.init.Blocks; import net.minecraft.inventory.EntityEquipmentSlot; @@ -37,6 +38,7 @@ import net.minecraftforge.fml.common.event.*; import net.minecraftforge.fml.common.eventhandler.EventPriority; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.PlayerEvent; import net.minecraftforge.fml.common.network.NetworkRegistry; import net.minecraftforge.fml.common.registry.EntityRegistry; import net.minecraftforge.fml.common.registry.GameRegistry; @@ -50,9 +52,11 @@ import zmaster587.advancedRocketry.api.*; import zmaster587.advancedRocketry.api.capability.CapabilitySpaceArmor; import zmaster587.advancedRocketry.api.satellite.SatelliteProperties; +import zmaster587.advancedRocketry.api.stations.ISpaceObject; import zmaster587.advancedRocketry.armor.ItemSpaceArmor; import zmaster587.advancedRocketry.armor.ItemSpaceChest; import zmaster587.advancedRocketry.block.*; +import zmaster587.advancedRocketry.block.inventory.BlockInvHatch; import zmaster587.advancedRocketry.block.multiblock.BlockARHatch; import zmaster587.advancedRocketry.block.plant.BlockLightwoodLeaves; import zmaster587.advancedRocketry.block.plant.BlockLightwoodPlanks; @@ -68,6 +72,7 @@ import zmaster587.advancedRocketry.enchant.EnchantmentSpaceBreathing; import zmaster587.advancedRocketry.entity.*; import zmaster587.advancedRocketry.event.CableTickHandler; +import zmaster587.advancedRocketry.event.EntityEventHandler; import zmaster587.advancedRocketry.event.PlanetEventHandler; import zmaster587.advancedRocketry.event.WorldEvents; import zmaster587.advancedRocketry.integration.CompatibilityMgr; @@ -127,7 +132,10 @@ import zmaster587.libVulpes.network.PacketItemModifcation; import zmaster587.libVulpes.recipe.RecipesMachine; import zmaster587.libVulpes.tile.TileMaterial; +import zmaster587.libVulpes.tile.energy.TilePlugBase; import zmaster587.libVulpes.tile.multiblock.TileMultiBlock; +import zmaster587.libVulpes.tile.multiblock.hatch.TileFluidHatch; +import zmaster587.libVulpes.tile.multiblock.hatch.TileInventoryHatch; import zmaster587.libVulpes.util.FluidUtils; import zmaster587.libVulpes.util.HashedBlockPosition; import zmaster587.libVulpes.util.InputSyncHandler; @@ -319,6 +327,7 @@ public void preInit(FMLPreInitializationEvent event) { PacketHandler.INSTANCE.addDiscriminator(PacketConfigSync.class); PacketHandler.INSTANCE.addDiscriminator(PacketFluidParticle.class); PacketHandler.INSTANCE.addDiscriminator(PacketSatellitesUpdate.class); + PacketHandler.INSTANCE.addDiscriminator(PacketSyncKnownPlanets.class); //if(zmaster587.advancedRocketry.api.Configuration.allowMakingItemsForOtherMods) @@ -351,6 +360,7 @@ public void preInit(FMLPreInitializationEvent event) { //TileEntity Registration --------------------------------------------------------------------------------------------- GameRegistry.registerTileEntity(TileBrokenPart.class, "ARbrokenPart"); + GameRegistry.registerTileEntity(TileRocketServiceStation.class, "ARserviceStation"); GameRegistry.registerTileEntity(TileRocketAssemblingMachine.class, "ARrocketBuilder"); GameRegistry.registerTileEntity(TileWarpCore.class, "ARwarpCore"); //GameRegistry.registerTileEntity(TileModelRender.class, "ARmodelRenderer"); @@ -364,6 +374,7 @@ public void preInit(FMLPreInitializationEvent event) { GameRegistry.registerTileEntity(TileCuttingMachine.class, "ARcuttingmachine"); GameRegistry.registerTileEntity(TileDataBus.class, "ARdataBus"); GameRegistry.registerTileEntity(TileSatelliteHatch.class, "ARsatelliteHatch"); + GameRegistry.registerTileEntity(TileInventoryHatch.class, "ARinventoryHatch"); GameRegistry.registerTileEntity(TileGuidanceComputerAccessHatch.class, "ARguidanceComputerHatch"); GameRegistry.registerTileEntity(TileSatelliteBuilder.class, "ARsatelliteBuilder"); GameRegistry.registerTileEntity(TileSatelliteTerminal.class, "ARTileEntitySatelliteControlCenter"); @@ -590,6 +601,12 @@ public void registerItems(RegistryEvent.Register evt) { OreDictionary.registerOre("slab", new ItemStack(Blocks.STONE_SLAB)); OreDictionary.registerOre("blockWarpCoreCore", new ItemStack(Blocks.GOLD_BLOCK)); OreDictionary.registerOre("blockWarpCoreRim", MaterialRegistry.getMaterialFromName("Titanium").getProduct(AllowedProducts.getProductByName("BLOCK"))); + + Item.getItemFromBlock(AdvancedRocketryBlocks.blockEngine).setMaxDamage(10); + Item.getItemFromBlock(AdvancedRocketryBlocks.blockAdvEngine).setMaxDamage(10); + Item.getItemFromBlock(AdvancedRocketryBlocks.blockBipropellantEngine).setMaxDamage(10); + Item.getItemFromBlock(AdvancedRocketryBlocks.blockAdvBipropellantEngine).setMaxDamage(10); + Item.getItemFromBlock(AdvancedRocketryBlocks.blockNuclearEngine).setMaxDamage(10); } @SubscribeEvent(priority = EventPriority.HIGH) @@ -643,7 +660,8 @@ public void registerBlocks(RegistryEvent.Register evt) { AdvancedRocketryBlocks.blockSpaceElevatorController = new BlockMultiblockMachine(TileSpaceElevator.class, GuiHandler.guiId.MODULAR.ordinal()).setCreativeTab(tabAdvRocketry).setUnlocalizedName("spaceElevatorController").setHardness(3f); //Configurable stuff if (ARConfiguration.getCurrentConfig().enableTerraforming) - AdvancedRocketryBlocks.blockAtmosphereTerraformer = new BlockMultiblockMachine(TileAtmosphereTerraformer.class, GuiHandler.guiId.MODULARNOINV.ordinal()).setUnlocalizedName("atmosphereTerraformer").setCreativeTab(tabAdvRocketry).setHardness(3f); + //AdvancedRocketryBlocks.blockAtmosphereTerraformer = new BlockMultiblockMachine(TileAtmosphereTerraformer.class, GuiHandler.guiId.MODULARNOINV.ordinal()).setUnlocalizedName("atmosphereTerraformer").setCreativeTab(tabAdvRocketry).setHardness(3f); + AdvancedRocketryBlocks.blockAtmosphereTerraformer = new BlockAtmosphereTerraformer(TileAtmosphereTerraformer.class, GuiHandler.guiId.MODULARNOINV.ordinal()).setUnlocalizedName("atmosphereTerraformer").setCreativeTab(tabAdvRocketry).setHardness(3f); if (ARConfiguration.getCurrentConfig().enableGravityController) AdvancedRocketryBlocks.blockGravityMachine = new BlockMultiblockMachine(TileAreaGravityController.class, GuiHandler.guiId.MODULARNOINV.ordinal()).setUnlocalizedName("gravityMachine").setCreativeTab(tabAdvRocketry).setHardness(3f); if (ARConfiguration.getCurrentConfig().enableLaserDrill) @@ -668,6 +686,8 @@ public void registerBlocks(RegistryEvent.Register evt) { AdvancedRocketryBlocks.blockIntake = new BlockIntake(Material.IRON).setUnlocalizedName("gasIntake").setCreativeTab(tabAdvRocketry).setHardness(3f); AdvancedRocketryBlocks.blockDrill = new BlockMiningDrill().setUnlocalizedName("drill").setCreativeTab(tabAdvRocketry).setHardness(3f); AdvancedRocketryBlocks.blockLandingFloat = new Block(Material.IRON).setUnlocalizedName("landingfloat").setCreativeTab(tabAdvRocketry).setHardness(1).setResistance(1f); + AdvancedRocketryBlocks.blockServiceMonitor = new RotatableBlock(Material.IRON).setUnlocalizedName("servicemonitor").setCreativeTab(tabAdvRocketry).setHardness(1).setResistance(1f); + AdvancedRocketryBlocks.blockInvHatch = new BlockInvHatch(Material.IRON).setUnlocalizedName("invhatch").setCreativeTab(tabAdvRocketry).setHardness(1).setResistance(1f); //Assembly machines AdvancedRocketryBlocks.blockRocketBuilder = new BlockTileWithMultitooltip(TileRocketAssemblingMachine.class, GuiHandler.guiId.MODULARNOINV.ordinal()).setUnlocalizedName("rocketAssembler").setCreativeTab(tabAdvRocketry).setHardness(3f); AdvancedRocketryBlocks.blockStationBuilder = new BlockTileWithMultitooltip(TileStationAssembler.class, GuiHandler.guiId.MODULAR.ordinal()).setUnlocalizedName("stationAssembler").setCreativeTab(tabAdvRocketry).setHardness(3f); @@ -678,6 +698,7 @@ public void registerBlocks(RegistryEvent.Register evt) { AdvancedRocketryBlocks.blockMonitoringStation = new BlockTileNeighborUpdate(TileRocketMonitoringStation.class, GuiHandler.guiId.MODULARNOINV.ordinal()).setCreativeTab(tabAdvRocketry).setHardness(3f).setUnlocalizedName("monitoringstation"); AdvancedRocketryBlocks.blockSatelliteControlCenter = new BlockTile(TileSatelliteTerminal.class, GuiHandler.guiId.MODULAR.ordinal()).setCreativeTab(tabAdvRocketry).setHardness(3f).setUnlocalizedName("satelliteMonitor"); AdvancedRocketryBlocks.blockTerraformingTerminal = new BlockTileTerraformer(TileTerraformingTerminal.class, GuiHandler.guiId.MODULAR.ordinal()).setCreativeTab(tabAdvRocketry).setHardness(3f).setUnlocalizedName("terraformingTerminal"); + AdvancedRocketryBlocks.blockServiceStation = new BlockTile(TileRocketServiceStation.class, GuiHandler.guiId.MODULARNOINV.ordinal()).setCreativeTab(tabAdvRocketry).setHardness(3f).setUnlocalizedName("serviceStation"); //Station machines AdvancedRocketryBlocks.blockWarpShipMonitor = new BlockWarpController(TileWarpController.class, GuiHandler.guiId.MODULARNOINV.ordinal()).setCreativeTab(tabAdvRocketry).setHardness(3f).setUnlocalizedName("stationmonitor"); @@ -838,12 +859,15 @@ public void registerBlocks(RegistryEvent.Register evt) { LibVulpesBlocks.registerBlock(AdvancedRocketryBlocks.blockIntake.setRegistryName("intake")); LibVulpesBlocks.registerBlock(AdvancedRocketryBlocks.blockDrill.setRegistryName("drill")); LibVulpesBlocks.registerBlock(AdvancedRocketryBlocks.blockLandingFloat.setRegistryName("landingfloat")); + LibVulpesBlocks.registerBlock(AdvancedRocketryBlocks.blockServiceMonitor.setRegistryName("servicemonitor")); + LibVulpesBlocks.registerBlock(AdvancedRocketryBlocks.blockInvHatch.setRegistryName("invhatch")); //Assembly machines LibVulpesBlocks.registerBlock(AdvancedRocketryBlocks.blockRocketBuilder.setRegistryName("rocketBuilder")); LibVulpesBlocks.registerBlock(AdvancedRocketryBlocks.blockStationBuilder.setRegistryName("stationBuilder")); LibVulpesBlocks.registerBlock(AdvancedRocketryBlocks.blockDeployableRocketBuilder.setRegistryName("deployableRocketBuilder")); //Infrastructure machines LibVulpesBlocks.registerBlock(AdvancedRocketryBlocks.blockLoader.setRegistryName("loader"), ItemBlockMeta.class, false); + LibVulpesBlocks.registerBlock(AdvancedRocketryBlocks.blockServiceStation.setRegistryName("serviceStation")); LibVulpesBlocks.registerBlock(AdvancedRocketryBlocks.blockFuelingStation.setRegistryName("fuelingStation")); LibVulpesBlocks.registerBlock(AdvancedRocketryBlocks.blockMonitoringStation.setRegistryName("monitoringStation")); LibVulpesBlocks.registerBlock(AdvancedRocketryBlocks.blockSatelliteControlCenter.setRegistryName("satelliteControlCenter")); @@ -1070,6 +1094,9 @@ public void postInit(FMLPostInitializationEvent event) { MinecraftForge.EVENT_BUS.register(handle); MinecraftForge.ORE_GEN_BUS.register(handle); + // Async weather fix + MinecraftForge.EVENT_BUS.register(new EntityEventHandler()); + CableTickHandler cable = new CableTickHandler(); MinecraftForge.EVENT_BUS.register(cable); @@ -1112,6 +1139,9 @@ public void postInit(FMLPostInitializationEvent event) { //Add the overworld as a discovered planet zmaster587.advancedRocketry.api.ARConfiguration.getCurrentConfig().initiallyKnownPlanets.add(0); + + TilePlugBase.energy_multiplier = zmaster587.advancedRocketry.api.ARConfiguration.getCurrentConfig(). blockEnergyHatchCapacityMultiplier; + TileFluidHatch.capacityMultiplier = zmaster587.advancedRocketry.api.ARConfiguration.getCurrentConfig().blockLiquidHatchCapacityMultiplier; } @EventHandler @@ -1253,4 +1283,20 @@ public void registerOre(OreRegisterEvent event) { } } } + + // pretty hacky way and AR also have it's own syncing mechanism, but i just dont trust it + @SubscribeEvent + public void onPlayerLogin(PlayerEvent.PlayerLoggedInEvent event) { + if (event.player instanceof EntityPlayerMP) { + EntityPlayerMP player = (EntityPlayerMP) event.player; + + for (ISpaceObject spaceObject : SpaceObjectManager.getSpaceManager().getSpaceObjects()) { + if (spaceObject instanceof SpaceStationObject) { + SpaceStationObject station = (SpaceStationObject) spaceObject; + PacketHandler.sendToPlayer(new PacketSyncKnownPlanets(station.getId(), station.getKnownPlanetList()), player); + } + } + + } + } } diff --git a/src/main/java/zmaster587/advancedRocketry/advancements/ARAdvancements.java b/src/main/java/zmaster587/advancedRocketry/advancements/ARAdvancements.java index f7b843db9..1fe2560ac 100644 --- a/src/main/java/zmaster587/advancedRocketry/advancements/ARAdvancements.java +++ b/src/main/java/zmaster587/advancedRocketry/advancements/ARAdvancements.java @@ -14,13 +14,19 @@ public class ARAdvancements { public static final CustomTrigger WENT_TO_THE_MOON = new CustomTrigger("wenttothemoon"); public static final CustomTrigger ALL_SHE_GOT = new CustomTrigger("givingitallshesgot"); public static final CustomTrigger FLIGHT_OF_PHOENIX = new CustomTrigger("flightofpheonix"); + + public static final CustomTrigger DEATH_STAR = new CustomTrigger("deathstar"); + public static final CustomTrigger ATM_TERRAFORMER = new CustomTrigger("pressurize"); + public static final CustomTrigger[] TRIGGER_ARRAY = new CustomTrigger[]{ MOON_LANDING, ONE_SMALL_STEP, BEER, WENT_TO_THE_MOON, ALL_SHE_GOT, - FLIGHT_OF_PHOENIX + FLIGHT_OF_PHOENIX, + ATM_TERRAFORMER, + DEATH_STAR }; private static Method CriterionRegister; diff --git a/src/main/java/zmaster587/advancedRocketry/api/ARConfiguration.java b/src/main/java/zmaster587/advancedRocketry/api/ARConfiguration.java index 0c1601918..617d27f1f 100644 --- a/src/main/java/zmaster587/advancedRocketry/api/ARConfiguration.java +++ b/src/main/java/zmaster587/advancedRocketry/api/ARConfiguration.java @@ -11,6 +11,7 @@ import net.minecraftforge.common.config.Configuration; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidRegistry; +import net.minecraftforge.fml.common.Loader; import net.minecraftforge.oredict.OreDictionary; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -19,6 +20,7 @@ import zmaster587.advancedRocketry.api.fuel.FuelRegistry.FuelType; import zmaster587.advancedRocketry.atmosphere.AtmosphereVacuum; import zmaster587.advancedRocketry.dimension.DimensionManager; +import zmaster587.advancedRocketry.integration.MatterOvedriveIntegration; import zmaster587.advancedRocketry.util.Asteroid; import zmaster587.advancedRocketry.util.SealableBlockHandler; @@ -89,9 +91,9 @@ public class ARConfiguration { public boolean enableNausea = true; @ConfigProperty public boolean enableOxygen = true; - @ConfigProperty + @ConfigProperty(needsSync = true) public boolean launchingDestroysBlocks; - @ConfigProperty + @ConfigProperty(needsSync = true) public float buildSpeedMultiplier = 1f; @ConfigProperty public boolean generateCopper; @@ -181,6 +183,10 @@ public class ARConfiguration { @ConfigProperty public float blockTankCapacity; @ConfigProperty + public float blockEnergyHatchCapacityMultiplier; + @ConfigProperty + public float blockLiquidHatchCapacityMultiplier; + @ConfigProperty public LinkedList laserBlackListDims = new LinkedList<>(); @ConfigProperty public LinkedList standardLaserDrillOres = new LinkedList<>(); @@ -236,6 +242,8 @@ public class ARConfiguration { @ConfigProperty public int planetDiscoveryChance; @ConfigProperty + public boolean allowNonArBiomesInTerraforming; + @ConfigProperty public double oxygenVentPowerMultiplier; @ConfigProperty public boolean skyOverride; @@ -272,15 +280,23 @@ public class ARConfiguration { @ConfigProperty(needsSync = true) public boolean experimentalSpaceFlight; - public ARConfiguration() { + @ConfigProperty + public boolean advancedWeightSystem; + @ConfigProperty + public boolean advancedWeightSystemInventories; - } + @ConfigProperty + public boolean partsWearSystem; + + @ConfigProperty + public double increaseWearIntensityProb; + + public ARConfiguration() {} public ARConfiguration(ARConfiguration config) { Field[] fields = ARConfiguration.class.getDeclaredFields(); List fieldList = new ArrayList<>(fields.length); - // getDeclaredFields returns an unordered list, so we need to sort them for (Field field : fields) { if (field.isAnnotationPresent(ConfigProperty.class)) @@ -348,6 +364,9 @@ public static void loadPreInit() { arConfig.jetPackThrust = (float) config.get(Configuration.CATEGORY_GENERAL, "jetPackForce", 1.3, "Amount of force the jetpack provides with respect to gravity, 1 is the same acceleration as caused by Earth's gravity, 2 is 2x the acceleration caused by Earth's gravity, etc. To make jetpack only work on low gravity planets, simply set it to a value less than 1").getDouble(); arConfig.buildSpeedMultiplier = (float) config.get(Configuration.CATEGORY_GENERAL, "buildSpeedMultiplier", 1f, "Multiplier for the build speed of the Rocket Builder (0.5 is twice as fast 2 is half as fast").getDouble(); arConfig.blockTankCapacity = (float) config.get(Configuration.CATEGORY_GENERAL, "blockTankCapacity", 1.0f, "Multiplier for the pressurized tank's (block) capacity", 0, Float.MAX_VALUE).getDouble(); + arConfig.blockEnergyHatchCapacityMultiplier = (float) config.get(Configuration.CATEGORY_GENERAL, "blockEnergyHatchCapacityMultiplier", 1.0f, "Multiplier for the energy hatch capacity", 0, Float.MAX_VALUE).getDouble(); + arConfig.blockLiquidHatchCapacityMultiplier = (float) config.get(Configuration.CATEGORY_GENERAL, "blockLiquidHatchCapacityMultiplier", 1.0f, "Multiplier for the liquid hatch (in/out) capacity", 0, Float.MAX_VALUE).getDouble(); + //Enriched Lava in the centrifuge arConfig.lavaCentrifugeOutputs = config.getStringList("lavaCentrifugeOutputs", Configuration.CATEGORY_GENERAL, new String[]{"nuggetCopper:100", "nuggetIron:100", "nuggetTin:100", "nuggetLead:100", "nuggetSilver:100", "nuggetGold:75", "nuggetDiamond:10", "nuggetUranium:10", "nuggetIridium:1"}, "Outputs and chances of objects from Enriched Lava in the Centrifuge. Format: :. Larger weights are more frequent"); arConfig.lavaCentrifugePower = config.getInt("lavaCentrifugePower", Configuration.CATEGORY_GENERAL, 10,0,999999,"The power per tick required to process enriched lava"); @@ -355,7 +374,7 @@ public static void loadPreInit() { arConfig.crystalliserMaximumGravity = (float) config.get(Configuration.CATEGORY_GENERAL, "crystalliserMaximumGravity", 0f, "Maximum gravity the crystalliser will function at. Use 0.0 to disable!").getDouble(); arConfig.enableLaserDrill = config.get(Configuration.CATEGORY_GENERAL, "EnableLaserDrill", true, "Enables the laser drill machine").getBoolean(); arConfig.spaceLaserPowerMult = (float) config.get(Configuration.CATEGORY_GENERAL, "LaserDrillPowerMultiplier", 1d, "Power multiplier for the laser drill machine").getDouble(); - arConfig.laserDrillPlanet = config.get(Configuration.CATEGORY_GENERAL, "laserDrillPlanet", false, "If true the orbital laser will actually mine blocks on the planet below (currently not working)").getBoolean(); + arConfig.laserDrillPlanet = config.get(Configuration.CATEGORY_GENERAL, "laserDrillPlanet", false, "If true the orbital laser will actually mine blocks on the planet below").getBoolean(); String[] str = config.getStringList("spaceLaserDimIdBlackList", Configuration.CATEGORY_GENERAL, new String[]{}, "Laser drill will not mine these dimension"); arConfig.enableTerraforming = config.get(Configuration.CATEGORY_GENERAL, "EnableTerraforming", true, "Enables terraforming items and blocks").getBoolean(); arConfig.terraformSpeed = config.get(Configuration.CATEGORY_GENERAL, "terraformMult", 1f, "Multplier for atmosphere change speed").getDouble(); @@ -364,6 +383,7 @@ public static void loadPreInit() { arConfig.terraformliquidRate = config.get(Configuration.CATEGORY_GENERAL, "TerraformerFluidConsumeRate", 40, "how many millibuckets/t are required to keep the terraformer running").getInt(); arConfig.allowTerraformNonAR = config.get(Configuration.CATEGORY_GENERAL, "allowTerraformingNonARWorlds", false, "If true dimensions not added by AR can be terraformed, including the overworld").getBoolean(); arConfig.enableGravityController = config.get(Configuration.CATEGORY_GENERAL, "enableGravityMachine", true, "If false the gravity controller cannot be built or used").getBoolean(); + arConfig.allowNonArBiomesInTerraforming = config.get(Configuration.CATEGORY_GENERAL, "allowNonArBiomesInTerraforming", false, "non-ar biomes from mods with custom world gen can not be decorated in terraforming. If you want fully decorated terraforming with only default biomes, set this to false").getBoolean(); //Oxygen arConfig.enableOxygen = config.get(OXYGEN, "EnableAtmosphericEffects", true, "If true, allows players being hurt due to lack of oxygen and allows effects from non-standard atmosphere types").getBoolean(); @@ -429,10 +449,10 @@ public static void loadPreInit() { //Rockets arConfig.rocketRequireFuel = config.get(ROCKET, "rocketsRequireFuel", true, "Set to false if rockets should not require fuel to fly").getBoolean(); arConfig.canBeFueledByHand = config.get(ROCKET, "canBeFueledByHand", true, "Set to false if rockets should not be able to be fueled by and and will require a fueling station").getBoolean(); - liquidMonopropellant = config.get(ROCKET, "rocketFuels", new String[]{"rocketfuel;2"}, "List of fluid names for fluids that can be used as rocket monopropellants").getStringList(); - liquidBipropellantFuel = config.get(ROCKET, "rocketBipropellants", new String[]{"hydrogen"}, "List of fluid names for fluids that can be used as rocket bipropellant fuels").getStringList(); - liquidBipropellantOxidizer = config.get(ROCKET, "rocketOxidizers", new String[]{"oxygen"}, "List of fluid names for fluids that can be used as rocket bipropellant oxidizers").getStringList(); - liquidNuclearWorkingFluid = config.get(ROCKET, "rocketNuclearWorkingFluids", new String[]{"hydrogen"}, "List of fluid names for fluids that can be used as rocket nuclear working fluids").getStringList(); + liquidMonopropellant = config.get(ROCKET, "rocketFuels", new String[]{"rocketfuel;10"}, "List of fluid names for fluids that can be used as rocket monopropellants").getStringList(); + liquidBipropellantFuel = config.get(ROCKET, "rocketBipropellants", new String[]{"hydrogen;10"}, "List of fluid names for fluids that can be used as rocket bipropellant fuels").getStringList(); + liquidBipropellantOxidizer = config.get(ROCKET, "rocketOxidizers", new String[]{"oxygen;10"}, "List of fluid names for fluids that can be used as rocket bipropellant oxidizers").getStringList(); + liquidNuclearWorkingFluid = config.get(ROCKET, "rocketNuclearWorkingFluids", new String[]{"hydrogen;10"}, "List of fluid names for fluids that can be used as rocket nuclear working fluids").getStringList(); arConfig.rocketThrustMultiplier = config.get(ROCKET, "thrustMultiplier", 1f, "Multiplier for per-engine thrust").getDouble(); arConfig.fuelCapacityMultiplier = config.get(ROCKET, "fuelCapacityMultiplier", 1f, "Multiplier for per-tank capacity").getDouble(); arConfig.nuclearCoreThrustRatio = config.get(ROCKET, "nuclearCoreThrustRatio", 1.0, "The multiplier for the thrust of the nuclear core block. With default configuration, this value provides a (max) thrust of 1000 per core.").getDouble(); @@ -446,6 +466,10 @@ public static void loadPreInit() { arConfig.gravityAffectsFuel = config.get(ROCKET, "gravityAffectsFuels", true, "If true planets with higher gravity require more fuel and lower gravity would require less").getBoolean(); arConfig.launchingDestroysBlocks = config.get(ROCKET, "launchBlockDestruction", false, "If true rocket launches will kill plants, glass soil, turn rock into lava, and more").getBoolean(); blackListRocketBlocksStr = config.getStringList("rocketBlockBlackList", ROCKET, new String[]{"minecraft:portal", "minecraft:bedrock", "minecraft:snow_layer", "minecraft:water", "minecraft:flowing_water", "minecraft:lava", "minecraft:flowing_lava", "minecraft:fire", "advancedrocketry:rocketfire"}, "Mod:Blockname for example \"minecraft:chest\""); + arConfig.advancedWeightSystem = config.get(ROCKET, "advancedWeightSystem", true, "Enables advanced weight system which computes rocket weight, including the handled inventories. Block weights are stores in weights.json").getBoolean(); + arConfig.advancedWeightSystemInventories = config.get(ROCKET, "advancedWeightSystemInventories", true, "Enables advanced weight system for inventories - may not work with modded inventories (eg IE storage chests)").getBoolean(); + arConfig.partsWearSystem = config.get(ROCKET, "partsWearSystem", true, "Enables rocket parts wear subsystem. Every rocket start it has probability to explode based on parts' wear intensities").getBoolean(); + arConfig.increaseWearIntensityProb = config.get(ROCKET, "increaseWearIntensityProb", 0.025, "Every rocket usage every part has this probability to increase wear intensity").getDouble(); //Ore and worldgen configuration //Ore configuration @@ -682,6 +706,9 @@ public static void loadPostInit() { //Add armor stand by default arConfig.bypassEntity.add(EntityArmorStand.class); + if (Loader.isModLoaded("matteroverdrive")) { + MatterOvedriveIntegration.addAndroidsToBypassList(arConfig); + } for (String str : entityList) { diff --git a/src/main/java/zmaster587/advancedRocketry/api/AdvancedRocketryBlocks.java b/src/main/java/zmaster587/advancedRocketry/api/AdvancedRocketryBlocks.java index 72e54a4b6..ad05c0b22 100644 --- a/src/main/java/zmaster587/advancedRocketry/api/AdvancedRocketryBlocks.java +++ b/src/main/java/zmaster587/advancedRocketry/api/AdvancedRocketryBlocks.java @@ -28,6 +28,7 @@ public class AdvancedRocketryBlocks { public static Block blockBipropellantFuelTank; public static Block blockOxidizerFuelTank; public static Block blockFuelingStation; + public static Block blockServiceStation; public static Block blockMonitoringStation, blockSatelliteBuilder, blockSatelliteControlCenter; public static Block blockNuclearFuelTank; public static Block blockMoonTurf, blockHotTurf; @@ -106,4 +107,6 @@ public class AdvancedRocketryBlocks { public static Block blockSolarArray; public static Block blockSolarArrayPanel; public static Block blockRocketFire; + public static Block blockServiceMonitor; + public static Block blockInvHatch; } diff --git a/src/main/java/zmaster587/advancedRocketry/api/MaterialGeode.java b/src/main/java/zmaster587/advancedRocketry/api/MaterialGeode.java index 50fb85c4a..e034b59e4 100644 --- a/src/main/java/zmaster587/advancedRocketry/api/MaterialGeode.java +++ b/src/main/java/zmaster587/advancedRocketry/api/MaterialGeode.java @@ -10,6 +10,6 @@ public class MaterialGeode extends Material { public MaterialGeode(MapColor p_i2116_1_) { super(p_i2116_1_); this.setRequiresTool(); + this.setNoPushMobility(); } - } diff --git a/src/main/java/zmaster587/advancedRocketry/api/SatelliteRegistry.java b/src/main/java/zmaster587/advancedRocketry/api/SatelliteRegistry.java index 2c9921bd2..6504b9379 100644 --- a/src/main/java/zmaster587/advancedRocketry/api/SatelliteRegistry.java +++ b/src/main/java/zmaster587/advancedRocketry/api/SatelliteRegistry.java @@ -137,7 +137,7 @@ public static SatelliteProperties getSatelliteProperties(@Nonnull ItemStack stac if (nbt != null) { if (stack.getItem() instanceof ItemSatellite) { - SatelliteProperties properties = new SatelliteProperties(nbt.getInteger("powerGeneration"), nbt.getInteger("powerStorage"), nbt.getString("dataType"), nbt.getInteger("maxData")); + SatelliteProperties properties = new SatelliteProperties(nbt.getInteger("powerGeneration"), nbt.getInteger("powerStorage"), nbt.getString("dataType"), nbt.getInteger("maxData"), nbt.getFloat("weight")); properties.setId(SatelliteRegistry.getSatelliteId(stack)); return properties; } diff --git a/src/main/java/zmaster587/advancedRocketry/api/StatsRocket.java b/src/main/java/zmaster587/advancedRocketry/api/StatsRocket.java index 7ca844d81..427f01ee4 100644 --- a/src/main/java/zmaster587/advancedRocketry/api/StatsRocket.java +++ b/src/main/java/zmaster587/advancedRocketry/api/StatsRocket.java @@ -3,8 +3,11 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagFloat; import net.minecraft.nbt.NBTTagInt; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidRegistry; import zmaster587.advancedRocketry.api.fuel.FuelRegistry; import zmaster587.advancedRocketry.api.fuel.FuelRegistry.FuelType; +import zmaster587.advancedRocketry.util.WeightEngine; import zmaster587.libVulpes.util.HashedBlockPosition; import zmaster587.libVulpes.util.Vector3F; @@ -24,7 +27,7 @@ public class StatsRocket { public float injectionBurnLenghtMult; HashedBlockPosition pilotSeatPos; private int thrust; - private int weight; + private float weight; private float drillingPower; private String fuelFluid; private String oxidizerFluid; @@ -128,11 +131,25 @@ public void setThrust(int thrust) { this.thrust = thrust; } - public int getWeight() { - return weight; + public float getWeight_NoFuel() {return weight;} + + public float getWeight() { + float fluidWeight = 0; + if (ARConfiguration.getCurrentConfig().advancedWeightSystem) { + if (FluidRegistry.isFluidRegistered(getFuelFluid())) { + Fluid f = FluidRegistry.getFluid(getFuelFluid()); + fluidWeight += WeightEngine.INSTANCE.getWeight(f, getFuelAmount(FuelType.LIQUID_MONOPROPELLANT)); + fluidWeight += WeightEngine.INSTANCE.getWeight(f, getFuelAmount(FuelType.LIQUID_BIPROPELLANT)); + } + if (FluidRegistry.isFluidRegistered(getOxidizerFluid())) { + Fluid f = FluidRegistry.getFluid(getOxidizerFluid()); + fluidWeight += WeightEngine.INSTANCE.getWeight(f, getFuelAmount(FuelType.LIQUID_OXIDIZER)); + } + } + return weight + fluidWeight; } - public void setWeight(int weight) { + public void setWeight(float weight) { this.weight = weight; } @@ -169,7 +186,8 @@ public void setDrillingPower(float power) { } public float getAcceleration(float gravitationalMultiplier) { - return (getThrust() - (weight * ((ARConfiguration.getCurrentConfig().gravityAffectsFuel) ? gravitationalMultiplier : 1))) / 10000f; + float N = getThrust() - (getWeight() * ((ARConfiguration.getCurrentConfig().gravityAffectsFuel) ? gravitationalMultiplier : 1)); + return N/getWeight() /20f; } public List> getEngineLocations() { @@ -552,6 +570,16 @@ public void reset() { passengerSeats.clear(); statTags.clear(); } + public void reset_no_fuel() { + thrust = 0; + weight = 0; + drillingPower = 0f; + + pilotSeatPos.x = INVALID_SEAT; + clearEngineLocations(); + passengerSeats.clear(); + statTags.clear(); + } public void setStatTag(String str, float value) { statTags.put(str, value); @@ -574,7 +602,7 @@ public void writeToNBT(NBTTagCompound nbt) { NBTTagCompound stats = new NBTTagCompound(); stats.setInteger("thrust", this.thrust); - stats.setInteger("weight", this.weight); + stats.setFloat("weight", this.weight); stats.setFloat("drillingPower", this.drillingPower); stats.setString("fuelFluid", this.fuelFluid); stats.setString("oxidizerFluid", this.oxidizerFluid); @@ -658,11 +686,11 @@ else if (obj instanceof Integer) } public void readFromNBT(NBTTagCompound nbt) { - +this.reset(); if (nbt.hasKey(TAGNAME)) { NBTTagCompound stats = nbt.getCompoundTag(TAGNAME); this.thrust = stats.getInteger("thrust"); - this.weight = stats.getInteger("weight"); + this.weight = stats.getFloat("weight"); this.fuelFluid = stats.getString("fuelFluid"); this.oxidizerFluid = stats.getString("oxidizerFluid"); this.workingFluid = stats.getString("workingFluid"); diff --git a/src/main/java/zmaster587/advancedRocketry/api/satellite/SatelliteProperties.java b/src/main/java/zmaster587/advancedRocketry/api/satellite/SatelliteProperties.java index 9772ee9e2..ee3bfbec4 100644 --- a/src/main/java/zmaster587/advancedRocketry/api/satellite/SatelliteProperties.java +++ b/src/main/java/zmaster587/advancedRocketry/api/satellite/SatelliteProperties.java @@ -9,17 +9,20 @@ public class SatelliteProperties implements IWeighted { private int powerGeneration, powerStorage, maxData; private long id; private String satType; + private float weight; + public SatelliteProperties() { satType = null; id = -1; } - public SatelliteProperties(int powerGeneration, int powerStorage, String satType, int maxData) { + public SatelliteProperties(int powerGeneration, int powerStorage, String satType, int maxData, float weight) { this(); this.powerGeneration = powerGeneration; this.powerStorage = powerStorage; this.satType = satType; this.maxData = maxData; + this.weight = weight; } /** @@ -79,7 +82,7 @@ public SatelliteProperties setPowerGeneration(int powerGeneration) { } public float getWeight() { - return 50 + getPowerStorage() * 0.1F + getPowerGeneration() * 0.2F + getMaxDataStorage() * 0.01F; + return this.weight; } /** @@ -136,6 +139,7 @@ public void writeToNBT(NBTTagCompound nbt) { nbt.setString("dataType", satType); nbt.setLong("satId", id); nbt.setInteger("maxData", maxData); + nbt.setFloat("weight", weight); } public void readFromNBT(NBTTagCompound nbt) { @@ -144,6 +148,7 @@ public void readFromNBT(NBTTagCompound nbt) { satType = nbt.getString("dataType"); id = nbt.getLong("satId"); maxData = nbt.getInteger("maxData"); + weight = nbt.getFloat("weight"); } public enum Property { diff --git a/src/main/java/zmaster587/advancedRocketry/asm/AdvancedRocketryPlugin.java b/src/main/java/zmaster587/advancedRocketry/asm/AdvancedRocketryPlugin.java index 52f49312d..d991a2128 100644 --- a/src/main/java/zmaster587/advancedRocketry/asm/AdvancedRocketryPlugin.java +++ b/src/main/java/zmaster587/advancedRocketry/asm/AdvancedRocketryPlugin.java @@ -3,6 +3,8 @@ import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin; import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin.MCVersion; import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin.TransformerExclusions; +import zmaster587.advancedRocketry.ARHookLoader; +import zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.minecraft.HookLoader; import java.util.Map; @@ -10,13 +12,15 @@ @MCVersion("1.12.2") public class AdvancedRocketryPlugin implements IFMLLoadingPlugin { + private final HookLoader hookLoader; + public AdvancedRocketryPlugin() { - // TODO Auto-generated constructor stub + hookLoader = new ARHookLoader(); } @Override public String[] getASMTransformerClass() { - return new String[]{ClassTransformer.class.getName()}; + return new String[]{ClassTransformer.class.getName(), hookLoader.getASMTransformerClass()[0]}; } @Override @@ -26,19 +30,16 @@ public String getModContainerClass() { @Override public String getSetupClass() { - // TODO Auto-generated method stub - return null; + return hookLoader.getSetupClass(); } @Override public void injectData(Map data) { - + hookLoader.injectData(data); } @Override public String getAccessTransformerClass() { - // TODO Auto-generated method stub - return null; + return hookLoader.getAccessTransformerClass(); } - } diff --git a/src/main/java/zmaster587/advancedRocketry/atmosphere/AtmosphereHandler.java b/src/main/java/zmaster587/advancedRocketry/atmosphere/AtmosphereHandler.java index 6dc2b9c12..b3711e857 100644 --- a/src/main/java/zmaster587/advancedRocketry/atmosphere/AtmosphereHandler.java +++ b/src/main/java/zmaster587/advancedRocketry/atmosphere/AtmosphereHandler.java @@ -135,6 +135,8 @@ public static void onBlockChange(@Nonnull World world, @Nonnull BlockPos bpos) { } + // sure.. causes stackoverflow left right center + /* else if (!handler.getAtmosphereType(bpos).allowsCombustion()) { if (world.getBlockState(bpos).getBlock().isLeaves(world.getBlockState(bpos), world, bpos)) { if (!(Boolean)world.getBlockState(bpos).getValue(BlockLeaves.CHECK_DECAY)) { @@ -152,6 +154,7 @@ else if (!handler.getAtmosphereType(bpos).allowsCombustion()) { world.setBlockState(bpos, Blocks.DIRT.getDefaultState()); } } + */ //Gasses should automatically vaporize and dissipate if (handler.getAtmosphereType(bpos) == AtmosphereType.VACUUM) { diff --git a/src/main/java/zmaster587/advancedRocketry/atmosphere/AtmosphereNeedsSuit.java b/src/main/java/zmaster587/advancedRocketry/atmosphere/AtmosphereNeedsSuit.java index 9c09a2d79..3a3b211b7 100644 --- a/src/main/java/zmaster587/advancedRocketry/atmosphere/AtmosphereNeedsSuit.java +++ b/src/main/java/zmaster587/advancedRocketry/atmosphere/AtmosphereNeedsSuit.java @@ -4,9 +4,11 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraft.item.ItemStack; +import net.minecraftforge.fml.common.Loader; import zmaster587.advancedRocketry.api.EntityRocketBase; import zmaster587.advancedRocketry.api.capability.CapabilitySpaceArmor; import zmaster587.advancedRocketry.entity.EntityElevatorCapsule; +import zmaster587.advancedRocketry.integration.MatterOvedriveIntegration; import zmaster587.advancedRocketry.util.ItemAirUtils; import javax.annotation.Nonnull; @@ -25,6 +27,9 @@ protected boolean onlyNeedsMask() { @Override public boolean isImmune(EntityLivingBase player) { + if (Loader.isModLoaded("matteroverdrive")) { + if(MatterOvedriveIntegration.isAndroidNeedNoOxygen(player)) return true; + } //Checks if player is wearing spacesuit or anything that extends ItemSpaceArmor diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockAdvancedBipropellantRocketMotor.java b/src/main/java/zmaster587/advancedRocketry/block/BlockAdvancedBipropellantRocketMotor.java index 6abd08a75..43dde33f6 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockAdvancedBipropellantRocketMotor.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockAdvancedBipropellantRocketMotor.java @@ -1,8 +1,14 @@ package zmaster587.advancedRocketry.block; import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import zmaster587.advancedRocketry.api.ARConfiguration; +import zmaster587.advancedRocketry.tile.TileBrokenPart; + +import javax.annotation.Nullable; public class BlockAdvancedBipropellantRocketMotor extends BlockBipropellantRocketMotor { @@ -19,4 +25,10 @@ public int getThrust(World world, BlockPos pos) { public int getFuelConsumptionRate(World world, int x, int y, int z) { return 3; } + + @Nullable + @Override + public TileEntity createTileEntity(final World worldIn, final IBlockState state) { + return new TileBrokenPart(10, (float) ARConfiguration.getCurrentConfig().increaseWearIntensityProb); + } } diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockAdvancedRocketMotor.java b/src/main/java/zmaster587/advancedRocketry/block/BlockAdvancedRocketMotor.java index 84b8e8ee6..546a9e845 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockAdvancedRocketMotor.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockAdvancedRocketMotor.java @@ -1,8 +1,14 @@ package zmaster587.advancedRocketry.block; import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import zmaster587.advancedRocketry.api.ARConfiguration; +import zmaster587.advancedRocketry.tile.TileBrokenPart; + +import javax.annotation.Nullable; public class BlockAdvancedRocketMotor extends BlockRocketMotor { @@ -19,4 +25,10 @@ public int getThrust(World world, BlockPos pos) { public int getFuelConsumptionRate(World world, int x, int y, int z) { return 3; } + + @Nullable + @Override + public TileEntity createTileEntity(final World worldIn, final IBlockState state) { + return new TileBrokenPart(10, (float) ARConfiguration.getCurrentConfig().increaseWearIntensityProb); + } } diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockAtmosphereTerraformer.java b/src/main/java/zmaster587/advancedRocketry/block/BlockAtmosphereTerraformer.java new file mode 100644 index 000000000..d4dc28943 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockAtmosphereTerraformer.java @@ -0,0 +1,39 @@ +package zmaster587.advancedRocketry.block; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import zmaster587.advancedRocketry.advancements.ARAdvancements; +import zmaster587.advancedRocketry.tile.multiblock.TileAtmosphereTerraformer; +import zmaster587.libVulpes.block.multiblock.BlockMultiblockMachine; +import zmaster587.libVulpes.tile.multiblock.TileMultiBlock; + +public class BlockAtmosphereTerraformer extends BlockMultiblockMachine { + + + public BlockAtmosphereTerraformer(Class tileClass, int guiId) { + super(tileClass, guiId); + } + + @Override + public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { + boolean r = super.onBlockActivated(world,pos,state,player,hand, facing,hitX,hitY,hitZ); + + if (!world.isRemote) { + if (world.getTileEntity(pos) instanceof TileAtmosphereTerraformer) { + if (((TileAtmosphereTerraformer) world.getTileEntity(pos)).isComplete()) { + ARAdvancements.ATM_TERRAFORMER.trigger((EntityPlayerMP) player); + } + } + + } + + return r; + } + + +} diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockBipropellantFuelTank.java b/src/main/java/zmaster587/advancedRocketry/block/BlockBipropellantFuelTank.java index 890e33532..dbac33ace 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockBipropellantFuelTank.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockBipropellantFuelTank.java @@ -13,54 +13,9 @@ import java.util.Locale; -public class BlockBipropellantFuelTank extends Block implements IFuelTank { - - public final static PropertyEnum TANKSTATES = PropertyEnum.create("tankstates", TankStates.class); - +public class BlockBipropellantFuelTank extends BlockFuelTank implements IFuelTank { public BlockBipropellantFuelTank(Material mat) { super(mat); - this.setDefaultState(this.getDefaultState().withProperty(TANKSTATES, TankStates.MIDDLE)); - } - - @Override - public IBlockState getStateFromMeta(int meta) { - return this.getDefaultState().withProperty(TANKSTATES, TankStates.values()[meta]); - } - - @Override - public int getMetaFromState(IBlockState state) { - return state.getValue(TANKSTATES).ordinal(); - } - - @Override - protected BlockStateContainer createBlockState() { - return new BlockStateContainer(this, TANKSTATES); - } - - @Override - public IBlockState getActualState(IBlockState state, IBlockAccess world, - BlockPos pos) { - int i = world.getBlockState(pos.add(0, 1, 0)).getBlock() == this ? 1 : 0; - i += world.getBlockState(pos.add(0, -1, 0)).getBlock() == this ? 2 : 0; - - //If there is no tank below this one - if (i == 1) { - return state.withProperty(TANKSTATES, TankStates.BOTTOM); - } - //If there is no tank above this one - else if (i == 2) { - return state.withProperty(TANKSTATES, TankStates.TOP); - } - //If there is a tank above and below this one - else { - return state.withProperty(TANKSTATES, TankStates.MIDDLE); - } - } - - - @Override - public boolean isOpaqueCube(IBlockState state) { - return false; } @Override @@ -68,15 +23,5 @@ public int getMaxFill(World world, BlockPos pos, IBlockState state) { return 1000; } - public enum TankStates implements IStringSerializable { - TOP, - BOTTOM, - MIDDLE; - @Override - public String getName() { - return name().toLowerCase(Locale.ENGLISH); - } - - } } diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockBipropellantRocketMotor.java b/src/main/java/zmaster587/advancedRocketry/block/BlockBipropellantRocketMotor.java index a375c2313..74d3d4a6b 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockBipropellantRocketMotor.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockBipropellantRocketMotor.java @@ -3,16 +3,26 @@ import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumBlockRenderType; import net.minecraft.util.EnumFacing; +import net.minecraft.util.NonNullList; import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; +import zmaster587.advancedRocketry.api.ARConfiguration; import zmaster587.advancedRocketry.api.IRocketEngine; +import zmaster587.advancedRocketry.tile.TileBrokenPart; +import zmaster587.advancedRocketry.util.IBrokenPartBlock; import zmaster587.libVulpes.block.BlockFullyRotatable; import javax.annotation.Nonnull; +import javax.annotation.Nullable; -public class BlockBipropellantRocketMotor extends BlockFullyRotatable implements IRocketEngine { +public class BlockBipropellantRocketMotor extends BlockFullyRotatable implements IRocketEngine, IBrokenPartBlock { public BlockBipropellantRocketMotor(Material mat) { super(mat); @@ -35,8 +45,69 @@ public int getFuelConsumptionRate(World world, int x, int y, int z) { } @Override - public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase placer, @Nonnull ItemStack stack) { + public EnumBlockRenderType getRenderType(final IBlockState state) { + return EnumBlockRenderType.INVISIBLE; + } + @Override + public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase placer, @Nonnull ItemStack stack) { world.setBlockState(pos, state.withProperty(FACING, EnumFacing.DOWN)); + + TileEntity te = world.getTileEntity(pos); + ((TileBrokenPart) te).setStage(stack.getItemDamage()); + } + +// @Override +// public boolean onBlockActivated(final World worldIn, final BlockPos pos, final IBlockState state, final EntityPlayer playerIn, final EnumHand hand, final EnumFacing facing, final float hitX, final float hitY, final float hitZ) { +// if (!worldIn.isRemote) { +// TileEntity te = worldIn.getTileEntity(pos); +// ((TileBrokenPart) te).transition(); +// } +// return super.onBlockActivated(worldIn, pos, state, playerIn, hand, facing, hitX, hitY, hitZ); +// } + + @Override + public void harvestBlock(final World world, final EntityPlayer player, final BlockPos pos, final IBlockState state, @Nullable final TileEntity te, final ItemStack stack) { + if (!world.isRemote && !player.isCreative()) { + TileBrokenPart tile = (TileBrokenPart) te; + + ItemStack drop = getDropItem(state, world, tile); + + world.spawnEntity(new EntityItem(world, pos.getX(), pos.getY(), pos.getZ(), drop)); + } + + super.harvestBlock(world, player, pos, state, te, stack); + } + + public IBlockState getStateFromMeta(int meta) { + if (meta > 5) { + return this.getDefaultState(); + } + return super.getStateFromMeta(meta); + } + + @Override + public void getDrops(final NonNullList drops, final IBlockAccess world, final BlockPos pos, final IBlockState state, final int fortune) { + // no drops here + } + + @Override + public boolean hasTileEntity(IBlockState state) { + return true; + } + + @Nullable + @Override + public TileEntity createTileEntity(final World worldIn, final IBlockState state) { + return new TileBrokenPart(10, (float) ARConfiguration.getCurrentConfig().increaseWearIntensityProb); + } + + @Override + public ItemStack getDropItem(final IBlockState state, final World world, final @Nullable TileBrokenPart te) { + ItemStack drop = new ItemStack(this.getItemDropped(state, world.rand, 0)); + if (te != null) { + drop.setItemDamage(te.getStage()); + } + return drop; } } diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockFuelTank.java b/src/main/java/zmaster587/advancedRocketry/block/BlockFuelTank.java index 37ce75e34..1a0b5ae46 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockFuelTank.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockFuelTank.java @@ -13,6 +13,7 @@ import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import zmaster587.advancedRocketry.api.IFuelTank; +import zmaster587.advancedRocketry.api.IRocketEngine; import zmaster587.libVulpes.block.BlockFullyRotatable; import javax.annotation.Nonnull; @@ -84,7 +85,7 @@ public IBlockState getActualState(@Nonnull IBlockState state, IBlockAccess world if (world.getBlockState(pos).getValue(FACING) == EnumFacing.DOWN || world.getBlockState(pos).getValue(FACING) == EnumFacing.UP) { int i = (world.getBlockState(pos.add(0, 1, 0)).getBlock() == this && world.getBlockState(pos.add(0, 1, 0)).getValue(FACING) == EnumFacing.UP) ? 1 : 0; - i += (world.getBlockState(pos.add(0, -1, 0)).getBlock() == this && world.getBlockState(pos.add(0, -1, 0)).getValue(FACING) == EnumFacing.UP) || world.getBlockState(pos.add(0, -1, 0)).getBlock() instanceof BlockRocketMotor ? 2 : 0; + i += (world.getBlockState(pos.add(0, -1, 0)).getBlock() == this && world.getBlockState(pos.add(0, -1, 0)).getValue(FACING) == EnumFacing.UP) || world.getBlockState(pos.add(0, -1, 0)).getBlock() instanceof IRocketEngine ? 2 : 0; //If there is no tank below this one and no engine below if (i == 1) { @@ -101,8 +102,8 @@ else if (i == 2) { } if (world.getBlockState(pos).getValue(FACING) == EnumFacing.EAST || world.getBlockState(pos).getValue(FACING) == EnumFacing.WEST) { - int i = (world.getBlockState(pos.add(1, 0, 0)).getBlock() == this && world.getBlockState(pos.add(1, 0, 0)).getValue(FACING) == EnumFacing.EAST) || world.getBlockState(pos.add(1, 0, 0)).getBlock() instanceof BlockRocketMotor ? 1 : 0; - i += (world.getBlockState(pos.add(-1, 0, 0)).getBlock() == this && world.getBlockState(pos.add(-1, 0, 0)).getValue(FACING) == EnumFacing.EAST) || world.getBlockState(pos.add(-1, 0, 0)).getBlock() instanceof BlockRocketMotor ? 2 : 0; + int i = (world.getBlockState(pos.add(1, 0, 0)).getBlock() == this && world.getBlockState(pos.add(1, 0, 0)).getValue(FACING) == EnumFacing.EAST) || world.getBlockState(pos.add(1, 0, 0)).getBlock() instanceof IRocketEngine ? 1 : 0; + i += (world.getBlockState(pos.add(-1, 0, 0)).getBlock() == this && world.getBlockState(pos.add(-1, 0, 0)).getValue(FACING) == EnumFacing.EAST) || world.getBlockState(pos.add(-1, 0, 0)).getBlock() instanceof IRocketEngine ? 2 : 0; //If there is no tank below this one and no engine below if (i == 1) { @@ -119,8 +120,8 @@ else if (i == 2) { } if (world.getBlockState(pos).getValue(FACING) == EnumFacing.NORTH || world.getBlockState(pos).getValue(FACING) == EnumFacing.SOUTH) { - int i = (world.getBlockState(pos.add(0, 0, 1)).getBlock() == this && world.getBlockState(pos.add(0, 0, 1)).getValue(FACING) == EnumFacing.SOUTH) || world.getBlockState(pos.add(0, 0, 1)).getBlock() instanceof BlockRocketMotor ? 1 : 0; - i += (world.getBlockState(pos.add(0, 0, -1)).getBlock() == this && world.getBlockState(pos.add(0, 0, -1)).getValue(FACING) == EnumFacing.SOUTH) || world.getBlockState(pos.add(0, 0, -1)).getBlock() instanceof BlockRocketMotor ? 2 : 0; + int i = (world.getBlockState(pos.add(0, 0, 1)).getBlock() == this && world.getBlockState(pos.add(0, 0, 1)).getValue(FACING) == EnumFacing.SOUTH) || world.getBlockState(pos.add(0, 0, 1)).getBlock() instanceof IRocketEngine ? 1 : 0; + i += (world.getBlockState(pos.add(0, 0, -1)).getBlock() == this && world.getBlockState(pos.add(0, 0, -1)).getValue(FACING) == EnumFacing.SOUTH) || world.getBlockState(pos.add(0, 0, -1)).getBlock() instanceof IRocketEngine ? 2 : 0; //If there is no tank below this one and no engine below if (i == 1) { diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearFuelTank.java b/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearFuelTank.java index 7afd5e4eb..4e8b21c1e 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearFuelTank.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearFuelTank.java @@ -13,70 +13,14 @@ import java.util.Locale; -public class BlockNuclearFuelTank extends Block implements IFuelTank { - - public final static PropertyEnum TANKSTATES = PropertyEnum.create("tankstates", TankStates.class); +public class BlockNuclearFuelTank extends BlockFuelTank implements IFuelTank { public BlockNuclearFuelTank(Material mat) { super(mat); - this.setDefaultState(this.getDefaultState().withProperty(TANKSTATES, TankStates.MIDDLE)); - } - - @Override - public IBlockState getStateFromMeta(int meta) { - return this.getDefaultState().withProperty(TANKSTATES, TankStates.values()[meta]); - } - - @Override - public int getMetaFromState(IBlockState state) { - return state.getValue(TANKSTATES).ordinal(); - } - - @Override - protected BlockStateContainer createBlockState() { - return new BlockStateContainer(this, TANKSTATES); - } - - @Override - public IBlockState getActualState(IBlockState state, IBlockAccess world, - BlockPos pos) { - int i = world.getBlockState(pos.add(0, 1, 0)).getBlock() == this ? 1 : 0; - i += world.getBlockState(pos.add(0, -1, 0)).getBlock() == this ? 2 : 0; - - //If there is no tank below this one - if (i == 1) { - return state.withProperty(TANKSTATES, TankStates.BOTTOM); - } - //If there is no tank above this one - else if (i == 2) { - return state.withProperty(TANKSTATES, TankStates.TOP); - } - //If there is a tank above and below this one - else { - return state.withProperty(TANKSTATES, TankStates.MIDDLE); - } - } - - - @Override - public boolean isOpaqueCube(IBlockState state) { - return false; } @Override public int getMaxFill(World world, BlockPos pos, IBlockState state) { return 1000; } - - public enum TankStates implements IStringSerializable { - TOP, - BOTTOM, - MIDDLE; - - @Override - public String getName() { - return name().toLowerCase(Locale.ENGLISH); - } - - } } diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearRocketMotor.java b/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearRocketMotor.java index 23327bf87..ed84d34d5 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearRocketMotor.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearRocketMotor.java @@ -1,8 +1,14 @@ package zmaster587.advancedRocketry.block; import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import zmaster587.advancedRocketry.api.ARConfiguration; +import zmaster587.advancedRocketry.tile.TileBrokenPart; + +import javax.annotation.Nullable; public class BlockNuclearRocketMotor extends BlockRocketMotor { @@ -19,4 +25,10 @@ public int getThrust(World world, BlockPos pos) { public int getFuelConsumptionRate(World world, int x, int y, int z) { return 1; } + + @Nullable + @Override + public TileEntity createTileEntity(final World worldIn, final IBlockState state) { + return new TileBrokenPart(10, 4 * (float) ARConfiguration.getCurrentConfig().increaseWearIntensityProb); + } } diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockOrbitalLaserDrill.java b/src/main/java/zmaster587/advancedRocketry/block/BlockOrbitalLaserDrill.java index d0bd9f506..5f9c49c55 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockOrbitalLaserDrill.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockOrbitalLaserDrill.java @@ -1,11 +1,17 @@ package zmaster587.advancedRocketry.block; import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; import net.minecraft.world.Explosion; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; +import zmaster587.advancedRocketry.advancements.ARAdvancements; +import zmaster587.advancedRocketry.tile.multiblock.TileAtmosphereTerraformer; import zmaster587.advancedRocketry.tile.multiblock.orbitallaserdrill.TileOrbitalLaserDrill; import zmaster587.libVulpes.block.multiblock.BlockMultiblockMachine; import zmaster587.libVulpes.inventory.GuiHandler; @@ -19,6 +25,7 @@ public BlockOrbitalLaserDrill() { setTickRandomly(true).setUnlocalizedName("spaceLaser"); } + @Override public TileEntity createTileEntity(World world, IBlockState state) { return new TileOrbitalLaserDrill(); @@ -36,6 +43,20 @@ public void onNeighborChange(IBlockAccess world, BlockPos pos, BlockPos neighbor ((TileOrbitalLaserDrill) world.getTileEntity(pos)).checkCanRun(); } + + @Override + public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { + boolean r = super.onBlockActivated(worldIn, pos, state, playerIn, hand, facing, hitX, hitY, hitZ); + if (!worldIn.isRemote) { + if (worldIn.getTileEntity(pos) instanceof TileOrbitalLaserDrill) { + if (((TileOrbitalLaserDrill) worldIn.getTileEntity(pos)).isComplete()) { + ARAdvancements.DEATH_STAR.trigger((EntityPlayerMP) playerIn); + } + } + } + return r; + } + @Override public void breakBlock(World worldIn, BlockPos pos, IBlockState state) { super.breakBlock(worldIn, pos, state); diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockOxidizerFuelTank.java b/src/main/java/zmaster587/advancedRocketry/block/BlockOxidizerFuelTank.java index cb8f3cd72..cbdc850c2 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockOxidizerFuelTank.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockOxidizerFuelTank.java @@ -14,57 +14,11 @@ import javax.annotation.Nonnull; import java.util.Locale; -public class BlockOxidizerFuelTank extends Block implements IFuelTank { +public class BlockOxidizerFuelTank extends BlockFuelTank implements IFuelTank { - public final static PropertyEnum TANKSTATES = PropertyEnum.create("tankstates", TankStates.class); public BlockOxidizerFuelTank(Material mat) { super(mat); - this.setDefaultState(this.getDefaultState().withProperty(TANKSTATES, TankStates.MIDDLE)); - } - - @Override - @Nonnull - public IBlockState getStateFromMeta(int meta) { - return this.getDefaultState().withProperty(TANKSTATES, TankStates.values()[meta]); - } - - @Override - public int getMetaFromState(IBlockState state) { - return state.getValue(TANKSTATES).ordinal(); - } - - @Override - @Nonnull - protected BlockStateContainer createBlockState() { - return new BlockStateContainer(this, TANKSTATES); - } - - @Override - @Nonnull - public IBlockState getActualState(@Nonnull IBlockState state, IBlockAccess world, - BlockPos pos) { - int i = world.getBlockState(pos.add(0, 1, 0)).getBlock() == this ? 1 : 0; - i += world.getBlockState(pos.add(0, -1, 0)).getBlock() == this ? 2 : 0; - - //If there is no tank below this one - if (i == 1) { - return state.withProperty(TANKSTATES, TankStates.BOTTOM); - } - //If there is no tank above this one - else if (i == 2) { - return state.withProperty(TANKSTATES, TankStates.TOP); - } - //If there is a tank above and below this one - else { - return state.withProperty(TANKSTATES, TankStates.MIDDLE); - } - } - - - @Override - public boolean isOpaqueCube(IBlockState state) { - return false; } @Override @@ -72,15 +26,4 @@ public int getMaxFill(World world, BlockPos pos, IBlockState state) { return 1000; } - public enum TankStates implements IStringSerializable { - TOP, - BOTTOM, - MIDDLE; - - @Override - public String getName() { - return name().toLowerCase(Locale.ENGLISH); - } - - } } diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockPressurizedFluidTank.java b/src/main/java/zmaster587/advancedRocketry/block/BlockPressurizedFluidTank.java index b6ef309cf..cd6dffcfa 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockPressurizedFluidTank.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockPressurizedFluidTank.java @@ -39,7 +39,7 @@ public class BlockPressurizedFluidTank extends Block { public BlockPressurizedFluidTank(Material material) { super(material); - isBlockContainer = true; + hasTileEntity = true; } @Override diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockRocketMotor.java b/src/main/java/zmaster587/advancedRocketry/block/BlockRocketMotor.java index 86aa18612..088ac702e 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockRocketMotor.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockRocketMotor.java @@ -4,22 +4,25 @@ import net.minecraft.block.state.IBlockState; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.item.EntityItem; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumBlockRenderType; import net.minecraft.util.EnumFacing; import net.minecraft.util.NonNullList; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; +import zmaster587.advancedRocketry.api.ARConfiguration; import zmaster587.advancedRocketry.api.IRocketEngine; import zmaster587.advancedRocketry.tile.TileBrokenPart; +import zmaster587.advancedRocketry.util.IBrokenPartBlock; import zmaster587.libVulpes.block.BlockFullyRotatable; import javax.annotation.Nonnull; import javax.annotation.Nullable; -public class BlockRocketMotor extends BlockFullyRotatable implements IRocketEngine { +public class BlockRocketMotor extends BlockFullyRotatable implements IRocketEngine, IBrokenPartBlock { public BlockRocketMotor(Material mat) { super(mat); @@ -45,7 +48,17 @@ public IBlockState getActualState(@Nonnull IBlockState state, IBlockAccess world if (world.getBlockState(pos.add(0, 0, -1)).getBlock() instanceof BlockFuelTank) { return state.withProperty(FACING, EnumFacing.NORTH); } - return state; + return super.getActualState(state, world, pos); + } + + @Override + public int getThrust(World world, BlockPos pos) { + return 10; + } + + @Override + public int getFuelConsumptionRate(World world, int x, int y, int z) { + return 1; } @Override @@ -54,26 +67,21 @@ public boolean isOpaqueCube(@Nonnull IBlockState state) { } @Override - public int getThrust(World world, BlockPos pos) { - return 10; + public boolean isBlockNormalCube(@Nonnull final IBlockState state) { + return false; } @Override - public int getFuelConsumptionRate(World world, int x, int y, int z) { - return 1; + public EnumBlockRenderType getRenderType(final IBlockState state) { + return EnumBlockRenderType.INVISIBLE; } @Override public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase placer, @Nonnull ItemStack stack) { - NBTTagCompound compound = stack.getTagCompound(); - int stage = 0; - if (compound != null && compound.hasKey("destruction_stage")) { - stage = compound.getInteger("destruction_stage"); - } world.setBlockState(pos, state.withProperty(FACING, EnumFacing.DOWN)); TileEntity te = world.getTileEntity(pos); - ((TileBrokenPart) te).setStage(stage); + ((TileBrokenPart) te).setStage(stack.getItemDamage()); } // @Override @@ -86,19 +94,23 @@ public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, Entity // } @Override - public void breakBlock(final World world, final BlockPos pos, final IBlockState state) { - if (!world.isRemote) { - ItemStack drop = new ItemStack(this.getItemDropped(state, world.rand, 0)); + public void harvestBlock(final World world, final EntityPlayer player, final BlockPos pos, final IBlockState state, @Nullable final TileEntity te, final ItemStack stack) { + if (!world.isRemote && !player.isCreative()) { + TileBrokenPart tile = (TileBrokenPart) te; - TileBrokenPart te = (TileBrokenPart) world.getTileEntity(pos); - NBTTagCompound compound = new NBTTagCompound(); - compound.setInteger("destruction_stage", te.getStage()); - drop.setTagCompound(compound); + ItemStack drop = getDropItem(state, world, tile); world.spawnEntity(new EntityItem(world, pos.getX(), pos.getY(), pos.getZ(), drop)); } - super.breakBlock(world, pos, state); + super.harvestBlock(world, player, pos, state, te, stack); + } + + public IBlockState getStateFromMeta(int meta) { + if (meta > 5) { + return this.getDefaultState(); + } + return super.getStateFromMeta(meta); } @Override @@ -114,6 +126,15 @@ public boolean hasTileEntity(IBlockState state) { @Nullable @Override public TileEntity createTileEntity(final World worldIn, final IBlockState state) { - return new TileBrokenPart(10, 0.1F); + return new TileBrokenPart(10, 2 * (float) ARConfiguration.getCurrentConfig().increaseWearIntensityProb); + } + + @Override + public ItemStack getDropItem(final IBlockState state, final World world, final @Nullable TileBrokenPart te) { + ItemStack drop = new ItemStack(this.getItemDropped(state, world.rand, 0)); + if (te != null) { + drop.setItemDamage(te.getStage()); + } + return drop; } } diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockTileTerraformer.java b/src/main/java/zmaster587/advancedRocketry/block/BlockTileTerraformer.java index 7ac0de83a..2ebf763ca 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockTileTerraformer.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockTileTerraformer.java @@ -8,6 +8,7 @@ import net.minecraft.block.properties.PropertyBool; import net.minecraft.block.state.BlockStateContainer; import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.IInventory; @@ -20,12 +21,16 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; +import org.lwjgl.Sys; +import scala.tools.nsc.doc.base.comment.EntityLink; import zmaster587.advancedRocketry.dimension.DimensionManager; import zmaster587.advancedRocketry.tile.satellite.TileTerraformingTerminal; import zmaster587.libVulpes.LibVulpes; import zmaster587.libVulpes.block.RotatableBlock; import zmaster587.libVulpes.util.IAdjBlockUpdate; +import javax.annotation.Nonnull; + public class BlockTileTerraformer extends RotatableBlock { protected Class tileClass; protected int guiId; @@ -100,7 +105,18 @@ public boolean isOpaqueCube(IBlockState state) { return false; } + @Override + public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase player, @Nonnull ItemStack itemstack) { + super.onBlockPlacedBy(world, pos, state, player, itemstack); + if (!world.isRemote) { + DimensionManager.getInstance().getDimensionProperties(world.provider.getDimension()).registerProtectingBlock(pos); + System.out.println("terminal placed"); + } + } public void breakBlock(World world, BlockPos pos, IBlockState state) { + if (!world.isRemote) + DimensionManager.getInstance().getDimensionProperties(world.provider.getDimension()).unregisterProtectingBlock(pos); + TileEntity tile = world.getTileEntity(pos); @@ -133,6 +149,7 @@ public void breakBlock(World world, BlockPos pos, IBlockState state) { entityitem.getItem().setTagCompound(tag == null ? null : tag.copy()); } + // why double calling this?? world.spawnEntity(entityitem); world.spawnEntity(entityitem); } diff --git a/src/main/java/zmaster587/advancedRocketry/block/CrystalColorizer.java b/src/main/java/zmaster587/advancedRocketry/block/CrystalColorizer.java index 25c6df5b7..7139bf40d 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/CrystalColorizer.java +++ b/src/main/java/zmaster587/advancedRocketry/block/CrystalColorizer.java @@ -12,7 +12,7 @@ public class CrystalColorizer implements IBlockColor, IItemColor { @Override - public int getColorFromItemstack(@Nonnull ItemStack stack, int tintIndex) { + public int colorMultiplier(@Nonnull ItemStack stack, int tintIndex) { return BlockCrystal.EnumCrystal.values()[stack.getItemDamage()].getColor(); } diff --git a/src/main/java/zmaster587/advancedRocketry/block/inventory/BlockInvHatch.java b/src/main/java/zmaster587/advancedRocketry/block/inventory/BlockInvHatch.java new file mode 100644 index 000000000..c11e216ae --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/block/inventory/BlockInvHatch.java @@ -0,0 +1,39 @@ +package zmaster587.advancedRocketry.block.inventory; + +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import zmaster587.advancedRocketry.tile.hatch.TileInvHatch; +import zmaster587.libVulpes.LibVulpes; +import zmaster587.libVulpes.inventory.GuiHandler; + +public class BlockInvHatch extends Block { + + public BlockInvHatch(Material material) { + super(material); + } + + public boolean hasTileEntity(IBlockState state) { + return true; + } + + @Override + public TileEntity createTileEntity(World world, IBlockState state) { + return new TileInvHatch(1); + } + + @Override + public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { + if (!worldIn.isRemote) { + playerIn.openGui(LibVulpes.instance, GuiHandler.guiId.MODULAR.ordinal(), worldIn, pos.getX(), pos.getY(), pos.getZ()); + } + + return true; + } +} diff --git a/src/main/java/zmaster587/advancedRocketry/client/ClientProxy.java b/src/main/java/zmaster587/advancedRocketry/client/ClientProxy.java index 8a6f186f3..6dda69fc8 100644 --- a/src/main/java/zmaster587/advancedRocketry/client/ClientProxy.java +++ b/src/main/java/zmaster587/advancedRocketry/client/ClientProxy.java @@ -30,11 +30,15 @@ import net.minecraftforge.fml.client.registry.ClientRegistry; import net.minecraftforge.fml.client.registry.IRenderFactory; import net.minecraftforge.fml.client.registry.RenderingRegistry; +import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.relauncher.Side; import zmaster587.advancedRocketry.AdvancedRocketry; import zmaster587.advancedRocketry.api.AdvancedRocketryBlocks; import zmaster587.advancedRocketry.api.AdvancedRocketryItems; import zmaster587.advancedRocketry.api.stations.ISpaceObject; +import zmaster587.advancedRocketry.backwardCompat.ModelFormatException; +import zmaster587.advancedRocketry.backwardCompat.WavefrontObject; import zmaster587.advancedRocketry.block.BlockCrystal; import zmaster587.advancedRocketry.block.CrystalColorizer; import zmaster587.advancedRocketry.client.model.ModelRocket; @@ -47,6 +51,7 @@ import zmaster587.advancedRocketry.event.PlanetEventHandler; import zmaster587.advancedRocketry.event.RocketEventHandler; import zmaster587.advancedRocketry.stations.SpaceObjectManager; +import zmaster587.advancedRocketry.tile.TileBrokenPart; import zmaster587.advancedRocketry.tile.TileFluidTank; import zmaster587.advancedRocketry.tile.TileRocketAssemblingMachine; import zmaster587.advancedRocketry.tile.cables.TileDataPipe; @@ -64,16 +69,31 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.HashMap; +import java.util.Map; import java.util.Objects; +@Mod.EventBusSubscriber(value = Side.CLIENT) public class ClientProxy extends CommonProxy { private static final zmaster587.advancedRocketry.dimension.DimensionManager dimensionManagerClient = new zmaster587.advancedRocketry.dimension.DimensionManager(); + private static final Map models = new HashMap<>(); + + public static WavefrontObject getModel(ResourceLocation location) { + WavefrontObject model = models.getOrDefault(location, null); + if (model == null) { + try { + model = new WavefrontObject(location); + models.put(location, model); + } catch (ModelFormatException e) { + e.printStackTrace(); + } + } + return model; + } @Override public void registerRenderers() { - - ClientRegistry.bindTileEntitySpecialRenderer(TileRocketAssemblingMachine.class, new RendererRocketAssemblingMachine()); ClientRegistry.bindTileEntitySpecialRenderer(TilePrecisionAssembler.class, new RendererPrecisionAssembler()); ClientRegistry.bindTileEntitySpecialRenderer(TileCuttingMachine.class, new RendererCuttingMachine()); @@ -91,7 +111,7 @@ public void registerRenderers() { ClientRegistry.bindTileEntitySpecialRenderer(TileDataPipe.class, new RendererPipe(new ResourceLocation("AdvancedRocketry:textures/blocks/pipeData.png"))); ClientRegistry.bindTileEntitySpecialRenderer(TileEnergyPipe.class, new RendererPipe(new ResourceLocation("AdvancedRocketry:textures/blocks/pipeEnergy.png"))); ClientRegistry.bindTileEntitySpecialRenderer(TileMicrowaveReciever.class, new RendererMicrowaveReciever()); - ClientRegistry.bindTileEntitySpecialRenderer(TileOrbitalLaserDrill.class, new RenderOrbitalLaserDrillTile()); + //ClientRegistry.bindTileEntitySpecialRenderer(TileOrbitalLaserDrill.class, new RenderOrbitalLaserDrillTile()); ClientRegistry.bindTileEntitySpecialRenderer(TileBiomeScanner.class, new RenderBiomeScanner()); ClientRegistry.bindTileEntitySpecialRenderer(TileBlackHoleGenerator.class, new RenderBlackHoleGenerator()); ClientRegistry.bindTileEntitySpecialRenderer(TileAtmosphereTerraformer.class, new RenderTerraformerAtm()); @@ -104,6 +124,7 @@ public void registerRenderers() { ClientRegistry.bindTileEntitySpecialRenderer(zmaster587.advancedRocketry.tile.multiblock.machine.TileCentrifuge.class, new zmaster587.advancedRocketry.client.render.multiblocks.RenderCentrifuge()); ClientRegistry.bindTileEntitySpecialRenderer(TilePrecisionLaserEtcher.class, new RendererPrecisionLaserEtcher()); ClientRegistry.bindTileEntitySpecialRenderer(TileSolarArray.class, new RendererSolarArray()); + ClientRegistry.bindTileEntitySpecialRenderer(TileBrokenPart.class, new RendererBrokenPart()); //ClientRegistry.bindTileEntitySpecialRenderer(TileModelRenderRotatable.class, modelBlock); @@ -128,7 +149,7 @@ public void init() { Minecraft.getMinecraft().getItemColors().registerItemColorHandler(colorizer, Item.getItemFromBlock(AdvancedRocketryBlocks.blockCrystal)); Minecraft.getMinecraft().getItemColors().registerItemColorHandler(new IItemColor() { - public int getColorFromItemstack(@Nonnull ItemStack stack, int tintIndex) { + public int colorMultiplier(@Nonnull ItemStack stack, int tintIndex) { return tintIndex > 0 ? -1 : ((ItemArmor) stack.getItem()).getColor(stack); } }, AdvancedRocketryItems.itemSpaceSuit_Boots, AdvancedRocketryItems.itemSpaceSuit_Chest, AdvancedRocketryItems.itemSpaceSuit_Helmet, AdvancedRocketryItems.itemSpaceSuit_Leggings); @@ -240,8 +261,6 @@ public void preInitItems() { public void preinit() { OBJLoader.INSTANCE.addDomain("advancedrocketry"); registerRenderers(); - - } private void registerFluidModel(IFluidBlock fluidBlock) { @@ -272,7 +291,7 @@ public void modelBakeEvent(ModelBakeEvent event) { public void registerEventHandlers() { super.registerEventHandlers(); MinecraftForge.EVENT_BUS.register(new RocketEventHandler()); - + MinecraftForge.EVENT_BUS.register(new DelayedParticleRenderingEventHandler()); MinecraftForge.EVENT_BUS.register(ModuleContainerPan.class); MinecraftForge.EVENT_BUS.register(new RenderComponents()); } @@ -302,6 +321,24 @@ public void changeClientPlayerWorld(World world) { Minecraft.getMinecraft().player.world = world; } + @Override + public void spawnDynamicRocketSmoke(World world, double x, double y, + double z, double motionX, double motionY, double motionZ, int engineNum) { + TrailFx fx = new TrailFx(world, x, y, z, motionX, motionY, motionZ); + fx.register_additional_engines(engineNum); + Minecraft.getMinecraft().effectRenderer.addEffect(fx); + + } + @Override + public void spawnDynamicRocketFlame(World world, double x, double y, + double z, double motionX, double motionY, double motionZ, int engineNum) { + + RocketFx fx = new RocketFx(world, x, y, z, motionX, motionY, motionZ); + fx.register_additional_engines(engineNum); + Minecraft.getMinecraft().effectRenderer.addEffect(fx); + + } + @Override public void spawnParticle(String particle, World world, double x, double y, double z, double motionX, double motionY, double motionZ) { switch (particle) { diff --git a/src/main/java/zmaster587/advancedRocketry/client/render/DelayedParticleRenderingEventHandler.java b/src/main/java/zmaster587/advancedRocketry/client/render/DelayedParticleRenderingEventHandler.java new file mode 100644 index 000000000..3e775bcf2 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/client/render/DelayedParticleRenderingEventHandler.java @@ -0,0 +1,42 @@ +package zmaster587.advancedRocketry.client.render; + +import net.minecraft.client.particle.Particle; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraftforge.client.event.RenderWorldLastEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; +import org.lwjgl.opengl.GL11; +import zmaster587.advancedRocketry.entity.fx.InverseTrailFx; +import zmaster587.advancedRocketry.entity.fx.RocketFx; + +import java.util.ArrayList; +import java.util.List; + +public class DelayedParticleRenderingEventHandler { + public static List RocketFxParticles = new ArrayList<>(); + public static List TrailFxParticles = new ArrayList<>(); + + + @SubscribeEvent + public void onRenderWorldLast(RenderWorldLastEvent event) { + InverseTrailFx.renderAll(TrailFxParticles); + RocketFx.renderAll(RocketFxParticles); + } + @SubscribeEvent + public void onTick(TickEvent.ClientTickEvent event) { + + for (RocketFx p: RocketFxParticles){ + p.onUpdate2(); + } + for (InverseTrailFx p: TrailFxParticles){ + p.onUpdate2(); + } + + RocketFxParticles.removeIf(particle -> !particle.isAlive()); + TrailFxParticles.removeIf(particle -> !particle.isAlive()); + + } +} diff --git a/src/main/java/zmaster587/advancedRocketry/client/render/RenderLaser.java b/src/main/java/zmaster587/advancedRocketry/client/render/RenderLaser.java index c2591aae0..42daa9a9b 100644 --- a/src/main/java/zmaster587/advancedRocketry/client/render/RenderLaser.java +++ b/src/main/java/zmaster587/advancedRocketry/client/render/RenderLaser.java @@ -115,7 +115,7 @@ public void doRender(Particle entity, double x, double y, double z, GlStateManager.color(flareColor[0], flareColor[1], flareColor[2], flareColor[3]); for (int i = 0; i < 4; i++) { - RenderHelper.renderBottomFaceWithUV(buffer, -y + 200, -(i * 6) - x, -(i * 6) - z, (i * 6) - x, (i * 6) - z, 0, 1, 0, 1); + RenderHelper.renderBottomFaceWithUV(buffer, -y, -(i * 6) - x, -(i * 6) - z, (i * 6) - x, (i * 6) - z, 0, 1, 0, 1); } Tessellator.getInstance().draw(); diff --git a/src/main/java/zmaster587/advancedRocketry/client/render/RendererBrokenPart.java b/src/main/java/zmaster587/advancedRocketry/client/render/RendererBrokenPart.java new file mode 100644 index 000000000..f2dacc274 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/client/render/RendererBrokenPart.java @@ -0,0 +1,70 @@ +package zmaster587.advancedRocketry.client.render; + +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.Vec3i; +import zmaster587.advancedRocketry.backwardCompat.WavefrontObject; +import zmaster587.advancedRocketry.client.ClientProxy; +import zmaster587.advancedRocketry.tile.TileBrokenPart; +import zmaster587.advancedRocketry.util.IBrokenPartBlock; +import zmaster587.libVulpes.block.BlockFullyRotatable; + +public class RendererBrokenPart extends TileEntitySpecialRenderer { + + @Override + public void render(TileBrokenPart tile, double x, double y, double z, float t, int destroyStage, float a) { + ResourceLocation res = tile.getBlockType().getRegistryName(); + Block blk = tile.getBlockType(); + + if ((blk instanceof IBrokenPartBlock)) { + GlStateManager.pushMatrix(); + GlStateManager.translate((float) x, (float) y, (float) z); + + String name = blk.getUnlocalizedName().split("\\.")[1].toLowerCase(); + String pathToTexture = "textures/models/" + name + "_" + tile.getStage() / 3 + ".png"; + + if (tile.getBlockType() instanceof BlockFullyRotatable) { + IBlockState state = tile.getWorld().getBlockState(tile.getPos()); + EnumFacing facing = state.getBlock().getActualState(state, tile.getWorld(), tile.getPos()).getValue(BlockFullyRotatable.FACING); + Vec3i dir = facing.getDirectionVec(); + GlStateManager.translate(0.5F, 0.5F, 0.5F); + if (dir.getY() > 0) { + GlStateManager.rotate(180.0F, 1.0F, 0.0F, 0.0F); + } + if (dir.getX() != 0) { + GlStateManager.rotate(90.0F, 0.0F, 0.0F, -dir.getX()); + } + if (dir.getZ() != 0) { + GlStateManager.rotate(90.0F, dir.getZ(), 0.0F, 0.0F); + } + GlStateManager.translate(-0.5F, -0.5F, -0.5F); + } + + if (destroyStage >= 0) { + this.bindTexture(DESTROY_STAGES[destroyStage]); + GlStateManager.matrixMode(5890); + GlStateManager.pushMatrix(); + GlStateManager.scale(4.0F, 4.0F, 1.0F); + GlStateManager.translate(0.0625F, 0.0625F, 0.0625F); + GlStateManager.matrixMode(5888); + } else { + this.bindTexture(new ResourceLocation(res.getResourceDomain(), pathToTexture)); + } + + WavefrontObject model = ClientProxy.getModel(new ResourceLocation(res.getResourceDomain(), "models/block/models/" + name + ".obj")); + model.renderAll(); + + if (destroyStage >= 0) { + GlStateManager.matrixMode(5890); + GlStateManager.popMatrix(); + GlStateManager.matrixMode(5888); + } + + GlStateManager.popMatrix(); + } + } +} diff --git a/src/main/java/zmaster587/advancedRocketry/client/render/RendererRocket.java b/src/main/java/zmaster587/advancedRocketry/client/render/RendererRocket.java index 61a0f1fb1..57a958948 100644 --- a/src/main/java/zmaster587/advancedRocketry/client/render/RendererRocket.java +++ b/src/main/java/zmaster587/advancedRocketry/client/render/RendererRocket.java @@ -166,7 +166,6 @@ public void doRender(@Nonnull Entity entity, double x, double y, double z, float for (TileEntity tile : storage.getTileEntityList()) { TileEntitySpecialRenderer renderer = TileEntityRendererDispatcher.instance.renderers.get(tile.getClass()); if (renderer != null) { - if (tileEntityBlockChiseled == null || !tileEntityBlockChiseled.isInstance(tile)) { TileEntityRendererDispatcher.instance.render(tile, tile.getPos().getX(), tile.getPos().getY(), tile.getPos().getZ(), f1); } diff --git a/src/main/java/zmaster587/advancedRocketry/client/render/entity/RenderButtonUIEntity.java b/src/main/java/zmaster587/advancedRocketry/client/render/entity/RenderButtonUIEntity.java index e64f1f95e..f29e76128 100644 --- a/src/main/java/zmaster587/advancedRocketry/client/render/entity/RenderButtonUIEntity.java +++ b/src/main/java/zmaster587/advancedRocketry/client/render/entity/RenderButtonUIEntity.java @@ -36,7 +36,7 @@ public void doRender(EntityUIButton entity, double x, double y, double z, GL11.glTranslated(0, -.25, 0); - RenderHelper.renderTag(Minecraft.getMinecraft().player.getDistanceSqToEntity(entity), "Up a level", x, y, z, 8); + RenderHelper.renderTag(Minecraft.getMinecraft().player.getDistanceSq(entity), "Up a level", x, y, z, 8); GL11.glPopMatrix(); //Clean up and make player not transparent diff --git a/src/main/java/zmaster587/advancedRocketry/client/render/entity/RenderStarUIEntity.java b/src/main/java/zmaster587/advancedRocketry/client/render/entity/RenderStarUIEntity.java index 0bb88c62e..69fa6dac2 100644 --- a/src/main/java/zmaster587/advancedRocketry/client/render/entity/RenderStarUIEntity.java +++ b/src/main/java/zmaster587/advancedRocketry/client/render/entity/RenderStarUIEntity.java @@ -47,7 +47,7 @@ public void doRender(EntityUIStar entity, double x, double y, double z, GL11.glTranslated(x, y, z); GL11.glScalef(sizeScale, sizeScale, sizeScale); - RenderHelper.setupPlayerFacingMatrix(Minecraft.getMinecraft().player.getDistanceSqToEntity(entity), 0, -.45, 0); + RenderHelper.setupPlayerFacingMatrix(Minecraft.getMinecraft().player.getDistanceSq(entity), 0, -.45, 0); Minecraft.getMinecraft().renderEngine.bindTexture(TextureResources.locationSunNew); BufferBuilder buffer = Tessellator.getInstance().getBuffer(); diff --git a/src/main/java/zmaster587/advancedRocketry/client/render/multiblocks/RenderOrbitalLaserDrill.java b/src/main/java/zmaster587/advancedRocketry/client/render/multiblocks/RenderOrbitalLaserDrill.java index 0ec026cf7..1db456f7d 100644 --- a/src/main/java/zmaster587/advancedRocketry/client/render/multiblocks/RenderOrbitalLaserDrill.java +++ b/src/main/java/zmaster587/advancedRocketry/client/render/multiblocks/RenderOrbitalLaserDrill.java @@ -73,15 +73,15 @@ public void render(TileEntity tile, double x, for (float radius = 0.1F; radius < .5; radius += .1F) { for (double i = 0; i < 2 * Math.PI; i += Math.PI) { - buffer.pos(-x, -y - 100, -z).endVertex(); - buffer.pos(-x, -y - 100, -z).endVertex(); + buffer.pos(0, -y - 100,0).endVertex(); + buffer.pos(0, -y - 100, 0).endVertex(); buffer.pos(-(radius * Math.cos(i)) + 0.5F, 0, -(radius * Math.sin(i)) + 0.5F).endVertex(); buffer.pos((radius * Math.sin(i)) + 0.5F, 0, (radius * Math.cos(i)) + 0.5F).endVertex(); } for (double i = 0; i < 2 * Math.PI; i += Math.PI) { - buffer.pos(-x, -y - 100, -z).endVertex(); - buffer.pos(-x, -y - 100, -z).endVertex(); + buffer.pos(0, -y - 100, 0).endVertex(); + buffer.pos(0, -y - 100, 0).endVertex(); buffer.pos((radius * Math.sin(i)) + 0.5F, 0, -(radius * Math.cos(i)) + 0.5F).endVertex(); buffer.pos(-(radius * Math.cos(i)) + 0.5F, 0, (radius * Math.sin(i)) + 0.5F).endVertex(); } diff --git a/src/main/java/zmaster587/advancedRocketry/client/render/multiblocks/RendererCrystallizer.java b/src/main/java/zmaster587/advancedRocketry/client/render/multiblocks/RendererCrystallizer.java index 13c1db361..e4324f0a8 100644 --- a/src/main/java/zmaster587/advancedRocketry/client/render/multiblocks/RendererCrystallizer.java +++ b/src/main/java/zmaster587/advancedRocketry/client/render/multiblocks/RendererCrystallizer.java @@ -95,7 +95,7 @@ public void render(TileEntity tile, double x, GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - int color = Minecraft.getMinecraft().getItemColors().getColorFromItemstack(stack, 0); + int color = Minecraft.getMinecraft().getItemColors().colorMultiplier(stack, 0); float divisor = 1 / 255f; diff --git a/src/main/java/zmaster587/advancedRocketry/client/render/planet/RenderAsteroidSky.java b/src/main/java/zmaster587/advancedRocketry/client/render/planet/RenderAsteroidSky.java index b46c7fe84..75bac2b36 100644 --- a/src/main/java/zmaster587/advancedRocketry/client/render/planet/RenderAsteroidSky.java +++ b/src/main/java/zmaster587/advancedRocketry/client/render/planet/RenderAsteroidSky.java @@ -655,7 +655,7 @@ else if (DimensionManager.getInstance().isDimensionCreated(mc.world.provider.get GL11.glDepthMask(true); - RocketEventHandler.onPostWorldRender(partialTicks); + //RocketEventHandler.onPostWorldRender(partialTicks); //Fix player/items going transparent OpenGlHelper.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 0, 0); } diff --git a/src/main/java/zmaster587/advancedRocketry/client/render/planet/RenderPlanetarySky.java b/src/main/java/zmaster587/advancedRocketry/client/render/planet/RenderPlanetarySky.java index 67ae1aa86..8b8f4fd52 100644 --- a/src/main/java/zmaster587/advancedRocketry/client/render/planet/RenderPlanetarySky.java +++ b/src/main/java/zmaster587/advancedRocketry/client/render/planet/RenderPlanetarySky.java @@ -38,6 +38,7 @@ public class RenderPlanetarySky extends IRenderHandler { Vector3F axis; Minecraft mc = Minecraft.getMinecraft(); private int starGLCallList; + private int starGLCallListSmall; private int glSkyList; private int glSkyList2; @@ -51,14 +52,22 @@ public class RenderPlanetarySky extends IRenderHandler { public RenderPlanetarySky() { axis = new Vector3F<>(1f, 0f, 0f); - this.starGLCallList = GLAllocation.generateDisplayLists(3); + this.starGLCallList = GLAllocation.generateDisplayLists(4); GL11.glPushMatrix(); GL11.glNewList(this.starGLCallList, GL11.GL_COMPILE); this.renderStars(); GL11.glEndList(); GL11.glPopMatrix(); + + this.starGLCallListSmall = this.starGLCallList + 1; + GL11.glPushMatrix(); + GL11.glNewList(this.starGLCallListSmall, GL11.GL_COMPILE); + this.renderStarsSmall(); + GL11.glEndList(); + GL11.glPopMatrix(); + BufferBuilder buffer = Tessellator.getInstance().getBuffer(); - this.glSkyList = this.starGLCallList + 1; + this.glSkyList = this.starGLCallList + 2; GL11.glNewList(this.glSkyList, GL11.GL_COMPILE); byte b2 = 64; int i = 256 / b2 + 2; @@ -78,7 +87,7 @@ public RenderPlanetarySky() { } GL11.glEndList(); - this.glSkyList2 = this.starGLCallList + 2; + this.glSkyList2 = this.starGLCallList + 3; GL11.glNewList(this.glSkyList2, GL11.GL_COMPILE); f = -16.0F; buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION); @@ -417,6 +426,56 @@ private void renderStars() { //buffer.finishDrawing(); } + + private void renderStarsSmall() { + Random random = new Random(10842L); + BufferBuilder buffer = Tessellator.getInstance().getBuffer(); + buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION); + + for (int i = 0; i < 5000; ++i) { + double d0 = random.nextFloat() * 2.0F - 1.0F; + double d1 = random.nextFloat() * 2.0F - 1.0F; + double d2 = random.nextFloat() * 2.0F - 1.0F; + double d3 = 0.025F + random.nextFloat() * 0.05F; + double d4 = d0 * d0 + d1 * d1 + d2 * d2; + + if (d4 < 1.0D && d4 > 0.01D) { + d4 = 1.0D / Math.sqrt(d4); + d0 *= d4; + d1 *= d4; + d2 *= d4; + double d5 = d0 * 30.0D; + double d6 = d1 * 30.0D; + double d7 = d2 * 30.0D; + double d8 = Math.atan2(d0, d2); + double d9 = Math.sin(d8); + double d10 = Math.cos(d8); + double d11 = Math.atan2(Math.sqrt(d0 * d0 + d2 * d2), d1); + double d12 = Math.sin(d11); + double d13 = Math.cos(d11); + double d14 = random.nextDouble() * Math.PI * 2.0D; + double d15 = Math.sin(d14); + double d16 = Math.cos(d14); + + for (int j = 0; j < 4; ++j) { + double d17 = 0.0D; + double d18 = (double) ((j & 2) - 1) * d3; + double d19 = (double) ((j + 1 & 2) - 1) * d3; + double d20 = d18 * d16 - d19 * d15; + double d21 = d19 * d16 + d18 * d15; + double d22 = d20 * d12 + d17 * d13; + double d23 = d17 * d12 - d20 * d13; + double d24 = d23 * d9 - d21 * d10; + double d25 = d21 * d9 + d23 * d10; + buffer.pos(d5 + d24, d6 + d22, d7 + d25).endVertex(); + } + } + } + + Tessellator.getInstance().draw(); + //buffer.finishDrawing(); + } + @Override public void render(float partialTicks, WorldClient world, Minecraft mc) { @@ -494,8 +553,7 @@ public void render(float partialTicks, WorldClient world, Minecraft mc) { travelDirection = station.getForwardDirection(); } } - } - else if (DimensionManager.getInstance().isDimensionCreated(mc.world.provider.getDimension())) { + } else if (DimensionManager.getInstance().isDimensionCreated(mc.world.provider.getDimension())) { properties = DimensionManager.getInstance().getDimensionProperties(mc.world.provider.getDimension()); @@ -542,8 +600,7 @@ else if (DimensionManager.getInstance().isDimensionCreated(mc.world.provider.get travelDirection = station.getForwardDirection(); } } - } - else { + } else { children = new LinkedList<>(); isMoon = false; atmosphere = DimensionManager.overworldProperties.getAtmosphereDensityAtHeight(mc.getRenderViewEntity().posY); @@ -580,9 +637,9 @@ else if (DimensionManager.getInstance().isDimensionCreated(mc.world.provider.get f2 = atmosphereInt < 1 ? 0 : (float) Math.pow(f2, Math.sqrt(Math.max(atmosphere, 0.0001))); f3 = atmosphereInt < 1 ? 0 : (float) Math.pow(f3, Math.sqrt(Math.max(atmosphere, 0.0001))); - f1*=Math.min(1,atmosphere); - f2*=Math.min(1,atmosphere); - f3*=Math.min(1,atmosphere); + f1 *= Math.min(1, atmosphere); + f2 *= Math.min(1, atmosphere); + f3 *= Math.min(1, atmosphere); skycolor[0] = f1; skycolor[1] = f2; @@ -724,36 +781,41 @@ else if (DimensionManager.getInstance().isDimensionCreated(mc.world.provider.get float f18 = mc.world.getStarBrightness(partialTicks) * f6;//((atmosphere == 0 || (f1 < 0.09 && f2 < 0.09 && f3 < 0.09)) ? 1 : 0);// - (atmosphere > 1 ? atmosphere - 1 : 0); - float starAlpha = 1-((1-f18)*atmosphere); + float starAlpha = 1 - ((1 - f18) * atmosphere); //System.out.println(starAlpha+":"+f18+":"+atmosphere); //if (f18 > 0.0F) { - if (true){ + if (true) { GlStateManager.color(1, 1, 1, 1); + GL11.glPushMatrix(); if (isWarp) { - for (int i = -3; i < 5; i++) { - GL11.glPushMatrix(); - double magnitude = i * -100 + (((System.currentTimeMillis()) + 50) % 2000) / 20f; - GL11.glTranslated(-travelDirection.getFrontOffsetZ() * magnitude, 0, travelDirection.getFrontOffsetX() * magnitude); - GL11.glCallList(this.starGLCallList); - GL11.glPopMatrix(); + for (int i = -3; i < 6; i++) { + double magnitude = i * -50 + (((System.currentTimeMillis()) + 50) % 1000) / 20f; + for (int o = 1; o < 50; o++) { + GL11.glPushMatrix(); + GL11.glTranslated(-travelDirection.getFrontOffsetZ() *1* (magnitude+o*0.5) , 0, travelDirection.getFrontOffsetX() *1* (magnitude+o*0.5)); + GL11.glCallList(this.starGLCallListSmall); + GL11.glPopMatrix(); + } } + + //GL11.glTranslated(((System.currentTimeMillis()/10) + 50) % 100, 0, 0); } else { - GL11.glColor4f(1,1,1,starAlpha); + GL11.glColor4f(1, 1, 1, starAlpha); GL11.glCallList(this.starGLCallList); //Extra stars for low ATM if (atmosphere < 0.5) { - GL11.glColor4f(1,1,1,starAlpha/2); + GL11.glColor4f(1, 1, 1, starAlpha / 2); GL11.glPushMatrix(); GL11.glRotatef(-90, 0, 1, 0); GL11.glCallList(this.starGLCallList); GL11.glPopMatrix(); } if (atmosphere < 0.25) { - GL11.glColor4f(1,1,1,starAlpha/4); + GL11.glColor4f(1, 1, 1, starAlpha / 4); GL11.glPushMatrix(); GL11.glRotatef(90, 0, 1, 0); GL11.glCallList(this.starGLCallList); @@ -791,7 +853,12 @@ else if (DimensionManager.getInstance().isDimensionCreated(mc.world.provider.get GL11.glRotatef((float) myPhi, 0f, 0f, 1f); GL11.glRotatef(planetPositionTheta, 1f, 0f, 0f); - rotateAroundAntiAxis(); + + // THIS MESSES UP PLANET ROTATION ON SPACE STATIONS + // THIS SHOULD NOT BE CALLED WHEN ON SPACE STATION!!!!! + if (world.provider.getDimension() != ARConfiguration.getCurrentConfig().spaceDimId) { + rotateAroundAntiAxis(); + } float phiAngle = (float) ((myPhi) * Math.PI / 180f); @@ -869,10 +936,6 @@ else if (afloat != null && (planetPositionTheta < 105 || planetPositionTheta > 2 GL11.glPopMatrix(); GlStateManager.disableTexture2D(); - //GlStateManager.color(f1, f2, f3, 0.05F); - //GL11.glCallList(this.glSkyList); - - GlStateManager.color(0.0F, 0.0F, 0.0F); double d0 = this.mc.player.getPositionEyes(partialTicks).y - mc.world.getHorizon(); @@ -913,11 +976,101 @@ else if (afloat != null && (planetPositionTheta < 105 || planetPositionTheta > 2 } GlStateManager.enableTexture2D(); - GlStateManager.depthMask(true); - RocketEventHandler.onPostWorldRender(partialTicks); + //RocketEventHandler.onPostWorldRender(partialTicks); + + //hide texture bug by removing it while rocket is fireing engines + //rocket fires engine about at this height: + //int ch = 300 + world.getHeight((int) posX, (int) posZ); + + + float fade_out = 50; + + float target_texture_v = -20 + (float) (-mc.world.getHorizon() + mc.player.world.getHeight(mc.player.getPosition()).getY()+300 - fade_out); + + if (d0 > target_texture_v && mc.player.dimension != ARConfiguration.getCurrentConfig().spaceDimId && !isWarp) { + properties = DimensionManager.getInstance().getDimensionProperties(mc.player.dimension); + + + + // Calculate t using linear interpolation + float t = (float) (d0 - target_texture_v) / fade_out; + + // Clamp t to the range [0, 1] to ensure smooth blending + t = Math.min(1f, Math.max(0f, t)); + + //System.out.println("t"+t); + + + renderplanetbelow(buffer, properties, (float) d0 / 10f, t); + } + GlStateManager.depthMask(true); //Fix player/items going transparent GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + + } + + public void renderplanetbelow(BufferBuilder buffer, DimensionProperties properties, float dist, float transparency) { + + + + GL11.glPushMatrix(); + GlStateManager.depthMask(true); + + GlStateManager.disableFog(); + GlStateManager.disableAlpha(); + + // Enable blending for transparency + GL11.glEnable(GL11.GL_BLEND); + GlStateManager.enableBlend(); // Enable blending for transparency + + // Set the blend function for transparency (standard source alpha blending) + GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + + + + // Bind the planet's texture + mc.renderEngine.bindTexture(properties.getPlanetIconLEO()); + + // Set texture parameters for smooth scaling + GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); + GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); + + // Set planet size based on distance + float f10 = 300f * AstronomicalBodyHelper.getBodySizeMultiplier(dist); + + float Xoffset = (float) ((System.currentTimeMillis() / 1000000d % 1)); + + float f14 = 1f + Xoffset; + float f15 = 0f + Xoffset; + + + GlStateManager.color(1f, 1f, 1f, transparency); + + double yo = -10; + + // Start rendering the quad with the texture + buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); + buffer.pos(-f10, yo, f10).tex(f15, f14).endVertex(); + buffer.pos(f10, yo, f10).tex(f14, f14).endVertex(); + buffer.pos(f10, yo, -f10).tex(f14, f15).endVertex(); + buffer.pos(-f10, yo, -f10).tex(f15, f15).endVertex(); + + // Draw the texture + Tessellator.getInstance().draw(); + + + GL11.glPopMatrix(); + + //GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT); + + // Reset color to full opacity and enable fog again + GlStateManager.color(1f, 1f, 1f, 1f); + GlStateManager.enableFog(); + GlStateManager.disableBlend(); + GlStateManager.enableAlpha(); + + } protected ResourceLocation getTextureForPlanet(DimensionProperties properties) { diff --git a/src/main/java/zmaster587/advancedRocketry/client/render/planet/RenderSpaceSky.java b/src/main/java/zmaster587/advancedRocketry/client/render/planet/RenderSpaceSky.java index df1c95f75..ec84353be 100644 --- a/src/main/java/zmaster587/advancedRocketry/client/render/planet/RenderSpaceSky.java +++ b/src/main/java/zmaster587/advancedRocketry/client/render/planet/RenderSpaceSky.java @@ -21,6 +21,8 @@ import java.util.Objects; +import static java.lang.Math.*; + public class RenderSpaceSky extends RenderPlanetarySky { Minecraft mc = Minecraft.getMinecraft(); @@ -40,6 +42,7 @@ protected void drawStar(BufferBuilder buffer, StellarBody sun, DimensionProperti @Override public void renderPlanet2(BufferBuilder buffer, DimensionProperties properties, float size, float alphaMultiplier, double shadowAngle, boolean hasRing, float[] shadowColorMultiplier, float alphaMultiplier2) { //ResourceLocation icon, int locationX, int locationY, double zLevel, float planetOrbitalDistance, float alphaMultiplier, double angle, boolean hasAtmosphere, float[] atmColor, float[] ringColor, boolean isGasgiant, boolean hasRings, boolean hasDecorators) { + int clientRenderDistanceBlocks = mc.gameSettings.renderDistanceChunks * 16; ISpaceObject spaceObject = SpaceObjectManager.getSpaceManager().getSpaceStationFromBlockCoords(mc.player.getPosition()); @@ -47,10 +50,16 @@ public void renderPlanet2(BufferBuilder buffer, DimensionProperties properties, return; float planetOrbitalDistance = spaceObject.getOrbitalDistance(); + if (properties.isStar()) { planetOrbitalDistance = 190F; + + double tr_y = 100; + + size = 10f; + + float ro = -20f; if (properties.getStar().isBlackHole()) { - size = 10; GL11.glDepthMask(true); GL11.glEnable(GL11.GL_ALPHA_TEST); GL11.glAlphaFunc(GL11.GL_GREATER, 0.01f); @@ -58,79 +67,25 @@ public void renderPlanet2(BufferBuilder buffer, DimensionProperties properties, GL11.glDisable(GL11.GL_BLEND); GL11.glPushMatrix(); //GL11.glRotatef(50, 1, 0, 0); - GL11.glRotatef(120, -1, 0, 0); + GL11.glRotatef(140, -1, 0, 0); GL11.glRotatef(180, 0, 1, 0); //GL11.glRotatef(180, 0, 1, 0); - GL11.glPushMatrix(); - GL11.glTranslatef(0, 100, 0); - f10 = size * 2f * AstronomicalBodyHelper.getBodySizeMultiplier(planetOrbitalDistance); + GL11.glTranslatef(0, (float) tr_y, 0); - GlStateManager.color(0,0,0); - GlStateManager.disableCull(); - renderSphere(0,0,0,f10,32,23); - GlStateManager.enableCull(); - GL11.glEnable(GL11.GL_BLEND); - GL11.glDepthMask(false); - - GL11.glPopMatrix(); - /* GL11.glPushMatrix(); - mc.renderEngine.bindTexture(TextureResources.locationBlackHole); - GL11.glTranslatef(0, 100, 0); - //float phase = -((float)System.currentTimeMillis()/(float)3000.0); - //phase *= 36f; - float scale = 1 ; - //GL11.glRotatef(phase, 0, 1, 0); - - GL11.glScaled(scale, scale, scale); - - - //Set sun color and distance - GlStateManager.color((float) 1, (float) .5, (float) .4, 1f); - buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); f10 = size * 2f * AstronomicalBodyHelper.getBodySizeMultiplier(planetOrbitalDistance); - //multiplier = 2; - buffer.pos(-f10, 0.0D, -f10).tex(0.0D, 0.0D).endVertex(); - buffer.pos(f10, 0.0D, -f10).tex(1.0D, 0.0D).endVertex(); - buffer.pos(f10, 0.0D, f10).tex(1.0D, 1.0D).endVertex(); - buffer.pos(-f10, 0.0D, f10).tex(0.0D, 1.0D).endVertex(); - - - - - Tessellator.getInstance().draw(); - GL11.glPopMatrix(); - - + GlStateManager.color(0, 0, 0); + GlStateManager.disableCull(); + renderSphere(0, 0, 0, f10, 32, 23); + GlStateManager.enableCull(); GL11.glEnable(GL11.GL_BLEND); GL11.glDepthMask(false); - GL11.glPushMatrix(); - mc.renderEngine.bindTexture(TextureResources.locationBlackHoleBorder); - GL11.glTranslatef( 0, 99.8F, 0); - - //GL11.glRotatef(phase, 0, 1, 0); - - scale *= 1.1; - GL11.glScaled(scale, scale, scale); - - //Set sun color and distance - GlStateManager.color((float) 1, (float) .5, (float) .4, 1f); - buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); - f10 = size * 2f * AstronomicalBodyHelper.getBodySizeMultiplier(planetOrbitalDistance); - //multiplier = 2; - buffer.pos(-f10, 0.0D, -f10).tex(0.0D, 0.0D).endVertex(); - buffer.pos(f10, 0.0D, -f10).tex(1.0D, 0.0D).endVertex(); - buffer.pos(f10, 0.0D, f10).tex(1.0D, 1.0D).endVertex(); - buffer.pos(-f10, 0.0D, f10).tex(0.0D, 1.0D).endVertex(); - Tessellator.getInstance().draw(); GL11.glPopMatrix(); - */ - //Render accretion disk mc.renderEngine.bindTexture(TextureResources.locationAccretionDiskDense); @@ -141,7 +96,6 @@ public void renderPlanet2(BufferBuilder buffer, DimensionProperties properties, GL11.glPushMatrix(); - GL11.glTranslatef(0, 100, 0); GL11.glRotatef(90, 0f, 1f, 0f); //GL11.glRotatef(m, 1f, 0f, 0f); //GL11.glRotatef(diskangle, 0, 0, 1); @@ -165,8 +119,7 @@ public void renderPlanet2(BufferBuilder buffer, DimensionProperties properties, mc.renderEngine.bindTexture(TextureResources.locationAccretionDisk); GL11.glPushMatrix(); - GL11.glTranslatef(0, 100, 0); - GL11.glRotatef(60, 1, 0, 0); + GL11.glRotatef(60 + ro, 1, 0, 0); GL11.glRotatef((System.currentTimeMillis() % (int) (360 * 360 * speedMult)) / (360f * speedMult), 0, 1, 0); GlStateManager.color((float) 1, (float) .5, (float) .4, 1f); @@ -181,8 +134,8 @@ public void renderPlanet2(BufferBuilder buffer, DimensionProperties properties, GL11.glPushMatrix(); - GL11.glTranslatef(0, 99.9f, 0); - GL11.glRotatef(60, 1, 0, 0); + GL11.glTranslatef(0, -0.1f, 0); + GL11.glRotatef(60 + ro, 1, 0, 0); GL11.glRotatef((System.currentTimeMillis() % (int) (360 * 200 * speedMult)) / (200f * speedMult), 0, 1, 0); GlStateManager.color((float) 0.8, (float) .7, (float) .4, 1f); @@ -198,8 +151,8 @@ public void renderPlanet2(BufferBuilder buffer, DimensionProperties properties, GL11.glPushMatrix(); - GL11.glTranslatef(0, 99.8f, 0); - GL11.glRotatef(60, 1, 0, 0); + GL11.glTranslatef(0, -0.2f, 0); + GL11.glRotatef(60 + ro, 1, 0, 0); GL11.glRotatef((System.currentTimeMillis() % (int) (36000 * speedMult)) / (100f * speedMult), 0, 1, 0); GlStateManager.color((float) 0.2, (float) .4, (float) 1, 1f); @@ -231,6 +184,11 @@ public void renderPlanet2(BufferBuilder buffer, DimensionProperties properties, Tessellator.getInstance().draw(); GL11.glPopMatrix(); } + GlStateManager.depthMask(true); + GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT); + GlStateManager.depthMask(false); + + return; } if (Objects.equals(properties.customIcon, "void")) @@ -269,12 +227,12 @@ public void renderPlanet2(BufferBuilder buffer, DimensionProperties properties, //TODO: draw sky planets GlStateManager.color(1f, 1f, 1f, alphaMultiplier); - + double yo = -10; buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); - buffer.pos(-f10, -10.0D, f10).tex(f16, f17).endVertex(); - buffer.pos(f10, -10.0D, f10).tex(f14, f17).endVertex(); - buffer.pos(f10, -10.0D, -f10).tex(f14, f15).endVertex(); - buffer.pos(-f10, -10.0D, -f10).tex(f16, f15).endVertex(); + buffer.pos(-f10, yo, f10).tex(f16, f17).endVertex(); + buffer.pos(f10, yo, f10).tex(f14, f17).endVertex(); + buffer.pos(f10, yo, -f10).tex(f14, f15).endVertex(); + buffer.pos(-f10, yo, -f10).tex(f16, f15).endVertex(); Tessellator.getInstance().draw(); GL11.glPopAttrib(); @@ -305,10 +263,10 @@ public void renderPlanet2(BufferBuilder buffer, DimensionProperties properties, f16 = 0f + Xoffset; f17 = i + Xoffset; - RenderHelper.renderTopFaceWithUV(buffer, -10D + i * scalingMult, -f10, -f10, 0, 0, f14, f15, f16, f17); - RenderHelper.renderTopFaceWithUV(buffer, -10D + i * scalingMult, 0, 0, f10, f10, f14, f15, f16, f17); - RenderHelper.renderTopFaceWithUV(buffer, -10D + i * scalingMult, -f10, 0, 0, f10, f14, f15, f16, f17); - RenderHelper.renderTopFaceWithUV(buffer, -10D + i * scalingMult, 0, -f10, f10, 0, f14, f15, f16, f17); + RenderHelper.renderTopFaceWithUV(buffer, yo + i * scalingMult, -f10, -f10, 0, 0, f14, f15, f16, f17); + RenderHelper.renderTopFaceWithUV(buffer, yo + i * scalingMult, 0, 0, f10, f10, f14, f15, f16, f17); + RenderHelper.renderTopFaceWithUV(buffer, yo + i * scalingMult, -f10, 0, 0, f10, f14, f15, f16, f17); + RenderHelper.renderTopFaceWithUV(buffer, yo + i * scalingMult, 0, -f10, f10, 0, f14, f15, f16, f17); } Tessellator.getInstance().draw(); @@ -345,10 +303,10 @@ public void renderPlanet2(BufferBuilder buffer, DimensionProperties properties, f16 = f15; f17 = f14; - RenderHelper.renderTopFaceWithUV(buffer, -10D, -f10, -f10, 0, 0, f14, f15, f16, f17); - RenderHelper.renderTopFaceWithUV(buffer, -10D, 0, 0, f10, f10, f14, f15, f16, f17); - RenderHelper.renderTopFaceWithUV(buffer, -10D, -f10, 0, 0, f10, f14, f15, f16, f17); - RenderHelper.renderTopFaceWithUV(buffer, -10D, 0, -f10, f10, 0, f14, f15, f16, f17); + RenderHelper.renderTopFaceWithUV(buffer, yo, -f10, -f10, 0, 0, f14, f15, f16, f17); + RenderHelper.renderTopFaceWithUV(buffer, yo, 0, 0, f10, f10, f14, f15, f16, f17); + RenderHelper.renderTopFaceWithUV(buffer, yo, -f10, 0, 0, f10, f14, f15, f16, f17); + RenderHelper.renderTopFaceWithUV(buffer, yo, 0, -f10, f10, 0, f14, f15, f16, f17); Tessellator.getInstance().draw(); diff --git a/src/main/java/zmaster587/advancedRocketry/client/render/planet/RenderSpaceTravelSky.java b/src/main/java/zmaster587/advancedRocketry/client/render/planet/RenderSpaceTravelSky.java index 59a1be88a..ed3d2e159 100644 --- a/src/main/java/zmaster587/advancedRocketry/client/render/planet/RenderSpaceTravelSky.java +++ b/src/main/java/zmaster587/advancedRocketry/client/render/planet/RenderSpaceTravelSky.java @@ -823,7 +823,7 @@ public void render(float partialTicks, WorldClient world, Minecraft mc) { GlStateManager.enableTexture2D(); GlStateManager.depthMask(true); - RocketEventHandler.onPostWorldRender(partialTicks); + //RocketEventHandler.onPostWorldRender(partialTicks); //Fix player/items going transparent GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); diff --git a/src/main/java/zmaster587/advancedRocketry/common/CommonProxy.java b/src/main/java/zmaster587/advancedRocketry/common/CommonProxy.java index 1ddc1b439..4fdfd4965 100644 --- a/src/main/java/zmaster587/advancedRocketry/common/CommonProxy.java +++ b/src/main/java/zmaster587/advancedRocketry/common/CommonProxy.java @@ -25,12 +25,21 @@ public void registerEventHandlers() { } - public void spawnParticle(String particle, World world, double x, double y, double z, double motionX, double motionY, double motionZ) { } + public void spawnDynamicRocketSmoke(World world, double x, double y, + double z, double motionX, double motionY, double motionZ, int engineNum) { + + } + + public void spawnDynamicRocketFlame(World world, double x, double y, + double z, double motionX, double motionY, double motionZ, int engineNum) { + + } + public void registerKeyBindings() { } diff --git a/src/main/java/zmaster587/advancedRocketry/dimension/DimensionManager.java b/src/main/java/zmaster587/advancedRocketry/dimension/DimensionManager.java index be318ba03..235cbaa94 100644 --- a/src/main/java/zmaster587/advancedRocketry/dimension/DimensionManager.java +++ b/src/main/java/zmaster587/advancedRocketry/dimension/DimensionManager.java @@ -127,6 +127,15 @@ public static DimensionProperties getEffectiveDimId(World world, BlockPos pos) { } else return getInstance().getDimensionProperties(dimId); } + public static DimensionProperties getEffectiveDimId_byID(int dimId, BlockPos pos) { + + if (dimId == ARConfiguration.getCurrentConfig().spaceDimId) { + ISpaceObject spaceObject = SpaceObjectManager.getSpaceManager().getSpaceStationFromBlockCoords(pos); + if (spaceObject != null) return (DimensionProperties) spaceObject.getProperties().getParentProperties(); + else return defaultSpaceDimensionProperties; + } else return getInstance().getDimensionProperties(dimId); + } + /** * @return an Integer array of dimensions registered with this DimensionManager */ @@ -601,12 +610,13 @@ public void saveDimensions(String filePath) throws Exception { NBTTagCompound dimNbt = new NBTTagCompound(); dimSet.getValue().writeToNBT(dimNbt); - + dimSet.getValue().write_terraforming_data(dimNbt); dimListnbt.setTag(dimSet.getKey().toString(), dimNbt); } nbt.setTag("dimList", dimListnbt); + //Stats NBTTagCompound stats = new NBTTagCompound(); stats.setBoolean("hasReachedMoon", hasReachedMoon); @@ -974,8 +984,7 @@ public void createAndLoadDimensions(boolean resetFromXml) { if (loadedPlanets.containsKey(properties.getId())) { DimensionProperties loadedDim = (DimensionProperties) loadedPlanets.get(properties.getId()); if (loadedDim != null) { - properties.copySatellites(loadedDim); - properties.copyTerraformedBiomes(loadedDim); + properties.copyData(loadedDim); } } if (properties.isNativeDimension) @@ -1082,6 +1091,7 @@ public Map loadDimensions(String filePath) { for (String key : dimListNbt.getKeySet()) { DimensionProperties properties = DimensionProperties.createFromNBT(Integer.parseInt(key), dimListNbt.getCompoundTag(key)); + properties.read_terraforming_data(dimListNbt.getCompoundTag(key)); int keyInt = Integer.parseInt(key); /*if(!net.minecraftforge.common.DimensionManager.isDimensionRegistered(keyInt) && properties.isNativeDimension && !properties.isGasGiant()) { diff --git a/src/main/java/zmaster587/advancedRocketry/dimension/DimensionProperties.java b/src/main/java/zmaster587/advancedRocketry/dimension/DimensionProperties.java index 8fd616303..4a3f7bfe6 100644 --- a/src/main/java/zmaster587/advancedRocketry/dimension/DimensionProperties.java +++ b/src/main/java/zmaster587/advancedRocketry/dimension/DimensionProperties.java @@ -2,21 +2,17 @@ import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; -import net.minecraft.init.Biomes; import net.minecraft.init.Blocks; -import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.*; -import net.minecraft.server.MinecraftServer; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -import net.minecraft.world.WorldServer; import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.Biome.TempCategory; -import net.minecraft.world.biome.BiomeProvider; import net.minecraft.world.chunk.Chunk; import net.minecraftforge.common.BiomeDictionary; import net.minecraftforge.common.BiomeManager; @@ -24,6 +20,7 @@ import net.minecraftforge.common.util.Constants.NBT; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidRegistry; +import net.minecraftforge.fml.common.SidedProxy; import org.apache.commons.lang3.ArrayUtils; import zmaster587.advancedRocketry.AdvancedRocketry; import zmaster587.advancedRocketry.api.*; @@ -32,21 +29,12 @@ import zmaster587.advancedRocketry.api.dimension.solar.StellarBody; import zmaster587.advancedRocketry.api.satellite.SatelliteBase; import zmaster587.advancedRocketry.atmosphere.AtmosphereType; +import zmaster587.advancedRocketry.integrated_server_and_client_variable_sharing_fix.Afuckinginterface; import zmaster587.advancedRocketry.inventory.TextureResources; -import zmaster587.advancedRocketry.item.ItemBiomeChanger; -import zmaster587.advancedRocketry.item.ItemSatelliteIdentificationChip; import zmaster587.advancedRocketry.network.PacketDimInfo; import zmaster587.advancedRocketry.network.PacketSatellite; -import zmaster587.advancedRocketry.satellite.SatelliteBiomeChanger; -import zmaster587.advancedRocketry.satellite.SatelliteWeatherController; import zmaster587.advancedRocketry.stations.SpaceObjectManager; -import zmaster587.advancedRocketry.util.AstronomicalBodyHelper; -import zmaster587.advancedRocketry.util.OreGenProperties; -import zmaster587.advancedRocketry.util.SpacePosition; -import zmaster587.advancedRocketry.util.SpawnListEntryNBT; -import zmaster587.advancedRocketry.world.ChunkManagerPlanet; -import zmaster587.advancedRocketry.world.provider.WorldProviderPlanet; -import zmaster587.libVulpes.api.IUniversalEnergy; +import zmaster587.advancedRocketry.util.*; import zmaster587.libVulpes.network.PacketHandler; import zmaster587.libVulpes.util.HashedBlockPosition; import zmaster587.libVulpes.util.VulpineMath; @@ -55,8 +43,6 @@ import java.util.*; import java.util.Map.Entry; -import static org.apache.commons.lang3.RandomUtils.nextInt; - public class DimensionProperties implements Cloneable, IDimensionProperties { @@ -113,6 +99,15 @@ public class DimensionProperties implements Cloneable, IDimensionProperties { public int ringAngle; public boolean hasRivers; public List requiredArtifacts; + + // Custom weather properties + public int rainStartLength = 168000; + public int thunderStartLength = 168000; + public int rainProlongationLength = 12000; + public int thunderProlongationLength = 12000; + private int rainMarker; // -1 - never rain, 1 - always rain, 0 - regular weather + private int thunderMarker; // -1 - never thunder, 1 - always thunder, 0 - regular weather + IAtmosphere atmosphereType; StellarBody star; int starId; @@ -121,7 +116,6 @@ public class DimensionProperties implements Cloneable, IDimensionProperties { private String name; //public ExtendedBiomeProperties biomeProperties; private LinkedList allowedBiomes; - private LinkedList terraformedBiomes; private LinkedList craterBiomeWeights; private boolean isRegistered = false; //private boolean isTerraformed = false; @@ -152,11 +146,20 @@ public class DimensionProperties implements Cloneable, IDimensionProperties { private int seaLevel; private int generatorType; //public int target_sea_level; - public List terraformingChangeList; - public List terraformingChunkListCurrentCycle; - public BiomeProvider chunkMgrTerraformed; + + + @SidedProxy(serverSide = "zmaster587.advancedRocketry.integrated_server_and_client_variable_sharing_fix.serverlists", clientSide = "zmaster587.advancedRocketry.integrated_server_and_client_variable_sharing_fix.clientlists") + public static Afuckinginterface proxylists; + + + + public List terraformingChunksAlreadyAdded; + + //class + public List water_source_locked_positions; + //public boolean water_can_exist; public DimensionProperties(int id) { name = "Temp"; @@ -176,7 +179,6 @@ public DimensionProperties(int id) { craterOres = new ArrayList<>(); allowedBiomes = new LinkedList<>(); - terraformedBiomes = new LinkedList<>(); craterBiomeWeights = new LinkedList<>(); satellites = new HashMap<>(); requiredArtifacts = new LinkedList<>(); @@ -208,11 +210,11 @@ public DimensionProperties(int id) { generatorType = 0; //target_sea_level = seaLevel; - terraformingChangeList = new LinkedList<>(); - terraformingChunkListCurrentCycle = new LinkedList<>(); //water_can_exist = true; water_source_locked_positions = new ArrayList<>(); + terraformingChunksAlreadyAdded = new ArrayList<>(); + ringAngle = 70; @@ -220,59 +222,152 @@ public DimensionProperties(int id) { //this.chunkMgrTerraformed = new ChunkManagerPlanet(net.minecraftforge.common.DimensionManager.getWorld(id), net.minecraftforge.common.DimensionManager.getWorld(getId()).getWorldInfo().getGeneratorOptions(), getTerraformedBiomes()); } - public void reset_chunkmgr(){ - World world = net.minecraftforge.common.DimensionManager.getWorld(getId()); - getAverageTemp(); - setTerraformedBiomes(DimensionManager.getInstance().getDimensionProperties(world.provider.getDimension()).getViableBiomes(false)); - chunkMgrTerraformed = new ChunkManagerPlanet(world, world.getWorldInfo().getGeneratorOptions(), getTerraformedBiomes()); + public int getRainMarker() { + return rainMarker; } - public void add_chunk_to_terraforming_list(Chunk chunk) { - boolean is_there = false; - for (Chunk i : terraformingChunkListCurrentCycle) { - if (i.x == chunk.x && i.z == chunk.z) { - is_there = true; + public int getThunderMarker() { + return thunderMarker; + } + + public void setRainMarker(int marker) { + this.rainMarker = marker; + } + + public void setThunderMarker(int marker) { + this.thunderMarker = marker; + } + + public void load_terraforming_helper(boolean reset) { + if (!net.minecraftforge.common.DimensionManager.getWorld(getId()).isRemote) { + + if (!proxylists.isinitialized(getId())){ + proxylists.initdim(getId()); + } + + getAverageTemp(); + getViableBiomes(false); + if (reset) { + proxylists.getChunksFullyTerraformed(getId()).clear(); + proxylists.getChunksFullyBiomeChanged(getId()).clear(); + terraformingChunksAlreadyAdded.clear(); + } + + System.out.println("load helper with protecting blocks: " + proxylists.getProtectingBlocksForDimension(getId()).size() + " (" + reset + ")"); + + proxylists.sethelper(getId(), new TerraformingHelper(getId(), getBiomesEntries(getViableBiomes(false)), proxylists.getChunksFullyTerraformed(getId()), proxylists.getChunksFullyBiomeChanged(getId()))); + + System.out.println("num biomes: "+ getViableBiomes(false).size()); + + Collection list = (net.minecraftforge.common.DimensionManager.getWorld(getId())).getChunkProvider().getLoadedChunks(); + System.out.println("add chunks to tf list"); + if (!list.isEmpty()) { + for (Chunk chunk : list) { + add_chunk_to_terraforming_list(chunk); + } } + System.out.println("ok!"); } - if (!is_there) { - terraformingChunkListCurrentCycle.add(chunk); - for (int i = 0; i < 256; i++) { - int coord = i; - int x = (coord & 0xF) + chunk.x * 16; - int z = (coord >> 4) + chunk.z * 16; - terraformingChangeList.add(new HashedBlockPosition(x, 0, z)); + + } + + public void registerProtectingBlock(BlockPos p) { + boolean already_registered = false; + for (BlockPos i : proxylists.getProtectingBlocksForDimension(getId())) { + if (i.equals(p)) { + already_registered = true; + break; + } + } + //System.out.println("register protecting block called"); + if (!already_registered) { + proxylists.getProtectingBlocksForDimension(getId()).add(p); + //System.out.println("block registered"); + if (proxylists.gethelper(getId()) != null) { + proxylists.gethelper(getId()).recalculate_chunk_status(); } } } - private void reset_terraforming_chunk_positions(){ - terraformingChangeList.clear(); - terraformingChunkListCurrentCycle.clear(); - Collection list = (net.minecraftforge.common.DimensionManager.getWorld(getId())).getChunkProvider().getLoadedChunks(); - if (list.size() > 0) { - for (Chunk chunk:list){ - add_chunk_to_terraforming_list(chunk); + + public void unregisterProtectingBlock(BlockPos p) { + for (BlockPos i : proxylists.getProtectingBlocksForDimension(getId())) { + if (i.equals(p)) { + proxylists.getProtectingBlocksForDimension(getId()).remove(i); + if (proxylists.gethelper(getId()) != null) + proxylists.gethelper(getId()).recalculate_chunk_status(); + break; } } } - public HashedBlockPosition get_next_terraforming_block() { - if (terraformingChangeList.size() == 0) { - //long startTime = System.currentTimeMillis(); - reset_terraforming_chunk_positions(); - //long endTime = System.currentTimeMillis(); - //long executionTime = endTime - startTime; // Time in milliseconds - //System.out.println("reset chunklist: "+executionTime+"ms"); + + public void add_block_to_terraforming_queue(BlockPos p) { + proxylists.gethelper(getId()).add_position_to_queue(p); + } + public void add_chunk_to_terraforming_list_but_this_time_real_terraforming_and_not_biomechanging(ChunkPos pos){ + for (int x = 0; x < 16; x++) { + for (int z = 0; z < 16; z++) { + add_block_to_terraforming_queue(new BlockPos(pos.x * 16 + x, 0, pos.z * 16 + z)); + } } - if (terraformingChangeList.size() == 0) { - System.out.println("List is 0 - this should never happen!!"); - return null; // this should never happen. Yes it would crash the game, but if it does, my code is wrong and needs to be fixed anyway + } + + public void add_block_to_biomechanging_queue(BlockPos p) { + proxylists.gethelper(getId()).add_position_to_biomechanging_queue(p); + } + + synchronized boolean chunk_was_added_to_terraforming_list_if_not_add_it(ChunkPos pos){ + for (ChunkPos i : terraformingChunksAlreadyAdded) { + if (pos.x == i.x && pos.z == i.z) { + return true; + } } - return terraformingChangeList.remove(nextInt(0,terraformingChangeList.size())); - //return terraformingChangeList.remove(0); + terraformingChunksAlreadyAdded.add(new ChunkPos(pos.x,pos.z)); + return false; } + + //adds a chunk to the terraforming list + //adds it to be biomechanged by default + //if it already was biomechanged fully, add it directly to terraforming queue + public void add_chunk_to_terraforming_list(Chunk chunk) { + + if (proxylists.gethelper(getId()) != null) { + + boolean chunk_was_already_done = proxylists.getChunksFullyTerraformed(getId()).contains(new ChunkPos(chunk.x,chunk.z));; // do not add a chunk if it is already fully terraformed + if (chunk_was_already_done) + return; + + //System.out.println("add chunk to terraforming list: "+chunk.x+":"+chunk.z); + + chunkdata current_chunk = proxylists.gethelper(getId()).getChunkFromList(chunk.x, chunk.z); + if (current_chunk == null || !current_chunk.chunk_fully_biomechanged) { + + if(chunk_was_added_to_terraforming_list_if_not_add_it(new ChunkPos(chunk.x,chunk.z))) + return; + + + + for (int x = 0; x < 16; x++) { + for (int z = 0; z < 16; z++) { + if (current_chunk == null || !current_chunk.fully_generated[x][z]) + // if a position in the chunk is already fully generated, skip + add_block_to_biomechanging_queue(new BlockPos(chunk.x * 16 + x, 0, chunk.z * 16 + z)); + + } + } + }else if (!current_chunk.chunk_fully_generated) { + if(chunk_was_added_to_terraforming_list_if_not_add_it(new ChunkPos(chunk.x,chunk.z))) + return; + + add_chunk_to_terraforming_list_but_this_time_real_terraforming_and_not_biomechanging(new ChunkPos(chunk.x,chunk.z)); + } + } + } + public DimensionProperties(int id, String name) { this(id); this.name = name; } + public DimensionProperties(int id, boolean shouldRegister) { this(id); isStation = !shouldRegister; @@ -301,14 +396,11 @@ public static DimensionProperties createFromNBT(int id, NBTTagCompound nbt) { return properties; } - public void copySatellites(DimensionProperties props) { + public void copyData(DimensionProperties props) { this.satellites = props.satellites; this.tickingSatellites = props.tickingSatellites; } - public void copyTerraformedBiomes(DimensionProperties props) { - this.terraformedBiomes = props.terraformedBiomes; - } @Override public Object clone() { @@ -644,7 +736,7 @@ public void setParentOrbitalDistance(int distance) { * @return if a planet, the same as getParentOrbitalDistance(), if a moon, the moon's distance from the host star */ public int getSolarOrbitalDistance() { - if (this.isStar()){ + if (this.isStar()) { return 1; } if (parentPlanet != Constants.INVALID_PLANET) @@ -704,9 +796,6 @@ public boolean isMoon() { return parentPlanet != Constants.INVALID_PLANET && parentPlanet != SpaceObjectManager.WARPDIMID; } - /** - * @return true if currently terraformed - */ public int getAtmosphereDensity() { return atmosphereDensity; @@ -719,8 +808,7 @@ public void setAtmosphereDensity(int atmosphereDensity) { int prevAtm = this.atmosphereDensity; this.atmosphereDensity = atmosphereDensity; - reset_chunkmgr(); - + load_terraforming_helper(true); PacketHandler.sendToAll(new PacketDimInfo(getId(), this)); @@ -972,7 +1060,7 @@ public Collection getTickingSatellites() { public void tick() { Iterator iterator = tickingSatellites.values().iterator(); - + //System.out.println(":"+tickingSatellites.size()); while (iterator.hasNext()) { SatelliteBase satellite = iterator.next(); satellite.tickEntity(); @@ -994,14 +1082,31 @@ public void tick() { BlockPos p = i.pos.getBlockPos(); iterator_2.remove(); // Safe removal during iteration World world = (net.minecraftforge.common.DimensionManager.getWorld(getId())); - world.notifyNeighborsOfStateChange(p,world.getBlockState(p).getBlock(),false); + world.notifyNeighborsOfStateChange(p, world.getBlockState(p).getBlock(), false); } } + World world = (net.minecraftforge.common.DimensionManager.getWorld(getId())); + //world has to be loaded + if (world != null) { + if (proxylists.gethelper(getId()) != null) { + TerraformingHelper t = proxylists.gethelper(getId()); + if (t.has_blocks_in_dec_queue()) { + //if (new Random().nextInt(100) < 50) { + for (int i = 0; i < 5; i++) { + BlockPos target = t.get_next_position_decoration(true); + if (target != null) { + BiomeHandler.do_decoration(world, target, getId()); + } else break; + } + //} + } + } + } } - public void add_water_locked_pos(HashedBlockPosition pos){ - for (watersourcelocked i : water_source_locked_positions){ - if (i.pos.equals(pos)){ + public void add_water_locked_pos(HashedBlockPosition pos) { + for (watersourcelocked i : water_source_locked_positions) { + if (i.pos.equals(pos)) { i.reset_timer(); return; } @@ -1045,14 +1150,6 @@ public void setBiomes(List biomes) { addBiomes(biomes); } - public List getTerraformedBiomes() { - return terraformedBiomes; - } - - public void setTerraformedBiomes(List biomes) { - terraformedBiomes.clear(); - terraformedBiomes.addAll(getBiomesEntries(biomes)); - } /** * Used to determine if a biome is allowed to spawn on ANY planet @@ -1060,18 +1157,29 @@ public void setTerraformedBiomes(List biomes) { * @param biome biome to check * @return true if the biome is not allowed to spawn on any Dimension */ - public boolean isBiomeblackListed(Biome biome) { + public boolean isBiomeblackListed(Biome biome, boolean is_NOT_terraforming) { + + if (!is_NOT_terraforming) { + String modId = biome.getRegistryName().getResourceDomain(); + if (!ARConfiguration.getCurrentConfig().allowNonArBiomesInTerraforming) { + if (!modId.equals("minecraft") && !modId.equals("advancedrocketry")) { + return true; + } + } + } + if (biome.equals(AdvancedRocketryBiomes.spaceBiome)) return true; + return AdvancedRocketryBiomes.instance.getBlackListedBiomes().contains(Biome.getIdForBiome(biome)); } /** * @return a list of biomes allowed to spawn in this dimension */ - public List getViableBiomes(boolean allow_single_biome) { + public List getViableBiomes(boolean not_terraforming) { Random random = new Random(System.nanoTime()); List viableBiomes = new ArrayList<>(); - if (atmosphereDensity > AtmosphereTypes.LOW.value && random.nextInt(3) == 0 && allow_single_biome) { + if (atmosphereDensity > AtmosphereTypes.LOW.value && random.nextInt(3) == 0 && not_terraforming) { List list = new LinkedList<>(AdvancedRocketryBiomes.instance.getSingleBiome()); while (list.size() > 1) { @@ -1100,34 +1208,36 @@ public List getViableBiomes(boolean allow_single_biome) { } else if (Temps.getTempFromValue(averageTemperature).hotterOrEquals(Temps.HOT)) { for (Biome biome : Biome.REGISTRY) { - if (biome != null && (BiomeDictionary.getTypes(biome).contains(BiomeDictionary.Type.HOT) || BiomeDictionary.getTypes(biome).contains(BiomeDictionary.Type.OCEAN)) && !isBiomeblackListed(biome)) { + if (biome != null && (BiomeDictionary.getTypes(biome).contains(BiomeDictionary.Type.HOT) || BiomeDictionary.getTypes(biome).contains(BiomeDictionary.Type.OCEAN)) && !isBiomeblackListed(biome, not_terraforming)) { viableBiomes.add(biome); } } } else if (Temps.getTempFromValue(averageTemperature).hotterOrEquals(Temps.NORMAL)) { for (Biome biome : Biome.REGISTRY) { - if (biome != null && !BiomeDictionary.getTypes(biome).contains(BiomeDictionary.Type.COLD) && !isBiomeblackListed(biome)) { + if (biome != null && !BiomeDictionary.getTypes(biome).contains(BiomeDictionary.Type.COLD) && !isBiomeblackListed(biome, not_terraforming)) { viableBiomes.add(biome); } } - viableBiomes.addAll(BiomeDictionary.getBiomes(BiomeDictionary.Type.OCEAN)); + //if (not_terraforming) + //viableBiomes.addAll(BiomeDictionary.getBiomes(BiomeDictionary.Type.OCEAN)); } else if (Temps.getTempFromValue(averageTemperature).hotterOrEquals(Temps.COLD)) { for (Biome biome : Biome.REGISTRY) { - if (biome != null && !BiomeDictionary.getTypes(biome).contains(BiomeDictionary.Type.HOT) && !isBiomeblackListed(biome)) { + if (biome != null && !BiomeDictionary.getTypes(biome).contains(BiomeDictionary.Type.HOT) && !isBiomeblackListed(biome, not_terraforming)) { viableBiomes.add(biome); } } - viableBiomes.addAll(BiomeDictionary.getBiomes(BiomeDictionary.Type.OCEAN)); + //if (not_terraforming) + //viableBiomes.addAll(BiomeDictionary.getBiomes(BiomeDictionary.Type.OCEAN)); } else if (Temps.getTempFromValue(averageTemperature).hotterOrEquals(Temps.FRIGID)) { for (Biome biome : Biome.REGISTRY) { - if (biome != null && BiomeDictionary.getTypes(biome).contains(BiomeDictionary.Type.COLD) && !isBiomeblackListed(biome)) { + if (biome != null && BiomeDictionary.getTypes(biome).contains(BiomeDictionary.Type.COLD) && !isBiomeblackListed(biome, not_terraforming)) { viableBiomes.add(biome); } } } else { for (Biome biome : Biome.REGISTRY) { - if (biome != null && BiomeDictionary.getTypes(biome).contains(BiomeDictionary.Type.COLD) && !isBiomeblackListed(biome)) { + if (biome != null && BiomeDictionary.getTypes(biome).contains(BiomeDictionary.Type.COLD) && !isBiomeblackListed(biome, not_terraforming)) { viableBiomes.add(biome); } } @@ -1336,22 +1446,6 @@ private void readFromTechnicalNBT(NBTTagCompound nbt) { } else beaconLocations.clear(); - - //Load biomes - if (nbt.hasKey("biomesTerra")) { - - terraformedBiomes.clear(); - int[] biomeIds = nbt.getIntArray("biomesTerra"); - List biomesList = new ArrayList<>(); - - - for (int biomeId : biomeIds) { - biomesList.add(AdvancedRocketryBiomes.instance.getBiomeById(biomeId)); - } - - terraformedBiomes.addAll(getBiomesEntries(biomesList)); - } - //Satellites if (nbt.hasKey("satallites")) { @@ -1384,6 +1478,7 @@ private void readFromTechnicalNBT(NBTTagCompound nbt) { } public void readFromNBT(NBTTagCompound nbt) { + NBTTagList list; if (nbt.hasKey("skyColor")) { @@ -1531,6 +1626,14 @@ public void readFromNBT(NBTTagCompound nbt) { craterFrequencyMultiplier = nbt.getFloat("craterFrequencyMultiplier"); volcanoFrequencyMultiplier = nbt.getFloat("volcanoFrequencyMultiplier"); + // Custom weather info + rainStartLength = nbt.getInteger("rainStartLength"); + thunderStartLength = nbt.getInteger("thunderStartLength"); + rainProlongationLength = nbt.getInteger("rainProlongationLength"); + thunderProlongationLength = nbt.getInteger("thunderProlongationLength"); + rainMarker = nbt.getInteger("rainMarker"); + thunderMarker = nbt.getInteger("thunderMarker"); + //Hierarchy if (nbt.hasKey("childrenPlanets")) { @@ -1579,9 +1682,12 @@ public void readFromNBT(NBTTagCompound nbt) { } else fillerBlock = null; + readFromTechnicalNBT(nbt); } + + private void writeTechnicalNBT(NBTTagCompound nbt) { NBTTagList list; if (!beaconLocations.isEmpty()) { @@ -1593,16 +1699,6 @@ private void writeTechnicalNBT(NBTTagCompound nbt) { nbt.setTag("beaconLocations", list); } - - if (!terraformedBiomes.isEmpty()) { - int[] biomeId = new int[terraformedBiomes.size()]; - for (int i = 0; i < terraformedBiomes.size(); i++) { - - biomeId[i] = Biome.getIdForBiome(terraformedBiomes.get(i).biome); - } - nbt.setIntArray("biomesTerra", biomeId); - } - //Satellites if (!satellites.isEmpty()) { @@ -1614,9 +1710,116 @@ private void writeTechnicalNBT(NBTTagCompound nbt) { allSatelliteNBT.setTag(entry.getKey().toString(), satelliteNBT); } nbt.setTag("satallites", allSatelliteNBT); + } } + + //terraforming data + public void read_terraforming_data(NBTTagCompound nbt){ + + int dimid =getId(); + if (!proxylists.isinitialized(dimid)){ + proxylists.initdim(dimid); + } + + if (nbt.hasKey("fullyGeneratedChunks")) { + + NBTTagList list = nbt.getTagList("fullyGeneratedChunks", NBT.TAG_COMPOUND); + if (!list.hasNoTags()) + proxylists.setChunksFullyTerraformed(dimid, new HashSet()); + for (NBTBase entry : list) { + assert entry instanceof NBTTagCompound; + int x = ((NBTTagCompound) entry).getInteger("x"); + int z = ((NBTTagCompound) entry).getInteger("z"); + System.out.println("Chunk fully terraformed: " + x + ":" + z); + + boolean chunk_was_already_done = false; + for (ChunkPos i : proxylists.getChunksFullyTerraformed(dimid)) { + if (x == i.x && z == i.z) { + chunk_was_already_done = true; + break; + } + } + if (!chunk_was_already_done) + proxylists.getChunksFullyTerraformed(dimid).add(new ChunkPos(x, z)); + else System.out.println("Chunk is already in list: " + x + ":" + z); + } + } + + if (nbt.hasKey("fullyBiomeChangedChunks")) { + + NBTTagList list = nbt.getTagList("fullyBiomeChangedChunks", NBT.TAG_COMPOUND); + if (!list.hasNoTags()) + proxylists.setChunksFullyBiomeChanged(dimid, new HashSet()); + for (NBTBase entry : list) { + assert entry instanceof NBTTagCompound; + int x = ((NBTTagCompound) entry).getInteger("x"); + int z = ((NBTTagCompound) entry).getInteger("z"); + System.out.println("Chunk fully biome changed: " + x + ":" + z); + + boolean chunk_was_already_done = false; + for (ChunkPos i : proxylists.getChunksFullyBiomeChanged(dimid)) { + if (x == i.x && z == i.z) { + chunk_was_already_done = true; + break; + } + } + if (!chunk_was_already_done) + proxylists.getChunksFullyBiomeChanged(dimid).add(new ChunkPos(x, z)); + else System.out.println("Chunk is already in list: " + x + ":" + z); + } + } + + if (nbt.hasKey("terraformingProtectedBlocks")) { + + NBTTagList list = nbt.getTagList("terraformingProtectedBlocks", NBT.TAG_COMPOUND); + if (!list.hasNoTags()) + proxylists.setProtectingBlocksForDimension(dimid, new ArrayList<>()); + for (NBTBase entry : list) { + assert entry instanceof NBTTagCompound; + int x = ((NBTTagCompound) entry).getInteger("x"); + int z = ((NBTTagCompound) entry).getInteger("z"); + int y = ((NBTTagCompound) entry).getInteger("y"); + proxylists.getProtectingBlocksForDimension(dimid).add(new BlockPos(x, y, z)); + System.out.println("read protecting block at " + x + ":" + y + ":" + z + " - - " + proxylists.getProtectingBlocksForDimension(dimid).size()); + } } } + public void write_terraforming_data(NBTTagCompound nbt) { + // write terraforming data + int dimid = getId(); + if (!proxylists.isinitialized(dimid)){ + return; + } + NBTTagList list = new NBTTagList(); + for (ChunkPos pos : proxylists.getChunksFullyTerraformed(dimid)) { + NBTTagCompound entry = new NBTTagCompound(); + entry.setInteger("x", pos.x); + entry.setInteger("z", pos.z); + list.appendTag(entry); + } + nbt.setTag("fullyGeneratedChunks", list); + + list = new NBTTagList(); + for (ChunkPos pos : proxylists.getChunksFullyBiomeChanged(dimid)) { + NBTTagCompound entry = new NBTTagCompound(); + entry.setInteger("x", pos.x); + entry.setInteger("z", pos.z); + list.appendTag(entry); + } + nbt.setTag("fullyBiomeChangedChunks", list); + + list = new NBTTagList(); + for (BlockPos pos : proxylists.getProtectingBlocksForDimension(dimid)) { + NBTTagCompound entry = new NBTTagCompound(); + entry.setInteger("x", pos.getX()); + entry.setInteger("y", pos.getY()); + entry.setInteger("z", pos.getZ()); + list.appendTag(entry); + } + nbt.setTag("terraformingProtectedBlocks", list); + + + } public void writeToNBT(NBTTagCompound nbt) { NBTTagList list; @@ -1748,6 +1951,14 @@ public void writeToNBT(NBTTagCompound nbt) { nbt.setFloat("craterFrequencyMultiplier", craterFrequencyMultiplier); nbt.setFloat("volcanoFrequencyMultiplier", volcanoFrequencyMultiplier); + // Custom weather data + nbt.setInteger("rainStartLength", rainStartLength); + nbt.setInteger("thunderStartLength", thunderStartLength); + nbt.setInteger("rainProlongationLength", rainProlongationLength); + nbt.setInteger("thunderProlongationLength", thunderProlongationLength); + nbt.setInteger("rainMarker", rainMarker); + nbt.setInteger("thunderMarker", thunderMarker); + //Hierarchy if (!childPlanets.isEmpty()) { Integer[] intList = new Integer[childPlanets.size()]; @@ -1779,6 +1990,7 @@ public void writeToNBT(NBTTagCompound nbt) { } + writeTechnicalNBT(nbt); } @@ -2052,6 +2264,7 @@ public int getTemp() { public boolean hotterThan(Temps type) { return this.compareTo(type) < 0; } + public boolean hotterOrEquals(Temps type) { return this.compareTo(type) <= 0; } diff --git a/src/main/java/zmaster587/advancedRocketry/entity/EntityElevatorCapsule.java b/src/main/java/zmaster587/advancedRocketry/entity/EntityElevatorCapsule.java index c85dff3d0..f586548ab 100644 --- a/src/main/java/zmaster587/advancedRocketry/entity/EntityElevatorCapsule.java +++ b/src/main/java/zmaster587/advancedRocketry/entity/EntityElevatorCapsule.java @@ -314,9 +314,9 @@ public void onEntityUpdate() { for (Entity ent : list) { if (this.getRidingEntity() == null) ent.startRiding(this); - this.fallDistance = 0; // I have no idea what I am doing I just copied this from ent.fallDistance = 0; // entityRocket.java to prevent fall damage } + this.fallDistance = 0; // I have no idea what I am doing I just copied this from if (this.posY <= dstTilePos.pos.y + 1 && world.provider.getDimension() != ARConfiguration.getCurrentConfig().spaceDimId) { setCapsuleMotion(0); diff --git a/src/main/java/zmaster587/advancedRocketry/entity/EntityLaserNode.java b/src/main/java/zmaster587/advancedRocketry/entity/EntityLaserNode.java index a88335917..73e02255c 100644 --- a/src/main/java/zmaster587/advancedRocketry/entity/EntityLaserNode.java +++ b/src/main/java/zmaster587/advancedRocketry/entity/EntityLaserNode.java @@ -5,12 +5,12 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.DamageSource; import net.minecraft.util.SoundCategory; -import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import zmaster587.advancedRocketry.AdvancedRocketry; -import zmaster587.advancedRocketry.api.AdvancedRocketryBlocks; import zmaster587.advancedRocketry.util.AudioRegistry; import zmaster587.libVulpes.LibVulpes; @@ -22,11 +22,13 @@ public class EntityLaserNode extends Entity { // intentionally not saved, flag to determine if the entity controlling the laser is somehow disconnected boolean isValid = false; + private Vec3d poscorrection; public EntityLaserNode(World par1World) { super(par1World); ignoreFrustumCheck = true; noClip = true; + poscorrection = new Vec3d(0,0,0); } public EntityLaserNode(World world, double x, double y, double z) { @@ -59,18 +61,7 @@ public void setDead() { * Removes all the light blocks created by the laser */ private void cleanUp() { - if (!this.world.isRemote && this.isDead) - new Thread(() -> { - for (int h = 0; h < world.getHeight(); h++) { - for (int i = 0; i < 9; i++) { - int x = (int) posX + (i % 3) - 1; - int z = (int) posZ + (i / 3) - 1; - BlockPos pos = new BlockPos(x, h, z); - if (world.getBlockState(pos).getBlock() == AdvancedRocketryBlocks.blockLightSource) - world.setBlockToAir(pos); - } - } - }).start(); + } @Override @@ -82,6 +73,16 @@ public void onUpdate() { return; } + if (world.isRemote) { + double ct = 5; + double cx = poscorrection.x / ct; + double cy = poscorrection.y / ct; + double cz = poscorrection.z / ct; + poscorrection = poscorrection.subtract(cx, cy, cz); + + this.setPosition(posX + cx, posY + cy, posZ + cz); + + } super.onUpdate(); if (this.world.isRemote) { @@ -114,6 +115,19 @@ public boolean isInRangeToRenderDist(double par1) { } + + @Override + public void setPositionAndRotationDirect(double x, double y, double z, float yaw, float pitch, int posRotationIncrements, boolean teleport) { + + Vec3d new_pos = new Vec3d(x, y, z); + poscorrection = new_pos.subtract(posX, posY, posZ); + + + //Vec3d new_pos = new Vec3d(x, y, z); + //poscorrection = new_pos.subtract(posX, posY, posZ); + } + + //Dont need to write anything @Override protected void readEntityFromNBT(NBTTagCompound nbttagcompound) { diff --git a/src/main/java/zmaster587/advancedRocketry/entity/EntityRocket.java b/src/main/java/zmaster587/advancedRocketry/entity/EntityRocket.java index 4ced94e0f..96a725916 100644 --- a/src/main/java/zmaster587/advancedRocketry/entity/EntityRocket.java +++ b/src/main/java/zmaster587/advancedRocketry/entity/EntityRocket.java @@ -58,6 +58,7 @@ import zmaster587.advancedRocketry.event.PlanetEventHandler; import zmaster587.advancedRocketry.inventory.IPlanetDefiner; import zmaster587.advancedRocketry.inventory.TextureResources; +import zmaster587.advancedRocketry.inventory.modules.ModuleBrokenPart; import zmaster587.advancedRocketry.inventory.modules.ModulePlanetSelector; import zmaster587.advancedRocketry.inventory.modules.ModuleStellarBackground; import zmaster587.advancedRocketry.item.ItemAsteroidChip; @@ -68,7 +69,9 @@ import zmaster587.advancedRocketry.network.PacketSatellite; import zmaster587.advancedRocketry.stations.SpaceObjectManager; import zmaster587.advancedRocketry.stations.SpaceStationObject; +import zmaster587.advancedRocketry.tile.TileBrokenPart; import zmaster587.advancedRocketry.tile.TileGuidanceComputer; +import zmaster587.advancedRocketry.tile.TileRocketAssemblingMachine; import zmaster587.advancedRocketry.tile.hatch.TileSatelliteHatch; import zmaster587.advancedRocketry.util.*; import zmaster587.advancedRocketry.world.util.TeleporterNoPortal; @@ -90,9 +93,16 @@ public class EntityRocket extends EntityRocketBase implements INetworkEntity, IModularInventory, IProgressBar, IButtonInventory, ISelectionNotify, IPlanetDefiner { // set to 2 seconds because keyboard event is not sent to server - // might be a temporary solution. Better be stuck 2 seconds than 25 seconds. + // might be a temporary solution. Better be stuck 2 seconds than 25 seconds. but it needs 1 second to load private static final int DESCENT_TIMER = 2*20; + //client sync stuff + private Vec3d poscorrection; + private Vec3d velcorrection; + boolean last_was_in_orbit = false; + boolean reset_position = true; + boolean reset_motion = true; + private static final int BUTTON_ID_OFFSET = 25; private static final int STATION_LOC_OFFSET = 50; private static final int ENGINE_IGNITION_CNT = 100; @@ -132,6 +142,12 @@ public class EntityRocket extends EntityRocketBase implements INetworkEntity, IM private boolean rcs_mode = false; public EntityRocket(World p_i1582_1_) { super(p_i1582_1_); + + poscorrection = new Vec3d(0,0,0); + velcorrection = new Vec3d(0,0,0); + reset_position = true; + reset_motion = true; + isInOrbit = false; stats = new StatsRocket(); isInFlight = false; @@ -336,8 +352,10 @@ public String getTextOverlay() { displayStr += "\n" + LibVulpes.proxy.getLocalizedString("msg.entity.rocket.rcs") + ": " + getRCS(); } - if (isInOrbit() && !isInFlight()) - return LibVulpes.proxy.getLocalizedString("msg.entity.rocket.descend.1") + "\n" + LibVulpes.proxy.getLocalizedString("msg.entity.rocket.descend.2") + ((DESCENT_TIMER - this.ticksExisted) / 20); + if (isInOrbit() && !isInFlight()) { + //return LibVulpes.proxy.getLocalizedString("msg.entity.rocket.descend.1") + "\n" + LibVulpes.proxy.getLocalizedString("msg.entity.rocket.descend.2") + ((DESCENT_TIMER - this.ticksExisted) / 20); + return super.getTextOverlay(); + } else if (!isInFlight()) return LibVulpes.proxy.getLocalizedString("msg.entity.rocket.ascend.1") + "\n" + LibVulpes.proxy.getLocalizedString("msg.entity.rocket.ascend.2") + displayStr; @@ -596,6 +614,8 @@ protected boolean interact(@Nonnull EntityPlayer player) { if (!connectedInfrastructure.contains(tile)) { linkInfrastructure(infrastructure); + // TODO Translate + if (!world.isRemote) { player.sendMessage(new TextComponentString("Linked successfully")); } @@ -723,7 +743,18 @@ private boolean hasHumanPassenger() { } public boolean isDescentPhase() { - return ARConfiguration.getCurrentConfig().automaticRetroRockets && isInOrbit() && this.posY < 300 && (this.motionY < -0.4f || world.isRemote); + int ch = world.getHeight((int) posX, (int) posZ); + return ARConfiguration.getCurrentConfig().automaticRetroRockets && + isInOrbit() && + ( + (this.posY < ch + 300 && (this.motionY < -0.5f || world.isRemote)) || + (this.posY < ch + 150 && (this.motionY < -0.4f || world.isRemote)) || + (this.posY < ch + 100 && (this.motionY < -0.3f || world.isRemote)) || + (this.posY < ch + 70 && (this.motionY < -0.2f || world.isRemote)) || + (this.posY < ch + 50 && (this.motionY < -0.14f || world.isRemote)) || + (this.posY < ch + 20 && (this.motionY < -0.5f || world.isRemote))|| + (this.posY < ch + 10 && (this.motionY < -0.05f || world.isRemote)) + ); } public boolean isStartupPhase() { @@ -747,10 +778,40 @@ public boolean areEnginesRunning() { return this.motionY > 0 || isDescentPhase() || (getPassengerMovingForward() > 0) || isStartupPhase(); } + + + @Override + public void setPositionAndRotationDirect(double x, double y, double z, float yaw, float pitch, int posRotationIncrements, boolean teleport) { + + if(last_was_in_orbit != this.dataManager.get(INORBIT)){ + last_was_in_orbit = this.dataManager.get(INORBIT); + reset_motion= true; + reset_position = true; + } + + if (reset_position){ + this.setPosition(x,y,z); + reset_position = false; + }else { + Vec3d new_pos = new Vec3d(x, y, z); + poscorrection = new_pos.subtract(posX, posY, posZ); + } + + + //Vec3d new_pos = new Vec3d(x, y, z); + //poscorrection = new_pos.subtract(posX, posY, posZ); + } + + + private void runEngines() { //Spawn in the particle effects for the engines - int engineNum = 0; - if (world.isRemote && Minecraft.getMinecraft().gameSettings.particleSetting < 2 && areEnginesRunning()) { + int max_engine_for_smoke = 16; + int engineNum = stats.getEngineLocations().size(); + //System.out.println("engine locs:"+engineNum); + + + if (world.isRemote && areEnginesRunning()) { for (Vector3F vec : stats.getEngineLocations()) { AtmosphereHandler handler = AtmosphereHandler.getOxygenHandler(world.provider.getDimension()); @@ -759,11 +820,34 @@ private void runEngines() { if (handler != null) atmosphere = handler.getAtmosphereType(this); - if (Minecraft.getMinecraft().gameSettings.particleSetting < 1 && world.getTotalWorldTime() % 10 == 0 && (engineNum < 8 || ((world.getTotalWorldTime() / 10) % Math.max((stats.getEngineLocations().size() / 8), 1)) == (engineNum / 8)) && (handler == null || (atmosphere != null && atmosphere.allowsCombustion()))) - AdvancedRocketry.proxy.spawnParticle("rocketSmoke", world, this.posX + vec.x, this.posY + vec.y - 0.75, this.posZ + vec.z, 0, 0, 0); - for (int i = 0; i < 4; i++) { - AdvancedRocketry.proxy.spawnParticle("rocketFlame", world, this.posX + vec.x, this.posY + vec.y - 0.75, this.posZ + vec.z, (this.rand.nextFloat() - 0.5f) / 8f, -.75, (this.rand.nextFloat() - 0.5f) / 8f); + boolean can_smoke = true; + if (engineNum > max_engine_for_smoke) { + can_smoke = rand.nextInt(engineNum) <= max_engine_for_smoke; + } + + if (Minecraft.getMinecraft().gameSettings.particleSetting < 2 && can_smoke && Minecraft.getMinecraft().gameSettings.particleSetting < 1 && (handler == null || (atmosphere != null && atmosphere.allowsCombustion()))) { + for (int i = 0; i < 3; i++) { + + + double yo = 1 + this.rand.nextFloat(); + float xzv = 16f; + if (motionY > 0) + xzv = 32; + + double motionz = (this.rand.nextFloat() - 0.5f); + double motionx = (this.rand.nextFloat() - 0.5f); + double speed = (this.rand.nextFloat()) / xzv; + double speedxz = Math.sqrt(motionx * motionx + motionz * motionz); + motionx *= speed / speedxz; + motionz *= speed / speedxz; + + + AdvancedRocketry.proxy.spawnDynamicRocketSmoke(world, this.posX + vec.x, this.posY + vec.y - yo, this.posZ + vec.z, motionx, -0.75 - this.rand.nextFloat() / 6.0, motionz, engineNum); + } + } + for (float i = 0; i < 15; i++) { + AdvancedRocketry.proxy.spawnDynamicRocketFlame(world, this.posX + vec.x, this.posY + vec.y - 0.9 - (i*0.1f), this.posZ + vec.z, (this.rand.nextFloat() - 0.5f) / 6f, -0.75, (this.rand.nextFloat() - 0.5f) / 6f, engineNum); } } @@ -848,12 +932,72 @@ private Vec3d calculatePullFromPlanets() { public void setFire(int seconds) { } + private void syncRocket() { + NBTTagCompound nbtdata = new NBTTagCompound(); + + this.writeToNBT(nbtdata); + PacketHandler.sendToNearby(new PacketEntity(this, (byte) 0, nbtdata), world.provider.getDimension(), new BlockPos(this), 64); + } + + + //stfu + + @Override + public void setVelocity(double x, double y, double z) { + + if (reset_motion){ + velcorrection = new Vec3d(0,0,0); + this.motionX = x; + this.motionY = y; + this.motionZ = z; + reset_motion = false; + }else { + Vec3d new_vel = new Vec3d(x, y, z); + velcorrection = new_vel.subtract(motionX, motionY, motionZ); + } + + + //Vec3d new_vel = new Vec3d(x, y, z); + //velcorrection = new_vel.subtract(motionX, motionY, motionZ); + } + + + @Override public void onUpdate() { super.onUpdate(); long deltaTime = world.getTotalWorldTime() - lastWorldTickTicked; lastWorldTickTicked = world.getTotalWorldTime(); + if (world.isRemote) { + + double ct = 50; + + if (!this.dataManager.get(INORBIT) && poscorrection.y < -0.01) { + // if this code runs, rocket is out of fuel and will have a hard crash. no smooth syncing! + ct = 1; + } + + + double cx = poscorrection.x / ct; + double cy = poscorrection.y / ct; + double cz = poscorrection.z / ct; + poscorrection = poscorrection.subtract(cx, cy, cz); + this.setPosition(posX + cx, posY + cy, posZ + cz); + + + double ct2 = 10; + double vx = velcorrection.x / ct2; + double vy = velcorrection.y / ct2; + double vz = velcorrection.z / ct2; + velcorrection = velcorrection.subtract(vx, vy, vz); + + motionX += vx; + motionY += vy; + motionZ += vz; + + } + if (this.ticksExisted == 20) { //problems with loading on other world then where the infrastructure was set? @@ -912,8 +1056,6 @@ public void onUpdate() { for (Entity riddenByEntity : getPassengers()) { if (riddenByEntity instanceof EntityPlayer) { EntityPlayer player = (EntityPlayer) riddenByEntity; - - PacketHandler.sendToPlayer(new PacketEntity(this, (byte) PacketType.FORCEMOUNT.ordinal()), player); } } @@ -937,6 +1079,13 @@ else if (!getRCS() && rcs_mode_counter > 0) { damageGroundBelowRocket(world, (int) this.posX, (int) this.posY, (int) this.posZ, (int) Math.pow(stats.getThrust(), 0.4)); } + if(!world.isRemote){ + for(Entity entity : this.getPassengers()) { + entity.fallDistance = 0; + } + this.fallDistance = 0; + } + // When flying around in space if (getInSpaceFlight()) { double distanceFromPlanetToLeaveOrbitMult = 16.0; @@ -970,7 +1119,6 @@ else if (!getRCS() && rcs_mode_counter > 0) { if (distanceSq < properties.getRenderSizeSolarView() * properties.getRenderSizeSolarView() * 8) { this.spacePosition.world = (DimensionProperties) properties; - //Radius to put the player double radius = -properties.getRenderSizePlanetView() * 16; //Assume planet centered at 0 @@ -988,6 +1136,9 @@ else if (!getRCS() && rcs_mode_counter > 0) { double distanceSq = this.spacePosition.distanceToSpacePosition2(new SpacePosition()); //Land, only handle on server if (!world.isRemote) { + this.storage.damageParts(); + syncRocket(); + if (distanceSq < 0.5f * spacePosition.world.getRenderSizePlanetView() * spacePosition.world.getRenderSizePlanetView()) { this.destinationDimId = spacePosition.world.getId(); this.setRCS(false); @@ -1079,6 +1230,8 @@ else if (distanceSq > this.spacePosition.world.getRenderSizePlanetView() * this. if (burningFuel || descentPhase) { //Burn the rocket fuel + // TODO SHOULD WE BURN IN DECENT PHASE TOO??? + // TODO THIS COULD MAKE IT SO THAT OUT OF FUEL -> You crash -> rocket takes a lot of damage if (!world.isRemote && !descentPhase) { setFuelAmount(getRocketFuelType(), getFuelAmount(getRocketFuelType()) - getFuelConsumptionRate(getRocketFuelType())); if (getRocketFuelType() == FuelType.LIQUID_BIPROPELLANT) @@ -1095,34 +1248,29 @@ else if (distanceSq > this.spacePosition.world.getRenderSizePlanetView() * this. runEngines(); } + if (!world.isRemote) { - if (!this.getPassengers().isEmpty()) { - - for (Entity entity : this.getPassengers()) { - entity.fallDistance = 0; - this.fallDistance = 0; + if (isInOrbit() && descentPhase) { //going down & slowing + this.motionY -= this.motionY / 120f; + this.velocityChanged = true; + } else { + //If out of fuel or descending then accelerate downwards + if (isInOrbit() || !burningFuel) { + //this.motionY = Math.min(this.motionY - 0.001, 1); + this.motionY = this.motionY - 0.1f * 1 / 20f * 9.81 * (DimensionManager.getInstance().getDimensionProperties(this.world.provider.getDimension()).getGravitationalMultiplier()); + motionY = Math.max(-2, motionY); + this.velocityChanged = true; + } else { + //this.motionY = Math.min(this.motionY + 0.001, 1); + this.motionY += stats.getAcceleration(DimensionManager.getInstance().getDimensionProperties(this.world.provider.getDimension()).getGravitationalMultiplier()) * deltaTime; + this.velocityChanged = true; + } } - //if the player holds the forward key then decelerate - if (isInOrbit() && (burningFuel || descentPhase)) { - float vel = descentPhase ? 1f : getPassengerMovingForward(); - this.motionY -= this.motionY * vel / 50f; + if (isInOrbit() && descentPhase) { //going down & slowing + this.motionY -= this.motionY / 120f; + this.velocityChanged = true; } - this.velocityChanged = true; - - } else if (isInOrbit() && descentPhase) { //For unmanned rockets - this.motionY -= this.motionY / 50f; - this.velocityChanged = true; - } - - if (!world.isRemote) { - //If out of fuel or descending then accelerate downwards - if (isInOrbit() || !burningFuel) { - //this.motionY = Math.min(this.motionY - 0.001, 1); - this.motionY = this.motionY - 0.001; - } else - //this.motionY = Math.min(this.motionY + 0.001, 1); - this.motionY += stats.getAcceleration(DimensionManager.getInstance().getDimensionProperties(this.world.provider.getDimension()).getGravitationalMultiplier()) * deltaTime; double lastPosY = this.posY; @@ -1181,7 +1329,8 @@ else if (distanceSq > this.spacePosition.world.getRenderSizePlanetView() * this. this.setDead(); } } else { - this.move(MoverType.SELF, 0, this.motionY, 0); + this.move(MoverType.SELF, 0, this.motionY*deltaTime, 0); + //this.setPosition(posX, posY + this.motionY * deltaTime, posZ); } } else if (DimensionManager.getInstance().getDimensionProperties(this.world.provider.getDimension()).isAsteroid() && getRCS()) { @@ -1204,6 +1353,8 @@ else if (distanceSq > this.spacePosition.world.getRenderSizePlanetView() * this. if (this.posY < getTopBlock(getPosition()).getY() + 5 && this.posX > getTopBlock(getPosition()).getY() && ARConfiguration.getCurrentConfig().launchingDestroysBlocks && motionY < -0.1) { damageGroundBelowRocket(world, (int) this.posX, (int) this.posY - 1, (int) this.posZ, (int) Math.pow(stats.getThrust(), 0.4)); } + + //System.out.println("motiony:"+motionY); } public void onTurnRight(boolean state) { @@ -1255,7 +1406,7 @@ public void onOrbitReached() { break; } } - this.motionY = -this.motionY; + this.motionY = -2; setInOrbit(true); } else if (!stats.hasSeat()) { reachSpaceUnmanned(); @@ -1317,7 +1468,7 @@ private void reachSpaceUnmanned() { storage.setDestinationCoordinates(new Vector3F<>((float) this.posX, (float) this.posY, (float) this.posZ), this.world.provider.getDimension()); if (pos != null) { this.setInOrbit(true); - this.motionY = -this.motionY; + this.motionY = -2; //unlink any connected tiles Iterator connectedTiles = connectedInfrastructure.iterator(); @@ -1336,7 +1487,7 @@ private void reachSpaceUnmanned() { } this.setInOrbit(true); - this.motionY = -this.motionY; + this.motionY = -2; //unlink any connected tiles Iterator connectedTiles = connectedInfrastructure.iterator(); @@ -1353,7 +1504,7 @@ private void reachSpaceUnmanned() { storage.setDestinationCoordinates(new Vector3F<>((float) this.posX, (float) this.posY, (float) this.posZ), this.world.provider.getDimension()); if (pos != null) { this.setInOrbit(true); - this.motionY = -this.motionY; + this.motionY = -2; this.changeDimension(destinationDimId, pos.x, getEntryHeight(destinationDimId), pos.z); } else { @@ -1364,7 +1515,7 @@ private void reachSpaceUnmanned() { } this.setInOrbit(true); - this.motionY = -this.motionY; + this.motionY = -2; this.changeDimension(destinationDimId, this.posX, getEntryHeight(destinationDimId), this.posZ); } @@ -1373,7 +1524,7 @@ private void reachSpaceUnmanned() { int offX = (world.rand.nextInt() % 256) - 128; int offZ = (world.rand.nextInt() % 256) - 128; this.setInOrbit(true); - this.motionY = -this.motionY; + this.motionY = -2; this.setPosition(posX + offX, posY, posZ + offZ); //unlink any connected tiles @@ -1428,7 +1579,7 @@ private void reachSpaceManned() { } } else { - this.motionY = -this.motionY; + this.motionY = -2; setInOrbit(true); //If going to a station or something make sure to set coords accordingly //If in space land on the planet, if on the planet go to space @@ -1520,7 +1671,7 @@ private void unpackSatellites() { } } else { int destinationId = storage.getDestinationDimId(world.provider.getDimension(), (int) posX, (int) posZ); - DimensionProperties properties = DimensionManager.getEffectiveDimId(world, this.getPosition()); + DimensionProperties properties = DimensionManager.getEffectiveDimId_byID(destinationId, this.getPosition()); int world2; if (destinationId == ARConfiguration.getCurrentConfig().spaceDimId || destinationId == Constants.INVALID_PLANET) world2 = properties.getId(); @@ -1561,6 +1712,43 @@ public void prepareLaunch() { } } + private double gauss(double mean, double div) { + Random rand = world.rand; + return mean + (rand.nextDouble() - 0.5F) * 2F * div; + } + + public void explode() { + if (world.isRemote && Minecraft.getMinecraft().gameSettings.particleSetting < 2) { + AxisAlignedBB bb = getCollisionBoundingBox(); + double meanX = (bb.maxX + bb.minX) / 2; + double meanY = (bb.maxY + bb.minY) / 2; + double meanZ = (bb.maxZ + bb.minZ) / 2; + double divX = (bb.maxX - bb.minX) / 1.2; + double divY = (bb.maxY - bb.minY) / 1.2; + double divZ = (bb.maxZ - bb.minZ) / 1.2; + + if (Minecraft.getMinecraft().gameSettings.particleSetting < 1) { + for (int i = 0; i < 10; i++) { + AdvancedRocketry.proxy.spawnParticle("rocketSmoke", world, + gauss(meanX, divX), gauss(meanY, divY), gauss(meanZ, divZ), + (this.rand.nextFloat() - 0.5f) / 4f, (this.rand.nextFloat() - 0.5f) / 4f, (this.rand.nextFloat() - 0.5f) / 4f); + } + } + + for (int i = 0; i < 50; i++) { + AdvancedRocketry.proxy.spawnParticle("rocketFlame", world, + gauss(meanX, divX), gauss(meanY, divY), gauss(meanZ, divZ), + (this.rand.nextFloat() - 0.5f) / 4f, (this.rand.nextFloat() - 0.5f) / 4f, (this.rand.nextFloat() - 0.5f) / 4f); + } + } + + this.setDead(); + } + + public void recalculateStats(){ + this.storage.recalculateStats(this.stats); + } + /** * Launches the rocket post determining its height, checking whether it can launch to the selected planet and whether it can exist, * among other factors. Also handles orbital height calculations @@ -1568,12 +1756,39 @@ public void prepareLaunch() { @Override public void launch() { + if(world.isRemote)return; + if (isInFlight()) return; boolean allowLaunch = false; - this.stats.setWeight((int) storage.recalculateWeight()); + this.storage.recalculateStats(this.stats); + + NBTTagCompound nbtdata = new NBTTagCompound(); + writeToNBT(nbtdata); + // Can this be done without sending the entity packet again? + // It causes rocket to skip rendering a few frames when launching + PacketHandler.sendToNearby(new PacketEntity(this, (byte) 0, nbtdata), this.world.provider.getDimension(), this.getPosition(), 64); + + + if (ARConfiguration.getCurrentConfig().advancedWeightSystem) { + this.stats.setWeight(storage.recalculateWeight()); + for (HashedBlockPosition pos : this.infrastructureCoords) { + TileEntity te = world.getTileEntity(pos.getBlockPos()); + if (te instanceof TileRocketAssemblingMachine) { + //this does not work: getWeight() returns weight + fuel. setWeight() should not include fuel weight because it is calculated on every getweight() + // so if you say setweight(getweight()) and next time I call getweight() it returns weight+fuel+fuel + // we do not need this anyway because the assembler has IDataSync interface and syncs itself + //((TileRocketAssemblingMachine) te).getRocketStats().setWeight(this.stats.getWeight()); + } + } + } + + if (ARConfiguration.getCurrentConfig().partsWearSystem && storage.shouldBreak()) { + this.explode(); + return; + } if (ARConfiguration.getCurrentConfig().experimentalSpaceFlight && storage.getGuidanceComputer() != null && storage.getGuidanceComputer().isEmpty()) { allowLaunch = true; @@ -1621,6 +1836,10 @@ public void launch() { } + if (this.stats.getWeight() >= this.stats.getThrust()) { + allowLaunch = false; + } + //Check to see what place we should be going to //This is bad but it works and is mostly intelligible so it's here for now stats.orbitHeight = (storage.getGuidanceComputer() == null) ? getEntryHeight(this.world.provider.getDimension()) : storage.getGuidanceComputer().getLaunchSequence(this.world.provider.getDimension(), this.getPosition()); @@ -1628,8 +1847,6 @@ public void launch() { //TODO: Clean this logic a bit? if (allowLaunch || !stats.hasSeat() || ((DimensionManager.getInstance().isDimensionCreated(destinationDimId)) || destinationDimId == ARConfiguration.getCurrentConfig().spaceDimId || destinationDimId == 0)) { //Abort if destination is invalid - - setInFlight(true); Iterator connectedTiles = connectedInfrastructure.iterator(); @@ -1686,7 +1903,7 @@ public void deconstructRocket() { } //paste the rocket into the world as blocks - storage.pasteInWorld(this.world, (int) (this.posX - storage.getSizeX() / 2f), (int) this.posY, (int) (this.posZ - storage.getSizeZ() / 2f), true); + storage.pasteInWorld(this.world, (int) (this.posX - storage.getSizeX() / 2f), (int) this.posY, (int) (this.posZ - storage.getSizeZ() / 2f)); this.setDead(); } @@ -1787,6 +2004,9 @@ protected void readEntityFromNBT(NBTTagCompound nbt) { } setInFlight(isInFlight = nbt.getBoolean("flight")); + motionX = nbt.getDouble("motionX"); + motionY = nbt.getDouble("motionY"); + motionZ = nbt.getDouble("motionZ"); readMissionPersistentNBT(nbt); if (nbt.hasKey("data")) { @@ -1828,6 +2048,9 @@ protected void writeNetworkableNBT(NBTTagCompound nbt) { nbt.setBoolean("rcs_mode", rcs_mode); nbt.setInteger("rcs_mode_cnt", rcs_mode_counter); nbt.setBoolean("inSpaceFlight", getInSpaceFlight()); + nbt.setDouble("motionX", motionX); + nbt.setDouble("motionY", motionY); + nbt.setDouble("motionZ", motionZ); stats.writeToNBT(nbt); if (!infrastructureCoords.isEmpty()) { @@ -1886,7 +2109,7 @@ public void readDataFromNetwork(ByteBuf in, byte packetId, storage.readtiles(in); } if (packetId == PacketType.RECIEVENBT.ordinal()) { - storage = new StorageChunk(); + storage = new StorageChunk(); //this re-loading makes the rocket not render for a tick or two when launching storage.setEntity(this); storage.readFromNetwork(in); } else if (packetId == PacketType.SENDPLANETDATA.ordinal()) { @@ -1960,8 +2183,11 @@ public void writeDataToNetwork(ByteBuf out, byte id) { public void useNetworkData(EntityPlayer player, Side side, byte id, NBTTagCompound nbt) { + if(id==(byte)9987){ + // F*ck you little bug + } - if (id == PacketType.RECIEVENBT.ordinal()) { + else if (id == PacketType.RECIEVENBT.ordinal()) { this.readEntityFromNBT(nbt); initFromBounds(); } else if (id == PacketType.DECONSTRUCT.ordinal()) { @@ -2083,16 +2309,18 @@ public void updatePassenger(@Nonnull Entity entity) { //Conditional b/c for some reason client/server positions do not match float xOffset = this.storage.getSizeX() % 2 == 0 ? 0.5f : 0f; float zOffset = this.storage.getSizeZ() % 2 == 0 ? 0.5f : 0f; - float halfy = storage.getSizeY() / 2f; + //float halfy = storage.getSizeY() / 2f; + //float halfx = storage.getSizeX() / 2f; + //float halfz = storage.getSizeZ() / 2f; - double xPos = seatPos.x + xOffset; - double yPos = seatPos.y - 0.5f - halfy; - double zPos = seatPos.z + zOffset; + double xPos = seatPos.x + xOffset;// - halfx+0.5; + double yPos = seatPos.y - 0.5f;// - 0.5f; // this does not work :( + double zPos = seatPos.z + zOffset;// - halfz+0.5; float angle = (float) (getRCSRotateProgress() * 0.9f * Math.PI / 180f); double yNew = (yPos) * MathHelper.cos(angle) + (-zPos - 0.5) * MathHelper.sin(angle); double zNew = zPos * MathHelper.cos(angle) + (yPos + 1) * MathHelper.sin(angle); - yPos = yNew + this.posY + halfy; + yPos = yNew + this.posY; zPos = zNew; //Now do yaw @@ -2102,7 +2330,6 @@ public void updatePassenger(@Nonnull Entity entity) { xPos = this.posX + xNew; zPos = this.posZ + zNew; - entity.setPosition(xPos, yPos, zPos); } catch (IndexOutOfBoundsException e) { entity.setPosition(this.posX, this.posY, this.posZ); @@ -2125,6 +2352,23 @@ public List getModules(int ID, EntityPlayer player) { modules.add(new ModuleImage(173, 168, new IconResource(98, 168, 78, 3, CommonResources.genericBackground))); } + // Broken parts + // TODO Add check for the service monitor + + if (storage.hasServiceMonitor()) { + List serviceMonitorList = new ArrayList<>(); + + int ii = 0; + for (TileBrokenPart part : storage.getBrokenBlocks()) { + serviceMonitorList.add(new ModuleBrokenPart((ii % 5) * 18, (ii / 5) * 18, part.getDrop())); + ii++; + } + + modules.add(new ModuleContainerPanYOnly(8 + 80, 17, serviceMonitorList, new ArrayList<>(), null, 50, 45)); + modules.add(new ModuleText(80, 5, LibVulpes.proxy.getLocalizedString("msg.serviceStation.destroyProb") + + ": " + (int)(this.storage.getBreakingProbability() * 100) + "%", 0x000000)); + } + //TODO DEBUG tiles! //Render TEs in a pan-able list y-axis only List tiles = storage.getGUITiles(); @@ -2133,12 +2377,12 @@ public List getModules(int ID, EntityPlayer player) { TileEntity tile = tiles.get(i); IBlockState state = storage.getBlockState(tile.getPos()); try { - panModules.add(new ModuleSlotButton(18 * (i % 9), 18 * (i / 9), i + tilebuttonOffset, this, new ItemStack(state.getBlock(), 1, state.getBlock().getMetaFromState(state)), world)); + panModules.add(new ModuleSlotButton(18 * (i % 4), 18 * (i / 4), i + tilebuttonOffset, this, new ItemStack(state.getBlock(), 1, state.getBlock().getMetaFromState(state)), world)); } catch (NullPointerException e) { } } - modules.add(new ModuleContainerPanYOnly(8, 17, panModules, new LinkedList<>(), null, 171, 40, 0, 0)); + modules.add(new ModuleContainerPanYOnly(8, 17, panModules, new LinkedList<>(), null, 65, 45, 0, 0)); //Fuel modules.add(new ModuleProgress(192, 7, 0, new ProgressBarImage(2, 173, 12, 71, 17, 6, 3, 69, 1, 1, EnumFacing.UP, TextureResources.rocketHud), this)); @@ -2214,14 +2458,13 @@ public float getNormallizedProgress(int id) { if (id == 0 && fuelType != null) { switch (fuelType) { case LIQUID_BIPROPELLANT: - return (getFuelAmount(FuelType.LIQUID_OXIDIZER) / (float) getFuelCapacity(FuelType.LIQUID_OXIDIZER) + - getFuelAmount(fuelType)) / (float) getFuelCapacity(fuelType); case LIQUID_MONOPROPELLANT: case NUCLEAR_WORKING_FLUID: return getFuelAmount(fuelType) / (float) getFuelCapacity(fuelType); } } + return 0; } @@ -2275,7 +2518,7 @@ public void onInventoryButtonPressed(int buttonId) { @Override public boolean canInteractWithContainer(EntityPlayer entity) { - boolean ret = !this.isDead && this.getDistanceToEntity(entity) < 64; + boolean ret = !this.isDead && this.getDistance(entity) < 64; if (!ret) RocketInventoryHelper.removePlayerFromInventoryBypass(entity); diff --git a/src/main/java/zmaster587/advancedRocketry/entity/fx/InverseTrailFx.java b/src/main/java/zmaster587/advancedRocketry/entity/fx/InverseTrailFx.java index e77ed229b..a37ad655c 100644 --- a/src/main/java/zmaster587/advancedRocketry/entity/fx/InverseTrailFx.java +++ b/src/main/java/zmaster587/advancedRocketry/entity/fx/InverseTrailFx.java @@ -3,12 +3,17 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.particle.Particle; import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.entity.Entity; import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import org.lwjgl.opengl.GL11; +import zmaster587.advancedRocketry.client.render.DelayedParticleRenderingEventHandler; +import zmaster587.advancedRocketry.event.RocketEventHandler; + +import java.util.List; public class InverseTrailFx extends Particle { protected ResourceLocation icon; @@ -18,6 +23,8 @@ public InverseTrailFx(World world, double x, double y, double z, double motx, double moty, double motz) { super(world, x, y, z, motx, moty, motz); + DelayedParticleRenderingEventHandler.TrailFxParticles.add(this); + float chroma = this.rand.nextFloat() * 0.2f; this.particleRed = .8F + chroma; this.particleGreen = .8F + chroma; @@ -29,6 +36,7 @@ public InverseTrailFx(World world, double x, this.motionY = -moty; this.motionZ = -motz; + this.particleAlpha = 0; icon = new ResourceLocation("advancedrocketry:textures/particle/soft.png"); @@ -37,46 +45,93 @@ public InverseTrailFx(World world, double x, this.prevPosZ = this.posZ = z + motz * this.particleMaxAge; } + float partialTicks; + float rotationX; + float rotationZ; + float rotationYZ; + float rotationXY; + float rotationXZ; + + @Override public void renderParticle(BufferBuilder worldRendererIn, Entity entityIn, - float partialTicks, float rotationX, float rotationZ, - float rotationYZ, float rotationXY, float rotationXZ) { - //super.renderParticle(worldRendererIn, entityIn, partialTicks, rotationX, - //rotationZ, rotationYZ, rotationXY, rotationXZ); + float partialTicks, float rotationX, float rotationZ, + float rotationYZ, float rotationXY, float rotationXZ) { + + this. partialTicks = partialTicks; + this. rotationX = rotationX; + this. rotationZ = rotationZ; + this. rotationYZ = rotationYZ; + this. rotationXY = rotationXY; + this. rotationXZ = rotationXZ; + + } + + public void renderParticle2(BufferBuilder worldRendererIn) { + + float f11 = (float) (this.prevPosX + (this.posX - this.prevPosX) * (double) partialTicks - interpPosX); float f12 = (float) (this.prevPosY + (this.posY - this.prevPosY) * (double) partialTicks - interpPosY); float f13 = (float) (this.prevPosZ + (this.posZ - this.prevPosZ) * (double) partialTicks - interpPosZ); float f10 = 0.25F * this.particleScale; - int i = this.getBrightnessForRender(partialTicks); + int i = (240+this.getBrightnessForRender(partialTicks))/2; int j = i >> 16 & 65535; int k = i & 65535; + Minecraft.getMinecraft().getTextureManager().bindTexture(icon); - worldRendererIn.finishDrawing(); - worldRendererIn.begin(GL11.GL_QUADS, DefaultVertexFormats.PARTICLE_POSITION_TEX_COLOR_LMAP); - worldRendererIn.pos(f11 - rotationX * f10 - rotationXY * f10, f12 - rotationZ * f10, f13 - rotationYZ * f10 - rotationXZ * f10).tex(1, 1).color(this.particleRed, this.particleGreen, this.particleBlue, 1f).lightmap(j, k).endVertex(); - worldRendererIn.pos(f11 - rotationX * f10 + rotationXY * f10, f12 + rotationZ * f10, f13 - rotationYZ * f10 + rotationXZ * f10).tex(1, 0).color(this.particleRed, this.particleGreen, this.particleBlue, 1f).lightmap(j, k).endVertex(); - worldRendererIn.pos(f11 + rotationX * f10 + rotationXY * f10, f12 + rotationZ * f10, f13 + rotationYZ * f10 + rotationXZ * f10).tex(0, 0).color(this.particleRed, this.particleGreen, this.particleBlue, 1f).lightmap(j, k).endVertex(); - worldRendererIn.pos(f11 + rotationX * f10 - rotationXY * f10, f12 - rotationZ * f10, f13 + rotationYZ * f10 - rotationXZ * f10).tex(0, 1).color(this.particleRed, this.particleGreen, this.particleBlue, 1f).lightmap(j, k).endVertex(); - Tessellator.getInstance().draw(); - worldRendererIn.begin(GL11.GL_QUADS, DefaultVertexFormats.PARTICLE_POSITION_TEX_COLOR_LMAP); + + worldRendererIn.pos(f11 - rotationX * f10 - rotationXY * f10, f12 - rotationZ * f10, f13 - rotationYZ * f10 - rotationXZ * f10).tex(1, 1).color(this.particleRed, this.particleGreen, this.particleBlue, this.particleAlpha).lightmap(j, k).endVertex(); + worldRendererIn.pos(f11 - rotationX * f10 + rotationXY * f10, f12 + rotationZ * f10, f13 - rotationYZ * f10 + rotationXZ * f10).tex(1, 0).color(this.particleRed, this.particleGreen, this.particleBlue, this.particleAlpha).lightmap(j, k).endVertex(); + worldRendererIn.pos(f11 + rotationX * f10 + rotationXY * f10, f12 + rotationZ * f10, f13 + rotationYZ * f10 + rotationXZ * f10).tex(0, 0).color(this.particleRed, this.particleGreen, this.particleBlue, this.particleAlpha).lightmap(j, k).endVertex(); + worldRendererIn.pos(f11 + rotationX * f10 - rotationXY * f10, f12 - rotationZ * f10, f13 + rotationYZ * f10 - rotationXZ * f10).tex(0, 1).color(this.particleRed, this.particleGreen, this.particleBlue, this.particleAlpha).lightmap(j, k).endVertex(); + + } @Override public int getFXLayer() { - return 2; + return 0; } + @Override public boolean shouldDisableDepth() { return true; } + public static void renderAll(List TrailFxParticles){ + // Get the BufferBuilder for rendering + BufferBuilder buffer = Tessellator.getInstance().getBuffer(); + + GlStateManager.disableAlpha(); // Ensure alpha test is disabled + + GlStateManager.depthMask(false); + GlStateManager.enableBlend(); + GlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); + //GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE); + + buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.PARTICLE_POSITION_TEX_COLOR_LMAP); + + // Render custom particles + for (InverseTrailFx particle : TrailFxParticles) { + particle.renderParticle2(buffer); + } + + Tessellator.getInstance().draw(); + GlStateManager.enableDepth(); + GlStateManager.depthMask(true); + GlStateManager.enableAlpha(); + } + @Override public void onUpdate() { + + } + public void onUpdate2() { this.prevPosX = this.posX; this.prevPosY = this.posY; this.prevPosZ = this.posZ; diff --git a/src/main/java/zmaster587/advancedRocketry/entity/fx/RocketFx.java b/src/main/java/zmaster587/advancedRocketry/entity/fx/RocketFx.java index d582e217e..25d94d7c1 100644 --- a/src/main/java/zmaster587/advancedRocketry/entity/fx/RocketFx.java +++ b/src/main/java/zmaster587/advancedRocketry/entity/fx/RocketFx.java @@ -4,35 +4,61 @@ import net.minecraft.client.particle.Particle; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.entity.Entity; +import net.minecraft.init.Blocks; import net.minecraft.util.ResourceLocation; +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.client.event.RenderWorldLastEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import org.lwjgl.opengl.GL11; +import zmaster587.advancedRocketry.client.render.DelayedParticleRenderingEventHandler; +import zmaster587.advancedRocketry.event.RocketEventHandler; + +import java.util.List; + +import static java.lang.Math.min; public class RocketFx extends Particle { - public static final ResourceLocation icon = new ResourceLocation("advancedrocketry:textures/particle/soft.png"); + public static final ResourceLocation icon = new ResourceLocation("advancedrocketry:textures/particle/soft2.png"); + + float alpha = 0.45f; + + + float max_lt_increase = 20.0f; + int max_engines_for_calculation = 32; + //increase x-z motion + public void register_additional_engines(int n){ + float enginepx = min(1,n/(float)max_engines_for_calculation); + this.particleMaxAge += (int) (enginepx * max_lt_increase *(rand.nextFloat())); + //System.out.println("px:"+enginepx+":"+n); + } public RocketFx(World world, double x, double y, double z, double motx, double moty, double motz, float scale) { super(world, x, y, z, motx, moty, motz); + DelayedParticleRenderingEventHandler.RocketFxParticles.add(this); + this.prevPosX = this.posX = x; this.prevPosY = this.posY = y; this.prevPosZ = this.posZ = z; - + this.particleAlpha = alpha; this.particleRed = 0.9F + this.rand.nextFloat() / 10f; - this.particleGreen = 0.6F + this.rand.nextFloat() / 5f; - this.particleBlue = 0.0F; + this.particleGreen = 0.8F + this.rand.nextFloat() / 5f; + this.particleBlue = 0.6F; this.setSize(0.12F * scale, 0.12F * scale); this.particleScale *= (this.rand.nextFloat() * 0.6F + 6F) * scale; this.motionX = motx; this.motionY = moty; this.motionZ = motz; - this.particleMaxAge = (int) (8.0D / (Math.random() * 0.8D + 0.6D)); + this.particleMaxAge = (int) ((int) (8.0D / (Math.random() * 0.8D + 0.6D))*1.0); } public RocketFx(World world, double x, @@ -45,10 +71,31 @@ public int getFXLayer() { return 0; } + float partialTicks; + float rotationX; + float rotationZ; + float rotationYZ; + float rotationXY; + float rotationXZ; + + @Override public void renderParticle(BufferBuilder worldRendererIn, Entity entityIn, float partialTicks, float rotationX, float rotationZ, float rotationYZ, float rotationXY, float rotationXZ) { + + this. partialTicks = partialTicks; + this. rotationX = rotationX; + this. rotationZ = rotationZ; + this. rotationYZ = rotationYZ; + this. rotationXY = rotationXY; + this. rotationXZ = rotationXZ; + + } + + public void renderParticle2(BufferBuilder worldRendererIn) { + + float f; float f1; float f2; @@ -58,7 +105,7 @@ public void renderParticle(BufferBuilder worldRendererIn, Entity entityIn, float f5 = (float) (this.prevPosX + (this.posX - this.prevPosX) * (double) partialTicks - interpPosX); float f6 = (float) (this.prevPosY + (this.posY - this.prevPosY) * (double) partialTicks - interpPosY); float f7 = (float) (this.prevPosZ + (this.posZ - this.prevPosZ) * (double) partialTicks - interpPosZ); - int i = this.getBrightnessForRender(partialTicks); + int i = (240+this.getBrightnessForRender(partialTicks))/2; int j = i >> 16 & 65535; int k = i & 65535; Vec3d[] avec3d = new Vec3d[]{new Vec3d(-rotationX * f4 - rotationXY * f4, -rotationZ * f4, -rotationYZ * f4 - rotationXZ * f4), new Vec3d(-rotationX * f4 + rotationXY * f4, rotationZ * f4, -rotationYZ * f4 + rotationXZ * f4), new Vec3d(rotationX * f4 + rotationXY * f4, rotationZ * f4, rotationYZ * f4 + rotationXZ * f4), new Vec3d(rotationX * f4 - rotationXY * f4, -rotationZ * f4, rotationYZ * f4 - rotationXZ * f4)}; @@ -77,7 +124,8 @@ public void renderParticle(BufferBuilder worldRendererIn, Entity entityIn, } - GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE); + + Minecraft.getMinecraft().renderEngine.bindTexture(icon); f = 0f; f1 = 1f; @@ -89,7 +137,32 @@ public void renderParticle(BufferBuilder worldRendererIn, Entity entityIn, worldRendererIn.pos((double) f5 + avec3d[2].x, (double) f6 + avec3d[2].y, (double) f7 + avec3d[2].z).tex(f, f2).color(this.particleRed, this.particleGreen, this.particleBlue, this.particleAlpha).lightmap(j, k).endVertex(); worldRendererIn.pos((double) f5 + avec3d[3].x, (double) f6 + avec3d[3].y, (double) f7 + avec3d[3].z).tex(f, f3).color(this.particleRed, this.particleGreen, this.particleBlue, this.particleAlpha).lightmap(j, k).endVertex(); + + + } + + public static void renderAll(List RocketFxParticles){ + // Get the BufferBuilder for rendering + BufferBuilder buffer = Tessellator.getInstance().getBuffer(); + + GlStateManager.disableAlpha(); // Ensure alpha test is disabled + + GlStateManager.depthMask(false); + GlStateManager.enableBlend(); GlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); + //GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE); + + buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.PARTICLE_POSITION_TEX_COLOR_LMAP); + + // Render custom particles + for (RocketFx particle : RocketFxParticles) { + particle.renderParticle2(buffer); + } + + Tessellator.getInstance().draw(); + GlStateManager.enableDepth(); + GlStateManager.depthMask(true); + GlStateManager.enableAlpha(); } public boolean shouldDisableDepth() { @@ -98,18 +171,43 @@ public boolean shouldDisableDepth() { @Override public void onUpdate() { + } + + public void onUpdate2() { this.prevPosX = this.posX; this.prevPosY = this.posY; this.prevPosZ = this.posZ; //Change color and alpha over lifespan - this.particleAlpha = 1 - this.particleAge / (float) this.particleMaxAge; - this.particleGreen -= this.particleGreen * this.particleAge / ((float) this.particleMaxAge * 2); + this.particleAlpha = alpha-alpha*(this.particleAge / (float) this.particleMaxAge); //1 - (this.particleAge / (float) this.particleMaxAge); + this.particleGreen -= 0.6f / ((float) this.particleMaxAge); + this.particleBlue -= 0.6f / ((float) this.particleMaxAge); if (this.particleAge++ >= this.particleMaxAge) { this.setExpired(); } - this.setPosition(posX + this.motionX, posY + this.motionY, posZ + this.motionZ); + + int ch = world.getHeight((int) this.posX, (int) this.posZ); + if (this.posY < ch -0.8) { + this.motionY = 0; + //this.posY = ch -0.8 ; + + for (int i = 0; i < 3; i++) { + BlockPos p = new BlockPos(posX,posY+i,posZ); + if (world.getBlockState(p).equals(Blocks.AIR.getDefaultState())){ + this.posY = p.getY()-0.8; + break; + } + } + + this.motionX = (world.rand.nextFloat() - 0.5) / 2; + this.motionZ = (world.rand.nextFloat() - 0.5) / 2; + this.motionY = (world.rand.nextFloat()) / 6; + this.setPosition(posX + this.motionX, posY + this.motionY, posZ + this.motionZ); + + + } + } } diff --git a/src/main/java/zmaster587/advancedRocketry/entity/fx/TrailFx.java b/src/main/java/zmaster587/advancedRocketry/entity/fx/TrailFx.java index cf7f5c6d6..183eabde8 100644 --- a/src/main/java/zmaster587/advancedRocketry/entity/fx/TrailFx.java +++ b/src/main/java/zmaster587/advancedRocketry/entity/fx/TrailFx.java @@ -1,29 +1,52 @@ package zmaster587.advancedRocketry.entity.fx; +import net.minecraft.init.Blocks; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import zmaster587.advancedRocketry.client.render.DelayedParticleRenderingEventHandler; +import zmaster587.advancedRocketry.event.RocketEventHandler; + +import static java.lang.Math.min; +import static java.lang.Math.sqrt; public class TrailFx extends InverseTrailFx { - //public static final ResourceLocation icon = new ResourceLocation("advancedrocketry:textures/particle/soft.png"); + float max_speed_increase = 2f; + float current_speed_increase = 1.0f; + int max_engines_for_calculation = 64; + + //increase motion, increase particle size + public void register_additional_engines(int n){ + float enginepx = min(1,n/(float)max_engines_for_calculation); + float d = max_speed_increase - current_speed_increase; + current_speed_increase = current_speed_increase+d*enginepx; + particleScale*=1+(enginepx*1.5f); + } public TrailFx(World world, double x, double y, double z, double motx, double moty, double motz) { super(world, x, y, z, motx, moty, motz); + //DelayedParticleRenderingEventHandler.fxManager.addParticle(this); + this.prevPosX = this.posX = x; this.prevPosY = this.posY = y; this.prevPosZ = this.posZ = z; float chroma = this.rand.nextFloat() * 0.2f; - this.particleRed = .4F + chroma; - this.particleGreen = .4F + chroma; - this.particleBlue = .4F + chroma; + this.particleRed = .8F + chroma; + this.particleGreen = .8F + chroma; + this.particleBlue = .8F + chroma; + this.particleAlpha = 0.0f; this.setSize(0.12F, 0.12F); - this.particleScale = this.rand.nextFloat() * 0.6F + 6F; + this.particleScale = (this.rand.nextFloat() * 0.6F + 6F)*0.6f; this.motionX = motx; this.motionY = moty; this.motionZ = motz; - this.particleMaxAge = (int) (1000.0D); + this.particleMaxAge = (int) world.rand.nextInt(400) + 50; + + icon = new ResourceLocation("advancedrocketry:textures/particle/soft1.png"); } @Override @@ -31,24 +54,64 @@ public int getFXLayer() { return 0; } + @Override public boolean shouldDisableDepth() { return true; } @Override public void onUpdate() { + + } + public void onUpdate2() { this.prevPosX = this.posX; this.prevPosY = this.posY; this.prevPosZ = this.posZ; //Change color and alpha over lifespan - this.particleAlpha = 1 - this.particleAge / (float) this.particleMaxAge; - this.particleScale *= 1.002f; + this.particleAlpha = min(1 - (this.particleAge / (float) this.particleMaxAge), particleAge/10f)*0.8f; + double initial_expansion = 1.003; + double final_expansion = 1.001; + double current_expansion = initial_expansion - (initial_expansion - final_expansion) * (this.particleAge / (float) this.particleMaxAge); + this.particleScale *= (float) current_expansion; if (this.particleAge++ >= this.particleMaxAge) { this.setExpired(); } + int ch = world.getHeight((int) this.posX, (int) this.posZ); + if (this.posY+0.0001 < ch) { + this.motionY = 0; + + for (int i = 1; i < 3; i++) { + if (world.getBlockState(new BlockPos(posX,posY+i,posZ)).equals(Blocks.AIR.getDefaultState())){ + this.posY = (int)(posY+i); + break; + } + } + + + this.motionX = (world.rand.nextFloat() - 0.5); + this.motionZ = (world.rand.nextFloat() - 0.5); + float speed = world.rand.nextFloat() / 20f+0.01f; + double l = sqrt(motionX*motionX+motionZ*motionZ); + motionX *= speed/l; + motionZ *= speed/l; + motionY = world.rand.nextFloat() / 60f; + + + } + if (this.motionY < 0) { + //fast slowdown when near ground AND moving lower + if (this.posY - ch < 10) { + this.motionY *= 0.99; + } + } + this.motionY *= 1-(0.02/(current_speed_increase)); + this.motionY += 0.0005; + + //this.motionX *= 1-(0.02/(current_speed_increase)); + //this.motionZ *= 1-(0.02/(current_speed_increase)); - this.setPosition(posX + this.motionX, posY + this.motionY, posZ + this.motionZ); + this.setPosition(posX + this.motionX*current_speed_increase, posY + this.motionY*current_speed_increase, posZ + this.motionZ*current_speed_increase); } } diff --git a/src/main/java/zmaster587/advancedRocketry/event/EntityEventHandler.java b/src/main/java/zmaster587/advancedRocketry/event/EntityEventHandler.java new file mode 100644 index 000000000..edf310199 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/event/EntityEventHandler.java @@ -0,0 +1,52 @@ +package zmaster587.advancedRocketry.event; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.network.play.server.SPacketChangeGameState; +import net.minecraft.world.World; +import net.minecraftforge.event.entity.EntityJoinWorldEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.PlayerEvent; + +public class EntityEventHandler { + + @SubscribeEvent + public void onJoinWorld(EntityJoinWorldEvent event) { + if (event.getEntity() instanceof EntityPlayer && !event.getWorld().isRemote) { + EntityPlayerMP player = (EntityPlayerMP) event.getEntity(); + World world = event.getWorld(); +// if (world.isRaining()) { +// player.connection.sendPacket(new SPacketChangeGameState(2, )); +// } + if (world.isRaining()) { + player.connection.sendPacket(new SPacketChangeGameState(1, 0.0F)); + player.connection.sendPacket(new SPacketChangeGameState(7, world.getRainStrength(1.0F))); + player.connection.sendPacket(new SPacketChangeGameState(8, world.getThunderStrength(1.0F))); + } else { + player.connection.sendPacket(new SPacketChangeGameState(2, 0.0F)); + player.connection.sendPacket(new SPacketChangeGameState(7, 0.0F)); + player.connection.sendPacket(new SPacketChangeGameState(8, 0.0F)); + } + } + } + + @SubscribeEvent + public void onPlayerChangedDimension(PlayerEvent.PlayerChangedDimensionEvent event) { + if (!event.player.world.isRemote) { + EntityPlayerMP player = (EntityPlayerMP) event.player; + World world = player.world; +// if (world.isRaining()) { +// player.connection.sendPacket(new SPacketChangeGameState(2, )); +// } + if (world.isRaining()) { + player.connection.sendPacket(new SPacketChangeGameState(1, 0.0F)); + player.connection.sendPacket(new SPacketChangeGameState(7, world.getRainStrength(1.0F))); + player.connection.sendPacket(new SPacketChangeGameState(8, world.getThunderStrength(1.0F))); + } else { + player.connection.sendPacket(new SPacketChangeGameState(2, 0.0F)); + player.connection.sendPacket(new SPacketChangeGameState(7, 0.0F)); + player.connection.sendPacket(new SPacketChangeGameState(8, 0.0F)); + } + } + } +} diff --git a/src/main/java/zmaster587/advancedRocketry/event/PlanetEventHandler.java b/src/main/java/zmaster587/advancedRocketry/event/PlanetEventHandler.java index 2af5c00a3..29d7cd5e1 100644 --- a/src/main/java/zmaster587/advancedRocketry/event/PlanetEventHandler.java +++ b/src/main/java/zmaster587/advancedRocketry/event/PlanetEventHandler.java @@ -190,10 +190,11 @@ public void onWorldGen(OreGenEvent.GenerateMinable event) { //Handle gravity @SubscribeEvent public void playerTick(LivingUpdateEvent event) { - +/* if (event.getEntity().world.isRemote && event.getEntity().posY > 260 && event.getEntity().posY < 270 && event.getEntity().motionY < -.1) { RocketEventHandler.destroyOrbitalTextures(event.getEntity().world); } + */ if (event.getEntity().isInWater()) { if (AtmosphereType.LOWOXYGEN.isImmune(event.getEntityLiving())) event.getEntity().setAir(300); diff --git a/src/main/java/zmaster587/advancedRocketry/event/RocketEventHandler.java b/src/main/java/zmaster587/advancedRocketry/event/RocketEventHandler.java index 93df51a90..a28d54afe 100644 --- a/src/main/java/zmaster587/advancedRocketry/event/RocketEventHandler.java +++ b/src/main/java/zmaster587/advancedRocketry/event/RocketEventHandler.java @@ -1,4 +1,7 @@ package zmaster587.advancedRocketry.event; +// This code does not work - it should display the earth below rockets at start but it does not. +// The detailed map is scaled too small and it is ugly even with correct scale +// maybe just use leo as earth? import net.minecraft.block.material.MapColor; import net.minecraft.block.state.IBlockState; @@ -24,6 +27,7 @@ import net.minecraftforge.client.IRenderHandler; import net.minecraftforge.client.event.RenderGameOverlayEvent; import net.minecraftforge.client.event.RenderGameOverlayEvent.ElementType; +import net.minecraftforge.client.event.RenderWorldLastEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.PlayerEvent; import net.minecraftforge.fml.relauncher.Side; @@ -53,6 +57,7 @@ public class RocketEventHandler extends Gui { + private static final int getImgSize = 512; private static final int outerImgSize = getImgSize / 8; private static final int numTicksToDisplay = 100; @@ -78,259 +83,12 @@ public static void setOverlay(long endTime, String msg) { lastDisplayTime = endTime; } - @SideOnly(Side.CLIENT) - public static void destroyOrbitalTextures(World world) { - if (!ARConfiguration.getCurrentConfig().skyOverride && !(world.provider instanceof IPlanetaryProvider)) { - world.provider.setSkyRenderer(prevRenderHanlder); - prevRenderHanlder = null; - } - - if (earth != null) - GL11.glDeleteTextures(earth.getTextureId()); - if (outerBounds != null) - GL11.glDeleteTextures(outerBounds.getTextureId()); - outerBounds = null; - earth = null; - mapReady = false; - } - - //@SubscribeEvent - public static void onPostWorldRender(float partialTicks) { - - if (!mapReady) - return; - - - if (mapNeedsBinding) { - mapNeedsBinding = false; - earth.setByteBuffer(table); - outerBounds.setByteBuffer(outerBoundsTable); - } - - GL11.glPushMatrix(); - GL11.glTranslatef(0, -5, 0); - GL11.glPushAttrib(GL11.GL_ALPHA_TEST_FUNC); - GlStateManager.enableBlend(); - GlStateManager.disableFog(); - GlStateManager.alphaFunc(GL11.GL_GREATER, .01f); - GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - - float brightness = 16; - - if (Minecraft.getMinecraft().getRenderViewEntity() != null && Minecraft.getMinecraft().getRenderViewEntity().world != null) - brightness = Minecraft.getMinecraft().getRenderViewEntity().world.getSunBrightness(partialTicks); - - double deltaY = (Minecraft.getMinecraft().getRenderViewEntity().posY - Minecraft.getMinecraft().getRenderViewEntity().lastTickPosY) * partialTicks; - double size = (getImgSize / (5 * Minecraft.getMinecraft().getRenderViewEntity().posY * (1000f / ARConfiguration.getCurrentConfig().orbit))); - - - BufferBuilder buffer = Tessellator.getInstance().getBuffer(); - - //Less detailed land - - buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); - GlStateManager.bindTexture(outerBounds.getTextureId()); - double size2 = size * 400; - float brightness2 = brightness * .43f; - GlStateManager.color(brightness2, brightness2, brightness2, MathHelper.clamp(((float) Minecraft.getMinecraft().getRenderViewEntity().posY - 200f) / 50f, 0f, 1f)); - RenderHelper.renderTopFaceWithUV(buffer, -10.1, size2, size2, -size2, -size2, 0, 1, 0, 1); - Tessellator.getInstance().draw(); - - - buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); - GlStateManager.bindTexture(earth.getTextureId()); - - float opacityFromHeight = MathHelper.clamp(((float) Minecraft.getMinecraft().getRenderViewEntity().posY - 200f) / 100f, 0f, 1f); - - //Detailed Land - GlStateManager.color(brightness2, brightness2, brightness2, MathHelper.clamp(((float) Minecraft.getMinecraft().getRenderViewEntity().posY - 200f) / 50f, 0f, 1f)); - RenderHelper.renderTopFaceWithUV(buffer, -10, -size, -size, size, size, 0f, 1f, 0f, 1f); - - Tessellator.getInstance().draw(); - - //AtmosphereGlow - Vec3d skyColor = Minecraft.getMinecraft().getRenderViewEntity().world.provider.getSkyColor(Minecraft.getMinecraft().getRenderViewEntity(), partialTicks); - - GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - GlStateManager.disableTexture2D(); - GlStateManager.bindTexture(0); - - buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_NORMAL); - GlStateManager.color((float) skyColor.x, (float) skyColor.y, (float) skyColor.z, 0.05f); - - size = (getImgSize * 100 / (180 - Minecraft.getMinecraft().getRenderViewEntity().posY - deltaY)); - - - for (int i = 0; i < 5 * MathHelper.clamp(((DimensionManager.getInstance().getDimensionProperties(Minecraft.getMinecraft().getRenderViewEntity().world.provider.getDimension()).getAtmosphereDensity() * .01f * (float) Minecraft.getMinecraft().getRenderViewEntity().posY - 280f)) / 150f, 0f, 2f); i++) { - RenderHelper.renderTopFace(buffer, -9 + i * .6, size, size, -size, -size); - } - - // - GlStateManager.enableTexture2D(); - - Tessellator.getInstance().draw(); - GlStateManager.disableBlend(); - GlStateManager.enableFog(); - GL11.glPopAttrib(); - GL11.glPopMatrix(); - GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - } - - @SubscribeEvent - public void onRocketDeorbit(RocketEvent.RocketDeOrbitingEvent event) { - if (event.world.isRemote) { - prepareOrbitalMap(event); - - //Sky blend color gets stuck and doesnt update unless a new X/Z coord is passed - //So fix that... - ForgeHooksClient.getSkyBlendColour(event.world, event.getEntity().getPosition()); - - if (ARConfiguration.getCurrentConfig().planetSkyOverride && !DimensionManager.getInstance().getDimensionProperties(event.world.provider.getDimension()).skyRenderOverride && !(event.world.provider instanceof IPlanetaryProvider)) { - prevRenderHanlder = event.world.provider.getSkyRenderer(); - event.world.provider.setSkyRenderer(new RenderPlanetarySky()); - } - } - } - @SubscribeEvent public void playerTeleportEvent(PlayerEvent.PlayerChangedDimensionEvent event) { //Fix O2, space elevator popup displaying after teleporting lastDisplayTime = -1000; } - @SubscribeEvent - public void onRocketLaunch(RocketEvent.RocketLaunchEvent event) { - if (ARConfiguration.getCurrentConfig().planetSkyOverride && !DimensionManager.getInstance().getDimensionProperties(event.world.provider.getDimension()).skyRenderOverride && event.world.isRemote && !event.getEntity().getPassengers().isEmpty() && event.getEntity().getPassengers().contains(Minecraft.getMinecraft().player)) { - prepareOrbitalMap(event); - prevRenderHanlder = event.world.provider.getSkyRenderer(); - event.world.provider.setSkyRenderer(new RenderPlanetarySky()); - } - } - - @SideOnly(Side.CLIENT) - private void prepareOrbitalMap(RocketEvent event) { - mapReady = false; - - //Attempt to generate everything on seperate thread - if (earth == null) { - earth = new ClientDynamicTexture(getImgSize, getImgSize); - outerBounds = new ClientDynamicTexture(outerImgSize, outerImgSize); - } - - if (event.world.provider.getDimension() == ARConfiguration.getCurrentConfig().spaceDimId) { - destroyOrbitalTextures(event.world); - return; - } - - //Multi thread texture creation b/c it can be expensive - final World worldObj = event.world; - final Entity entity = event.getEntity(); - - if (thread == null || !thread.isAlive()) { - - thread = new Thread(() -> { - - int numChunksLoaded = 0; - - table = earth.getByteBuffer(); - outerBoundsTable = outerBounds.getByteBuffer(); - - //Get the average of each edge RGB - long[] total = new long[]{0, 0, 0}; - - - do { - for (int i = 0; i < getImgSize * getImgSize; i++) { - //TODO: Optimize - int xOffset = (i % getImgSize); - int yOffset = (i / getImgSize); - - int xPosition = (int) entity.posX - (getImgSize / 2) + xOffset; - int zPosition = (int) entity.posZ - (getImgSize / 2) + yOffset; - BlockPos thisPos = new BlockPos(xPosition, 0, zPosition); - Chunk chunk = worldObj.getChunkFromBlockCoords(thisPos); - - if (chunk.isLoaded() && !chunk.isEmpty()) { - //Get Xcoord and ZCoords in the chunk - numChunksLoaded++; - int heightValue = chunk.getHeightValue(xPosition + (chunk.x >= 0 ? -(Math.abs(chunk.x) << 4) : (Math.abs(chunk.x) << 4)), zPosition + (chunk.z >= 0 ? -(Math.abs(chunk.z) << 4) : (Math.abs(chunk.z) << 4))); - MapColor color = MapColor.AIR; - int yPosition; - - IBlockState block = null; - - //Get the first non-air block - for (yPosition = heightValue; yPosition > 0; yPosition--) { - block = worldObj.getBlockState(new BlockPos(xPosition, yPosition, zPosition)); - if ((color = block.getMapColor(worldObj, thisPos)) != MapColor.AIR) { - break; - } - } - if (block == null) - continue; - - int intColor; - - if (block.getBlock() == Blocks.GRASS || block.getBlock() == Blocks.TALLGRASS) { - int color2 = worldObj.getBiome(thisPos).getGrassColorAtPos(thisPos.add(0, yPosition, 0)); - int r = (color2 & 0xFF); - int g = ((color2 >>> 8) & 0xFF); - int b = ((color2 >>> 16) & 0xFF); - intColor = b | (g << 8) | (r << 16); - } else if (block.getBlock() == Blocks.LEAVES || block.getBlock() == Blocks.LEAVES2) { - int color2 = worldObj.getBiome(thisPos).getFoliageColorAtPos(thisPos.add(0, yPosition, 0)); - int r = (color2 & 0xFF); - int g = ((color2 >>> 8) & 0xFF); - int b = ((color2 >>> 16) & 0xFF); - intColor = b | (g << 8) | (r << 16); - } else - intColor = ((color.colorValue & 0xFF) << 16) | ((color.colorValue >>> 16) & 0xFF) | (color.colorValue & 0xFF00); - - //Put into the table and make opaque - table.put(i, intColor | 0xFF000000); - - //Background in case chunk doesnt load - total[0] += intColor & 0xFF; - total[1] += (intColor & 0xFF00) >>> 8; - total[2] += (intColor & 0xFF0000) >>> 16; - - } - } - } while (numChunksLoaded == 0); - - int multiplierGreen = 1; - int multiplierBlue = 1; - - //Get the outer layer - total[0] = ZUtils.getAverageColor(total[0], total[1] * multiplierGreen, total[2] * multiplierBlue, numChunksLoaded); - - Random random = new Random(); - - int randomMax = 0x2A; - - for (int i = 0; i < outerImgSize * outerImgSize; i++) { - - int randR = randomMax - random.nextInt(randomMax) / 2; - int randG = (randomMax - random.nextInt(randomMax) / 2) << 8; - int randB = (randomMax - random.nextInt(randomMax) / 2) << 16; - - - int color = MathHelper.clamp((int) ((total[0] & 0xFF) + randR), 0, 0xFF) | - MathHelper.clamp((int) (total[0] & 0xFF00) + randG, 0x0100, 0xFF00) | - MathHelper.clamp((int) ((total[0] & 0xFF0000) + randB), 0x010000, 0xFF0000); - - outerBoundsTable.put(i, color | 0xff000000); - } - - outerBoundsTable.flip(); - table.flip(); //Yes really - mapNeedsBinding = true; - mapReady = true; - }, "Planet Texture Creator"); - thread.start(); - } - } - @SubscribeEvent public void onScreenRender(RenderGameOverlayEvent.Post event) { Entity ride; diff --git a/src/main/java/zmaster587/advancedRocketry/integrated_server_and_client_variable_sharing_fix/Afuckinginterface.java b/src/main/java/zmaster587/advancedRocketry/integrated_server_and_client_variable_sharing_fix/Afuckinginterface.java new file mode 100644 index 000000000..9d89e925e --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/integrated_server_and_client_variable_sharing_fix/Afuckinginterface.java @@ -0,0 +1,35 @@ +package zmaster587.advancedRocketry.integrated_server_and_client_variable_sharing_fix; + + +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import zmaster587.advancedRocketry.util.TerraformingHelper; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; + +public interface Afuckinginterface { + + public void initdim(int dim); + + public boolean isinitialized(int dim); + + public List getProtectingBlocksForDimension(int dim); + + public void setProtectingBlocksForDimension(int dim, ArrayList blocks); + + public void setChunksFullyTerraformed(int dim, HashSet lpos); + + public HashSet getChunksFullyTerraformed(int dim); + + + public void setChunksFullyBiomeChanged(int dim, HashSet lpos); + + public HashSet getChunksFullyBiomeChanged(int dim); + + public void sethelper(int dim, TerraformingHelper helper); + + public TerraformingHelper gethelper(int dim); + +} diff --git a/src/main/java/zmaster587/advancedRocketry/integrated_server_and_client_variable_sharing_fix/clientlists.java b/src/main/java/zmaster587/advancedRocketry/integrated_server_and_client_variable_sharing_fix/clientlists.java new file mode 100644 index 000000000..4b13ed57c --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/integrated_server_and_client_variable_sharing_fix/clientlists.java @@ -0,0 +1,67 @@ +package zmaster587.advancedRocketry.integrated_server_and_client_variable_sharing_fix; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import zmaster587.advancedRocketry.util.TerraformingHelper; + +import java.util.*; + +public class clientlists implements Afuckinginterface { + Map terraforminginfolists; + + public clientlists(){ + this.terraforminginfolists = new HashMap<>(); + } + + public void initdim(int dim){ + if (terraforminginfolists.get(dim) != null){ + terraforminginfolists.get(dim).terraformingChunksDone = new HashSet<>(); + terraforminginfolists.get(dim).biomeChangingChunksDone = new HashSet<>(); + terraforminginfolists.get(dim).terraformingProtectedBlocks = new ArrayList<>(); + }else{ + dimensionTerraformingInfo info = new dimensionTerraformingInfo(); + info.terraformingChunksDone = new HashSet<>(); + info.biomeChangingChunksDone = new HashSet<>(); + info.terraformingProtectedBlocks = new ArrayList<>(); + terraforminginfolists.put(dim,info); + } + } + public boolean isinitialized(int dim){ + return (terraforminginfolists.get(dim) != null); + } + public List getProtectingBlocksForDimension(int dim){ + if (terraforminginfolists.get(dim) == null)return null; + return terraforminginfolists.get(dim).terraformingProtectedBlocks; + } + public void setProtectingBlocksForDimension(int dim, ArrayList blocks){ + if (terraforminginfolists.get(dim) == null)return; + terraforminginfolists.get(dim).terraformingProtectedBlocks = blocks; + } + + public void setChunksFullyTerraformed(int dim, HashSet lpos){ + if (terraforminginfolists.get(dim) == null)return; + terraforminginfolists.get(dim).terraformingChunksDone = lpos; + } + public HashSet getChunksFullyTerraformed(int dim){ + if (terraforminginfolists.get(dim) == null)return null; + return terraforminginfolists.get(dim).terraformingChunksDone; + } + + public void setChunksFullyBiomeChanged(int dim, HashSet lpos){ + if (terraforminginfolists.get(dim) == null)return; + terraforminginfolists.get(dim).biomeChangingChunksDone = lpos; + } + public HashSet getChunksFullyBiomeChanged(int dim){ + if (terraforminginfolists.get(dim) == null)return null; + return terraforminginfolists.get(dim).biomeChangingChunksDone; + } + + public void sethelper(int dim, TerraformingHelper helper){ + if (terraforminginfolists.get(dim) == null)return; + terraforminginfolists.get(dim).terraformingHelper= helper; + } + public TerraformingHelper gethelper(int dim){ + if (terraforminginfolists.get(dim) == null)return null; + return terraforminginfolists.get(dim).terraformingHelper; + } +} diff --git a/src/main/java/zmaster587/advancedRocketry/integrated_server_and_client_variable_sharing_fix/dimensionTerraformingInfo.java b/src/main/java/zmaster587/advancedRocketry/integrated_server_and_client_variable_sharing_fix/dimensionTerraformingInfo.java new file mode 100644 index 000000000..672c62d0d --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/integrated_server_and_client_variable_sharing_fix/dimensionTerraformingInfo.java @@ -0,0 +1,16 @@ +package zmaster587.advancedRocketry.integrated_server_and_client_variable_sharing_fix; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import zmaster587.advancedRocketry.util.TerraformingHelper; + +import java.util.ArrayList; +import java.util.HashSet; + +public class dimensionTerraformingInfo{ + public dimensionTerraformingInfo(){} + public ArrayList terraformingProtectedBlocks; + public HashSet terraformingChunksDone; + public HashSet biomeChangingChunksDone; + public TerraformingHelper terraformingHelper; +} diff --git a/src/main/java/zmaster587/advancedRocketry/integrated_server_and_client_variable_sharing_fix/serverlists.java b/src/main/java/zmaster587/advancedRocketry/integrated_server_and_client_variable_sharing_fix/serverlists.java new file mode 100644 index 000000000..9268a97b4 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/integrated_server_and_client_variable_sharing_fix/serverlists.java @@ -0,0 +1,68 @@ +package zmaster587.advancedRocketry.integrated_server_and_client_variable_sharing_fix; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import zmaster587.advancedRocketry.util.TerraformingHelper; + +import java.util.*; + + +public class serverlists implements Afuckinginterface { + Map terraforminginfolists; + + public serverlists(){ + this.terraforminginfolists = new HashMap<>(); + } + + public void initdim(int dim){ + if (terraforminginfolists.get(dim) != null){ + terraforminginfolists.get(dim).terraformingChunksDone = new HashSet<>(); + terraforminginfolists.get(dim).biomeChangingChunksDone = new HashSet<>(); + terraforminginfolists.get(dim).terraformingProtectedBlocks = new ArrayList<>(); + }else{ + dimensionTerraformingInfo info = new dimensionTerraformingInfo(); + info.terraformingChunksDone = new HashSet<>(); + info.biomeChangingChunksDone = new HashSet<>(); + info.terraformingProtectedBlocks = new ArrayList<>(); + terraforminginfolists.put(dim,info); + } + } + public boolean isinitialized(int dim){ + return (terraforminginfolists.get(dim) != null); + } + public List getProtectingBlocksForDimension(int dim){ + if (terraforminginfolists.get(dim) == null)return null; + return terraforminginfolists.get(dim).terraformingProtectedBlocks; + } + public void setProtectingBlocksForDimension(int dim, ArrayList blocks){ + if (terraforminginfolists.get(dim) == null)return; + terraforminginfolists.get(dim).terraformingProtectedBlocks = blocks; + } + + public void setChunksFullyTerraformed(int dim, HashSet lpos){ + if (terraforminginfolists.get(dim) == null)return; + terraforminginfolists.get(dim).terraformingChunksDone = lpos; + } + public HashSet getChunksFullyTerraformed(int dim){ + if (terraforminginfolists.get(dim) == null)return null; + return terraforminginfolists.get(dim).terraformingChunksDone; + } + + public void setChunksFullyBiomeChanged(int dim, HashSet lpos){ + if (terraforminginfolists.get(dim) == null)return; + terraforminginfolists.get(dim).biomeChangingChunksDone = lpos; + } + public HashSet getChunksFullyBiomeChanged(int dim){ + if (terraforminginfolists.get(dim) == null)return null; + return terraforminginfolists.get(dim).biomeChangingChunksDone; + } + + public void sethelper(int dim, TerraformingHelper helper){ + if (terraforminginfolists.get(dim) == null)return; + terraforminginfolists.get(dim).terraformingHelper= helper; + } + public TerraformingHelper gethelper(int dim){ + if (terraforminginfolists.get(dim) == null)return null; + return terraforminginfolists.get(dim).terraformingHelper; + } +} diff --git a/src/main/java/zmaster587/advancedRocketry/integration/MatterOvedriveIntegration.java b/src/main/java/zmaster587/advancedRocketry/integration/MatterOvedriveIntegration.java new file mode 100644 index 000000000..ba0b65be3 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/integration/MatterOvedriveIntegration.java @@ -0,0 +1,25 @@ +package zmaster587.advancedRocketry.integration; + +import matteroverdrive.entity.*; +import matteroverdrive.entity.monster.EntityMeleeRougeAndroidMob; +import matteroverdrive.entity.monster.EntityRangedRogueAndroidMob; +import matteroverdrive.entity.player.MOPlayerCapabilityProvider; +import matteroverdrive.init.OverdriveBioticStats; +import net.minecraft.entity.EntityLivingBase; +import zmaster587.advancedRocketry.api.ARConfiguration; + +public class MatterOvedriveIntegration { + public static boolean isAndroidNeedNoOxygen(EntityLivingBase player) { + return (MOPlayerCapabilityProvider.GetAndroidCapability(player) != null + && MOPlayerCapabilityProvider.GetAndroidCapability(player).isAndroid() + && MOPlayerCapabilityProvider.GetAndroidCapability(player).isUnlocked(OverdriveBioticStats.oxygen, 1)); + } + + public static void addAndroidsToBypassList(ARConfiguration arConfig) { + // for some reason AR cant register MO entities to bypass, so we just make this a dummy method + + arConfig.bypassEntity.add(EntityDrone.class); + arConfig.bypassEntity.add(EntityRangedRogueAndroidMob.class); + arConfig.bypassEntity.add(EntityMeleeRougeAndroidMob.class); + } +} diff --git a/src/main/java/zmaster587/advancedRocketry/inventory/ContainerOrbitalLaserDrill.java b/src/main/java/zmaster587/advancedRocketry/inventory/ContainerOrbitalLaserDrill.java index ca13db187..e69de29bb 100644 --- a/src/main/java/zmaster587/advancedRocketry/inventory/ContainerOrbitalLaserDrill.java +++ b/src/main/java/zmaster587/advancedRocketry/inventory/ContainerOrbitalLaserDrill.java @@ -1,164 +0,0 @@ -package zmaster587.advancedRocketry.inventory; - -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.entity.player.InventoryPlayer; -import net.minecraft.inventory.Container; -import net.minecraft.inventory.IContainerListener; -import net.minecraft.inventory.Slot; -import net.minecraft.item.ItemStack; -import zmaster587.advancedRocketry.api.AdvancedRocketryItems; -import zmaster587.advancedRocketry.tile.multiblock.orbitallaserdrill.TileOrbitalLaserDrill; -import zmaster587.libVulpes.gui.SlotSingleItem; - -import javax.annotation.Nonnull; - -public class ContainerOrbitalLaserDrill extends Container { - - private TileOrbitalLaserDrill laserTile; - private boolean finished, jammed; - private int prevEnergy = 0, prevLaserX = 0, prevLaserZ = 0, buildingX, buildingZ; - private TileOrbitalLaserDrill.MODE currMode; - - ContainerOrbitalLaserDrill(InventoryPlayer inventoryPlayer, TileOrbitalLaserDrill tile) { - super(); - laserTile = tile; - - addSlotToContainer(new SlotSingleItem(tile, 0, 56, 54, AdvancedRocketryItems.itemLens)); - - // Player inventory - for (int i1 = 0; i1 < 3; i1++) { - for (int l1 = 0; l1 < 9; l1++) { - addSlotToContainer(new Slot(inventoryPlayer, l1 + i1 * 9 + 9, 8 + l1 * 18, 89 + i1 * 18)); - } - } - // Player hotbar - for (int j1 = 0; j1 < 9; j1++) { - addSlotToContainer(new Slot(inventoryPlayer, j1, 8 + j1 * 18, 147)); - } - - currMode = laserTile.getMode(); - jammed = false; - finished = false; - } - - @Override - public void detectAndSendChanges() { - super.detectAndSendChanges(); - if (laserTile.getBatteries().getUniversalEnergyStored() != prevEnergy) { - prevEnergy = laserTile.getBatteries().getUniversalEnergyStored(); - for (IContainerListener listener : this.listeners) { - listener.sendWindowProperty(this, 0, prevEnergy / 100); - } - } - - if (laserTile.laserX != prevLaserX) { - prevLaserX = laserTile.laserX; - - - for (IContainerListener listener : this.listeners) { - listener.sendWindowProperty(this, 1, prevLaserX & 65535); - - int j = prevLaserX >>> 16; - //if(j != 0) - listener.sendWindowProperty(this, 2, j); - } - } - - if (laserTile.laserZ != prevLaserZ) { - prevLaserZ = laserTile.laserZ; - - for (IContainerListener listener : this.listeners) { - listener.sendWindowProperty(this, 3, prevLaserZ & 65535); - - int j = prevLaserZ >>> 16; - //if(j != 0) - listener.sendWindowProperty(this, 4, j); - } - } - if (currMode.compareTo(laserTile.getMode()) != 0) { - for (IContainerListener listener : this.listeners) { - listener.sendWindowProperty(this, 5, laserTile.getMode().ordinal()); - } - } - if (jammed != laserTile.isJammed()) { - jammed = laserTile.isJammed(); - for (IContainerListener listener : this.listeners) { - listener.sendWindowProperty(this, 6, laserTile.isJammed() ? 1 : 0); - } - } - if (finished != laserTile.isFinished()) { - finished = laserTile.isFinished(); - for (IContainerListener listener : this.listeners) { - listener.sendWindowProperty(this, 7, laserTile.isFinished() ? 1 : 0); - } - } - } - - @Override - public void updateProgressBar(int id, int value) { - if (id == 0) { - laserTile.setEnergy(value * 100); - } else if (id == 1) { - buildingX = value; - } else if (id == 2) { - buildingX |= value << 16; - laserTile.laserX = buildingX; - buildingX = 0; - } else if (id == 3) { - buildingZ = value; - } else if (id == 4) { - buildingZ |= value << 16; - laserTile.laserZ = buildingZ; - buildingZ = 0; - } else if (id == 5) { - laserTile.setMode(TileOrbitalLaserDrill.MODE.values()[value]); - } else if (id == 6) - laserTile.setJammed(value == 1); - else if (id == 7) - laserTile.setFinished(value == 1); - } - - @Override - @Nonnull - public ItemStack transferStackInSlot(EntityPlayer player, int slot) { - ItemStack stack = ItemStack.EMPTY; - Slot slotObject = inventorySlots.get(slot); - //null checks and checks if the item can be stacked (maxStackSize > 1) - if (slotObject != null && slotObject.getHasStack()) { - - ItemStack stackInSlot = slotObject.getStack(); - stack = stackInSlot.copy(); - - //merges the item into player inventory since its in the tileEntity - if (slot == 0) { - if (!this.mergeItemStack(stackInSlot, 1, 35, true)) { - return ItemStack.EMPTY; - } - } - //placing it into the tileEntity is possible since its in the player inventory - //check to make sure it's valid for the slot - else if (!laserTile.isItemValidForSlot(0, stack) || !this.mergeItemStack(stackInSlot, 0, 1, false)) { - return ItemStack.EMPTY; - } - - if (stackInSlot.getCount() == 0) { - slotObject.putStack(ItemStack.EMPTY); - } else { - slotObject.onSlotChanged(); - } - - if (stackInSlot.getCount() == stack.getCount()) { - return ItemStack.EMPTY; - } - slotObject.onTake(player, stackInSlot); - } - - return stack; - } - - - @Override - public boolean canInteractWith(@Nonnull EntityPlayer entityplayer) { - return laserTile.isUsableByPlayer(entityplayer); - } -} diff --git a/src/main/java/zmaster587/advancedRocketry/inventory/GuiOrbitalLaserDrill.java b/src/main/java/zmaster587/advancedRocketry/inventory/GuiOrbitalLaserDrill.java index 7dbd55da1..e69de29bb 100644 --- a/src/main/java/zmaster587/advancedRocketry/inventory/GuiOrbitalLaserDrill.java +++ b/src/main/java/zmaster587/advancedRocketry/inventory/GuiOrbitalLaserDrill.java @@ -1,196 +0,0 @@ -package zmaster587.advancedRocketry.inventory; - -import net.minecraft.client.gui.GuiButton; -import net.minecraft.client.gui.GuiTextField; -import net.minecraft.client.gui.inventory.GuiContainer; -import net.minecraft.entity.player.InventoryPlayer; -import net.minecraft.util.ResourceLocation; -import org.lwjgl.input.Keyboard; -import zmaster587.advancedRocketry.tile.multiblock.orbitallaserdrill.TileOrbitalLaserDrill; -import zmaster587.libVulpes.gui.GuiImageButton; -import zmaster587.libVulpes.network.PacketHandler; -import zmaster587.libVulpes.network.PacketMachine; - -import java.io.IOException; -import java.util.LinkedList; - -/** - * @author zmaster587 - */ -public class GuiOrbitalLaserDrill extends GuiContainer { - - private ResourceLocation backdrop = new ResourceLocation("advancedrocketry", "textures/gui/LaserTile.png"); - private TileOrbitalLaserDrill laserTile; - private int prevX, prevZ; - - private GuiTextField xbox, ybox; - private GuiImageButton modeUp, modeDown; - - public GuiOrbitalLaserDrill(InventoryPlayer inventoryPlayer, TileOrbitalLaserDrill tile) { - super(new ContainerOrbitalLaserDrill(inventoryPlayer, tile)); - laserTile = tile; - } - - //TODO: enter button - @Override - public void initGui() { - super.initGui(); - - int x = (width - xSize) / 2; - int y = (height - ySize) / 2; - - //Create and setup the textboxes - xbox = new GuiTextField(0, this.fontRenderer, x + 113, y + 31, 50, 10); - ybox = new GuiTextField(1, this.fontRenderer, x + 113, y + 41, 50, 10); - xbox.setMaxStringLength(15); - xbox.setEnableBackgroundDrawing(true); - xbox.setFocused(true); - xbox.setCanLoseFocus(true); - xbox.setEnabled(true); - ybox.setMaxStringLength(15); - ybox.setEnableBackgroundDrawing(true); - ybox.setFocused(false); - ybox.setCanLoseFocus(true); - ybox.setEnabled(true); - - modeDown = new GuiImageButton(0, x + 103, y + 20, 5, 8, zmaster587.libVulpes.inventory.TextureResources.buttonLeft); - modeUp = new GuiImageButton(1, x + 157, y + 20, 5, 8, zmaster587.libVulpes.inventory.TextureResources.buttonRight); - this.buttonList.add(modeUp); - this.buttonList.add(modeDown); - this.buttonList.add(new GuiButton(2, x + 103, y + 62, 34, 20, "Reset")); - } - - @Override - protected void keyTyped(char par1, int par2) throws IOException { - //Don't let players change the coords while the machine is running - if (!laserTile.isRunning()) { - if (Character.isDigit(par1) || par1 == '-' || par2 == Keyboard.KEY_BACK || par2 == Keyboard.KEY_DELETE || par2 == Keyboard.KEY_LEFT || par2 == Keyboard.KEY_RIGHT) { - if (xbox.isFocused() && (par1 != '-' || (xbox.getCursorPosition() == 0 && !xbox.getText().startsWith("-")))) { - xbox.textboxKeyTyped(par1, par2); - - if (!xbox.getText().isEmpty() && !xbox.getText().contentEquals("-")) - laserTile.laserX = Integer.parseInt(xbox.getText()); - - PacketHandler.sendToServer(new PacketMachine(laserTile, (byte) 0)); - } else if (ybox.isFocused() && (par1 != '-' || (ybox.getCursorPosition() == 0 && !ybox.getText().startsWith("-")))) { - ybox.textboxKeyTyped(par1, par2); - if (!ybox.getText().isEmpty() && !ybox.getText().contentEquals("-")) - laserTile.laserZ = Integer.parseInt(ybox.getText()); - - PacketHandler.sendToServer(new PacketMachine(laserTile, (byte) 1)); - } - } - } - - if (par2 == Keyboard.KEY_TAB) { - if (xbox.isFocused()) { - xbox.setFocused(false); - ybox.setFocused(true); - } else if (ybox.isFocused()) { - xbox.setFocused(true); - ybox.setFocused(false); - } - } - - super.keyTyped(par1, par2); - } - - //Overridden so the mouse works properly - @Override - protected void actionPerformed(GuiButton guiButton) { - //TODO: debug - if (guiButton.id == 0) { - laserTile.decrementMode(); - } else if (guiButton.id == 1) { - laserTile.incrementMode(); - } else if (guiButton.id == 2) { - PacketHandler.sendToServer(new PacketMachine(laserTile, (byte) 4)); - return; - } else - return; - - if (!laserTile.isRunning()) - PacketHandler.sendToServer(new PacketMachine(laserTile, (byte) 3)); - } - - @Override - public void drawScreen(int a, int b, float c) { - super.drawScreen(a, b, c); - //Don't bother updating unless somthing has changed - if (laserTile.laserX != prevX) { - xbox.setText(String.valueOf(laserTile.laserX)); - prevX = laserTile.laserX; - } - if (laserTile.laserZ != prevZ) { - ybox.setText(String.valueOf(laserTile.laserZ)); - prevZ = laserTile.laserZ; - } - xbox.drawTextBox(); - ybox.drawTextBox(); - - int x = (width - xSize) / 2, y = (height - ySize) / 2; - - if (a > x + 11 && a < x + 27 && b < y + 85 && b > y + 43) { - LinkedList text = new LinkedList<>(); - text.add(laserTile.getBatteries().getUniversalEnergyStored() + " / " + laserTile.getBatteries().getMaxEnergyStored() + " RF"); - this.drawHoveringText(text, a, b, this.fontRenderer); - } - - //Buttons don't need to be drawn because that is taken care of by super - } - - /** - * Args: x, y, buttonClicked - * - * @throws IOException - */ - @Override - public void mouseClicked(int xPos, int yPos, int par3) throws IOException { - //Make sure we can focus the textboxes - int x = (width - xSize) / 2, y = (height - ySize) / 2; - if (!xbox.isFocused() && yPos < y + 40 && yPos > y + 31 && xPos < x + 163 && xPos > x + 113) { - xbox.setFocused(true); - ybox.setFocused(false); - } - - if (!ybox.isFocused() && yPos < y + 50 && yPos > y + 41 && xPos < x + 163 && xPos > x + 113) { - ybox.setFocused(true); - xbox.setFocused(false); - } - - super.mouseClicked(xPos, yPos, par3); - } - - @Override - protected void drawGuiContainerBackgroundLayer(float f, int i, int j) { - this.mc.renderEngine.bindTexture(backdrop); - //get starting X and Y for the interface - int x = (width - xSize) / 2, y = (height - ySize) / 2; - this.drawTexturedModalRect(x, y, 0, 0, 176, 171); - - //Render the energy bar only if energy exists - if (laserTile.hasEnergy()) { - int offset = laserTile.getEnergyPercentScaled(42); - this.drawTexturedModalRect(x + 11, y + 85 - offset, 176, 42 - offset, 16, offset); - } - - //Display status - if (laserTile.isFinished() || laserTile.getStackInSlot(0).isEmpty()) - this.drawTexturedModalRect(x + 145, y + 64, 32, 171, 16, 16); - else if (laserTile.isRunning() || laserTile.isJammed()) - this.drawTexturedModalRect(x + 145, y + 64, 16, 171, 16, 16); - else - this.drawTexturedModalRect(x + 145, y + 64, 0, 171, 16, 16); - - //Draw labels next to the input boxes - this.drawString(this.fontRenderer, "X:", x + 103, y + 31, 0xffffff); - this.drawString(this.fontRenderer, "Y:", x + 103, y + 41, 0xffffff); - - //Draw jamming indicator if jammed - if (laserTile.isJammed()) - this.drawString(this.fontRenderer, "Jam!", x + 143, y + 68, 0xffffff); - - //Draw mode indicator - this.drawCenteredString(this.fontRenderer, laserTile.getMode().toString(), x + 130, y + 20, 0xffffff); - } -} diff --git a/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleBrokenPart.java b/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleBrokenPart.java new file mode 100644 index 000000000..5066fa63f --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleBrokenPart.java @@ -0,0 +1,74 @@ +package zmaster587.advancedRocketry.inventory.modules; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.client.renderer.texture.TextureManager; +import net.minecraft.item.ItemStack; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import org.lwjgl.opengl.GL11; +import zmaster587.libVulpes.LibVulpes; +import zmaster587.libVulpes.gui.CommonResources; +import zmaster587.libVulpes.inventory.modules.ModuleBase; + +import javax.annotation.Nonnull; +import java.util.Arrays; +import java.util.List; + +public class ModuleBrokenPart extends ModuleBase { + + private final ItemStack part; + + public ModuleBrokenPart(final int offsetX, final int offsetY, @Nonnull ItemStack part) { + super(offsetX, offsetY); + this.part = part; + this.sizeX = 18; + this.sizeY = 18; + } + + @SideOnly(Side.CLIENT) + @Override + public void renderBackground(GuiContainer gui, int x, int y, int mouseX, int mouseY, FontRenderer font) { + // render stack + + TextureManager textureManager = Minecraft.getMinecraft().getTextureManager(); + textureManager.bindTexture(CommonResources.genericBackground); + gui.drawTexturedModalRect(x + this.offsetX - 1, y + this.offsetY - 1, 176, 0, 18, 18); + int relativeX = x + this.offsetX; + int relativeY = y + this.offsetY; + int zLevel = 500; + + GL11.glPushMatrix(); + RenderHelper.disableStandardItemLighting(); + RenderHelper.enableGUIStandardItemLighting(); + + GL11.glTranslatef(relativeX, relativeY, zLevel); + Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI(part, 0, 0); + Minecraft.getMinecraft().getRenderItem().renderItemOverlayIntoGUI(font, part, 0, 0, ""); + + RenderHelper.disableStandardItemLighting(); + GL11.glPopMatrix(); + } + + private boolean isMouseOver(int mouseX, int mouseY) { + int relativeX = mouseX - this.offsetX; + int relativeY = mouseY - this.offsetY; + return relativeX > 0 && relativeX < this.sizeX && relativeY > 0 && relativeY < this.sizeY; + } + + @SideOnly(Side.CLIENT) + @Override + public void renderToolTip(final int guiOffsetX, final int guiOffsetY, final int mouseX, final int mouseY, final float zLevel, final GuiContainer gui, final FontRenderer font) { + super.renderToolTip(guiOffsetX, guiOffsetY, mouseX, mouseY, zLevel, gui, font); + + if (this.part != null && this.isMouseOver(mouseX, mouseY)) { + List list = Arrays.asList( + LibVulpes.proxy.getLocalizedString(this.part.getUnlocalizedName() + ".name"), + LibVulpes.proxy.getLocalizedString("msg.brokenstage.text") + ": " + this.part.getItemDamage() / 3 + ); + this.drawTooltip(gui, list, mouseX, mouseY, zLevel, font); + } + } +} diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemBiomeChanger.java b/src/main/java/zmaster587/advancedRocketry/item/ItemBiomeChanger.java index e2eb16af5..eb460113d 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemBiomeChanger.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemBiomeChanger.java @@ -47,12 +47,12 @@ public List getModules(int id, EntityPlayer player) { int j = 0; for (byte biomeByte : sat.discoveredBiomes()) { Biome biome = Biome.getBiome(biomeByte); - String biomeName = AdvancedRocketry.proxy.getNameFromBiome(biome); - - list2.add(new ModuleButton(32, 16 + 24 * (j++), Biome.getIdForBiome(biome), biomeName, this, TextureResources.buttonBuild)); + if (biome != null) { + String biomeName = AdvancedRocketry.proxy.getNameFromBiome(biome); + list2.add(new ModuleButton(32, 16 + 24 * (j++), Biome.getIdForBiome(biome), biomeName, this, TextureResources.buttonBuild)); + } } - //Relying on a bug, is this safe? ModuleContainerPan pan = new ModuleContainerPan(32, 16, list2, new LinkedList<>(), null, 128, 128, 0, -64, 0, 1000); @@ -78,7 +78,8 @@ else if (mapping == null) list.add(LibVulpes.proxy.getLocalizedString("msg.biomechanger.nosat")); else if (mapping.getDimensionId() == player.provider.getDimension()) { list.add(LibVulpes.proxy.getLocalizedString("msg.connected")); - list.add(LibVulpes.proxy.getLocalizedString("msg.biomechanger.selBiome") + mapping.getBiome().getBiomeName()); + if (mapping.getBiome()!=null) + list.add(LibVulpes.proxy.getLocalizedString("msg.biomechanger.selBiome") + mapping.getBiome().getBiomeName()); list.add(LibVulpes.proxy.getLocalizedString("msg.biomechanger.numBiome") + mapping.discoveredBiomes().size()); } else list.add(LibVulpes.proxy.getLocalizedString("msg.notconnected")); diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemBlockFluidTank.java b/src/main/java/zmaster587/advancedRocketry/item/ItemBlockFluidTank.java index cb52a1a50..614a958ae 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemBlockFluidTank.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemBlockFluidTank.java @@ -15,6 +15,7 @@ import net.minecraftforge.fluids.FluidTank; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; +import zmaster587.advancedRocketry.api.ARConfiguration; import zmaster587.advancedRocketry.tile.TileFluidTank; import javax.annotation.Nonnull; @@ -38,7 +39,7 @@ public void addInformation(@Nonnull ItemStack stack, @Nullable World world, List if (fluidStack == null) { list.add("Empty"); } else { - list.add(fluidStack.getLocalizedName() + ": " + fluidStack.amount + "/64000mb"); + list.add(fluidStack.getLocalizedName() + ": " + fluidStack.amount/1000 + "/"+64* ARConfiguration.getCurrentConfig().blockTankCapacity+"b"); } } @@ -62,7 +63,7 @@ public boolean placeBlockAt(@Nonnull ItemStack stack, EntityPlayer player, World public void fill(@Nonnull ItemStack stack, FluidStack fluid) { NBTTagCompound nbt; - FluidTank tank = new FluidTank(640000); + FluidTank tank = new FluidTank((int) (640000* ARConfiguration.getCurrentConfig().blockTankCapacity)); if (stack.hasTagCompound()) { nbt = stack.getTagCompound(); tank.readFromNBT(nbt); @@ -77,7 +78,7 @@ public void fill(@Nonnull ItemStack stack, FluidStack fluid) { public FluidStack drain(@Nonnull ItemStack stack, int amt) { NBTTagCompound nbt; - FluidTank tank = new FluidTank(640000); + FluidTank tank = new FluidTank((int) (640000* ARConfiguration.getCurrentConfig().blockTankCapacity)); if (stack.hasTagCompound()) { nbt = stack.getTagCompound(); tank.readFromNBT(nbt); @@ -94,7 +95,7 @@ public FluidStack drain(@Nonnull ItemStack stack, int amt) { public FluidStack getFluid(@Nonnull ItemStack stack) { NBTTagCompound nbt; - FluidTank tank = new FluidTank(640000); + FluidTank tank = new FluidTank((int) (640000* ARConfiguration.getCurrentConfig().blockTankCapacity)); if (stack.hasTagCompound()) { nbt = stack.getTagCompound(); tank.readFromNBT(nbt); diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemJackHammer.java b/src/main/java/zmaster587/advancedRocketry/item/ItemJackHammer.java index ebae06bd7..6aa3551b3 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemJackHammer.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemJackHammer.java @@ -21,7 +21,7 @@ public class ItemJackHammer extends ItemTool { public ItemJackHammer(ToolMaterial toolMaterial) { super(toolMaterial, items); - efficiencyOnProperMaterial = 50f; + efficiency = 50f; } @Override @@ -30,9 +30,10 @@ public boolean getIsRepairable(@Nonnull ItemStack stackMe, ItemStack stackItem) return OreDictionary.itemMatches(OreDictionary.getOres("stickTitanium").get(0), stackItem, false);//super.getIsRepairable(p_82789_1_, p_82789_2_); } + @Override @ParametersAreNonnullByDefault - public float getStrVsBlock(@Nonnull ItemStack stack, IBlockState state) { - return state.getMaterial() == Material.IRON || state.getMaterial() == Material.ROCK || state.getMaterial() == MaterialGeode.geode ? this.efficiencyOnProperMaterial : super.getStrVsBlock(stack, state); + public float getDestroySpeed(@Nonnull ItemStack stack, IBlockState state) { + return state.getMaterial() == Material.IRON || state.getMaterial() == Material.ROCK || state.getMaterial() == MaterialGeode.geode ? this.efficiency : super.getDestroySpeed(stack, state); } diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemSatellite.java b/src/main/java/zmaster587/advancedRocketry/item/ItemSatellite.java index 50eabb4aa..8510fc3f4 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemSatellite.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemSatellite.java @@ -66,6 +66,7 @@ public void addInformation(@Nonnull ItemStack stack, World player, List SatelliteProperties properties = SatelliteRegistry.getSatelliteProperties(stack); int dataStorage, powerGeneration, powerStorage; + float weight; list.add(getName(stack)); list.add("ID: " + properties.getId()); @@ -90,6 +91,12 @@ public void addInformation(@Nonnull ItemStack stack, World player, List else list.add(ChatFormatting.YELLOW + LibVulpes.proxy.getLocalizedString("msg.itemsatellite.nodata")); } + + if ((weight = properties.getWeight()) > 0) + list.add(LibVulpes.proxy.getLocalizedString("msg.itemsatellite.weight") + weight); + else + list.add(ChatFormatting.YELLOW + LibVulpes.proxy.getLocalizedString("msg.itemsatellite.noweight")); + } else { list.add(ChatFormatting.RED + LibVulpes.proxy.getLocalizedString("msg.itemsatellite.empty")); } diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemSatelliteIdentificationChip.java b/src/main/java/zmaster587/advancedRocketry/item/ItemSatelliteIdentificationChip.java index b851f176a..dc39132a1 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemSatelliteIdentificationChip.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemSatelliteIdentificationChip.java @@ -82,6 +82,7 @@ public void setSatellite(@Nonnull ItemStack stack, SatelliteProperties satellite nbt.setString("satelliteName", satellite2.getName()); nbt.setLong("satelliteId", satellite.getId()); + nbt.setFloat("weight", satellite.getWeight()); stack.setTagCompound(nbt); } diff --git a/src/main/java/zmaster587/advancedRocketry/item/tools/ItemBasicLaserGun.java b/src/main/java/zmaster587/advancedRocketry/item/tools/ItemBasicLaserGun.java index cf9f24fba..2e50ef406 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/tools/ItemBasicLaserGun.java +++ b/src/main/java/zmaster587/advancedRocketry/item/tools/ItemBasicLaserGun.java @@ -41,7 +41,7 @@ public ItemBasicLaserGun() { } @Override - public float getStrVsBlock(@Nonnull ItemStack stack, IBlockState state) { + public float getDestroySpeed(@Nonnull ItemStack stack, IBlockState state) { return 0; } diff --git a/src/main/java/zmaster587/advancedRocketry/network/PacketBiomeIDChange.java b/src/main/java/zmaster587/advancedRocketry/network/PacketBiomeIDChange.java index 2edd83d15..fad66204f 100644 --- a/src/main/java/zmaster587/advancedRocketry/network/PacketBiomeIDChange.java +++ b/src/main/java/zmaster587/advancedRocketry/network/PacketBiomeIDChange.java @@ -66,10 +66,9 @@ public void executeClient(EntityPlayer thePlayer) { chunk.setBiomeArray(array); BlockPos pos2 = pos.getBlockPos();// new BlockPos(chunk.xPosition << 4, 48, chunk.zPosition << 4); thePlayer.world.markBlockRangeForRenderUpdate(pos2, pos2.add(1, 64, 1)); - - if (Minecraft.getMinecraft().gameSettings.particleSetting < 2) - AdvancedRocketry.proxy.spawnParticle("smallLazer", thePlayer.world, pos.x, pos.y, pos.z, 0, 0, 0); } + if (Minecraft.getMinecraft().gameSettings.particleSetting < 2) + AdvancedRocketry.proxy.spawnParticle("smallLazer", thePlayer.world, pos.x, pos.y, pos.z, 0, 0, 0); } } diff --git a/src/main/java/zmaster587/advancedRocketry/network/PacketSyncKnownPlanets.java b/src/main/java/zmaster587/advancedRocketry/network/PacketSyncKnownPlanets.java new file mode 100644 index 000000000..7bef4f934 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/network/PacketSyncKnownPlanets.java @@ -0,0 +1,67 @@ +package zmaster587.advancedRocketry.network; + +import io.netty.buffer.ByteBuf; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.network.PacketBuffer; +import zmaster587.advancedRocketry.dimension.DimensionManager; +import zmaster587.advancedRocketry.stations.SpaceObjectManager; +import zmaster587.advancedRocketry.stations.SpaceStationObject; +import zmaster587.libVulpes.network.BasePacket; + +import java.util.HashSet; +import java.util.Set; + +public class PacketSyncKnownPlanets extends BasePacket { + + public int stationId; + private Set knownPlanets; + + public PacketSyncKnownPlanets() { + } + + public PacketSyncKnownPlanets(int stationId, Set knownPlanets) { + this.stationId = stationId; + this.knownPlanets = knownPlanets; + this.knownPlanets.addAll(DimensionManager.getInstance().knownPlanets); + } + + @Override + public void write(ByteBuf out) { + PacketBuffer buffer = new PacketBuffer(out); + buffer.writeInt(stationId); + buffer.writeInt(knownPlanets.size()); + for (Integer planetId : knownPlanets) { + buffer.writeInt(planetId); + } + } + + @Override + public void readClient(ByteBuf in) { + PacketBuffer buffer = new PacketBuffer(in); + stationId = buffer.readInt(); + int size = buffer.readInt(); + knownPlanets = new HashSet<>(); + + for (int i = 0; i < size; i++) { + knownPlanets.add(buffer.readInt()); + } + } + + @Override + public void read(ByteBuf in) { + } + + @Override + public void executeClient(EntityPlayer player) { + SpaceStationObject spaceObject = (SpaceStationObject) SpaceObjectManager.getSpaceManager().getSpaceStation(stationId); + if (spaceObject != null) { + spaceObject.getKnownPlanetList().clear(); + spaceObject.getKnownPlanetList().addAll(knownPlanets); + } + } + + @Override + public void executeServer(EntityPlayerMP player) { + } +} diff --git a/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/AsmHook.java b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/AsmHook.java new file mode 100644 index 000000000..2029b25c1 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/AsmHook.java @@ -0,0 +1,810 @@ +package zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.asm; + +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +import java.util.ArrayList; +import java.util.List; + +import static org.objectweb.asm.Opcodes.*; +import static org.objectweb.asm.Type.*; + +/** + * Class places one hook to one method + * Terminology: + * hook - the call of your hook-method from extra code + * targetMethod - method, where the hook would be injected + * targetClass - class, whose method would be hooked + * hookMethod - YOUR static method, which represents the hook + * hookClass - class with HOOK-method + */ +public class AsmHook implements Cloneable, Comparable { + + private String targetClassName; // через точки + private String targetMethodName; + private List targetMethodParameters = new ArrayList(2); + private Type targetMethodReturnType; //если не задано, то не проверяется + + private String hooksClassName; // через точки + private String hookMethodName; + // -1 - значение return + private List transmittableVariableIds = new ArrayList(2); + private List hookMethodParameters = new ArrayList(2); + private Type hookMethodReturnType = Type.VOID_TYPE; + private boolean hasReturnValueParameter; // если в хук-метод передается значение из return + + private ReturnCondition returnCondition = ReturnCondition.NEVER; + private ReturnValue returnValue = ReturnValue.VOID; + private Object primitiveConstant; + + private HookInjectorFactory injectorFactory = ON_ENTER_FACTORY; + private HookPriority priority = HookPriority.NORMAL; + + public static final HookInjectorFactory ON_ENTER_FACTORY = HookInjectorFactory.MethodEnter.INSTANCE; + public static final HookInjectorFactory ON_EXIT_FACTORY = HookInjectorFactory.MethodExit.INSTANCE; + + // может быть без возвращаемого типа + private String targetMethodDescription; + private String hookMethodDescription; + private String returnMethodName; + // может быть без возвращаемого типа + private String returnMethodDescription; + + private boolean createMethod; + private boolean isMandatory; + + protected String getTargetClassName() { + return targetClassName; + } + + private String getTargetClassInternalName() { + return targetClassName.replace('.', '/'); + } + + private String getHookClassInternalName() { + return hooksClassName.replace('.', '/'); + } + + protected boolean isTargetMethod(String name, String desc) { + return (targetMethodReturnType == null && desc.startsWith(targetMethodDescription) || + desc.equals(targetMethodDescription)) && name.equals(targetMethodName); + } + + protected boolean getCreateMethod() { + return createMethod; + } + + protected boolean isMandatory() { + return isMandatory; + } + + protected HookInjectorFactory getInjectorFactory() { + return injectorFactory; + } + + private boolean hasHookMethod() { + return hookMethodName != null && hooksClassName != null; + } + + protected void createMethod(HookInjectorClassVisitor classVisitor) { + ClassMetadataReader.MethodReference superMethod = classVisitor.transformer.classMetadataReader + .findVirtualMethod(getTargetClassInternalName(), targetMethodName, targetMethodDescription); + // юзаем название суперметода, потому что findVirtualMethod может вернуть метод с другим названием + MethodVisitor mv = classVisitor.visitMethod(Opcodes.ACC_PUBLIC, + superMethod == null ? targetMethodName : superMethod.name, targetMethodDescription, null, null); + if (mv instanceof HookInjectorMethodVisitor) { + HookInjectorMethodVisitor inj = (HookInjectorMethodVisitor) mv; + inj.visitCode(); + inj.visitLabel(new Label()); + if (superMethod == null) { + injectDefaultValue(inj, targetMethodReturnType); + } else { + injectSuperCall(inj, superMethod); + } + injectReturn(inj, targetMethodReturnType); + inj.visitLabel(new Label()); + inj.visitMaxs(0, 0); + inj.visitEnd(); + } else { + throw new IllegalArgumentException("Hook injector not created"); + } + } + + protected void inject(HookInjectorMethodVisitor inj) { + Type targetMethodReturnType = inj.methodType.getReturnType(); + + // сохраняем значение, которое было передано return в локальную переменную + int returnLocalId = -1; + if (hasReturnValueParameter) { + returnLocalId = inj.newLocal(targetMethodReturnType); + inj.visitVarInsn(targetMethodReturnType.getOpcode(54), returnLocalId); //storeLocal + } + + // вызываем хук-метод + int hookResultLocalId = -1; + if (hasHookMethod()) { + injectInvokeStatic(inj, returnLocalId, hookMethodName, hookMethodDescription); + + if (returnValue == ReturnValue.HOOK_RETURN_VALUE || returnCondition.requiresCondition) { + hookResultLocalId = inj.newLocal(hookMethodReturnType); + inj.visitVarInsn(hookMethodReturnType.getOpcode(54), hookResultLocalId); //storeLocal + } + } + + // вызываем return + if (returnCondition != ReturnCondition.NEVER) { + Label label = inj.newLabel(); + + // вставляем GOTO-переход к label'у после вызова return + if (returnCondition != ReturnCondition.ALWAYS) { + inj.visitVarInsn(hookMethodReturnType.getOpcode(21), hookResultLocalId); //loadLocal + if (returnCondition == ReturnCondition.ON_TRUE) { + inj.visitJumpInsn(IFEQ, label); + } else if (returnCondition == ReturnCondition.ON_NULL) { + inj.visitJumpInsn(IFNONNULL, label); + } else if (returnCondition == ReturnCondition.ON_NOT_NULL) { + inj.visitJumpInsn(IFNULL, label); + } + } + + // вставляем в стак значение, которое необходимо вернуть + if (returnValue == ReturnValue.NULL) { + inj.visitInsn(Opcodes.ACONST_NULL); + } else if (returnValue == ReturnValue.PRIMITIVE_CONSTANT) { + inj.visitLdcInsn(primitiveConstant); + } else if (returnValue == ReturnValue.HOOK_RETURN_VALUE) { + inj.visitVarInsn(hookMethodReturnType.getOpcode(21), hookResultLocalId); //loadLocal + } else if (returnValue == ReturnValue.ANOTHER_METHOD_RETURN_VALUE) { + String returnMethodDescription = this.returnMethodDescription; + // если не был определён заранее нужный возвращаемый тип, то добавляем его к описанию + if (returnMethodDescription.endsWith(")")) { + returnMethodDescription += targetMethodReturnType.getDescriptor(); + } + injectInvokeStatic(inj, returnLocalId, returnMethodName, returnMethodDescription); + } + + // вызываем return + injectReturn(inj, targetMethodReturnType); + + // вставляем label, к которому идет GOTO-переход + inj.visitLabel(label); + } + + //кладем в стек значение, которое шло в return + if (hasReturnValueParameter) { + injectLoad(inj, targetMethodReturnType, returnLocalId); + } + } + + private void injectLoad(HookInjectorMethodVisitor inj, Type parameterType, int variableId) { + int opcode; + if (parameterType == INT_TYPE || parameterType == BYTE_TYPE || parameterType == CHAR_TYPE || + parameterType == BOOLEAN_TYPE || parameterType == SHORT_TYPE) { + opcode = ILOAD; + } else if (parameterType == LONG_TYPE) { + opcode = LLOAD; + } else if (parameterType == FLOAT_TYPE) { + opcode = FLOAD; + } else if (parameterType == DOUBLE_TYPE) { + opcode = DLOAD; + } else { + opcode = ALOAD; + } + inj.visitVarInsn(opcode, variableId); + } + + private void injectSuperCall(HookInjectorMethodVisitor inj, ClassMetadataReader.MethodReference method) { + int variableId = 0; + for (int i = 0; i <= targetMethodParameters.size(); i++) { + Type parameterType = i == 0 ? TypeHelper.getType(targetClassName) : targetMethodParameters.get(i - 1); + injectLoad(inj, parameterType, variableId); + if (parameterType.getSort() == Type.DOUBLE || parameterType.getSort() == Type.LONG) { + variableId += 2; + } else { + variableId++; + } + } + inj.visitMethodInsn(INVOKESPECIAL, method.owner, method.name, method.desc, false); + } + + private void injectDefaultValue(HookInjectorMethodVisitor inj, Type targetMethodReturnType) { + switch (targetMethodReturnType.getSort()) { + case Type.VOID: + break; + case Type.BOOLEAN: + case Type.CHAR: + case Type.BYTE: + case Type.SHORT: + case Type.INT: + inj.visitInsn(Opcodes.ICONST_0); + break; + case Type.FLOAT: + inj.visitInsn(Opcodes.FCONST_0); + break; + case Type.LONG: + inj.visitInsn(Opcodes.LCONST_0); + break; + case Type.DOUBLE: + inj.visitInsn(Opcodes.DCONST_0); + break; + default: + inj.visitInsn(Opcodes.ACONST_NULL); + break; + } + } + + private void injectReturn(HookInjectorMethodVisitor inj, Type targetMethodReturnType) { + if (targetMethodReturnType == INT_TYPE || targetMethodReturnType == SHORT_TYPE || + targetMethodReturnType == BOOLEAN_TYPE || targetMethodReturnType == BYTE_TYPE + || targetMethodReturnType == CHAR_TYPE) { + inj.visitInsn(IRETURN); + } else if (targetMethodReturnType == LONG_TYPE) { + inj.visitInsn(LRETURN); + } else if (targetMethodReturnType == FLOAT_TYPE) { + inj.visitInsn(FRETURN); + } else if (targetMethodReturnType == DOUBLE_TYPE) { + inj.visitInsn(DRETURN); + } else if (targetMethodReturnType == VOID_TYPE) { + inj.visitInsn(RETURN); + } else { + inj.visitInsn(ARETURN); + } + } + + private void injectInvokeStatic(HookInjectorMethodVisitor inj, int returnLocalId, String name, String desc) { + for (int i = 0; i < hookMethodParameters.size(); i++) { + Type parameterType = hookMethodParameters.get(i); + int variableId = transmittableVariableIds.get(i); + if (inj.isStatic) { + // если попытка передачи this из статического метода, то передаем null + if (variableId == 0) { + inj.visitInsn(Opcodes.ACONST_NULL); + continue; + } + // иначе сдвигаем номер локальной переменной + if (variableId > 0) variableId--; + } + if (variableId == -1) variableId = returnLocalId; + injectLoad(inj, parameterType, variableId); + } + + inj.visitMethodInsn(INVOKESTATIC, getHookClassInternalName(), name, desc, false); + } + + public String getPatchedMethodName() { + return targetClassName + '#' + targetMethodName + targetMethodDescription; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("AsmHook: "); + + sb.append(targetClassName).append('#').append(targetMethodName); + sb.append(targetMethodDescription); + sb.append(" -> "); + sb.append(hooksClassName).append('#').append(hookMethodName); + sb.append(hookMethodDescription); + + sb.append(", ReturnCondition=").append(returnCondition); + sb.append(", ReturnValue=").append(returnValue); + if (returnValue == ReturnValue.PRIMITIVE_CONSTANT) sb.append(", Constant=").append(primitiveConstant); + sb.append(", InjectorFactory: ").append(injectorFactory.getClass().getName()); + sb.append(", CreateMethod = ").append(createMethod); + + return sb.toString(); + } + + @Override + public int compareTo(AsmHook o) { + if (injectorFactory.isPriorityInverted && o.injectorFactory.isPriorityInverted) { + return priority.ordinal() > o.priority.ordinal() ? -1 : 1; + } else if (!injectorFactory.isPriorityInverted && !o.injectorFactory.isPriorityInverted) { + return priority.ordinal() > o.priority.ordinal() ? 1 : -1; + } else { + return injectorFactory.isPriorityInverted ? 1 : -1; + } + } + + public static Builder newBuilder() { + return new AsmHook().new Builder(); + } + + public class Builder extends AsmHook { + + private Builder() { + + } + + /** + * --- ОБЯЗАТЕЛЬНО ВЫЗВАТЬ --- + * Определяет название класса, в который необходимо установить хук. + * + * @param className Название класса с указанием пакета, разделенное точками. + * Например: net.minecraft.world.World + */ + public Builder setTargetClass(String className) { + AsmHook.this.targetClassName = className; + return this; + } + + /** + * --- ОБЯЗАТЕЛЬНО ВЫЗВАТЬ --- + * Определяет название метода, в который необходимо вставить хук. + * Если нужно пропатчить конструктор, то в названии метода нужно указать . + * + * @param methodName Название метода. + * Например: getBlockId + */ + public Builder setTargetMethod(String methodName) { + AsmHook.this.targetMethodName = methodName; + return this; + } + + /** + * --- ОБЯЗАТЕЛЬНО ВЫЗВАТЬ, ЕСЛИ У ЦЕЛЕВОГО МЕТОДА ЕСТЬ ПАРАМЕТРЫ --- + * Добавляет один или несколько параметров к списку параметров целевого метода. + *

+ * Эти параметры используются, чтобы составить описание целевого метода. + * Чтобы однозначно определить целевой метод, недостаточно только его названия - нужно ещё и описание. + *

+ * Примеры использования: + * import static org.cifrazia.repack.gloomyfolken.hooklib.asm.TypeHelper.* + * //... + * addTargetMethodParameters(Type.INT_TYPE) + * Type worldType = getType("net.minecraft.world.World") + * Type playerType = getType("net.minecraft.entity.player.EntityPlayer") + * addTargetMethodParameters(worldType, playerType, playerType) + * + * @param parameterTypes Типы параметров целевого метода + * @see TypeHelper + */ + public Builder addTargetMethodParameters(Type... parameterTypes) { + for (Type type : parameterTypes) { + AsmHook.this.targetMethodParameters.add(type); + } + return this; + } + + /** + * Добавляет один или несколько параметров к списку параметров целевого метода. + * Обёртка над addTargetMethodParameters(Type... parameterTypes), которая сама строит типы из названия. + * + * @param parameterTypeNames Названия классов параметров целевого метода. + * Например: net.minecraft.world.World + */ + + public Builder addTargetMethodParameters(String... parameterTypeNames) { + Type[] types = new Type[parameterTypeNames.length]; + for (int i = 0; i < parameterTypeNames.length; i++) { + types[i] = TypeHelper.getType(parameterTypeNames[i]); + } + return addTargetMethodParameters(types); + } + + /** + * Изменяет тип, возвращаемый целевым методом. + * Вовращаемый тип используется, чтобы составить описание целевого метода. + * Чтобы однозначно определить целевой метод, недостаточно только его названия - нужно ещё и описание. + * По умолчанию хук применяется ко всем методам, подходящим по названию и списку параметров. + * + * @param returnType Тип, возвращаемый целевым методом + * @see TypeHelper + */ + public Builder setTargetMethodReturnType(Type returnType) { + AsmHook.this.targetMethodReturnType = returnType; + return this; + } + + /** + * Изменяет тип, возвращаемый целевым методом. + * Обёртка над setTargetMethodReturnType(Type returnType) + * + * @param returnType Название класса, экземпляр которого возвращает целевой метод + */ + public Builder setTargetMethodReturnType(String returnType) { + return setTargetMethodReturnType(TypeHelper.getType(returnType)); + } + + /** + * --- ОБЯЗАТЕЛЬНО ВЫЗВАТЬ, ЕСЛИ НУЖЕН ХУК-МЕТОД, А НЕ ПРОСТО return SOME_CONSTANT --- + * Определяет название класса, в котором находится хук-метод. + * + * @param className Название класса с указанием пакета, разделенное точками. + * Например: net.myname.mymod.asm.MyHooks + */ + public Builder setHookClass(String className) { + AsmHook.this.hooksClassName = className; + return this; + } + + /** + * --- ОБЯЗАТЕЛЬНО ВЫЗВАТЬ, ЕСЛИ НУЖЕН ХУК-МЕТОД, А НЕ ПРОСТО return SOME_CONSTANT --- + * Определяет название хук-метода. + * ХУК-МЕТОД ДОЛЖЕН БЫТЬ СТАТИЧЕСКИМ, А ПРОВЕРКИ НА ЭТО НЕТ. Будьте внимательны. + * + * @param methodName Название хук-метода. + * Например: myFirstHook + */ + public Builder setHookMethod(String methodName) { + AsmHook.this.hookMethodName = methodName; + return this; + } + + /** + * --- ОБЯЗАТЕЛЬНО ВЫЗВАТЬ, ЕСЛИ У ХУК-МЕТОДА ЕСТЬ ПАРАМЕТРЫ --- + * Добавляет параметр в список параметров хук-метода. + * В байткоде не сохраняются названия параметров. Вместо этого приходится использовать их номера. + * Например, в классе EntityLivingBase есть метод attackEntityFrom(DamageSource damageSource, float damage). + * В нём будут использоваться такие номера параметров: + * 1 - damageSource + * 2 - damage + * ВАЖНЫЙ МОМЕНТ: LONG И DOUBLE "ЗАНИМАЮТ" ДВА НОМЕРА. + * Теоретически, кроме параметров в хук-метод можно передать и локальные переменные, но их + * номера сложнее посчитать. + * Например, в классе Entity есть метод setPosition(double x, double y, double z). + * В нём будут такие номера параметров: + * 1 - x + * 2 - пропущено + * 3 - y + * 4 - пропущено + * 5 - z + * 6 - пропущено + *

+ * Код этого метода таков: + * //... + * float f = ...; + * float f1 = ...; + * //... + * В таком случае у f будет номер 7, а у f1 - 8. + *

+ * Если целевой метод static, то не нужно начинать отсчет локальных переменных с нуля, номера + * будут смещены автоматически. + * + * @param parameterType Тип параметра хук-метода + * @param variableId ID значения, передаваемого в хук-метод + * @throws IllegalStateException если не задано название хук-метода или класса, который его содержит + */ + public Builder addHookMethodParameter(Type parameterType, int variableId) { + if (!AsmHook.this.hasHookMethod()) { + throw new IllegalStateException("Hook method is not specified, so can not append " + + "parameter to its parameters list."); + } + AsmHook.this.hookMethodParameters.add(parameterType); + AsmHook.this.transmittableVariableIds.add(variableId); + return this; + } + + /** + * Добавляет параметр в список параметров целевого метода. + * Обёртка над addHookMethodParameter(Type parameterType, int variableId) + * + * @param parameterTypeName Название типа параметра хук-метода. + * Например: net.minecraft.world.World + * @param variableId ID значения, передаваемого в хук-метод + */ + public Builder addHookMethodParameter(String parameterTypeName, int variableId) { + return addHookMethodParameter(TypeHelper.getType(parameterTypeName), variableId); + } + + /** + * Добавляет в список параметров хук-метода целевой класс и передает хук-методу this. + * Если целевой метод static, то будет передано null. + * + * @throws IllegalStateException если не задан хук-метод + */ + public Builder addThisToHookMethodParameters() { + if (!AsmHook.this.hasHookMethod()) { + throw new IllegalStateException("Hook method is not specified, so can not append " + + "parameter to its parameters list."); + } + AsmHook.this.hookMethodParameters.add(TypeHelper.getType(targetClassName)); + AsmHook.this.transmittableVariableIds.add(0); + return this; + } + + /** + * Добавляет в список параметров хук-метода тип, возвращаемый целевым методом и + * передает хук-методу значение, которое вернёт return. + * Более формально, при вызове хук-метода указывает в качестве этого параметра верхнее значение в стеке. + * На практике основное применение - + * Например, есть такой код метода: + * int foo = bar(); + * return foo; + * Или такой: + * return bar() + *

+ * В обоих случаях хук-методу можно передать возвращаемое значение перед вызовом return. + * + * @throws IllegalStateException если целевой метод возвращает void + * @throws IllegalStateException если не задан хук-метод + */ + public Builder addReturnValueToHookMethodParameters() { + if (!AsmHook.this.hasHookMethod()) { + throw new IllegalStateException("Hook method is not specified, so can not append " + + "parameter to its parameters list."); + } + if (AsmHook.this.targetMethodReturnType == Type.VOID_TYPE) { + throw new IllegalStateException("Target method's return type is void, it does not make sense to " + + "transmit its return value to hook method."); + } + AsmHook.this.hookMethodParameters.add(AsmHook.this.targetMethodReturnType); + AsmHook.this.transmittableVariableIds.add(-1); + AsmHook.this.hasReturnValueParameter = true; + return this; + } + + /** + * Задает условие, при котором после вызова хук-метода вызывается return. + * По умолчанию return не вызывается вообще. + * Кроме того, этот метод изменяет тип возвращаемого значения хук-метода: + * NEVER -> void + * ALWAYS -> void + * ON_TRUE -> boolean + * ON_NULL -> Object + * ON_NOT_NULL -> Object + * + * @param condition Условие выхода после вызова хук-метода + * @throws IllegalArgumentException если condition == ON_TRUE, ON_NULL или ON_NOT_NULL, но не задан хук-метод. + * @see ReturnCondition + */ + public Builder setReturnCondition(ReturnCondition condition) { + if (condition.requiresCondition && AsmHook.this.hookMethodName == null) { + throw new IllegalArgumentException("Hook method is not specified, so can not use return " + + "condition that depends on hook method."); + } + + AsmHook.this.returnCondition = condition; + Type returnType; + switch (condition) { + case NEVER: + case ALWAYS: + returnType = VOID_TYPE; + break; + case ON_TRUE: + returnType = BOOLEAN_TYPE; + break; + default: + returnType = getType(Object.class); + break; + } + AsmHook.this.hookMethodReturnType = returnType; + return this; + } + + /** + * --- ОБЯЗАТЕЛЬНО ВЫЗВАТЬ, ЕСЛИ ЦЕЛЕВОЙ МЕТОД ВОЗВРАЩАЕТ НЕ void, И ВЫЗВАН setReturnCondition --- + * Задает значение, которое возвращается при вызове return после вызова хук-метода. + * Следует вызывать после setReturnCondition. + * По умолчанию возвращается void. + * Кроме того, если value == ReturnValue.HOOK_RETURN_VALUE, то этот метод изменяет тип возвращаемого + * значения хук-метода на тип, указанный в setTargetMethodReturnType() + * + * @param value возвращаемое значение + * @throws IllegalStateException если returnCondition == NEVER (т. е. если setReturnCondition() не вызывался). + * Нет смысла указывать возвращаемое значение, если return не вызывается. + * @throws IllegalArgumentException если value == ReturnValue.HOOK_RETURN_VALUE, а тип возвращаемого значения + * целевого метода указан как void (или setTargetMethodReturnType ещё не вызывался). + * Нет смысла использовать значение, которое вернул хук-метод, если метод возвращает void. + */ + public Builder setReturnValue(ReturnValue value) { + if (AsmHook.this.returnCondition == ReturnCondition.NEVER) { + throw new IllegalStateException("Current return condition is ReturnCondition.NEVER, so it does not " + + "make sense to specify the return value."); + } + Type returnType = AsmHook.this.targetMethodReturnType; + if (value != ReturnValue.VOID && returnType == VOID_TYPE) { + throw new IllegalArgumentException("Target method return value is void, so it does not make sense to " + + "return anything else."); + } + if (value == ReturnValue.VOID && returnType != VOID_TYPE) { + throw new IllegalArgumentException("Target method return value is not void, so it is impossible " + + "to return VOID."); + } + if (value == ReturnValue.PRIMITIVE_CONSTANT && returnType != null && !isPrimitive(returnType)) { + throw new IllegalArgumentException("Target method return value is not a primitive, so it is " + + "impossible to return PRIVITIVE_CONSTANT."); + } + if (value == ReturnValue.NULL && returnType != null && isPrimitive(returnType)) { + throw new IllegalArgumentException("Target method return value is a primitive, so it is impossible " + + "to return NULL."); + } + if (value == ReturnValue.HOOK_RETURN_VALUE && !hasHookMethod()) { + throw new IllegalArgumentException("Hook method is not specified, so can not use return " + + "value that depends on hook method."); + } + + AsmHook.this.returnValue = value; + if (value == ReturnValue.HOOK_RETURN_VALUE) { + AsmHook.this.hookMethodReturnType = AsmHook.this.targetMethodReturnType; + } + return this; + } + + /** + * Возвращает тип возвращаемого значения хук-метода, если кому-то сложно "вычислить" его самостоятельно. + * + * @return тип возвращаемого значения хук-метода + */ + public Type getHookMethodReturnType() { + return hookMethodReturnType; + } + + /** + * Напрямую указывает тип, возвращаемый хук-методом. + * + * @param type + */ + protected void setHookMethodReturnType(Type type) { + AsmHook.this.hookMethodReturnType = type; + } + + private boolean isPrimitive(Type type) { + return type.getSort() > 0 && type.getSort() < 9; + } + + /** + * --- ОБЯЗАТЕЛЬНО ВЫЗВАТЬ, ЕСЛИ ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ УСТАНОВЛЕНО НА PRIMITIVE_CONSTANT --- + * Следует вызывать после setReturnValue(ReturnValue.PRIMITIVE_CONSTANT) + * Задает константу, которая будет возвращена при вызове return. + * Класс заданного объекта должен соответствовать примитивному типу. + * Например, если целевой метод возвращает int, то в этот метод должен быть передан объект класса Integer. + * + * @param constant Объект, класс которого соответствует примитиву, который следует возвращать. + * @throws IllegalStateException если возвращаемое значение не установлено на PRIMITIVE_CONSTANT + * @throws IllegalArgumentException если класс объекта constant не является обёрткой + * для примитивного типа, который возвращает целевой метод. + */ + public Builder setPrimitiveConstant(Object constant) { + if (AsmHook.this.returnValue != ReturnValue.PRIMITIVE_CONSTANT) { + throw new IllegalStateException("Return value is not PRIMITIVE_CONSTANT, so it does not make sence" + + "to specify that constant."); + } + Type returnType = AsmHook.this.targetMethodReturnType; + if (returnType == BOOLEAN_TYPE && !(constant instanceof Boolean) || + returnType == CHAR_TYPE && !(constant instanceof Character) || + returnType == BYTE_TYPE && !(constant instanceof Byte) || + returnType == SHORT_TYPE && !(constant instanceof Short) || + returnType == INT_TYPE && !(constant instanceof Integer) || + returnType == LONG_TYPE && !(constant instanceof Long) || + returnType == FLOAT_TYPE && !(constant instanceof Float) || + returnType == DOUBLE_TYPE && !(constant instanceof Double)) { + throw new IllegalArgumentException("Given object class does not math target method return type."); + } + + AsmHook.this.primitiveConstant = constant; + return this; + } + + /** + * --- ОБЯЗАТЕЛЬНО ВЫЗВАТЬ, ЕСЛИ ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ УСТАНОВЛЕНО НА ANOTHER_METHOD_RETURN_VALUE --- + * Следует вызывать после setReturnValue(ReturnValue.ANOTHER_METHOD_RETURN_VALUE) + * Задает метод, результат вызова которого будет возвращён при вызове return. + * + * @param methodName название метода, результат вызова которого следует возвращать + * @throws IllegalStateException если возвращаемое значение не установлено на ANOTHER_METHOD_RETURN_VALUE + */ + public Builder setReturnMethod(String methodName) { + if (AsmHook.this.returnValue != ReturnValue.ANOTHER_METHOD_RETURN_VALUE) { + throw new IllegalStateException("Return value is not ANOTHER_METHOD_RETURN_VALUE, " + + "so it does not make sence to specify that method."); + } + + AsmHook.this.returnMethodName = methodName; + return this; + } + + /** + * Задает фабрику, которая создаст инжектор для этого хука. + * Если говорить более человеческим языком, то этот метод определяет, где будет вставлен хук: + * в начале метода, в конце или где-то ещё. + * Если не создавать своих инжекторов, то можно использовать две фабрики: + * AsmHook.ON_ENTER_FACTORY (вставляет хук на входе в метод, используется по умолчанию) + * AsmHook.ON_EXIT_FACTORY (вставляет хук на выходе из метода) + * + * @param factory Фабрика, создающая инжектор для этого хука + */ + public Builder setInjectorFactory(HookInjectorFactory factory) { + AsmHook.this.injectorFactory = factory; + return this; + } + + /** + * Задает приоритет хука. + * Хуки с большим приоритетом вызаваются раньше. + */ + public Builder setPriority(HookPriority priority) { + AsmHook.this.priority = priority; + return this; + } + + /** + * Позволяет не только вставлять хуки в существующие методы, но и добавлять новые. Это может понадобиться, + * когда нужно переопределить метод суперкласса. Если супер-метод найден, то тело генерируемого метода + * представляет собой вызов супер-метода. Иначе это просто пустой метод или return false/0/null в зависимости + * от возвращаемого типа. + */ + public Builder setCreateMethod(boolean createMethod) { + AsmHook.this.createMethod = createMethod; + return this; + } + + /** + * Позволяет объявить хук "обязательным" для запуска игры. В случае неудачи во время вставки такого хука + * будет не просто выведено сообщение в лог, а крашнется игра. + */ + public Builder setMandatory(boolean isMandatory) { + AsmHook.this.isMandatory = isMandatory; + return this; + } + + private String getMethodDesc(Type returnType, List paramTypes) { + Type[] paramTypesArray = paramTypes.toArray(new Type[0]); + if (returnType == null) { + String voidDesc = Type.getMethodDescriptor(Type.VOID_TYPE, paramTypesArray); + return voidDesc.substring(0, voidDesc.length() - 1); + } else { + return Type.getMethodDescriptor(returnType, paramTypesArray); + } + } + + /** + * Создает хук по заданным параметрам. + * + * @return полученный хук + * @throws IllegalStateException если не был вызван какой-либо из обязательных методов + */ + public AsmHook build() { + AsmHook hook = AsmHook.this; + + if (hook.createMethod && hook.targetMethodReturnType == null) { + hook.targetMethodReturnType = hook.hookMethodReturnType; + } + hook.targetMethodDescription = getMethodDesc(hook.targetMethodReturnType, hook.targetMethodParameters); + + if (hook.hasHookMethod()) { + hook.hookMethodDescription = Type.getMethodDescriptor(hook.hookMethodReturnType, + hook.hookMethodParameters.toArray(new Type[0])); + } + if (hook.returnValue == ReturnValue.ANOTHER_METHOD_RETURN_VALUE) { + hook.returnMethodDescription = getMethodDesc(hook.targetMethodReturnType, hook.hookMethodParameters); + } + + try { + hook = (AsmHook) AsmHook.this.clone(); + } catch (CloneNotSupportedException impossible) { + } + + if (hook.targetClassName == null) { + throw new IllegalStateException("Target class name is not specified. " + + "Call setTargetClassName() before build()."); + } + + if (hook.targetMethodName == null) { + throw new IllegalStateException("Target method name is not specified. " + + "Call setTargetMethodName() before build()."); + } + + if (hook.returnValue == ReturnValue.PRIMITIVE_CONSTANT && hook.primitiveConstant == null) { + throw new IllegalStateException("Return value is PRIMITIVE_CONSTANT, but the constant is not " + + "specified. Call setReturnValue() before build()."); + } + + if (hook.returnValue == ReturnValue.ANOTHER_METHOD_RETURN_VALUE && hook.returnMethodName == null) { + throw new IllegalStateException("Return value is ANOTHER_METHOD_RETURN_VALUE, but the method is not " + + "specified. Call setReturnMethod() before build()."); + } + + if (!(hook.injectorFactory instanceof HookInjectorFactory.MethodExit) && hook.hasReturnValueParameter) { + throw new IllegalStateException("Can not pass return value to hook method " + + "because hook location is not return insn."); + } + + return hook; + } + + } + +} diff --git a/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/ClassMetadataReader.java b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/ClassMetadataReader.java new file mode 100644 index 000000000..db885e14f --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/ClassMetadataReader.java @@ -0,0 +1,201 @@ +package zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.asm; + +import org.apache.commons.io.IOUtils; +import org.objectweb.asm.*; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collections; + +/** + * Позволяет при помощи велосипеда из костылей искать методы внутри незагруженных классов + * и общие суперклассы для чего угодно. Работает через поиск class-файлов в classpath, и, в случае провала - + * ищет через рефлексию. Для работы с майнкрафтом используется сабкласс под названием DeobfuscationMetadataReader, + * + */ +public class ClassMetadataReader { + private static Method m; + + static { + try { + m = ClassLoader.class.getDeclaredMethod("findLoadedClass", String.class); + m.setAccessible(true); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } + } + + public byte[] getClassData(String className) throws IOException { + String classResourceName = '/' + className.replace('.', '/') + ".class"; + return IOUtils.toByteArray(ClassMetadataReader.class.getResourceAsStream(classResourceName)); + } + + public void acceptVisitor(byte[] classData, ClassVisitor visitor) { + new ClassReader(classData).accept(visitor, 0); + } + + public void acceptVisitor(String className, ClassVisitor visitor) throws IOException { + acceptVisitor(getClassData(className), visitor); + } + + public MethodReference findVirtualMethod(String owner, String name, String desc) { + ArrayList superClasses = getSuperClasses(owner); + for (int i = superClasses.size() - 1; i > 0; i--) { // чекать текущий класс смысла нет + String className = superClasses.get(i); + MethodReference methodReference = getMethodReference(className, name, desc); + if (methodReference != null) { + System.out.println("found virtual method: " + methodReference); + return methodReference; + } + } + return null; + } + + private MethodReference getMethodReference(String type, String methodName, String desc) { + try { + return getMethodReferenceASM(type, methodName, desc); + } catch (Exception e) { + return getMethodReferenceReflect(type, methodName, desc); + } + } + + protected MethodReference getMethodReferenceASM(String type, String methodName, String desc) throws IOException { + FindMethodClassVisitor cv = new FindMethodClassVisitor(methodName, desc); + acceptVisitor(type, cv); + if (cv.found) { + return new MethodReference(type, cv.targetName, cv.targetDesc); + } + return null; + } + + protected MethodReference getMethodReferenceReflect(String type, String methodName, String desc) { + Class loadedClass = getLoadedClass(type); + if (loadedClass != null) { + for (Method m : loadedClass.getDeclaredMethods()) { + if (checkSameMethod(methodName, desc, m.getName(), Type.getMethodDescriptor(m))) { + return new MethodReference(type, m.getName(), Type.getMethodDescriptor(m)); + } + } + } + return null; + } + + protected boolean checkSameMethod(String sourceName, String sourceDesc, String targetName, String targetDesc) { + return sourceName.equals(targetName) && sourceDesc.equals(targetDesc); + } + + /** + * Возвращает суперклассы в порядке возрастающей конкретности (начиная с java/lang/Object + * и заканчивая данным типом) + */ + public ArrayList getSuperClasses(String type) { + ArrayList superclasses = new ArrayList(1); + superclasses.add(type); + while ((type = getSuperClass(type)) != null) { + superclasses.add(type); + } + Collections.reverse(superclasses); + return superclasses; + } + + private Class getLoadedClass(String type) { + if (m != null) { + try { + ClassLoader classLoader = ClassMetadataReader.class.getClassLoader(); + return (Class) m.invoke(classLoader, type.replace('/', '.')); + } catch (Exception e) { + e.printStackTrace(); + } + } + return null; + } + + public String getSuperClass(String type) { + try { + return getSuperClassASM(type); + } catch (Exception e) { + return getSuperClassReflect(type); + } + } + + protected String getSuperClassASM(String type) throws IOException { + CheckSuperClassVisitor cv = new CheckSuperClassVisitor(); + acceptVisitor(type, cv); + return cv.superClassName; + } + + protected String getSuperClassReflect(String type) { + Class loadedClass = getLoadedClass(type); + if (loadedClass != null) { + if (loadedClass.getSuperclass() == null) return null; + return loadedClass.getSuperclass().getName().replace('.', '/'); + } + return "java/lang/Object"; + } + + private class CheckSuperClassVisitor extends ClassVisitor { + + String superClassName; + + public CheckSuperClassVisitor() { + super(Opcodes.ASM5); + } + + @Override + public void visit(int version, int access, String name, String signature, + String superName, String[] interfaces) { + this.superClassName = superName; + } + } + + protected class FindMethodClassVisitor extends ClassVisitor { + + public String targetName; + public String targetDesc; + public boolean found; + + public FindMethodClassVisitor(String name, String desc) { + super(Opcodes.ASM5); + this.targetName = name; + this.targetDesc = desc; + } + + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + System.out.println("visiting " + name + "#" + desc); + if ((access & Opcodes.ACC_PRIVATE) == 0 && checkSameMethod(name, desc, targetName, targetDesc)) { + found = true; + targetName = name; + targetDesc = desc; + } + return null; + } + } + + public static class MethodReference { + + public final String owner; + public final String name; + public final String desc; + + public MethodReference(String owner, String name, String desc) { + this.owner = owner; + this.name = name; + this.desc = desc; + } + + public Type getType() { + return Type.getMethodType(desc); + } + + @Override public String toString() { + return "MethodReference{" + + "owner='" + owner + '\'' + + ", name='" + name + '\'' + + ", desc='" + desc + '\'' + + '}'; + } + } + +} diff --git a/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/Hook.java b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/Hook.java new file mode 100644 index 000000000..4517ca3f2 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/Hook.java @@ -0,0 +1,139 @@ +package zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.asm; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +/** + * Чтобы сделать метод хуком, нужно повесить над ним эту аннотацию и зарегистрировать класс с хуком. + *

+ * Целевой класс определяется первым параметром хук-метода. Если целевой метод static, то туда прилетает null, + * иначе - this. + *

+ * Название целевого метода по умолчанию такое же, как название хук-метода, но его можно переопределить через + * targetMethod. + *

+ * Список параметров целевого метода определяется списком параметров хук-метода. Нужно добавить все те же параметры + * в том же порядке. + *

+ * Возвращаемый тип целевого метода по умолчанию не указывается вообще. Предполагается, что методов с одинаковым + * названием и списком параметров нет. Если всё же нужно указать, то это можно сделать через returnType. + */ +@Target(ElementType.METHOD) +public @interface Hook { + + /** + * Задает условие, по которому после вызова хука будет вызван return. + * Если целевой метод возвращает не void, то по умолчанию будет возвращено то, что вернул хук-метод. + * Это можно переопредилить несколькими элементами аннотации: + * returnAnotherMethod, returnNull и %type%ReturnConstant. + */ + ReturnCondition returnCondition() default ReturnCondition.NEVER; + + /** + * Задает приоритет хука. + * Хуки с большим приоритетом вызаваются раньше. + */ + HookPriority priority() default HookPriority.NORMAL; + + /** + * Задает название целевого метода. + * По умолчанию используется название хук-метода. + * Эта опция полезна, когда нужно вставить хук в конструктор или инициализацию класса. + * Для конструктора targetMethod должен быть "", для инициализации класса - "" + */ + String targetMethod() default ""; + + /** + * Задает тип, возвращаемый целевым методом. + * С точки зрения JVM могут быть методы, которые отличаются только возращаемым типом. + * На практике компиляторы таких методов не генерируют, но в некоторых случаях они + * могут встретиться (например, это можно сделать при обфускации через ProGuard) + * Если возвращаемый тип не указан, то хук применяется к первому методу, подходящему + * по названию и списку параметров. + * + * Основной предполагаемый способ использования этого параметра - вместе с createMethod = true. + * В этом случае созданный метод будет по умолчанию иметь тот же возвращаемый тип, что и хук-метод, + * а с помощью этого параметра это можно изменить. + * + * Указывать нужно полное название класса: java.lang.String, void, int и т.д. + */ + String returnType() default ""; + + /** + * Позволяет не только вставлять хуки в существующие методы, но и добавлять новые. Это может понадобиться, + * когда нужно переопределить метод суперкласса. Если супер-метод найден, то тело генерируемого метода + * представляет собой вызов супер-метода. Иначе это просто пустой метод или return false/0/null в зависимости + * от возвращаемого типа. + */ + boolean createMethod() default false; + + + /** + * Позволяет объявить хук "обязательным" для запуска игры. В случае неудачи во время вставки такого хука + * будет не просто выведено сообщение в лог, а крашнется игра. + */ + // CUSTOM: in original version the default was false + boolean isMandatory() default true; + + /** + * По умолчанию хук вставляется в начало целевого метода. + * Если указать здесь true, то он будет вставлен в конце и перед каждым вызовом return. + */ + boolean injectOnExit() default false; + + /** + * По умолчанию хук вставляется в начало целевого метода. + * Если указать здесь true, то он будет вставлен в начале указанной строки. + * Использовать не рекомендуется, потому что: + * 1) Вставить можно только на строку с инструкцией + * 2) Может ВНЕЗАПНО сломаться (например, от того, что какой-нибудь оптифайн подменит класс целиком) + */ + @Deprecated int injectOnLine() default -1; + + /** + * Если указано это название, то при вызове return в целевом методе будет сначала вызван этот метод. + * Он должен находиться в том же классе и иметь тот же список параметров, что и хук-метод. + * В итоге будет возвращено значение, которое вернёт этот метод. + */ + String returnAnotherMethod() default ""; + + /** + * Если true, то при вызове return в целевом методе будет возвращено null + */ + boolean returnNull() default false; + + /** + * Если определена одна из этих констант, то она будет возвращена при вызове return в целевом методе + */ + + boolean booleanReturnConstant() default false; + + byte byteReturnConstant() default 0; + + short shortReturnConstant() default 0; + + int intReturnConstant() default 0; + + long longReturnConstant() default 0L; + + float floatReturnConstant() default 0.0F; + + double doubleReturnConstant() default 0.0D; + + char charReturnConstant() default 0; + + String stringReturnConstant() default ""; + + @Target(ElementType.PARAMETER) + @interface LocalVariable { + int value(); + } + + /** + * Перехватывает значение, которое изначально шло в return, и передает его хук-методу. + * Говоря более формально, передает последнее значение в стаке. + * Можно использовать только когда injectOnExit() == true и целевой метод возвращает не void. + */ + @Target(ElementType.PARAMETER) + @interface ReturnValue {} +} diff --git a/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/HookClassTransformer.java b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/HookClassTransformer.java new file mode 100644 index 000000000..59cb2abc0 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/HookClassTransformer.java @@ -0,0 +1,108 @@ +package zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.asm; + +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassWriter; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; + +public class HookClassTransformer { + + public HookLogger logger = new HookLogger.SystemOutLogger(); + protected HashMap> hooksMap = new HashMap>(); + private HookContainerParser containerParser = new HookContainerParser(this); + protected ClassMetadataReader classMetadataReader = new ClassMetadataReader(); + + public void registerHook(AsmHook hook) { + if (hooksMap.containsKey(hook.getTargetClassName())) { + hooksMap.get(hook.getTargetClassName()).add(hook); + } else { + List list = new ArrayList(2); + list.add(hook); + hooksMap.put(hook.getTargetClassName(), list); + } + } + + public void registerHookContainer(String className) { + containerParser.parseHooks(className); + } + + public void registerHookContainer(byte[] classData) { + containerParser.parseHooks(classData); + } + + public byte[] transform(String className, byte[] bytecode) { + List hooks = hooksMap.get(className); + + if (hooks != null) { + Collections.sort(hooks); + logger.debug("Injecting hooks into class " + className); + try { + /* + Начиная с седьмой версии джавы, сильно изменился процесс верификации байткода. + Ради этого приходится включать автоматическую генерацию stack map frame'ов. + На более старых версиях байткода это лишняя трата времени. + Подробнее здесь: http://stackoverflow.com/questions/25109942 + */ + int majorVersion = ((bytecode[6] & 0xFF) << 8) | (bytecode[7] & 0xFF); + boolean java7 = majorVersion > 50; + + + ClassReader cr = new ClassReader(bytecode); + ClassWriter cw = createClassWriter(java7 ? ClassWriter.COMPUTE_FRAMES : ClassWriter.COMPUTE_MAXS); + HookInjectorClassVisitor hooksWriter = createInjectorClassVisitor(cw, hooks); + cr.accept(hooksWriter, java7 ? ClassReader.SKIP_FRAMES : ClassReader.EXPAND_FRAMES); + bytecode = cw.toByteArray(); + for (AsmHook hook : hooksWriter.injectedHooks) { + logger.debug("Patching method " + hook.getPatchedMethodName()); + } + hooks.removeAll(hooksWriter.injectedHooks); + } catch (Exception e) { + logger.severe("A problem has occurred during transformation of class " + className + "."); + logger.severe("Attached hooks:"); + for (AsmHook hook : hooks) { + logger.severe(hook.toString()); + } + logger.severe("Stack trace:", e); + } + + for (AsmHook notInjected : hooks) { + if (notInjected.isMandatory()) { + throw new RuntimeException("Can not find target method of mandatory hook " + notInjected); + } else { + logger.warning("Can not find target method of hook " + notInjected); + } + } + } + return bytecode; + } + + /** + * Создает ClassVisitor для списка хуков. + * Метод можно переопределить, если в ClassVisitor'e нужна своя логика для проверки, + * является ли метод целевым (isTargetMethod()) + * + * @param cw ClassWriter, который должен стоять в цепочке после этого ClassVisitor'a + * @param hooks Список хуков, вставляемых в класс + * @return ClassVisitor, добавляющий хуки + */ + protected HookInjectorClassVisitor createInjectorClassVisitor(ClassWriter cw, List hooks) { + return new HookInjectorClassVisitor(this, cw, hooks); + } + + /** + * Создает ClassWriter для сохранения трансформированного класса. + * Метод можно переопределить, если в ClassWriter'e нужна своя реализация метода getCommonSuperClass(). + * Стандартная реализация работает для уже загруженных классов и для классов, .class файлы которых есть + * в classpath, но они ещё не загружены. Во втором случае происходит загрузка (но не инициализация) классов. + * Если загрузка классов является проблемой, то можно воспользоваться SafeClassWriter. + * + * @param flags Список флагов, которые нужно передать в конструктор ClassWriter'a + * @return ClassWriter, сохраняющий трансформированный класс + */ + protected ClassWriter createClassWriter(int flags) { + return new SafeClassWriter(classMetadataReader, flags); + } +} diff --git a/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/HookContainerParser.java b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/HookContainerParser.java new file mode 100644 index 000000000..df83cb9ad --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/HookContainerParser.java @@ -0,0 +1,266 @@ +package zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.asm; + +import org.objectweb.asm.*; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map.Entry; + +public class HookContainerParser { + + private HookClassTransformer transformer; + private String currentClassName; + private String currentMethodName; + private String currentMethodDesc; + private boolean currentMethodPublicStatic; + + /* + Ключ - название значения аннотации + */ + private HashMap annotationValues; + + /* + Ключ - номер параметра, значение - номер локальной переменной для перехвата + или -1 для перехвата значения наверху стека. + */ + private HashMap parameterAnnotations = new HashMap(); + + private boolean inHookAnnotation; + + private static final String HOOK_DESC = Type.getDescriptor(Hook.class); + private static final String LOCAL_DESC = Type.getDescriptor(Hook.LocalVariable.class); + private static final String RETURN_DESC = Type.getDescriptor(ReturnValue.class); + + public HookContainerParser(HookClassTransformer transformer) { + this.transformer = transformer; + } + + protected void parseHooks(String className) { + transformer.logger.debug("Parsing hooks container " + className); + try { + transformer.classMetadataReader.acceptVisitor(className, new HookClassVisitor()); + } catch (IOException e) { + transformer.logger.severe("Can not parse hooks container " + className, e); + } + } + + protected void parseHooks(byte[] classData) { + + } + + private void invalidHook(String message) { + transformer.logger.warning("Found invalid hook " + currentClassName + "#" + currentMethodName); + transformer.logger.warning(message); + } + + private void createHook() { + AsmHook.Builder builder = AsmHook.newBuilder(); + Type methodType = Type.getMethodType(currentMethodDesc); + Type[] argumentTypes = methodType.getArgumentTypes(); + + if (!currentMethodPublicStatic) { + invalidHook("Hook method must be public and static."); + return; + } + + if (argumentTypes.length < 1) { + invalidHook("Hook method has no parameters. First parameter of a " + + "hook method must belong the type of the target class."); + return; + } + + if (argumentTypes[0].getSort() != Type.OBJECT) { + invalidHook("First parameter of the hook method is not an object. First parameter of a " + + "hook method must belong the type of the target class."); + return; + } + + builder.setTargetClass(argumentTypes[0].getClassName()); + + if (annotationValues.containsKey("targetMethod")) { + builder.setTargetMethod((String) annotationValues.get("targetMethod")); + } else { + builder.setTargetMethod(currentMethodName); + } + + builder.setHookClass(currentClassName); + builder.setHookMethod(currentMethodName); + builder.addThisToHookMethodParameters(); + + boolean injectOnExit = Boolean.TRUE.equals(annotationValues.get("injectOnExit")); + + int currentParameterId = 1; + for (int i = 1; i < argumentTypes.length; i++) { + Type argType = argumentTypes[i]; + if (parameterAnnotations.containsKey(i)) { + int localId = parameterAnnotations.get(i); + if (localId == -1) { + builder.setTargetMethodReturnType(argType); + builder.addReturnValueToHookMethodParameters(); + } else { + builder.addHookMethodParameter(argType, localId); + } + } else { + builder.addTargetMethodParameters(argType); + builder.addHookMethodParameter(argType, currentParameterId); + currentParameterId += argType == Type.LONG_TYPE || argType == Type.DOUBLE_TYPE ? 2 : 1; + } + } + + if (injectOnExit) builder.setInjectorFactory(AsmHook.ON_EXIT_FACTORY); + + if (annotationValues.containsKey("injectOnLine")) { + int line = (Integer) annotationValues.get("injectOnLine"); + builder.setInjectorFactory(new HookInjectorFactory.LineNumber(line)); + } + + if (annotationValues.containsKey("returnType")) { + builder.setTargetMethodReturnType((String) annotationValues.get("returnType")); + } + + ReturnCondition returnCondition = ReturnCondition.NEVER; + if (annotationValues.containsKey("returnCondition")) { + returnCondition = ReturnCondition.valueOf((String) annotationValues.get("returnCondition")); + builder.setReturnCondition(returnCondition); + } + + if (returnCondition != ReturnCondition.NEVER) { + Object primitiveConstant = getPrimitiveConstant(); + if (primitiveConstant != null) { + builder.setReturnValue(ReturnValue.PRIMITIVE_CONSTANT); + builder.setPrimitiveConstant(primitiveConstant); + } else if (Boolean.TRUE.equals(annotationValues.get("returnNull"))) { + builder.setReturnValue(ReturnValue.NULL); + } else if (annotationValues.containsKey("returnAnotherMethod")) { + builder.setReturnValue(ReturnValue.ANOTHER_METHOD_RETURN_VALUE); + builder.setReturnMethod((String) annotationValues.get("returnAnotherMethod")); + } else if (methodType.getReturnType() != Type.VOID_TYPE) { + builder.setReturnValue(ReturnValue.HOOK_RETURN_VALUE); + } + } + + // setReturnCondition и setReturnValue сетают тип хук-метода, поэтому сетнуть его вручную можно только теперь + builder.setHookMethodReturnType(methodType.getReturnType()); + + if (returnCondition == ReturnCondition.ON_TRUE && methodType.getReturnType() != Type.BOOLEAN_TYPE) { + invalidHook("Hook method must return boolean if returnCodition is ON_TRUE."); + return; + } + if ((returnCondition == ReturnCondition.ON_NULL || returnCondition == ReturnCondition.ON_NOT_NULL) && + methodType.getReturnType().getSort() != Type.OBJECT && + methodType.getReturnType().getSort() != Type.ARRAY) { + invalidHook("Hook method must return object if returnCodition is ON_NULL or ON_NOT_NULL."); + return; + } + + if (annotationValues.containsKey("priority")) { + builder.setPriority(HookPriority.valueOf((String) annotationValues.get("priority"))); + } + + if (annotationValues.containsKey("createMethod")) { + builder.setCreateMethod(Boolean.TRUE.equals(annotationValues.get("createMethod"))); + } + if (annotationValues.containsKey("isMandatory")) { + builder.setMandatory(Boolean.TRUE.equals(annotationValues.get("isMandatory"))); + } + + transformer.registerHook(builder.build()); + } + + private Object getPrimitiveConstant() { + for (Entry entry : annotationValues.entrySet()) { + if (entry.getKey().endsWith("Constant")) { + return entry.getValue(); + } + } + return null; + } + + + private class HookClassVisitor extends ClassVisitor { + public HookClassVisitor() { + super(Opcodes.ASM5); + } + + @Override + public void visit(int version, int access, String name, String signature, + String superName, String[] interfaces) { + currentClassName = name.replace('/', '.'); + } + + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + currentMethodName = name; + currentMethodDesc = desc; + currentMethodPublicStatic = (access & Opcodes.ACC_PUBLIC) != 0 && (access & Opcodes.ACC_STATIC) != 0; + return new HookMethodVisitor(); + } + } + + private class HookMethodVisitor extends MethodVisitor { + + public HookMethodVisitor() { + super(Opcodes.ASM5); + } + + @Override + public AnnotationVisitor visitAnnotation(String desc, boolean visible) { + if (HOOK_DESC.equals(desc)) { + annotationValues = new HashMap(); + inHookAnnotation = true; + } + return new HookAnnotationVisitor(); + } + + @Override + public AnnotationVisitor visitParameterAnnotation(final int parameter, String desc, boolean visible) { + if (RETURN_DESC.equals(desc)) { + parameterAnnotations.put(parameter, -1); + } + if (LOCAL_DESC.equals(desc)) { + return new AnnotationVisitor(Opcodes.ASM5) { + @Override + public void visit(String name, Object value) { + parameterAnnotations.put(parameter, (Integer) value); + } + }; + } + return null; + } + + @Override + public void visitEnd() { + if (annotationValues != null) { + createHook(); + } + parameterAnnotations.clear(); + currentMethodName = currentMethodDesc = null; + currentMethodPublicStatic = false; + annotationValues = null; + } + } + + private class HookAnnotationVisitor extends AnnotationVisitor { + + public HookAnnotationVisitor() { + super(Opcodes.ASM5); + } + + @Override + public void visit(String name, Object value) { + if (inHookAnnotation) { + annotationValues.put(name, value); + } + } + + @Override + public void visitEnum(String name, String desc, String value) { + visit(name, value); + } + + @Override + public void visitEnd() { + inHookAnnotation = false; + } + } +} diff --git a/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/HookInjectorClassVisitor.java b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/HookInjectorClassVisitor.java new file mode 100644 index 000000000..6b1702e38 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/HookInjectorClassVisitor.java @@ -0,0 +1,59 @@ +package zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.asm; + +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +import java.util.ArrayList; +import java.util.List; + +public class HookInjectorClassVisitor extends ClassVisitor { + + List hooks; + List injectedHooks = new ArrayList(1); + boolean visitingHook; + HookClassTransformer transformer; + + String superName; + + public HookInjectorClassVisitor(HookClassTransformer transformer, ClassWriter cv, List hooks) { + super(Opcodes.ASM5, cv); + this.hooks = hooks; + this.transformer = transformer; + } + + @Override public void visit(int version, int access, String name, + String signature, String superName, String[] interfaces) { + this.superName = superName; + super.visit(version, access, name, signature, superName, interfaces); + } + + @Override + public MethodVisitor visitMethod(int access, String name, String desc, + String signature, String[] exceptions) { + MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); + for (AsmHook hook : hooks) { + if (isTargetMethod(hook, name, desc) && !injectedHooks.contains(hook)) { + // добавляет MethodVisitor в цепочку + mv = hook.getInjectorFactory().createHookInjector(mv, access, name, desc, hook, this); + injectedHooks.add(hook); + } + } + return mv; + } + + @Override + public void visitEnd() { + for (AsmHook hook : hooks) { + if (hook.getCreateMethod() && !injectedHooks.contains(hook)) { + hook.createMethod(this); + } + } + super.visitEnd(); + } + + protected boolean isTargetMethod(AsmHook hook, String name, String desc) { + return hook.isTargetMethod(name, desc); + } +} diff --git a/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/HookInjectorFactory.java b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/HookInjectorFactory.java new file mode 100644 index 000000000..dbdf26b87 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/HookInjectorFactory.java @@ -0,0 +1,67 @@ +package zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.asm; + +import org.objectweb.asm.MethodVisitor; + +/** + * Фабрика, задающая тип инжектора хуков. Фактически, от выбора фабрики зависит то, в какие участки кода попадёт хук. + * "Из коробки" доступно два типа инжекторов: MethodEnter, который вставляет хук на входе в метод, + * и MethodExit, который вставляет хук на каждом выходе. + */ +public abstract class HookInjectorFactory { + + /** + * Метод AdviceAdapter#visitInsn() - штука странная. Там почему-то вызов следующего MethodVisitor'a + * производится после логики, а не до, как во всех остальных случаях. Поэтому для MethodExit приоритет + * хуков инвертируется. + */ + protected boolean isPriorityInverted = false; + + abstract HookInjectorMethodVisitor createHookInjector(MethodVisitor mv, int access, String name, String desc, + AsmHook hook, HookInjectorClassVisitor cv); + + + static class MethodEnter extends HookInjectorFactory { + + public static final MethodEnter INSTANCE = new MethodEnter(); + + private MethodEnter() {} + + @Override + public HookInjectorMethodVisitor createHookInjector(MethodVisitor mv, int access, String name, String desc, + AsmHook hook, HookInjectorClassVisitor cv) { + return new HookInjectorMethodVisitor.MethodEnter(mv, access, name, desc, hook, cv); + } + + } + + static class MethodExit extends HookInjectorFactory { + + public static final MethodExit INSTANCE = new MethodExit(); + + private MethodExit() { + isPriorityInverted = true; + } + + @Override + public HookInjectorMethodVisitor createHookInjector(MethodVisitor mv, int access, String name, String desc, + AsmHook hook, HookInjectorClassVisitor cv) { + return new HookInjectorMethodVisitor.MethodExit(mv, access, name, desc, hook, cv); + } + } + + static class LineNumber extends HookInjectorFactory { + + private int lineNumber; + + public LineNumber(int lineNumber) { + this.lineNumber = lineNumber; + } + + @Override + public HookInjectorMethodVisitor createHookInjector(MethodVisitor mv, int access, String name, String desc, + AsmHook hook, HookInjectorClassVisitor cv) { + return new HookInjectorMethodVisitor.LineNumber(mv, access, name, desc, hook, cv, lineNumber); + } + } + +} diff --git a/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/HookInjectorMethodVisitor.java b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/HookInjectorMethodVisitor.java new file mode 100644 index 000000000..869179363 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/HookInjectorMethodVisitor.java @@ -0,0 +1,101 @@ +package zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.asm; + +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.commons.AdviceAdapter; + +/** + * Класс, непосредственно вставляющий хук в метод. + * Чтобы указать конкретное место вставки хука, нужно создать класс extends HookInjector. + */ +public abstract class HookInjectorMethodVisitor extends AdviceAdapter { + + protected final AsmHook hook; + protected final HookInjectorClassVisitor cv; + public final String methodName; + public final Type methodType; + public final boolean isStatic; + + protected HookInjectorMethodVisitor(MethodVisitor mv, int access, String name, String desc, + AsmHook hook, HookInjectorClassVisitor cv) { + super(Opcodes.ASM5, mv, access, name, desc); + this.hook = hook; + this.cv = cv; + isStatic = (access & Opcodes.ACC_STATIC) != 0; + this.methodName = name; + this.methodType = Type.getMethodType(desc); + } + + /** + * Вставляет хук в байткод. + */ + protected final void visitHook() { + if (!cv.visitingHook) { + cv.visitingHook = true; + hook.inject(this); + cv.visitingHook = false; + } + } + + MethodVisitor getBasicVisitor() { + return mv; + } + + /** + * Вставляет хук в начале метода. + */ + public static class MethodEnter extends HookInjectorMethodVisitor { + + public MethodEnter(MethodVisitor mv, int access, String name, String desc, + AsmHook hook, HookInjectorClassVisitor cv) { + super(mv, access, name, desc, hook, cv); + } + + @Override + protected void onMethodEnter() { + visitHook(); + } + + } + + /** + * Вставляет хук на каждом выходе из метода, кроме выходов через throw. + */ + public static class MethodExit extends HookInjectorMethodVisitor { + + public MethodExit(MethodVisitor mv, int access, String name, String desc, + AsmHook hook, HookInjectorClassVisitor cv) { + super(mv, access, name, desc, hook, cv); + } + + @Override + protected void onMethodExit(int opcode) { + if (opcode != Opcodes.ATHROW) { + visitHook(); + } + } + } + + /** + * Вставляет хук по номеру строки. + */ + public static class LineNumber extends HookInjectorMethodVisitor { + + private int lineNumber; + + public LineNumber(MethodVisitor mv, int access, String name, String desc, + AsmHook hook, HookInjectorClassVisitor cv, int lineNumber) { + super(mv, access, name, desc, hook, cv); + this.lineNumber = lineNumber; + } + + @Override + public void visitLineNumber(int line, Label start) { + super.visitLineNumber(line, start); + if (this.lineNumber == line) visitHook(); + } + } + +} diff --git a/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/HookLogger.java b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/HookLogger.java new file mode 100644 index 000000000..fb4ef45de --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/HookLogger.java @@ -0,0 +1,69 @@ +package zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.asm; + +import java.util.logging.Level; +import java.util.logging.Logger; + +public interface HookLogger { + + void debug(String message); + + void warning(String message); + + void severe(String message); + + void severe(String message, Throwable cause); + + class SystemOutLogger implements HookLogger { + + @Override + public void debug(String message) { + System.out.println("[DEBUG] " + message); + } + + @Override + public void warning(String message) { + System.out.println("[WARNING] " + message); + } + + @Override + public void severe(String message) { + System.out.println("[SEVERE] " + message); + } + + @Override + public void severe(String message, Throwable cause) { + severe(message); + cause.printStackTrace(); + } + } + + class VanillaLogger implements HookLogger { + + private Logger logger; + + public VanillaLogger(Logger logger) { + this.logger = logger; + } + + @Override + public void debug(String message) { + logger.fine(message); + } + + @Override + public void warning(String message) { + logger.warning(message); + } + + @Override + public void severe(String message) { + logger.severe(message); + } + + @Override + public void severe(String message, Throwable cause) { + logger.log(Level.SEVERE, message, cause); + } + } + +} diff --git a/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/HookPriority.java b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/HookPriority.java new file mode 100644 index 000000000..2f56335c8 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/HookPriority.java @@ -0,0 +1,11 @@ +package zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.asm; + +public enum HookPriority { + + HIGHEST, // Вызывается первым + HIGH, + NORMAL, + LOW, + LOWEST // Вызывается последним + +} diff --git a/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/ReadClassHelper.java b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/ReadClassHelper.java new file mode 100644 index 000000000..4151dcf55 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/ReadClassHelper.java @@ -0,0 +1,28 @@ +package zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.asm; + +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; + +import java.io.InputStream; + +public class ReadClassHelper { + + public static InputStream getClassData(String className) { + String classResourceName = '/' + className.replace('.', '/') + ".class"; + return ReadClassHelper.class.getResourceAsStream(classResourceName); + } + + public static void acceptVisitor(InputStream classData, ClassVisitor visitor) { + try { + ClassReader reader = new ClassReader(classData); + reader.accept(visitor, 0); + classData.close(); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + + public static void acceptVisitor(String className, ClassVisitor visitor) { + acceptVisitor(getClassData(className), visitor); + } +} diff --git a/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/ReturnCondition.java b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/ReturnCondition.java new file mode 100644 index 000000000..2f333d38b --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/ReturnCondition.java @@ -0,0 +1,43 @@ +package zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.asm; + +/** + * В зависимости от этого значения после вызова хук-метода может быть вызван return. + */ + +public enum ReturnCondition { + + /** + * return не вызывается никогда. + */ + NEVER(false), + + /** + * return вызывается всегда. + */ + ALWAYS(false), + + /** + * return вызывается, если хук-метод вернул true. + * Нельзя применить, если хук-метод не возвращает тип boolean. + */ + ON_TRUE(true), + + /** + * return вызывается, если хук-метод вернул null. + * Нельзя применить, если хук-метод возвращает void или примитив. + */ + ON_NULL(true), + + /** + * return вызывается, если хук-метод вернул не null. + * Нельзя применить, если хук-метод возвращает void или примитив. + */ + ON_NOT_NULL(true); + + public final boolean requiresCondition; + + ReturnCondition(boolean requiresCondition) { + this.requiresCondition = requiresCondition; + } + +} diff --git a/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/ReturnValue.java b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/ReturnValue.java new file mode 100644 index 000000000..3ad322281 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/ReturnValue.java @@ -0,0 +1,40 @@ +package zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.asm; + + +/** + * В зависимости от этого значения определяется, что вернёт целевой метод + * при выходе return после вызова хук-метода. + */ +public enum ReturnValue { + + /** + * Возвращается void. + * Используется тогда и только тогда, когда целевой метод возвращает void. + */ + VOID, + + /** + * Возвращается заранее установленное примитичное значение. + * Можно использовать только когда целевой метод возвращает примитив. + */ + PRIMITIVE_CONSTANT, + + /** + * Возвращается null. + * Можно использовать только когда целевой метод возвращает объект. + */ + NULL, + + /** + * Возвращается тот примитив или объект, который вернул хук-метод. + * Можно использовать во всех случаях, кроме того, когда целевой метод возвращает void. + */ + HOOK_RETURN_VALUE, + + /** + * Вызывает другой метод в том же классе и с теми же параметрами, что и хук-метод, но с другим названием. + * Возвращает примитив или объект, который вернул вызванный метод. + */ + ANOTHER_METHOD_RETURN_VALUE + +} diff --git a/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/SafeClassWriter.java b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/SafeClassWriter.java new file mode 100644 index 000000000..034185028 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/SafeClassWriter.java @@ -0,0 +1,37 @@ +package zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.asm; + +import org.objectweb.asm.ClassWriter; + +import java.util.ArrayList; + +/** + * ClassWriter с другой реализацией метода getCommonSuperClass: при его использовании не происходит загрузки классов. + * Однако, сама по себе загрузка классов редко является проблемой, потому что инициализация класса (вызов статических + * блоков) происходит не при загрузке класса. Проблемы появляются, когда хуки вставляются в зависимые друг от друга + * классы, тогда стандартная реализация отваливается с ClassCircularityError. + */ +public class SafeClassWriter extends ClassWriter { + + private final ClassMetadataReader classMetadataReader; + + public SafeClassWriter(ClassMetadataReader classMetadataReader, int flags) { + super(flags); + this.classMetadataReader = classMetadataReader; + } + + @Override + protected String getCommonSuperClass(String type1, String type2) { + ArrayList superClasses1 = classMetadataReader.getSuperClasses(type1); + ArrayList superClasses2 = classMetadataReader.getSuperClasses(type2); + int size = Math.min(superClasses1.size(), superClasses2.size()); + int i; + for (i = 0; i < size && superClasses1.get(i).equals(superClasses2.get(i)); i++); + if (i == 0) { + return "java/lang/Object"; + } else { + return superClasses1.get(i-1); + } + } + + +} diff --git a/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/TypeHelper.java b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/TypeHelper.java new file mode 100644 index 000000000..ea14466de --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/TypeHelper.java @@ -0,0 +1,90 @@ +package zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.asm; + +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +import java.util.HashMap; +import java.util.Map; + +/** + * Класс, позволяющий создавать типы из разных входных данных. + * Эти типы нужны для того, чтобы задавать параметры и возвращаемые значения методов. + */ +public class TypeHelper { + + private static final Map primitiveTypes = new HashMap(9); + + static { + primitiveTypes.put("void", Type.VOID_TYPE); + primitiveTypes.put("boolean", Type.BOOLEAN_TYPE); + primitiveTypes.put("byte", Type.BYTE_TYPE); + primitiveTypes.put("short", Type.SHORT_TYPE); + primitiveTypes.put("char", Type.CHAR_TYPE); + primitiveTypes.put("int", Type.INT_TYPE); + primitiveTypes.put("float", Type.FLOAT_TYPE); + primitiveTypes.put("long", Type.LONG_TYPE); + primitiveTypes.put("double", Type.DOUBLE_TYPE); + } + + /** + * Создает тип по названию класса или примитива. + * Пример использования: getType("net.minecraft.world.World") - вернёт тип для World + * + * @param className необфусцированное название класса + * @return соответствующий тип + */ + public static Type getType(String className) { + return getArrayType(className, 0); + } + + /** + * Создает тип для одномерного массива указанного класса или примитиа. + * Пример использования: getArrayType("net.minecraft.world.World") - вернёт тип для World[] + * + * @param className необфусцированное название класса + * @return соответствующий классу тип одномерного массива + */ + public static Type getArrayType(String className) { + return getArrayType(className, 1); + } + + /** + * Создает тип для n-мерного массива указанного класса или примитива. + * Пример использования: getArrayType("net.minecraft.world.World", 2) - вернёт тип для World[][] + * + * @param className название класса + * @return соответствующий классу тип n-мерного массива + */ + public static Type getArrayType(String className, int arrayDimensions) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < arrayDimensions; i++) { + sb.append("["); + } + Type primitive = primitiveTypes.get(className); + if (primitive == null) { + sb.append("L"); + sb.append(className.replace(".", "/")); + sb.append(";"); + } else { + sb.append(primitive.getDescriptor()); + } + return Type.getType(sb.toString()); + } + + static Object getStackMapFrameEntry(Type type) { + if (type == Type.BOOLEAN_TYPE || type == Type.BYTE_TYPE || type == Type.SHORT_TYPE || + type == Type.CHAR_TYPE || type == Type.INT_TYPE) { + return Opcodes.INTEGER; + } + if (type == Type.FLOAT_TYPE) { + return Opcodes.FLOAT; + } + if (type == Type.DOUBLE_TYPE) { + return Opcodes.DOUBLE; + } + if (type == Type.LONG_TYPE) { + return Opcodes.LONG; + } + return type.getInternalName(); + } +} diff --git a/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/VariableIdHelper.java b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/VariableIdHelper.java new file mode 100644 index 000000000..1197a9cf2 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/asm/VariableIdHelper.java @@ -0,0 +1,58 @@ +package zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.asm; + +import org.objectweb.asm.*; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class VariableIdHelper { + + private static ClassMetadataReader classMetadataReader = new ClassMetadataReader(); + + public static List listLocalVariables(byte[] classData, final String methodName, Type... argTypes) { + final List localVariables = new ArrayList(); + String methodDesc = Type.getMethodDescriptor(Type.VOID_TYPE, argTypes); + final String methodDescWithoutReturnType = methodDesc.substring(0, methodDesc.length() - 1); + + ClassVisitor cv = new ClassVisitor(Opcodes.ASM5) { + + @Override + public MethodVisitor visitMethod(final int acc, String name, String desc, + String signature, String[] exceptions) { + if (methodName.equals(name) && desc.startsWith(methodDescWithoutReturnType)) { + return new MethodVisitor(Opcodes.ASM5) { + @Override + public void visitLocalVariable(String name, String desc, + String signature, Label start, Label end, int index) { + String typeName = Type.getType(desc).getClassName(); + int fixedIndex = index + ((acc & Opcodes.ACC_STATIC) != 0 ? 1 : 0); + localVariables.add(fixedIndex + ": " + typeName + " " + name); + } + }; + } + return null; + } + }; + + classMetadataReader.acceptVisitor(classData, cv); + return localVariables; + } + + public static List listLocalVariables(String className, final String methodName, Type... argTypes) throws IOException { + return listLocalVariables(classMetadataReader.getClassData(className), methodName, argTypes); + } + + public static void printLocalVariables(byte[] classData, String methodName, Type... argTypes) { + List locals = listLocalVariables(classData, methodName, argTypes); + for (String str : locals) { + System.out.println(str); + } + } + + public static void printLocalVariables(String className, String methodName, Type... argTypes) throws IOException { + printLocalVariables(classMetadataReader.getClassData(className), methodName, argTypes); + } + + +} diff --git a/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/disk/DiskHookLib.java b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/disk/DiskHookLib.java new file mode 100644 index 000000000..e0ce4b62b --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/disk/DiskHookLib.java @@ -0,0 +1,53 @@ +package zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.disk; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.asm.HookClassTransformer; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class DiskHookLib { + + public static void main(String[] args) throws IOException { + new DiskHookLib().process(); + } + + File untransformedDir = new File("untransformed"); + File transformedDir = new File("transformed"); + File hooksDir = new File("hooks"); + + void process() throws IOException { + HookClassTransformer transformer = new HookClassTransformer(); + for (File file : getFiles(".class", hooksDir)) { + transformer.registerHookContainer(FileUtils.readFileToByteArray(file)); + // теперь file надо скопировать в transformedDir, сохранив путь + } + for (File file : getFiles(".class", untransformedDir)) { + byte[] bytes = IOUtils.toByteArray(new FileInputStream(file)); + String className = ""; //нужно из пути получить название класса через точки вроде ru.lol.DatClass + byte[] newBytes = transformer.transform(className, bytes); + // надо закинуть файл, состоящий из newBytes в transformedDir, сохранив путь + } + } + + private static List getFiles(String postfix, File dir) throws IOException { + ArrayList files = new ArrayList(); + File[] filesArray = dir.listFiles(); + if (filesArray != null) { + for (File file : dir.listFiles()) { + if (file.isDirectory()) { + files.addAll(getFiles(postfix, file)); + } else if (file.getName().toLowerCase().endsWith(postfix)) { + files.add(file); + } + } + } + return files; + } + + +} diff --git a/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/helper/DictionaryGenerator.java b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/helper/DictionaryGenerator.java new file mode 100644 index 000000000..7affb4ef8 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/helper/DictionaryGenerator.java @@ -0,0 +1,43 @@ +package zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.helper; + +import org.apache.commons.io.FileUtils; + +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Генерирует из mcp-шного methods.csv словарь с названиями методов для хуклибы. + * Файл methods.csv лежит в mcp/conf/ + * + * Настоятельно рекомендую сгенерировать methods.bin самостоятельно для своей версии mcp, иначе могут быть + * внезапные ошибки уровня "can not find target method of hook". + */ +public class DictionaryGenerator { + + public static void main(String[] args) throws Exception { + List lines = FileUtils.readLines(new File("C:\\Users\\Quarter\\Documents\\AdvancedRocketry\\build\\extractMappings\\methods.csv")); + lines.remove(0); + HashMap map = new HashMap(); + for (String str : lines) { + String[] splitted = str.split(","); + int first = splitted[0].indexOf('_'); + int second = splitted[0].indexOf('_', first+1); + int id = Integer.valueOf(splitted[0].substring(first+1, second)); + map.put(id, splitted[1]); + } + + DataOutputStream out = new DataOutputStream(new FileOutputStream("C:\\Users\\Quarter\\Documents\\methods.bin")); + out.writeInt(map.size()); + + for (Map.Entry entry : map.entrySet()) { + out.writeInt(entry.getKey()); + out.writeUTF(entry.getValue()); + } + + out.close(); + } +} diff --git a/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/minecraft/DeobfuscationMetadataReader.java b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/minecraft/DeobfuscationMetadataReader.java new file mode 100644 index 000000000..d7a97c1c9 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/minecraft/DeobfuscationMetadataReader.java @@ -0,0 +1,91 @@ +package zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.minecraft; + +import net.minecraft.launchwrapper.Launch; +import net.minecraft.launchwrapper.LaunchClassLoader; +import net.minecraftforge.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; +import zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.asm.ClassMetadataReader; + +import java.io.IOException; +import java.lang.reflect.Method; + +/** + * Еще больше костылей вдобавок к ClassMetadataReader для работы с майновской обфускацией. + */ +public class DeobfuscationMetadataReader extends ClassMetadataReader { + + private static Method runTransformers; + + static { + try { + runTransformers = LaunchClassLoader.class.getDeclaredMethod("runTransformers", + String.class, String.class, byte[].class); + runTransformers.setAccessible(true); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public byte[] getClassData(String className) throws IOException { + byte[] bytes = super.getClassData(unmap(className.replace('.', '/'))); + return deobfuscateClass(className, bytes); + } + + @Override + protected boolean checkSameMethod(String sourceName, String sourceDesc, String targetName, String targetDesc) { + return checkSameMethod(sourceName, targetName) && sourceDesc.equals(targetDesc); + } + + // Фордж и прочее могут своими патчами добавлять методы, которые нужно уметь оверрайдить хуками. + // Для этого приходится применять трансформеры во время поиска супер-методов + // этот метод должен вызываться только во время загрузки сабклассов проверяемого класса, + // так что все должно быть норм + @Override + protected MethodReference getMethodReferenceASM(String type, String methodName, String desc) throws IOException { + FindMethodClassVisitor cv = new FindMethodClassVisitor(methodName, desc); + byte[] bytes = getTransformedBytes(type); + acceptVisitor(bytes, cv); + return cv.found ? new MethodReference(type, cv.targetName, cv.targetDesc) : null; + } + + static byte[] deobfuscateClass(String className, byte[] bytes) { + if (HookLoader.getDeobfuscationTransformer() != null) { + bytes = HookLoader.getDeobfuscationTransformer().transform(className, className, bytes); + } + return bytes; + } + + private static byte[] getTransformedBytes(String type) throws IOException { + String obfName = unmap(type); + byte[] bytes = Launch.classLoader.getClassBytes(obfName); + if (bytes == null) { + throw new RuntimeException("Bytes for " + obfName + " not found"); + } + try { + bytes = (byte[]) runTransformers.invoke(Launch.classLoader, obfName, type, bytes); + } catch (Exception e) { + e.printStackTrace(); + } + return bytes; + } + + // возвращает из необфусцированного названия типа обфусцированное + private static String unmap(String type) { + if (HookLibPlugin.getObfuscated()) { + return FMLDeobfuscatingRemapper.INSTANCE.unmap(type); + } + return type; + } + + private static boolean checkSameMethod(String srgName, String mcpName) { + if (HookLibPlugin.getObfuscated() && MinecraftClassTransformer.instance != null) { + int methodId = MinecraftClassTransformer.getMethodId(srgName); + String remappedName = MinecraftClassTransformer.instance.getMethodNames().get(methodId); + if (remappedName != null && remappedName.equals(mcpName)) { + return true; + } + } + return srgName.equals(mcpName); + } + +} diff --git a/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/minecraft/HookLibPlugin.java b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/minecraft/HookLibPlugin.java new file mode 100644 index 000000000..aba41bc64 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/minecraft/HookLibPlugin.java @@ -0,0 +1,57 @@ +package zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.minecraft; + +import net.minecraftforge.fml.relauncher.CoreModManager; +import net.minecraftforge.fml.relauncher.FMLRelaunchLog; +import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin; + +import java.lang.reflect.Field; +import java.util.Map; + +public class HookLibPlugin implements IFMLLoadingPlugin { + + private static boolean obf; + private static boolean checked; + + // 1.6.x only + public String[] getLibraryRequestClass() { + return null; + } + + // 1.7.x only + public String getAccessTransformerClass() { + return null; + } + + @Override + public String[] getASMTransformerClass() { + return new String[]{PrimaryClassTransformer.class.getName()}; + } + + @Override + public String getModContainerClass() { + return null; + } + + @Override + public String getSetupClass() { + return null; + } + + @Override + public void injectData(Map data) {} + + public static boolean getObfuscated() { + if (!checked) { + try { + Field deobfField = CoreModManager.class.getDeclaredField("deobfuscatedEnvironment"); + deobfField.setAccessible(true); + obf = !deobfField.getBoolean(null); + FMLRelaunchLog.info("[HOOKLIB] " + " Obfuscated: " + obf); + } catch (Exception e) { + e.printStackTrace(); + } + checked = true; + } + return obf; + } +} diff --git a/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/minecraft/HookLoader.java b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/minecraft/HookLoader.java new file mode 100644 index 000000000..c90447da2 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/minecraft/HookLoader.java @@ -0,0 +1,86 @@ +package zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.minecraft; + +import net.minecraftforge.fml.common.asm.transformers.DeobfuscationTransformer; +import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin; +import zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.asm.AsmHook; +import zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.asm.ClassMetadataReader; +import zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.asm.HookClassTransformer; + +import java.util.Map; + +/** + * Удобная базовая реализация IFMLLoadingPlugin для использования HookLib. + * Регистрировать хуки и контейнеры нужно в registerHooks(). + */ +public abstract class HookLoader implements IFMLLoadingPlugin { + + private static DeobfuscationTransformer deobfuscationTransformer; + + private static ClassMetadataReader deobfuscationMetadataReader; + + static { + deobfuscationMetadataReader = new DeobfuscationMetadataReader(); + } + + public static HookClassTransformer getTransformer() { + return PrimaryClassTransformer.instance.registeredSecondTransformer ? + MinecraftClassTransformer.instance : PrimaryClassTransformer.instance; + } + + /** + * Регистрирует вручную созданный хук + */ + public static void registerHook(AsmHook hook) { + getTransformer().registerHook(hook); + } + + /** + * Деобфусцирует класс с хуками и регистрирует хуки из него + */ + public static void registerHookContainer(String className) { + getTransformer().registerHookContainer(className); + } + + public static ClassMetadataReader getDeobfuscationMetadataReader() { + return deobfuscationMetadataReader; + } + + static DeobfuscationTransformer getDeobfuscationTransformer() { + if (HookLibPlugin.getObfuscated() && deobfuscationTransformer == null) { + deobfuscationTransformer = new DeobfuscationTransformer(); + } + return deobfuscationTransformer; + } + + // 1.6.x only + public String[] getLibraryRequestClass() { + return null; + } + + // 1.7.x only + public String getAccessTransformerClass() { + return null; + } + + @Override + public String[] getASMTransformerClass() { + return null; + } + + @Override + public String getModContainerClass() { + return null; + } + + @Override + public String getSetupClass() { + return null; + } + + @Override + public void injectData(Map data) { + registerHooks(); + } + + protected abstract void registerHooks(); +} diff --git a/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/minecraft/MinecraftClassTransformer.java b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/minecraft/MinecraftClassTransformer.java new file mode 100644 index 000000000..aa918b8e4 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/minecraft/MinecraftClassTransformer.java @@ -0,0 +1,108 @@ +package zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.minecraft; + +import net.minecraft.launchwrapper.IClassTransformer; +import org.objectweb.asm.ClassWriter; +import zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.asm.AsmHook; +import zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.asm.HookClassTransformer; +import zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.asm.HookInjectorClassVisitor; + +import java.io.BufferedInputStream; +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Этот трансформер занимается вставкой хуков с момента запуска майнкрафта. Здесь сосредоточены все костыли, + * которые необходимы для правильной работы с обфусцированными названиями методов. + */ +public class MinecraftClassTransformer extends HookClassTransformer implements IClassTransformer { + + static MinecraftClassTransformer instance; + private Map methodNames; + + private static List postTransformers = new ArrayList(); + + public MinecraftClassTransformer() { + instance = this; + + if (HookLibPlugin.getObfuscated()) { + try { + long timeStart = System.currentTimeMillis(); + methodNames = loadMethodNames(); + long time = System.currentTimeMillis() - timeStart; + logger.debug("Methods dictionary loaded in " + time + " ms"); + } catch (IOException e) { + logger.severe("Can not load obfuscated method names", e); + } + } + + this.classMetadataReader = HookLoader.getDeobfuscationMetadataReader(); + + this.hooksMap.putAll(PrimaryClassTransformer.instance.getHooksMap()); + PrimaryClassTransformer.instance.getHooksMap().clear(); + PrimaryClassTransformer.instance.registeredSecondTransformer = true; + } + + private HashMap loadMethodNames() throws IOException { + InputStream resourceStream = getClass().getResourceAsStream("/methods.bin"); + if (resourceStream == null) throw new IOException("Methods dictionary not found"); + DataInputStream input = new DataInputStream(new BufferedInputStream(resourceStream)); + int numMethods = input.readInt(); + HashMap map = new HashMap(numMethods); + for (int i = 0; i < numMethods; i++) { + map.put(input.readInt(), input.readUTF()); + } + input.close(); + return map; + } + + @Override + public byte[] transform(String oldName, String newName, byte[] bytecode) { + bytecode = transform(newName, bytecode); + for (int i = 0; i < postTransformers.size(); i++) { + bytecode = postTransformers.get(i).transform(oldName, newName, bytecode); + } + return bytecode; + } + + @Override + protected HookInjectorClassVisitor createInjectorClassVisitor(ClassWriter cw, List hooks) { + return new HookInjectorClassVisitor(this, cw, hooks) { + @Override + protected boolean isTargetMethod(AsmHook hook, String name, String desc) { + if (HookLibPlugin.getObfuscated()) { + String mcpName = methodNames.get(getMethodId(name)); + if (mcpName != null && super.isTargetMethod(hook, mcpName, desc)) { + return true; + } + } + return super.isTargetMethod(hook, name, desc); + } + }; + } + + public Map getMethodNames() { + return methodNames; + } + + public static int getMethodId(String srgName) { + if (srgName.startsWith("func_")) { + int first = srgName.indexOf('_'); + int second = srgName.indexOf('_', first + 1); + return Integer.valueOf(srgName.substring(first + 1, second)); + } else { + return -1; + } + } + + /** + * Регистрирует трансформер, который будет запущен после обычных, и в том числе после деобфусцирующего трансформера. + */ + public static void registerPostTransformer(IClassTransformer transformer) { + postTransformers.add(transformer); + } +} diff --git a/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/minecraft/PrimaryClassTransformer.java b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/minecraft/PrimaryClassTransformer.java new file mode 100644 index 000000000..6c7455b28 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/minecraft/PrimaryClassTransformer.java @@ -0,0 +1,96 @@ +package zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.minecraft; + +import net.minecraft.launchwrapper.IClassTransformer; +import net.minecraftforge.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Type; +import zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.asm.AsmHook; +import zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.asm.HookClassTransformer; +import zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.asm.HookInjectorClassVisitor; + +import java.util.HashMap; +import java.util.List; + +/** Этим трансформером трансформятся все классы, которые грузятся раньше майновских. + * В момент начала загрузки майна (точнее, чуть раньше - в Loader.injectData) все хуки отсюда переносятся в + * MinecraftClassTransformer. Такой перенос нужен, чтобы трансформеры хуклибы применялись последними - в частности, + * после деобфускации, которую делает фордж. + */ +public class PrimaryClassTransformer extends HookClassTransformer implements IClassTransformer { + + // костыль для случая, когда другой мод дергает хуклиб раньше, чем она запустилась + static PrimaryClassTransformer instance = new PrimaryClassTransformer(); + boolean registeredSecondTransformer; + + public PrimaryClassTransformer() { + this.classMetadataReader = HookLoader.getDeobfuscationMetadataReader(); + + if (instance != null) { + // переносим хуки, которые уже успели нарегистрировать + this.hooksMap.putAll(PrimaryClassTransformer.instance.getHooksMap()); + PrimaryClassTransformer.instance.getHooksMap().clear(); + } else { + registerHookContainer(SecondaryTransformerHook.class.getName()); + } + instance = this; + } + + @Override + public byte[] transform(String oldName, String newName, byte[] bytecode) { + return transform(newName, bytecode); + } + + @Override + protected HookInjectorClassVisitor createInjectorClassVisitor(ClassWriter cw, List hooks) { + // Если ничего не сломается, то никакие майновские классы не должны грузиться этим трансформером - + // соответственно, и костыли для деобфускации названий методов тут не нужны. + return new HookInjectorClassVisitor(this, cw, hooks) { + @Override + protected boolean isTargetMethod(AsmHook hook, String name, String desc) { + return super.isTargetMethod(hook, name, mapDesc(desc)); + } + }; + } + + HashMap> getHooksMap() { + return hooksMap; + } + + static String mapDesc(String desc) { + if (!HookLibPlugin.getObfuscated()) return desc; + + Type methodType = Type.getMethodType(desc); + Type mappedReturnType = map(methodType.getReturnType()); + Type[] argTypes = methodType.getArgumentTypes(); + Type[] mappedArgTypes = new Type[argTypes.length]; + for (int i = 0; i < mappedArgTypes.length; i++) { + mappedArgTypes[i] = map(argTypes[i]); + } + return Type.getMethodDescriptor(mappedReturnType, mappedArgTypes); + } + + static Type map(Type type) { + if (!HookLibPlugin.getObfuscated()) return type; + + // void or primitive + if (type.getSort() < 9) return type; + + //array + if (type.getSort() == 9) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < type.getDimensions(); i++) { + sb.append("["); + } + boolean isPrimitiveArray = type.getSort() < 9; + if (!isPrimitiveArray) sb.append("L"); + sb.append(map(type.getElementType()).getInternalName()); + if (!isPrimitiveArray) sb.append(";"); + return Type.getType(sb.toString()); + } else if (type.getSort() == 10) { + String unmappedName = FMLDeobfuscatingRemapper.INSTANCE.map(type.getInternalName()); + return Type.getType("L" + unmappedName + ";"); + } else { + throw new IllegalArgumentException("Can not map method type!"); + } + } +} diff --git a/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/minecraft/SecondaryTransformerHook.java b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/minecraft/SecondaryTransformerHook.java new file mode 100644 index 000000000..7fab719bc --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/repack/gloomyfolken/hooklib/minecraft/SecondaryTransformerHook.java @@ -0,0 +1,22 @@ +package zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.minecraft; + +import net.minecraft.launchwrapper.LaunchClassLoader; +import net.minecraftforge.fml.common.Loader; +import zmaster587.advancedRocketry.repack.gloomyfolken.hooklib.asm.Hook; + +public class SecondaryTransformerHook { + + /** + * Регистрирует хук-трансформер последним. + */ + @Hook + public static void injectData(Loader loader, Object... data) { + ClassLoader classLoader = SecondaryTransformerHook.class.getClassLoader(); + if (classLoader instanceof LaunchClassLoader) { + ((LaunchClassLoader)classLoader).registerTransformer(MinecraftClassTransformer.class.getName()); + } else { + System.out.println("HookLib was not loaded by LaunchClassLoader. Hooks will not be injected."); + } + } + +} diff --git a/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteBiomeChanger.java b/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteBiomeChanger.java index 090b36f40..67639e104 100644 --- a/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteBiomeChanger.java +++ b/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteBiomeChanger.java @@ -99,7 +99,7 @@ public void tickEntity() { HashedBlockPosition pos = toChangeList.remove(world.rand.nextInt(toChangeList.size())); //HashedBlockPosition pos = toChangeList.remove(toChangeList.size()-1); - BiomeHandler.changeBiome(world, biomeId, pos.getBlockPos(), true); + BiomeHandler.terraform(world, biomeId, pos.getBlockPos(), true, world.provider.getDimension()); } } else break; diff --git a/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteData.java b/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteData.java index 2ba335720..5c36fa337 100644 --- a/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteData.java +++ b/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteData.java @@ -53,6 +53,8 @@ public boolean acceptsItemInConstruction(@Nonnull ItemStack item) { public void setProperties(@Nonnull ItemStack satelliteProperties) { super.setProperties(satelliteProperties); data.setMaxData(this.satelliteProperties.getMaxDataStorage()); + powerConsumption = getPowerPerTick(); + collectionTime = (int) (200 / Math.sqrt(0.1 * powerConsumption)); } @@ -113,6 +115,7 @@ public void tickEntity() { //Add data to the buffer, if the satellite has enough power data.addData(getDataCreated(), data.getDataType(), true); + //System.out.println("data: "+data.getData()+":"+getDataCreated()+":"+collectionTime); } @Override diff --git a/src/main/java/zmaster587/advancedRocketry/stations/SpaceStationObject.java b/src/main/java/zmaster587/advancedRocketry/stations/SpaceStationObject.java index a2a10bd3b..10340153f 100644 --- a/src/main/java/zmaster587/advancedRocketry/stations/SpaceStationObject.java +++ b/src/main/java/zmaster587/advancedRocketry/stations/SpaceStationObject.java @@ -77,6 +77,10 @@ public SpaceStationObject() { rotation = new double[3]; } + public Set getKnownPlanetList() { + return knownPlanetList; + } + public long getExpireTime() { return Long.MAX_VALUE; } diff --git a/src/main/java/zmaster587/advancedRocketry/tile/TileBrokenPart.java b/src/main/java/zmaster587/advancedRocketry/tile/TileBrokenPart.java index 3909eb0eb..8922ab5fb 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/TileBrokenPart.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/TileBrokenPart.java @@ -1,6 +1,8 @@ package zmaster587.advancedRocketry.tile; +import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +import zmaster587.advancedRocketry.util.IBrokenPartBlock; import javax.annotation.Nonnull; import java.util.Random; @@ -67,6 +69,15 @@ public boolean transition() { return false; } + @Override + public boolean canRenderBreaking() { + return true; + } + + public ItemStack getDrop() { + return ((IBrokenPartBlock) this.getBlockType()).getDropItem(world.getBlockState(pos), world, this); + } + @Nonnull @Override public NBTTagCompound writeToNBT(final NBTTagCompound compound) { diff --git a/src/main/java/zmaster587/advancedRocketry/tile/TileEntitySyncable.java b/src/main/java/zmaster587/advancedRocketry/tile/TileEntitySyncable.java index 909793a55..ca3ca3df8 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/TileEntitySyncable.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/TileEntitySyncable.java @@ -10,8 +10,10 @@ public class TileEntitySyncable extends TileEntity { public void markDirty() { super.markDirty(); - IBlockState state = world.getBlockState(pos); - world.notifyBlockUpdate(pos, state, state, 3); + if (hasWorld()) { + IBlockState state = world.getBlockState(pos); + world.notifyBlockUpdate(pos, state, state, 3); + } } @Override diff --git a/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java b/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java index a85c9bee6..23b5385c5 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java @@ -65,7 +65,7 @@ public class TileRocketAssemblingMachine extends TileEntityRFConsumer implements private final static int MAXSCANDELAY = 10; private final static int ENERGYFOROP = 100; private final static int MAX_SIZE = 16; - private final static int MAX_SIZE_Y = 64; + private final static int MAX_SIZE_Y = 128; private final static int MIN_SIZE = 3; private final static int MIN_SIZE_Y = 4; private static final ProgressBarImage horizontalProgressBar = new ProgressBarImage(89, 9, 81, 17, 176, 0, 80, 15, 0, 2, EnumFacing.EAST, backdrop); @@ -152,7 +152,7 @@ public float getAcceleration(float gravitationalMultiplier) { return stats.getAcceleration(gravitationalMultiplier); } - public int getWeight() { + public float getWeight() { return stats.getWeight(); } @@ -164,8 +164,14 @@ public float getNeededThrust() { return getWeight(); } - public float getNeededFuel(@Nonnull FuelType fuelType) { - return getAcceleration(getGravityMultiplier()) > 0 ? 2 * stats.getBaseFuelRate(fuelType) * MathHelper.sqrt((2 * (ARConfiguration.getCurrentConfig().orbit - this.getPos().getY())) / getAcceleration(getGravityMultiplier())) : 0; + public boolean hasEnoughFuel(@Nonnull FuelType fuelType) { + //return getAcceleration(getGravityMultiplier()) > 0 ? 2 * stats.getBaseFuelRate(fuelType) * MathHelper.sqrt((2 * (ARConfiguration.getCurrentConfig().orbit - this.getPos().getY())) / getAcceleration(getGravityMultiplier())) : 0; + float a = getAcceleration(getGravityMultiplier()); + float fueltime = (float) stats.getFuelCapacity(fuelType) / stats.getBaseFuelRate(fuelType); + float s_can = a/2f*fueltime*fueltime; + float target_s = 1 * ARConfiguration.getCurrentConfig().orbit - this.getPos().getY(); // for way back *2 + return s_can > target_s; + } public float getGravityMultiplier() { @@ -211,6 +217,7 @@ public void performFunction() { //TODO call function instead if (thrustText != null) updateText(); + } progress++; @@ -239,9 +246,32 @@ public boolean isScanning() { return totalProgress > 0; } - public void scanRocket(World world, BlockPos pos2, AxisAlignedBB bb) { + public AxisAlignedBB scanRocket(World world, BlockPos pos2, AxisAlignedBB bb) { + + world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 3); + + stats = new StatsRocket(); // reset stats + + //if already a rocket exists, output their stats + + if (getBBCache() == null) { + bbCache = getRocketPadBounds(world, pos); + } + + if (getBBCache() != null) { + double buffer = 0.0001; + AxisAlignedBB bufferedBB = bbCache.grow(buffer, buffer, buffer); + List rockets = world.getEntitiesWithinAABB(EntityRocket.class, bufferedBB); + if (rockets.size() == 1){ // only if axactly one rocket is here + rockets.get(0).recalculateStats(); + this.stats = rockets.get(0).stats; + status = ErrorCodes.ALREADY_ASSEMBLED; // to prevent assembly + return null; + } + } + - int thrustMonopropellant = 0; + int thrustMonopropellant = 0; int thrustBipropellant = 0; int thrustNuclearNozzleLimit = 0; int thrustNuclearReactorLimit = 0; @@ -253,7 +283,7 @@ public void scanRocket(World world, BlockPos pos2, AxisAlignedBB bb) { int fuelCapacityBipropellant = 0; int fuelCapacityOxidizer = 0; int fuelCapacityNuclearWorkingFluid = 0; - int numBlocks = 0; + float drillPower = 0f; stats.reset(); @@ -318,9 +348,11 @@ public void scanRocket(World world, BlockPos pos2, AxisAlignedBB bb) { continue; } - numBlocks++; - - weight += WeightEngine.INSTANCE.getWeight(world, currBlockPos); + if (ARConfiguration.getCurrentConfig().advancedWeightSystem) { + weight += WeightEngine.INSTANCE.getWeight(world, currBlockPos); + } else { + weight += 1; + } //If rocketEngine increaseThrust final float x = xCurr - actualMinX - ((actualMaxX - actualMinX) / 2f); @@ -336,18 +368,18 @@ public void scanRocket(World world, BlockPos pos2, AxisAlignedBB bb) { monopropellantfuelUse += ((IRocketEngine) block).getFuelConsumptionRate(world, xCurr, yCurr, zCurr); thrustMonopropellant += ((IRocketEngine) block).getThrust(world, currBlockPos); } - stats.addEngineLocation(x, yCurr - actualMinY, z); + stats.addEngineLocation(x + 0.5f, yCurr - actualMinY + 0.5f, z + 0.5f); } if (block instanceof IFuelTank) { - if (block instanceof BlockFuelTank) { - fuelCapacityMonopropellant += (((IFuelTank) block).getMaxFill(world, currBlockPos, state) * ARConfiguration.getCurrentConfig().fuelCapacityMultiplier); - } else if (block instanceof BlockBipropellantFuelTank) { + if (block instanceof BlockBipropellantFuelTank) { fuelCapacityBipropellant += (((IFuelTank) block).getMaxFill(world, currBlockPos, state) * ARConfiguration.getCurrentConfig().fuelCapacityMultiplier); } else if (block instanceof BlockOxidizerFuelTank) { fuelCapacityOxidizer += (((IFuelTank) block).getMaxFill(world, currBlockPos, state) * ARConfiguration.getCurrentConfig().fuelCapacityMultiplier); } else if (block instanceof BlockNuclearFuelTank) { fuelCapacityNuclearWorkingFluid += (((IFuelTank) block).getMaxFill(world, currBlockPos, state) * ARConfiguration.getCurrentConfig().fuelCapacityMultiplier); + } else if (block instanceof BlockFuelTank) { + fuelCapacityMonopropellant += (((IFuelTank) block).getMaxFill(world, currBlockPos, state) * ARConfiguration.getCurrentConfig().fuelCapacityMultiplier); } } @@ -356,7 +388,7 @@ public void scanRocket(World world, BlockPos pos2, AxisAlignedBB bb) { } if (block instanceof BlockSeat && world.getBlockState(abovePos).getBlock().isPassable(world, abovePos)) { - stats.addPassengerSeat((int) (x), yCurr - actualMinY, (int) (z)); + stats.addPassengerSeat((int) Math.floor(x), yCurr - actualMinY, (int) Math.floor(z)); } if (block instanceof IMiningDrill) { @@ -366,12 +398,14 @@ public void scanRocket(World world, BlockPos pos2, AxisAlignedBB bb) { TileEntity tile = world.getTileEntity(currBlockPos); if (tile instanceof TileSatelliteHatch) { hasSatellite = true; - TileSatelliteHatch hatch = (TileSatelliteHatch) tile; - if (hatch.getSatellite() != null) { - weight += hatch.getSatellite().getProperties().getWeight(); - } else if (hatch.getStackInSlot(0).getItem() instanceof ItemPackedStructure) { - ItemPackedStructure struct = (ItemPackedStructure) hatch.getStackInSlot(0).getItem(); - weight += struct.getStructure(hatch.getStackInSlot(0)).getWeight(); + if (ARConfiguration.getCurrentConfig().advancedWeightSystem) { + TileSatelliteHatch hatch = (TileSatelliteHatch) tile; + if (hatch.getSatellite() != null) { + weight += hatch.getSatellite().getProperties().getWeight(); + } else if (hatch.getStackInSlot(0).getItem() instanceof ItemPackedStructure) { + ItemPackedStructure struct = (ItemPackedStructure) hatch.getStackInSlot(0).getItem(); + weight += struct.getStructure(hatch.getStackInSlot(0)).getWeight(); + } } } else if (tile instanceof TileGuidanceComputer) { hasGuidance = true; @@ -402,13 +436,14 @@ public void scanRocket(World world, BlockPos pos2, AxisAlignedBB bb) { stats.setFuelCapacity(FuelType.NUCLEAR_WORKING_FLUID, fuelCapacityNuclearWorkingFluid); //Non-fuel stats - stats.setWeight((int) weight); + stats.setWeight(weight); stats.setThrust(Math.max(Math.max(thrustMonopropellant, thrustBipropellant), thrustNuclearTotalLimit)); stats.setDrillingPower(drillPower); //Total stats, used to check if the user has tried to apply two or more types of thrust/fuel int totalFuel = fuelCapacityBipropellant + fuelCapacityNuclearWorkingFluid + fuelCapacityMonopropellant; int totalFuelUse = bipropellantfuelUse + nuclearWorkingFluidUse + monopropellantfuelUse; + //System.out.println("rocket fuel use:"+totalFuelUse); //Set status if (invalidBlock) @@ -421,11 +456,13 @@ else if (!hasGuidance && !hasSatellite) status = ErrorCodes.NOGUIDANCE; else if (getThrust() <= getNeededThrust()) status = ErrorCodes.NOENGINES; - else if (((thrustBipropellant > 0) && getFuel(FuelType.LIQUID_BIPROPELLANT) < getNeededFuel(FuelType.LIQUID_BIPROPELLANT)) || ((thrustMonopropellant > 0) && getFuel(FuelType.LIQUID_MONOPROPELLANT) < getNeededFuel(FuelType.LIQUID_MONOPROPELLANT)) || ((thrustNuclearTotalLimit > 0) && getFuel(FuelType.NUCLEAR_WORKING_FLUID) < getNeededFuel(FuelType.NUCLEAR_WORKING_FLUID))) + else if (((thrustBipropellant > 0) && !hasEnoughFuel(FuelType.LIQUID_BIPROPELLANT)) || ((thrustMonopropellant > 0) && !hasEnoughFuel(FuelType.LIQUID_MONOPROPELLANT)) || ((thrustNuclearTotalLimit > 0) && !hasEnoughFuel(FuelType.NUCLEAR_WORKING_FLUID))) status = ErrorCodes.NOFUEL; else status = ErrorCodes.SUCCESS; } + + return new AxisAlignedBB(actualMinX, actualMinY, actualMinZ, actualMaxX, actualMaxY, actualMaxZ); } private void removeReplaceableBlocks(AxisAlignedBB bb) { @@ -452,8 +489,8 @@ public void assembleRocket() { if (bbCache == null || world.isRemote) return; - //Need to scan again b/c something may have changed - scanRocket(world, pos, bbCache); + // Need to scan again b/c something may have changed + AxisAlignedBB rocketBB = scanRocket(world, pos, bbCache); if (status != ErrorCodes.SUCCESS) return; @@ -468,7 +505,10 @@ public void assembleRocket() { return; } - EntityRocket rocket = new EntityRocket(world, storageChunk, stats.copy(), bbCache.minX + (bbCache.maxX - bbCache.minX) / 2f + .5f, this.getPos().getY(), bbCache.minZ + (bbCache.maxZ - bbCache.minZ) / 2f + .5f); + EntityRocket rocket = new EntityRocket(world, storageChunk, stats.copy(), + rocketBB.minX + (rocketBB.maxX - rocketBB.minX) / 2f + .5f, + this.getPos().getY(), + rocketBB.minZ + (rocketBB.maxZ - rocketBB.minZ) / 2f + .5f); world.spawnEntity(rocket); NBTTagCompound nbtdata = new NBTTagCompound(); @@ -484,6 +524,8 @@ public void assembleRocket() { for (IInfrastructure infrastructure : getConnectedInfrastructure()) { rocket.linkInfrastructure(infrastructure); } + + scanRocket(world, pos, bbCache); // to show stats } /** @@ -754,9 +796,9 @@ public void useNetworkData(EntityPlayer player, Side side, byte id, } protected void updateText() { - thrustText.setText(isScanning() ? (LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.thrust") + ": ???") : String.format("%s: %dkN", LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.thrust"), getThrust() * 10)); - weightText.setText(isScanning() ? (LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.weight") + ": ???") : String.format("%s: %.2fkN", LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.weight"), (getWeight() * 10 * getGravityMultiplier()))); - fuelText.setText(isScanning() ? (LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.fuel") + ": ???") : String.format("%s: %dmb/s", LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.fuel"), getRocketStats().getBaseFuelRate((stats.getFuelCapacity(FuelType.LIQUID_MONOPROPELLANT) > 0) ? FuelType.LIQUID_MONOPROPELLANT : (stats.getFuelCapacity(FuelType.NUCLEAR_WORKING_FLUID) > 0) ? FuelType.NUCLEAR_WORKING_FLUID : FuelType.LIQUID_BIPROPELLANT))); + thrustText.setText(isScanning() ? (LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.thrust") + ": ???") : String.format("%s: %dkN", LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.thrust"), getThrust())); + weightText.setText(isScanning() ? (LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.weight") + ": ???") : String.format("%s: %.2fkN", LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.weight"), (getWeight() * getGravityMultiplier()))); + fuelText.setText(isScanning() ? (LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.fuel") + ": ???") : String.format("%s: %dmb/s", LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.fuel"), 20* getRocketStats().getFuelRate((stats.getFuelCapacity(FuelType.LIQUID_MONOPROPELLANT) > 0) ? FuelType.LIQUID_MONOPROPELLANT : (stats.getFuelCapacity(FuelType.NUCLEAR_WORKING_FLUID) > 0) ? FuelType.NUCLEAR_WORKING_FLUID : FuelType.LIQUID_BIPROPELLANT))); accelerationText.setText(isScanning() ? (LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.acc") + ": ???") : String.format("%s: %.2fm/s\u00b2", LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.acc"), getAcceleration(getGravityMultiplier()) * 20f)); if (!world.isRemote) { if (getRocketPadBounds(world, pos) == null) @@ -799,7 +841,7 @@ public List getModules(int ID, EntityPlayer player) { updateText(); - for (int i = 0; i < 5; i++) + for (int i = 0; i < 15; i++) modules.add(new ModuleSync(i, this)); @@ -820,7 +862,7 @@ public float getNormallizedProgress(int id) { switch (id) { case 0: FuelType fuelType = (stats.getBaseFuelRate(FuelType.LIQUID_MONOPROPELLANT) > 0) ? FuelType.LIQUID_MONOPROPELLANT : (stats.getBaseFuelRate(FuelType.NUCLEAR_WORKING_FLUID) > 0) ? FuelType.NUCLEAR_WORKING_FLUID : FuelType.LIQUID_BIPROPELLANT; - return (this.getAcceleration(getGravityMultiplier()) > 0) ? MathHelper.clamp(0.5f + 0.5f * ((this.getFuel(fuelType) - this.getNeededFuel(fuelType)) / this.getNeededFuel(fuelType)), 0f, 1f) : 0; + return (this.getAcceleration(getGravityMultiplier()) > 0) ? MathHelper.clamp(0.5f + 0.5f * ((float) (this.getFuel(fuelType) - this.stats.getFuelCapacity(fuelType)) / this.stats.getFuelCapacity(fuelType)), 0f, 1f) : 0; case 1: return MathHelper.clamp(0.5f + this.getAcceleration(getGravityMultiplier()) * 10, 0f, 1f); case 2: @@ -866,19 +908,56 @@ public void setTotalProgress(int id, int progress) { public void setData(int id, int value) { switch (id) { case 0: - getRocketStats().setFuelRate(FuelType.LIQUID_MONOPROPELLANT, value); + getRocketStats().setWeight(value/1000f); break; case 1: - getRocketStats().setWeight(value); + getRocketStats().setThrust(value); break; case 2: - getRocketStats().setThrust(value); + setStatus(value); break; + + case 3: - getRocketStats().setFuelCapacity(FuelType.LIQUID_MONOPROPELLANT, value); + getRocketStats().setBaseFuelRate(FuelType.LIQUID_MONOPROPELLANT, value); break; case 4: - setStatus(value); + getRocketStats().setFuelAmount(FuelType.LIQUID_MONOPROPELLANT, value); + break; + case 5: + getRocketStats().setFuelCapacity(FuelType.LIQUID_MONOPROPELLANT, value); + break; + case 6: + getRocketStats().setFuelRate(FuelType.LIQUID_MONOPROPELLANT, value); + break; + + case 7: + getRocketStats().setFuelRate(FuelType.LIQUID_BIPROPELLANT, value); + break; + case 8: + getRocketStats().setFuelAmount(FuelType.LIQUID_BIPROPELLANT, value); + break; + case 9: + getRocketStats().setFuelRate(FuelType.LIQUID_BIPROPELLANT, value); + break; + case 10: + getRocketStats().setFuelRate(FuelType.LIQUID_BIPROPELLANT, value); + break; + + case 11: + getRocketStats().setFuelRate(FuelType.NUCLEAR_WORKING_FLUID, value); + break; + case 12: + getRocketStats().setFuelAmount(FuelType.NUCLEAR_WORKING_FLUID, value); + break; + case 13: + getRocketStats().setFuelRate(FuelType.NUCLEAR_WORKING_FLUID, value); + break; + case 14: + getRocketStats().setFuelRate(FuelType.NUCLEAR_WORKING_FLUID, value); + break; + + } updateText(); } @@ -886,16 +965,43 @@ public void setData(int id, int value) { @Override public int getData(int id) { switch (id) { + case 0: - return getRocketStats().getBaseFuelRate(FuelType.LIQUID_MONOPROPELLANT); + return (int)(getRocketStats().getWeight_NoFuel()*1000);// because it is a float really so take it *1000 case 1: - return getRocketStats().getWeight(); - case 2: return getRocketStats().getThrust(); + case 2: + return getStatus().ordinal(); + + case 3: - return getRocketStats().getFuelCapacity(FuelType.LIQUID_MONOPROPELLANT); + return getRocketStats().getBaseFuelRate(FuelType.LIQUID_MONOPROPELLANT); case 4: - return getStatus().ordinal(); + return getRocketStats().getFuelAmount(FuelType.LIQUID_MONOPROPELLANT); + case 5: + return getRocketStats().getFuelCapacity(FuelType.LIQUID_MONOPROPELLANT); + case 6: + return getRocketStats().getFuelRate(FuelType.LIQUID_MONOPROPELLANT); + + case 7: + return getRocketStats().getBaseFuelRate(FuelType.LIQUID_BIPROPELLANT); + case 8: + return getRocketStats().getFuelAmount(FuelType.LIQUID_BIPROPELLANT); + case 9: + return getRocketStats().getFuelCapacity(FuelType.LIQUID_BIPROPELLANT); + case 10: + return getRocketStats().getFuelRate(FuelType.LIQUID_BIPROPELLANT); + + case 11: + return getRocketStats().getBaseFuelRate(FuelType.NUCLEAR_WORKING_FLUID); + case 12: + return getRocketStats().getFuelAmount(FuelType.NUCLEAR_WORKING_FLUID); + case 13: + return getRocketStats().getFuelCapacity(FuelType.NUCLEAR_WORKING_FLUID); + case 14: + return getRocketStats().getFuelRate(FuelType.NUCLEAR_WORKING_FLUID); + + } return 0; } @@ -903,7 +1009,7 @@ public int getData(int id) { @Override public void onInventoryButtonPressed(int buttonId) { PacketHandler.sendToServer(new PacketMachine(this, (byte) (buttonId))); - updateText(); + //updateText(); } @Override @@ -926,12 +1032,12 @@ public boolean onLinkStart(@Nonnull ItemStack item, TileEntity entity, public boolean onLinkComplete(@Nonnull ItemStack item, TileEntity entity, EntityPlayer player, World world) { TileEntity tile = world.getTileEntity(ItemLinker.getMasterCoords(item)); - float maxlinkDistance = 5; + float maxlinkDistance = 15; if (tile instanceof IInfrastructure) { HashedBlockPosition pos = new HashedBlockPosition(tile.getPos()); - if (pos.getDistance(new HashedBlockPosition(this.pos)) > maxlinkDistance){ + if (pos.getDistance(new HashedBlockPosition(this.pos)) > maxlinkDistance) { if (!world.isRemote) player.sendMessage(new TextComponentTranslation("the machine is too far away to be linked")); return false; @@ -1047,7 +1153,8 @@ protected enum ErrorCodes { NOSATELLITECHIP(LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.nosatellitechip")), OUTPUTBLOCKED(LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.outputblocked")), INVALIDBLOCK(LibVulpes.proxy.getLocalizedString("msg.rocketbuild.invalidblock")), - COMBINEDTHRUST(LibVulpes.proxy.getLocalizedString("msg.rocketbuild.combinedthrust")); + COMBINEDTHRUST(LibVulpes.proxy.getLocalizedString("msg.rocketbuild.combinedthrust")), + ALREADY_ASSEMBLED("rocket already assembled"); String code; diff --git a/src/main/java/zmaster587/advancedRocketry/tile/TileStationAssembler.java b/src/main/java/zmaster587/advancedRocketry/tile/TileStationAssembler.java index 70f91ec02..74b2fdaaf 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/TileStationAssembler.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/TileStationAssembler.java @@ -60,7 +60,7 @@ public boolean canScan() { } @Override - public void scanRocket(World world, BlockPos pos2, AxisAlignedBB bb) { + public AxisAlignedBB scanRocket(World world, BlockPos pos2, AxisAlignedBB bb) { int actualMinX = (int) bb.maxX, actualMinY = (int) bb.maxY, @@ -94,6 +94,8 @@ public void scanRocket(World world, BlockPos pos2, AxisAlignedBB bb) { } status = ErrorCodes.SUCCESS_STATION; + + return new AxisAlignedBB(actualMinX, actualMinY, actualMinZ, actualMaxX, actualMaxY, actualMaxZ); } diff --git a/src/main/java/zmaster587/advancedRocketry/tile/TileUnmannedVehicleAssembler.java b/src/main/java/zmaster587/advancedRocketry/tile/TileUnmannedVehicleAssembler.java index 431243442..6869bb1ee 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/TileUnmannedVehicleAssembler.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/TileUnmannedVehicleAssembler.java @@ -155,8 +155,8 @@ public void assembleRocket() { //TODO get direction of rocket @Override - public void scanRocket(World world, BlockPos pos2, AxisAlignedBB bb) { - + public AxisAlignedBB scanRocket(World world, BlockPos pos2, AxisAlignedBB bb) { + // TODO Refactor! Duplicated with TileRocketAssemblingMachine int thrustMonopropellant = 0; int thrustBipropellant = 0; int thrustNuclearNozzleLimit = 0; @@ -321,11 +321,13 @@ else if (((thrustBipropellant > 0) && getFuel(FuelType.LIQUID_BIPROPELLANT) < ge else status = ErrorCodes.SUCCESS; } + + return new AxisAlignedBB(actualMinX, actualMinY, actualMinZ, actualMaxX, actualMaxY, actualMaxZ); } - @Override + public float getNeededFuel(@Nonnull FuelType fuelType) { - return getAcceleration(DimensionManager.getInstance().getDimensionProperties(world.provider.getDimension()).getGravitationalMultiplier()) > 0 ? stats.getFuelRate(fuelType) : 0; + return 1; } //No additional scanning is needed diff --git a/src/main/java/zmaster587/advancedRocketry/tile/atmosphere/TileOxygenVent.java b/src/main/java/zmaster587/advancedRocketry/tile/atmosphere/TileOxygenVent.java index 6f865e6bb..f154fd7f2 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/atmosphere/TileOxygenVent.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/atmosphere/TileOxygenVent.java @@ -55,7 +55,7 @@ public class TileOxygenVent extends TileInventoriedRFConsumerTank implements IBl private boolean hasFluid; private boolean soundInit; private boolean allowTrace; - private boolean lock; + private boolean blockUpdated; private int numScrubbers; private List scrubbers; private int radius = 0; @@ -103,23 +103,7 @@ public World getWorldObj() { @Override public void onAdjacentBlockUpdated() { - - if (isSealed) - activateAdjBlocks(); - scrubbers.clear(); - TileEntity[] tiles = new TileEntity[6]; - tiles[0] = world.getTileEntity(pos.add(1, 0, 0)); - tiles[1] = world.getTileEntity(pos.add(-1, 0, 0)); - tiles[2] = world.getTileEntity(pos.add(0, 1, 0)); - tiles[3] = world.getTileEntity(pos.add(0, -1, 0)); - tiles[4] = world.getTileEntity(pos.add(0, 0, 1)); - tiles[5] = world.getTileEntity(pos.add(0, 0, -1)); - - lock = true; - for (TileEntity tile : tiles) { - if (tile instanceof TileCO2Scrubber && world.getBlockState(tile.getPos()).getBlock() == AdvancedRocketryBlocks.blockCO2Scrubber) - scrubbers.add((TileCO2Scrubber) tile); - } + blockUpdated = true; // the performFunction will take it from here } private void activateAdjBlocks() { @@ -186,6 +170,28 @@ public boolean isTurnedOn() { @Override public void performFunction() { + + if (blockUpdated) { // this was moved from onAdjacentBlockUpdated(); to prevent crash + if (isSealed) + activateAdjBlocks(); + scrubbers.clear(); + TileEntity[] tiles = new TileEntity[6]; + tiles[0] = world.getTileEntity(pos.add(1, 0, 0)); + tiles[1] = world.getTileEntity(pos.add(-1, 0, 0)); + tiles[2] = world.getTileEntity(pos.add(0, 1, 0)); + tiles[3] = world.getTileEntity(pos.add(0, -1, 0)); + tiles[4] = world.getTileEntity(pos.add(0, 0, 1)); + tiles[5] = world.getTileEntity(pos.add(0, 0, -1)); + + + for (TileEntity tile : tiles) { + if (tile instanceof TileCO2Scrubber && world.getBlockState(tile.getPos()).getBlock() == AdvancedRocketryBlocks.blockCO2Scrubber) + scrubbers.add((TileCO2Scrubber) tile); + } + blockUpdated = false; + } + + /* NB: canPerformFunction returns false and must return true for performFunction to execute * if there is no O2 handler, this is why we can safely call AtmosphereHandler.getOxygenHandler * and not have to worry about an NPE being thrown @@ -232,8 +238,7 @@ public void performFunction() { } } - //Lock the vent while the scrubbers do their block updates - if (isSealed && !lock) { + if (isSealed) { //If scrubbers exist and the config allows then use the cartridge if (ARConfiguration.getCurrentConfig().scrubberRequiresCartrige) { @@ -266,8 +271,7 @@ public void performFunction() { hasFluid = false; } - } else - lock = false; + } } } diff --git a/src/main/java/zmaster587/advancedRocketry/tile/hatch/TileInvHatch.java b/src/main/java/zmaster587/advancedRocketry/tile/hatch/TileInvHatch.java new file mode 100644 index 000000000..53c3e90a2 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/tile/hatch/TileInvHatch.java @@ -0,0 +1,15 @@ +package zmaster587.advancedRocketry.tile.hatch; + +import zmaster587.libVulpes.tile.multiblock.hatch.TileInventoryHatch; + +public class TileInvHatch extends TileInventoryHatch { + + public TileInvHatch(int invSize) { + super(invSize); + } + + @Override + public String getModularInventoryName() { + return "container.invhatch"; + } +} diff --git a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketMonitoringStation.java b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketMonitoringStation.java index fc6a55e99..9ab6b6334 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketMonitoringStation.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketMonitoringStation.java @@ -48,6 +48,7 @@ public class TileRocketMonitoringStation extends TileEntity implements IModularI int rocketHeight; int velocity; int fuelLevel, maxFuelLevel; + int oxidizerFuelLevel; public TileRocketMonitoringStation() { mission = null; @@ -243,6 +244,7 @@ public List getModules(int ID, EntityPlayer player) { modules.add(new ModuleProgress(98, 4, 0, new IndicatorBarImage(2, 7, 12, 81, 17, 0, 6, 6, 1, 0, EnumFacing.UP, TextureResources.rocketHud), this)); modules.add(new ModuleProgress(120, 14, 1, new IndicatorBarImage(2, 95, 12, 71, 17, 0, 6, 6, 1, 0, EnumFacing.UP, TextureResources.rocketHud), this)); modules.add(new ModuleProgress(142, 14, 2, new ProgressBarImage(2, 173, 12, 71, 17, 6, 3, 69, 1, 1, EnumFacing.UP, TextureResources.rocketHud), this)); + modules.add(new ModuleProgress(148, 14, 6, new ProgressBarImage(2, 173, 12, 71, 17, 75, 3, 69, 1, 1, EnumFacing.UP, TextureResources.rocketHud), this)); //modules.add(redstoneControl); setMissionText(); @@ -319,6 +321,8 @@ else if (id == 1) velocity = progress; else if (id == 2) fuelLevel = progress; + else if (id == 6) + oxidizerFuelLevel = progress; } @Override @@ -333,15 +337,20 @@ else if (id == 1) return velocity; else if (id == 2) return fuelLevel; + else if (id == 6) + return oxidizerFuelLevel; if (linkedRocket == null) return 0; + if (id == 0) return (int) linkedRocket.posY; else if (id == 1) return (int) (linkedRocket.motionY * 100); else if (id == 2) - return (linkedRocket.getRocketFuelType() == FuelRegistry.FuelType.LIQUID_BIPROPELLANT) ? linkedRocket.getFuelAmount(linkedRocket.getRocketFuelType()) + linkedRocket.getFuelAmount(FuelRegistry.FuelType.LIQUID_OXIDIZER) : linkedRocket.getFuelAmount(linkedRocket.getRocketFuelType()); + return linkedRocket.getFuelAmount(linkedRocket.getRocketFuelType()); + else if (id == 6) + return linkedRocket.getFuelAmount(FuelRegistry.FuelType.LIQUID_OXIDIZER); return 0; } @@ -351,21 +360,32 @@ public int getTotalProgress(int id) { if (id == 0) return ARConfiguration.getCurrentConfig().orbit; else if (id == 1) - return 200; + return 1000; else if (id == 2) if (world.isRemote) return maxFuelLevel; else if (linkedRocket == null) return 0; else - return (linkedRocket.getRocketFuelType() == FuelRegistry.FuelType.LIQUID_BIPROPELLANT) ? linkedRocket.getFuelCapacity(linkedRocket.getRocketFuelType()) + linkedRocket.getFuelCapacity(FuelRegistry.FuelType.LIQUID_OXIDIZER) : linkedRocket.getFuelCapacity(linkedRocket.getRocketFuelType()); + return linkedRocket.getFuelCapacity(linkedRocket.getRocketFuelType()); + + else if (id == 6) + if (world.isRemote) + return maxFuelLevel; + else if (linkedRocket == null) + return 0; + else + return linkedRocket.getFuelCapacity(FuelRegistry.FuelType.LIQUID_OXIDIZER); + + + return 1; } @Override public void setTotalProgress(int id, int progress) { //Should only become an issue if configs are desynced or fuel - if (id == 2) + if (id == 2 || id == 6) maxFuelLevel = progress; } diff --git a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketServiceStation.java b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketServiceStation.java new file mode 100644 index 000000000..af31a044c --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketServiceStation.java @@ -0,0 +1,562 @@ +package zmaster587.advancedRocketry.tile.infrastructure; + +import io.netty.buffer.ByteBuf; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.ITickable; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.TextComponentTranslation; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import zmaster587.advancedRocketry.AdvancedRocketry; +import zmaster587.advancedRocketry.api.EntityRocketBase; +import zmaster587.advancedRocketry.api.IFuelTank; +import zmaster587.advancedRocketry.api.IInfrastructure; +import zmaster587.advancedRocketry.api.IMission; +import zmaster587.advancedRocketry.block.BlockBipropellantRocketMotor; +import zmaster587.advancedRocketry.block.BlockRocketMotor; +import zmaster587.advancedRocketry.block.BlockSeat; +import zmaster587.advancedRocketry.entity.EntityRocket; +import zmaster587.advancedRocketry.inventory.TextureResources; +import zmaster587.advancedRocketry.tile.TileBrokenPart; +import zmaster587.advancedRocketry.tile.multiblock.machine.TilePrecisionAssembler; +import zmaster587.advancedRocketry.util.IBrokenPartBlock; +import zmaster587.advancedRocketry.util.InventoryUtil; +import zmaster587.advancedRocketry.util.StorageChunk; +import zmaster587.advancedRocketry.util.nbt.NBTHelper; +import zmaster587.libVulpes.LibVulpes; +import zmaster587.libVulpes.block.BlockTile; +import zmaster587.libVulpes.interfaces.ILinkableTile; +import zmaster587.libVulpes.inventory.modules.*; +import zmaster587.libVulpes.items.ItemLinker; +import zmaster587.libVulpes.network.PacketEntity; +import zmaster587.libVulpes.network.PacketHandler; +import zmaster587.libVulpes.network.PacketMachine; +import zmaster587.libVulpes.tile.IComparatorOverride; +import zmaster587.libVulpes.tile.TileEntityRFConsumer; +import zmaster587.libVulpes.util.IAdjBlockUpdate; +import zmaster587.libVulpes.util.INetworkMachine; + +import javax.annotation.Nonnull; +import java.util.*; +import java.util.stream.Collectors; + +public class TileRocketServiceStation extends TileEntityRFConsumer implements IModularInventory, ITickable, IAdjBlockUpdate, IInfrastructure, ILinkableTile, INetworkMachine, IButtonInventory, IProgressBar, IComparatorOverride { + + EntityRocketBase linkedRocket; + + ModuleText destroyProbText; + ModuleText destroyProgressText; + ModuleText wornMotorsText; + ModuleText wornSeatsText; + ModuleText wornTanksText; + ModuleText wornMotorsCount; + ModuleText wornSeatsCount; + ModuleText wornTanksCount; + boolean was_powered = false; + + List assemblers = new ArrayList<>(); + List assemblerPoses = new ArrayList<>(); + TileBrokenPart[] partsProcessing = new TileBrokenPart[0]; + IBlockState[] statesProcessing = new IBlockState[0]; + + int initialPartToRepairCount; + List partsToRepair = new LinkedList<>(); + List statesToRepair = new LinkedList<>(); + + public TileRocketServiceStation() { + super(10000); + + destroyProbText = new ModuleText(90, 30, LibVulpes.proxy.getLocalizedString("msg.serviceStation.destroyProbNA"), 0x2b2b2b, true); + wornMotorsText = new ModuleText(40, 30 + 30, LibVulpes.proxy.getLocalizedString("msg.serviceStation.wornMotorsText"), 0x2b2b2b, true); + wornSeatsText = new ModuleText(90, 30 + 30, LibVulpes.proxy.getLocalizedString("msg.serviceStation.wornSeatsText"), 0x2b2b2b, true); + wornTanksText = new ModuleText(140, 30 + 30, LibVulpes.proxy.getLocalizedString("msg.serviceStation.wornTanksText"), 0x2b2b2b, true); + destroyProgressText = new ModuleText(90, 120, LibVulpes.proxy.getLocalizedString("msg.serviceStation.serviceProgressNA"), 0x2b2b2b, true); + + wornMotorsCount = new ModuleText(40, 30 + 30 + 10, "0", 0x2b2b2b, true); + wornSeatsCount = new ModuleText(90, 30 + 30 + 10, "0", 0x2b2b2b, true); + wornTanksCount = new ModuleText(140, 30 + 30 + 10, "0", 0x2b2b2b, true); + } + + @Override + public void invalidate() { + super.invalidate(); + + if (linkedRocket != null) { + linkedRocket.unlinkInfrastructure(this); + unlinkRocket(); + } + } + + public boolean getEquivalentPower() { + //if (state == RedstoneState.OFF) + // return false; + + boolean state2 = world.isBlockIndirectlyGettingPowered(pos) > 0; + + //if (state == RedstoneState.INVERTED) + // state2 = !state2; + return state2; + } + + @Override + public void onAdjacentBlockUpdated() { + + } + + @Override + public int getMaxLinkDistance() { + return 3000; + } + + public void updateRepairList() { + updateRepairList(true); + } + + private void updateRepairList(boolean initial) { + EntityRocket rocket = (EntityRocket) linkedRocket; + partsToRepair = new LinkedList<>(); + statesToRepair = new LinkedList<>(); + + for (TileEntity te : rocket.storage.getTileEntityList()) { + if (te instanceof TileBrokenPart) { + TileBrokenPart part = (TileBrokenPart) te; + if (part.getStage() > 0) { + partsToRepair.add(part); + statesToRepair.add(rocket.storage.getBlockState(te.getPos())); + } + } + } + + if (initial) { + initialPartToRepairCount = partsToRepair.size(); + } + } + + private void scanForAssemblers() { + this.assemblers = new ArrayList<>(); + + int size = 5; + + for (int x = getPos().getX() - size; x < getPos().getX() + size; x++) { + for (int y = getPos().getY() - size; y < getPos().getY() + size; y++) { + for (int z = getPos().getZ() - size; z < getPos().getZ() + size; z++) { + TileEntity te = world.getTileEntity(new BlockPos(x, y, z)); + if (te instanceof TilePrecisionAssembler) { + this.assemblers.add((TilePrecisionAssembler) te); + } + } + } + } + + this.statesProcessing = new IBlockState[assemblers.size()]; + this.partsProcessing = new TileBrokenPart[assemblers.size()]; + } + + private boolean processAssemblerResult(int index) { + StorageChunk storage = ((EntityRocket) linkedRocket).storage; + TilePrecisionAssembler assembler = assemblers.get(index); + + if (InventoryUtil.hasItemInInventories(assembler.getItemOutPorts(), "rocket", true)) { + IBlockState state = statesProcessing[index]; + TileBrokenPart te = partsProcessing[index]; + + if (te == null) { + AdvancedRocketry.logger.warn("Rocket service station at " + getPos() + + " is out of sync with connected assemblers! Repairing part lost"); + return false; + } + + te.setStage(0); + storage.addTileEntity(te); + storage.setBlockState(te.getPos(), state); + + statesProcessing[index] = null; + partsProcessing[index] = null; + + assembler.markDirty(); + + return true; + } + return false; + } + + private void syncRocket() { + NBTTagCompound nbtdata = new NBTTagCompound(); + + linkedRocket.writeToNBT(nbtdata); + PacketHandler.sendToNearby(new PacketEntity((EntityRocket) linkedRocket, (byte) 0, nbtdata), linkedRocket.world.provider.getDimension(), this.pos, 64); + } + + private void consumePartToRepair(int assemblerIndex) { + StorageChunk storage = ((EntityRocket) linkedRocket).storage; + + TilePrecisionAssembler assembler = assemblers.get(assemblerIndex); + TileBrokenPart part = partsToRepair.get(0); + IBlockState state = statesToRepair.get(0); + if (!(part.getBlockType() instanceof IBrokenPartBlock)) { + AdvancedRocketry.logger.warn("Rocket part at " + part.getPos() + " is out of sync with its block! Removing"); + statesToRepair.remove(0); + partsToRepair.remove(0); + return; + } + IBrokenPartBlock partBlock = (IBrokenPartBlock) part.getBlockType(); + + // add to processing list + statesProcessing[assemblerIndex] = state; + partsProcessing[assemblerIndex] = part; + + // add to the assembler + ItemStack resultingStack = partBlock.getDropItem(statesToRepair.get(0), world, part); + if (!InventoryUtil.addItemToOneOfTheInventories(assembler.getItemInPorts(), resultingStack)) { + AdvancedRocketry.logger.error("Precision assembler at " + assembler.getPos() + " overflows. Repaired part lost"); + } + statesToRepair.remove(0); + partsToRepair.remove(0); + + // consume parts from the rocket + storage.getTileEntityList().remove(part); + storage.setBlockState(part.getPos(), Blocks.AIR.getDefaultState()); + assembler.onInventoryUpdated(); + } + + private void giveWorkToAssemblers() { + boolean dirty = false; + for (int i = 0; i < assemblers.size(); i++) { + if (assemblers.get(i).isInvalid()) { + // it is invalid, so we should not operate with it + assemblers.set(i, null); + partsProcessing[i] = null; + statesProcessing[i] = null; + continue; + } + + dirty = dirty || processAssemblerResult(i); + + TilePrecisionAssembler assembler = assemblers.get(i); + + if (InventoryUtil.hasItemInInventories(assembler.getItemInPorts(), "motor", false)) { + // assembler already have a motor for work, skipping + continue; + } + + if (!this.partsToRepair.isEmpty() && statesProcessing[i] == null) { + consumePartToRepair(i); + dirty = true; + } + } + if (dirty) { + syncRocket(); + } + } + + @Override + public void performFunction() { + if (linkedRocket instanceof EntityRocket) { + // stay with the right blockstate + IBlockState state = world.getBlockState(pos); + if (!state.getValue(BlockTile.STATE)) { + world.setBlockState(pos, state.withProperty(BlockTile.STATE, true)); + } + + if (getEquivalentPower() && linkedRocket != null) { + if (!was_powered) { + scanForAssemblers(); + was_powered = true; + } else { + if (assemblerPoses != null) { + // lazy access to assembler list loaded from NBT + assemblers = assemblerPoses.stream().map(pos -> (TilePrecisionAssembler) world.getTileEntity(pos)).collect(Collectors.toList()); + assemblerPoses = null; + + this.statesProcessing = new IBlockState[assemblers.size()]; + this.partsProcessing = new TileBrokenPart[assemblers.size()]; + + updateRepairList(false); + } + } + + giveWorkToAssemblers(); + } + } + if (!getEquivalentPower()) { + was_powered = false; + } + } + + @Override + public boolean canPerformFunction() { + if (world.isRemote || world.getWorldTime() % 20 != 0) { + return false; + } + + boolean hasWork = partsToRepair.size() > 0 || Arrays.stream(partsProcessing).anyMatch(Objects::nonNull); + + if (hasWork) { + return true; + } + + IBlockState state = world.getBlockState(pos); + if (state.getValue(BlockTile.STATE)) { + world.setBlockState(pos, state.withProperty(BlockTile.STATE, false)); + } + return false; + } + + @Override + public int getPowerPerOperation() { + return 10; + } + + @Override + public boolean onLinkStart(@Nonnull ItemStack item, TileEntity entity, EntityPlayer player, World world) { + ItemLinker.setMasterCoords(item, getPos()); + if (linkedRocket != null) { + linkedRocket.unlinkInfrastructure(this); + unlinkRocket(); + } + + if (player.world.isRemote) + Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentTranslation("%s %s", new TextComponentTranslation("msg.serviceStation.link"), ": " + getPos().getX() + " " + getPos().getY() + " " + getPos().getZ())); + return true; + } + + @Override + public boolean onLinkComplete(@Nonnull ItemStack item, TileEntity entity, EntityPlayer player, World world) { + if (player.world.isRemote) + Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentTranslation("msg.linker.error.firstMachine")); + return false; + } + + @Override + public void unlinkRocket() { + linkedRocket = null; + + dropRepairStats(); + } + + public void dropRepairStats() { + partsToRepair = new LinkedList<>(); + statesToRepair = new LinkedList<>(); + initialPartToRepairCount = 0; + } + + @Override + public boolean disconnectOnLiftOff() { + return true; + } + + @Override + public boolean linkRocket(EntityRocketBase rocket) { + this.linkedRocket = rocket; + if (rocket instanceof EntityRocket) { + updateRepairList(); + } + return true; + } + + @Override + public NBTTagCompound getUpdateTag() { + return writeToNBT(new NBTTagCompound()); + } + + @Override + public void readFromNBT(NBTTagCompound nbt) { + super.readFromNBT(nbt); + was_powered = nbt.getBoolean("was_powered"); + initialPartToRepairCount = nbt.getInteger("initialPartToRepairCount"); + + assemblerPoses = NBTHelper.readCollection("assemblerPoses", nbt, ArrayList::new, NBTHelper::readBlockPos); + partsProcessing = NBTHelper.readCollection("partsProcessing", nbt, ArrayList::new, NBTHelper::readTileEntity).toArray(new TileBrokenPart[0]); + statesProcessing = NBTHelper.readCollection("statesProcessing", nbt, ArrayList::new, NBTHelper::readState).toArray(new IBlockState[0]); + } + + @Override + public NBTTagCompound writeToNBT(NBTTagCompound nbt) { + super.writeToNBT(nbt); + nbt.setBoolean("was_powered", was_powered); + nbt.setInteger("initialPartToRepairCount", initialPartToRepairCount); + + NBTHelper.writeCollection("assemblerPoses", nbt, this.assemblers, te -> NBTHelper.writeBlockPos(te.getPos())); + NBTHelper.writeCollection("partsProcessing", nbt, Arrays.asList(this.partsProcessing), NBTHelper::writeTileEntity); + NBTHelper.writeCollection("statesProcessing", nbt, Arrays.asList(this.statesProcessing), NBTHelper::writeState); + + return nbt; + } + + @Override + public void writeDataToNetwork(ByteBuf out, byte id) { + + } + + @Override + public void readDataFromNetwork(ByteBuf in, byte packetId, + NBTTagCompound nbt) { + + } + + @Override + public List getModules(int ID, EntityPlayer player) { + LinkedList modules = new LinkedList<>(); + + modules.add(new ModulePower(10, 20, this.energy)); + modules.add(new ModuleButton(63 - 52 / 2, 100, 0, LibVulpes.proxy.getLocalizedString("msg.serviceStation.assemblerScan"), + this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild, 104, 16)); + + updateText(); + + modules.add(destroyProbText); + modules.add(wornMotorsText); + modules.add(wornSeatsText); + modules.add(wornTanksText); + modules.add(destroyProgressText); + modules.add(wornMotorsCount); + modules.add(wornSeatsCount); + modules.add(wornTanksCount); + + modules.add(new ModuleProgress(32, 133, 0, TextureResources.progressToMission, this)); + + if (!world.isRemote) { + PacketHandler.sendToPlayer(new PacketMachine(this, (byte) 1), player); + } + + return modules; + } + + private void updateText() { + if (linkedRocket != null) { + if (!(linkedRocket instanceof EntityRocket)) { +// System.out.println("Huh, error...."); + destroyProbText.setText(LibVulpes.proxy.getLocalizedString("msg.serviceStation.destroyProbNA")); + return; + } + EntityRocket rocket = (EntityRocket) linkedRocket; + destroyProbText.setText(LibVulpes.proxy.getLocalizedString("msg.serviceStation.destroyProb") + ": " + rocket.storage.getBreakingProbability()); + List brokenParts = rocket.storage.getBrokenBlocks(); + long motorsCount = brokenParts + .stream() + .filter(te -> te.getStage() > 0 && (te.getBlockType() instanceof BlockRocketMotor + || te.getBlockType() instanceof BlockBipropellantRocketMotor)) + .count(); + long seatsCount = brokenParts + .stream() + .filter(te -> te.getStage() > 0 && te.getBlockType() instanceof BlockSeat) + .count(); + long tanksCount = brokenParts + .stream() + .filter(te -> te.getStage() > 0 && te.getBlockType() instanceof IFuelTank) + .count(); + + this.wornMotorsCount.setText(String.valueOf(motorsCount)); + this.wornSeatsCount.setText(String.valueOf(seatsCount)); + this.wornTanksCount.setText(String.valueOf(tanksCount)); + } else { + destroyProbText.setText(LibVulpes.proxy.getLocalizedString("msg.serviceStation.destroyProbNA")); + } + } + + @Override + public void useNetworkData(EntityPlayer player, Side side, byte id, + NBTTagCompound nbt) { + if (id == 0) { + scanForAssemblers(); + } + } + + @Override + public void onInventoryButtonPressed(int buttonId) { + if (buttonId == 0) { + PacketHandler.sendToServer(new PacketMachine(this, (byte) 0)); + } + } + + @Override + public String getModularInventoryName() { + return "container.servicestation"; + } + + @Override + public float getNormallizedProgress(int id) { + if (id == 1) { + return Math.max(Math.min(0.5f + (getProgress(id) / (float) getTotalProgress(id)), 1), 0f); + } + + //keep text updated + if (world.isRemote) + updateText(); + + return Math.min(getProgress(id) / (float) getTotalProgress(id), 1.0f); + } + + @Override + public void setProgress(int id, int progress) { + + } + + @Override + public int getProgress(int id) { + //Try to keep client synced with server, this also allows us to put the monitor on a different world altogether + if (world.isRemote) + if (id == 0) { + if (!(linkedRocket instanceof EntityRocket)) { +// System.out.println("Huh, error...."); + return 0; + } + return initialPartToRepairCount - partsToRepair.size() - (int) Arrays.stream(partsProcessing).filter(Objects::nonNull).count(); + } + + return 0; + } + + @Override + public int getTotalProgress(int id) { +// if (id == 0) +// return ARConfiguration.getCurrentConfig().orbit;ё +// else if (id == 1) +// return 200; + if (id == 0) { + return initialPartToRepairCount; + } + return 0; + } + + @Override + public void setTotalProgress(int id, int progress) { + //Should only become an issue if configs are desynced or fuel +// if (id == 2) +// maxFuelLevel = progress; + } + + @Override + public boolean canInteractWithContainer(EntityPlayer entity) { + return true; + } + + @Override + public boolean linkMission(IMission mission) { + return false; + } + + @Override + public void unlinkMission() { + updateText(); + } + + @Override + public boolean canRenderConnection() { + return false; + } + + @Override + public int getComparatorOverride() { +// if (linkedRocket instanceof EntityRocket) { +// return (int) (15 * ((EntityRocket) linkedRocket).getRelativeHeightFraction()); +// } + return 0; + } +} diff --git a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileAtmosphereTerraformer.java b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileAtmosphereTerraformer.java index 101fe3ccd..9da712a97 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileAtmosphereTerraformer.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileAtmosphereTerraformer.java @@ -2,37 +2,25 @@ import io.netty.buffer.ByteBuf; import net.minecraft.client.Minecraft; -import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.init.Blocks; -import net.minecraft.inventory.IInventory; -import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.network.NetworkManager; -import net.minecraft.network.play.server.SPacketUpdateTileEntity; -import net.minecraft.server.MinecraftServer; import net.minecraft.util.EnumFacing; import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundEvent; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.TextComponentString; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import zmaster587.advancedRocketry.AdvancedRocketry; -import zmaster587.advancedRocketry.api.*; -import zmaster587.advancedRocketry.api.satellite.SatelliteBase; +import zmaster587.advancedRocketry.api.ARConfiguration; +import zmaster587.advancedRocketry.api.AdvancedRocketryBlocks; +import zmaster587.advancedRocketry.api.AdvancedRocketryFluids; import zmaster587.advancedRocketry.dimension.DimensionManager; import zmaster587.advancedRocketry.dimension.DimensionProperties; -import zmaster587.advancedRocketry.item.ItemSatelliteIdentificationChip; -import zmaster587.advancedRocketry.network.PacketBiomeIDChange; -import zmaster587.advancedRocketry.satellite.SatelliteBiomeChanger; import zmaster587.advancedRocketry.util.AudioRegistry; -import zmaster587.advancedRocketry.world.ChunkManagerPlanet; import zmaster587.advancedRocketry.world.provider.WorldProviderPlanet; import zmaster587.libVulpes.LibVulpes; import zmaster587.libVulpes.api.LibVulpesBlocks; @@ -44,16 +32,13 @@ import zmaster587.libVulpes.network.PacketMachine; import zmaster587.libVulpes.tile.multiblock.TileMultiPowerConsumer; import zmaster587.libVulpes.tile.multiblock.TileMultiblockMachine; -import zmaster587.libVulpes.tile.multiblock.TileMultiblockMachine.NetworkPackets; -import zmaster587.libVulpes.util.EmbeddedInventory; -import zmaster587.libVulpes.util.HashedBlockPosition; import zmaster587.libVulpes.util.INetworkMachine; import zmaster587.libVulpes.util.IconResource; -import javax.annotation.Nonnull; import java.util.LinkedList; import java.util.List; -import java.util.logging.Logger; + +//This code is a complete mess. it should be rewritten just like the space laser, but it kinda works, so I'll leave it with this for now public class TileAtmosphereTerraformer extends TileMultiPowerConsumer implements INetworkMachine { @@ -276,13 +261,16 @@ public class TileAtmosphereTerraformer extends TileMultiPowerConsumer implements private ModuleToggleSwitch buttonIncrease, buttonDecrease; private ModuleRadioButton radioButton; private ModuleText text; - //private EmbeddedInventory inv; + private boolean outOfFluid; - private boolean was_outOfFluid_last_tick; private int last_mode; int requiredN2 = 0, requiredO2 = 0; - //private boolean had_linker_last_tick; + + boolean client_contructed = false; + public TileAtmosphereTerraformer() { + super(); + completionTime = (int) (18000 * ARConfiguration.getCurrentConfig().terraformSpeed); buttonIncrease = new ModuleToggleSwitch(40, 20, 1, LibVulpes.proxy.getLocalizedString("msg.terraformer.atminc"), this, TextureResources.buttonScan, 80, 16, true); buttonDecrease = new ModuleToggleSwitch(40, 38, 2, LibVulpes.proxy.getLocalizedString("msg.terraformer.atmdec"), this, TextureResources.buttonScan, 80, 16, false); @@ -293,10 +281,15 @@ public TileAtmosphereTerraformer() { buttons.add(buttonIncrease); buttons.add(buttonDecrease); radioButton = new ModuleRadioButton(this, buttons); - //inv = new EmbeddedInventory(1); + outOfFluid = false; - was_outOfFluid_last_tick = false; last_mode = radioButton.getOptionSelected(); + + } + + @Override + public void update() { + super.update(); } private int getCompletionTime() { @@ -306,12 +299,12 @@ private int getCompletionTime() { @Override @SideOnly(Side.CLIENT) public double getMaxRenderDistanceSquared() { - return 160*160; + return 320 * 320; } @Override public List getModules(int ID, EntityPlayer player) { - List modules = super.getModules(ID, player); + List modules = super.getModules(ID, player); //Backgrounds if (world.isRemote) { @@ -322,6 +315,7 @@ public List getModules(int ID, EntityPlayer player) { modules.add(new ModuleProgress(30, 57, 0, zmaster587.advancedRocketry.inventory.TextureResources.terraformProgressBar, this)); modules.add(text); + setText(); int i = 0; @@ -338,6 +332,7 @@ private void setText() { String statusText; + if (outOfFluid) statusText = LibVulpes.proxy.getLocalizedString("msg.terraformer.outofgas"); @@ -362,36 +357,37 @@ public AxisAlignedBB getRenderBoundingBox() { @Override protected void onRunningPoweredTick() { - - + //System.out.println("energy:"+this.batteries.getUniversalEnergyStored()); if (world.isRemote && !outOfFluid) { if (Minecraft.getMinecraft().gameSettings.particleSetting < 2) { EnumFacing dir = RotatableBlock.getFront(world.getBlockState(pos)).getOpposite(); - if (radioButton.getOptionSelected() == 0) { - if (world.getTotalWorldTime() % 20 == 0) { - float xMot = (float) ((0.5f - world.rand.nextGaussian()) / 40f); - float zMot = (float) ((0.5f - world.rand.nextGaussian()) / 40f); + for (int i = 0; i < 3; i++) { + + + if (radioButton.getOptionSelected() == 0) { + float xMot = (float) ((world.rand.nextGaussian()) / 40f); + float zMot = (float) ((world.rand.nextGaussian()) / 40f); BlockPos offsetPos = pos.offset(dir); AdvancedRocketry.proxy.spawnParticle("rocketSmoke", world, offsetPos.getX() + 5, pos.getY() + 7, offsetPos.getZ() + 0.5, xMot, 0.02f, zMot); AdvancedRocketry.proxy.spawnParticle("rocketSmoke", world, offsetPos.getX() - 4, pos.getY() + 7, offsetPos.getZ() + 0.5, xMot, 0.02f, zMot); AdvancedRocketry.proxy.spawnParticle("rocketSmoke", world, offsetPos.getX() + 0.5f, pos.getY() + 7, offsetPos.getZ() - 4, xMot, 0.02f, zMot); AdvancedRocketry.proxy.spawnParticle("rocketSmoke", world, offsetPos.getX() + 0.5f, pos.getY() + 7, offsetPos.getZ() + 5, xMot, 0.02f, zMot); + + } else { + float xMot = (float) ((world.rand.nextGaussian()) / 4f); + float yMot = (float) (world.rand.nextGaussian() / 20f); + float zMot = (float) ((world.rand.nextGaussian()) / 4f); + BlockPos offsetPos = pos.offset(dir); + AdvancedRocketry.proxy.spawnParticle("rocketSmokeInverse", world, offsetPos.getX() + 5, pos.getY() + 7, offsetPos.getZ() + 0.5, xMot, 0.4f + yMot, zMot); + AdvancedRocketry.proxy.spawnParticle("rocketSmokeInverse", world, offsetPos.getX() - 4, pos.getY() + 7, offsetPos.getZ() + 0.5, xMot, 0.4f + yMot, zMot); + AdvancedRocketry.proxy.spawnParticle("rocketSmokeInverse", world, offsetPos.getX() + 0.5f, pos.getY() + 7, offsetPos.getZ() - 4, xMot, 0.4f + yMot, zMot); + AdvancedRocketry.proxy.spawnParticle("rocketSmokeInverse", world, offsetPos.getX() + 0.5f, pos.getY() + 7, offsetPos.getZ() + 5, xMot, 0.4f + yMot, zMot); } - } else { - float xMot = (float) ((0.5f - world.rand.nextGaussian()) / 4f); - float yMot = (float) (world.rand.nextGaussian() / 20f); - float zMot = (float) ((0.5f - world.rand.nextGaussian()) / 4f); - BlockPos offsetPos = pos.offset(dir); - AdvancedRocketry.proxy.spawnParticle("rocketSmokeInverse", world, offsetPos.getX() + 5, pos.getY() + 7, offsetPos.getZ() + 0.5, xMot, 0.4f + yMot, zMot); - AdvancedRocketry.proxy.spawnParticle("rocketSmokeInverse", world, offsetPos.getX() - 4, pos.getY() + 7, offsetPos.getZ() + 0.5, xMot, 0.4f + yMot, zMot); - AdvancedRocketry.proxy.spawnParticle("rocketSmokeInverse", world, offsetPos.getX() + 0.5f, pos.getY() + 7, offsetPos.getZ() - 4, xMot, 0.4f + yMot, zMot); - AdvancedRocketry.proxy.spawnParticle("rocketSmokeInverse", world, offsetPos.getX() + 0.5f, pos.getY() + 7, offsetPos.getZ() + 5, xMot, 0.4f + yMot, zMot); } } } - if (!ARConfiguration.getCurrentConfig().terraformRequiresFluid) return; @@ -421,29 +417,12 @@ protected void onRunningPoweredTick() { if (requiredN2 != 0 || requiredO2 != 0) { - outOfFluid = true; - if (!was_outOfFluid_last_tick){ - was_outOfFluid_last_tick = true; - PacketHandler.sendToNearby(new PacketMachine(this, (byte)23),world.provider.getDimension(),pos,256.0); - } - - //this.setMachineEnabled(false); - //this.setMachineRunning(false); - //markDirty(); + setOOF(true); } else { - outOfFluid = false; - if (was_outOfFluid_last_tick){ - was_outOfFluid_last_tick = false; - PacketHandler.sendToNearby(new PacketMachine(this, (byte)23),world.provider.getDimension(),pos,256.0); - } - } - } - else{ - outOfFluid = false; - if (was_outOfFluid_last_tick){ - was_outOfFluid_last_tick = false; - PacketHandler.sendToNearby(new PacketMachine(this, (byte)23),world.provider.getDimension(),pos,256.0); + setOOF(false); } + } else { + setOOF(false); } } @@ -459,6 +438,7 @@ protected void onRunningPoweredTick() { /////////from the super method } } + public SoundEvent getSound() { return AudioRegistry.machineLarge; } @@ -468,19 +448,6 @@ public int getSoundDuration() { return 80; } - //moved to new machine: TerraformingTerminal -/* - private boolean hasValidBiomeChanger() { - ItemStack biomeChanger = inv.getStackInSlot(0); - SatelliteBase satellite; - - return !biomeChanger.isEmpty() && - (biomeChanger.getItem() instanceof ItemBiomeChanger) && - SatelliteRegistry.getSatellite(biomeChanger) != null && - (satellite = ((ItemSatelliteIdentificationChip) AdvancedRocketryItems.itemBiomeChanger).getSatellite(biomeChanger)).getDimensionId() == world.provider.getDimension() && - satellite instanceof SatelliteBiomeChanger; - } -*/ @Override protected void playMachineSound(SoundEvent event) { world.playSound(getPos().getX(), getPos().getY() + 7, getPos().getZ(), event, SoundCategory.BLOCKS, Minecraft.getMinecraft().gameSettings.getSoundLevel(SoundCategory.BLOCKS), 0.975f + world.rand.nextFloat() * 0.05f, false); @@ -489,7 +456,9 @@ protected void playMachineSound(SoundEvent event) { @Override public boolean isRunning() { - boolean bool = getMachineEnabled() && super.isRunning() && zmaster587.advancedRocketry.api.ARConfiguration.getCurrentConfig().enableTerraforming; + boolean bool = getMachineEnabled() && + //super.isRunning() && + zmaster587.advancedRocketry.api.ARConfiguration.getCurrentConfig().enableTerraforming; if (!bool) currentTime = 0; @@ -497,21 +466,28 @@ public boolean isRunning() { return bool; } - @Override - public SPacketUpdateTileEntity getUpdatePacket() { - NBTTagCompound nbt = new NBTTagCompound(); - writeToNBT(nbt); - return new SPacketUpdateTileEntity(pos, 0, nbt); + public void setOOF(boolean x) { + if (!x && outOfFluid) { + outOfFluid = false; + this.world.notifyBlockUpdate(this.pos, this.world.getBlockState(this.pos), this.world.getBlockState(this.pos), 3); + + //System.out.println("s oof false"); + } else if (x && !outOfFluid) { + outOfFluid = true; + this.world.notifyBlockUpdate(this.pos, this.world.getBlockState(this.pos), this.world.getBlockState(this.pos), 3); + + //System.out.println("s oof true"); + } } @Override - public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt) { - NBTTagCompound nbt = pkt.getNbtCompound(); - readFromNBT(nbt); - setText(); + public void setMachineRunning(boolean running) { + super.setMachineRunning(running); + this.world.notifyBlockUpdate(this.pos, this.world.getBlockState(this.pos), this.world.getBlockState(this.pos), 3); } + @Override protected void processComplete() { super.processComplete(); @@ -526,6 +502,8 @@ protected void processComplete() { this.setMachineEnabled(false); this.setMachineRunning(false); markDirty(); + this.world.notifyBlockUpdate(this.pos, this.world.getBlockState(this.pos), this.world.getBlockState(this.pos), 3); + } } if (buttonDecrease.getState() && properties.getAtmosphereDensity() > 0) { @@ -534,6 +512,8 @@ protected void processComplete() { this.setMachineEnabled(false); this.setMachineRunning(false); markDirty(); + this.world.notifyBlockUpdate(this.pos, this.world.getBlockState(this.pos), this.world.getBlockState(this.pos), 3); + } } } @@ -542,29 +522,22 @@ protected void processComplete() { @Override public void readDataFromNetwork(ByteBuf in, byte packetId, NBTTagCompound nbt) { - super.readDataFromNetwork(in,packetId, nbt); + super.readDataFromNetwork(in, packetId, nbt); + if (packetId == (byte) TileMultiblockMachine.NetworkPackets.TOGGLE.ordinal()) { radioButton.setOptionSelected(in.readByte()); } - - if (packetId == (byte) 23){ - nbt.setBoolean("outOfFluid", in.readBoolean()); - } } @Override public void writeDataToNetwork(ByteBuf out, byte id) { - super.writeDataToNetwork(out,id); + super.writeDataToNetwork(out, id); if (id == (byte) TileMultiblockMachine.NetworkPackets.TOGGLE.ordinal()) { out.writeByte(radioButton.getOptionSelected()); } - - if (id == (byte) 23){ - out.writeBoolean(outOfFluid); - } - } + @Override public void setMachineEnabled(boolean enabled) { super.setMachineEnabled(enabled); @@ -573,60 +546,61 @@ public void setMachineEnabled(boolean enabled) { completionTime = getCompletionTime(); } - @Override - public void setMachineRunning(boolean running) { - super.setMachineRunning(running); - markDirty(); - } - @Override public void useNetworkData(EntityPlayer player, Side side, byte id, NBTTagCompound nbt) { super.useNetworkData(player, side, id, nbt); + if(!world.isRemote) { + setOOF(false); + markDirty(); + this.world.notifyBlockUpdate(this.pos, this.world.getBlockState(this.pos), this.world.getBlockState(this.pos), 3); - if (!world.isRemote && id == NetworkPackets.TOGGLE.ordinal()) { - outOfFluid = false; - was_outOfFluid_last_tick = false; - setMachineRunning(isRunning()); - } - - if(world.isRemote && id == (byte) 23) { - this.outOfFluid = nbt.getBoolean("outOfFluid"); } - } @Override public void onInventoryButtonPressed(int buttonId) { //if (hasValidBiomeChanger()) { - super.onInventoryButtonPressed(buttonId); - outOfFluid = false; - if (buttonId == 1 || buttonId == 2) { - PacketHandler.sendToServer(new PacketMachine(this, (byte) TileMultiblockMachine.NetworkPackets.TOGGLE.ordinal())); - } - setText(); + super.onInventoryButtonPressed(buttonId); + if (buttonId == 1 || buttonId == 2) { + PacketHandler.sendToServer(new PacketMachine(this, (byte) TileMultiblockMachine.NetworkPackets.TOGGLE.ordinal())); + } //} } @Override - public NBTTagCompound writeToNBT(NBTTagCompound nbt) { - super.writeToNBT(nbt); - + protected void writeNetworkData(NBTTagCompound nbt) { + super.writeNetworkData(nbt); nbt.setInteger("selected", radioButton.getOptionSelected()); - nbt.setBoolean("oofluid", outOfFluid); + //System.out.println("write oof:"+outOfFluid); + } - return nbt; + @Override + protected void readNetworkData(NBTTagCompound nbt) { + super.readNetworkData(nbt); + radioButton.setOptionSelected(nbt.getInteger("selected")); + outOfFluid = nbt.getBoolean("oofluid"); + //System.out.println("oof:"+outOfFluid); + + if (world !=null && world.isRemote){ + //if (!client_contructed) + //client_contructed = this.completeStructure(this.world.getBlockState(this.pos)); + + setText(); + } + } + @Override + public NBTTagCompound writeToNBT(NBTTagCompound nbt) { + super.writeToNBT(nbt); + return nbt; } @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); - - radioButton.setOptionSelected(nbt.getInteger("selected")); - outOfFluid = nbt.getBoolean("oofluid"); - + outOfFluid = false; } @Override diff --git a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java index 56360375e..576661819 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java @@ -642,7 +642,7 @@ public void loadData(int id) { for (TileDataBus tile : dataCables) { if (doesSlotIndexMatchDataType(data.getDataType(), chipSlot)) - dataItem.removeData(dataChip, tile.addData(Math.min(tile.getDataObject().getMaxData() - tile.getData(), data.getMaxData()), data.getDataType(), EnumFacing.UP, true), DataStorage.DataType.UNDEFINED); + dataItem.removeData(dataChip, tile.addData(Math.min(tile.getDataObject().getMaxData() - tile.getData(), data.getData()), data.getDataType(), EnumFacing.UP, true), DataStorage.DataType.UNDEFINED); } //dataItem.setData(dataChip, data.getData(), data.getData() != 0 ? data.getDataType() : DataType.UNDEFINED); diff --git a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/energy/TileSolarArray.java b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/energy/TileSolarArray.java index 431e1b27e..d9a3890f9 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/energy/TileSolarArray.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/energy/TileSolarArray.java @@ -140,7 +140,7 @@ public void update() { if (enabled && ((world.isDaytime() && world.canBlockSeeSky(this.pos.up())) || (world.provider.getDimension() == ARConfiguration.getCurrentConfig().spaceDimId && world.canBlockSeeSky(this.pos.down())))) { //Multiplied by two for 520W = 1 RF/t becoming 2 RF/t @ 100% efficiency, and by insolation mult for solar stuff //Slight adjustment to make Earth 0.9995 into a 1.0 - energyRecieved = (int) (numPanels * 1.0005d * 2 * insolationPowerMultiplier); + energyRecieved = Math.min(4096, (int) (numPanels * 1.0005d * 2 * insolationPowerMultiplier)); } powerMadeLastTick = energyRecieved * ARConfiguration.getCurrentConfig().solarGeneratorMult; diff --git a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/orbitallaserdrill/MiningDrill.java b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/orbitallaserdrill/MiningDrill.java index cdab4cff9..0ab3ac544 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/orbitallaserdrill/MiningDrill.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/orbitallaserdrill/MiningDrill.java @@ -2,11 +2,13 @@ import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.NonNullList; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; import net.minecraftforge.common.ForgeChunkManager; import net.minecraftforge.common.MinecraftForge; import zmaster587.advancedRocketry.AdvancedRocketry; @@ -14,6 +16,9 @@ import zmaster587.advancedRocketry.entity.EntityLaserNode; import zmaster587.advancedRocketry.event.BlockBreakEvent; +import java.util.ArrayList; +import java.util.List; + class MiningDrill extends AbstractDrill { protected boolean finished; @@ -27,7 +32,7 @@ class MiningDrill extends AbstractDrill { ItemStack[] performOperation() { - ItemStack[] stacks = new ItemStack[0]; + ArrayList stacks = new ArrayList<>(); for (int i = 0; i < 9; i++) { int x = (int) laser.posX + (i % 3) - 1; @@ -41,10 +46,19 @@ ItemStack[] performOperation() { if (event.isCanceled()) continue; + /* What is this shit? if (state == Blocks.AIR.getDefaultState() || state.getMaterial().isReplaceable() || state.getMaterial().isLiquid()) { laser.world.setBlockState(laserPos, AdvancedRocketryBlocks.blockLightSource.getDefaultState()); continue; } + */ + if (state.getMaterial().isReplaceable() || state.getMaterial().isLiquid()) { + laser.world.setBlockState(laserPos, Blocks.AIR.getDefaultState()); + continue; + } + if (state == Blocks.AIR.getDefaultState()){ + continue; + } NonNullList items = NonNullList.create(); state.getBlock().getDrops(items, laser.world, laserPos, state, 0); @@ -55,14 +69,13 @@ ItemStack[] performOperation() { if (items.isEmpty()) { - laser.world.setBlockState(laserPos, AdvancedRocketryBlocks.blockLightSource.getDefaultState()); + laser.world.setBlockState(laserPos, Blocks.AIR.getDefaultState()); continue; } - stacks = new ItemStack[items.size()]; - stacks = items.toArray(stacks); + stacks.addAll(items); - laser.world.setBlockState(laserPos, AdvancedRocketryBlocks.blockLightSource.getDefaultState()); + laser.world.setBlockState(laserPos, Blocks.AIR.getDefaultState()); } boolean blockInWay = false; @@ -98,26 +111,27 @@ ItemStack[] performOperation() { } } while (!blockInWay); - return stacks; + return stacks.toArray(new ItemStack[0]); } boolean activate(World world, int x, int z) { ticketLaser = ForgeChunkManager.requestTicket(AdvancedRocketry.instance, world, ForgeChunkManager.Type.NORMAL); if (ticketLaser != null) { - ForgeChunkManager.forceChunk(ticketLaser, new ChunkPos(x >> 4, z >> 4)); + Chunk chunk = world.getChunkFromBlockCoords(new BlockPos (x,0,z)); // force the chunk to generate + //System.out.println("pos"+x+":"+z); + //System.out.println("chunkpos"+chunk.x+":"+chunk.z); + ForgeChunkManager.forceChunk(ticketLaser, new ChunkPos(chunk.x, chunk.z)); int y = 64; - if (world.getChunkFromChunkCoords(x >> 4, z >> 4).isLoaded()) { int current; for (int i = 0; i < 9; i++) { current = world.getTopSolidOrLiquidBlock(new BlockPos(x + (i % 3) - 1, 0xFF, z + (i / 3) - 1)).getY(); if (current > y) y = current; } - } else - y = 255; + laser = new EntityLaserNode(world, x, y, z); laser.markValid(); diff --git a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/orbitallaserdrill/TileOrbitalLaserDrill.java b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/orbitallaserdrill/TileOrbitalLaserDrill.java index 483b9d39f..9e3ea86de 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/orbitallaserdrill/TileOrbitalLaserDrill.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/orbitallaserdrill/TileOrbitalLaserDrill.java @@ -3,33 +3,30 @@ import io.netty.buffer.ByteBuf; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.inventory.ISidedInventory; +import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.NetworkManager; import net.minecraft.network.play.server.SPacketUpdateTileEntity; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.ChunkPos; import net.minecraft.world.World; import net.minecraft.world.WorldServer; import net.minecraftforge.common.DimensionManager; -import net.minecraftforge.common.ForgeChunkManager; -import net.minecraftforge.common.ForgeChunkManager.Ticket; -import net.minecraftforge.common.ForgeChunkManager.Type; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; -import zmaster587.advancedRocketry.AdvancedRocketry; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; import zmaster587.advancedRocketry.api.ARConfiguration; import zmaster587.advancedRocketry.api.AdvancedRocketryBlocks; -import zmaster587.advancedRocketry.api.AdvancedRocketryItems; -import zmaster587.advancedRocketry.inventory.TextureResources; +import zmaster587.advancedRocketry.api.stations.ISpaceObject; import zmaster587.advancedRocketry.stations.SpaceObjectManager; +import zmaster587.advancedRocketry.util.TerraformingHelper; import zmaster587.advancedRocketry.world.provider.WorldProviderSpace; import zmaster587.libVulpes.LibVulpes; import zmaster587.libVulpes.api.LibVulpesBlocks; -import zmaster587.libVulpes.compat.InventoryCompat; import zmaster587.libVulpes.inventory.modules.*; import zmaster587.libVulpes.network.PacketHandler; import zmaster587.libVulpes.network.PacketMachine; @@ -38,17 +35,18 @@ import zmaster587.libVulpes.util.ZUtils; import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.LinkedList; import java.util.List; - -public class TileOrbitalLaserDrill extends TileMultiPowerConsumer implements ISidedInventory, IGuiCallback, IButtonInventory { +public class TileOrbitalLaserDrill extends TileMultiPowerConsumer implements IGuiCallback, IButtonInventory { private static final int POWER_PER_OPERATION = (int) (10000 * ARConfiguration.getCurrentConfig().spaceLaserPowerMult); - private final AbstractDrill drill; + private AbstractDrill drill; + private terraformingdrill terraformingDrill; + private AbstractDrill miningDrill; public int laserX, laserZ, tickSinceLastOperation; protected boolean isRunning, finished, isJammed; + private ModuleButton resetBtn; Object[][][] structure = new Object[][][]{ { {null, null, null, null, null, null, null, null, null, null, null}, @@ -84,34 +82,53 @@ public class TileOrbitalLaserDrill extends TileMultiPowerConsumer implements ISi {null, null, null, null, null, null, LibVulpesBlocks.blockAdvStructureBlock, AdvancedRocketryBlocks.blockVacuumLaser, AdvancedRocketryBlocks.blockVacuumLaser, AdvancedRocketryBlocks.blockVacuumLaser, null} }, }; - private ItemStack lens; - private int radius, xCenter, yCenter, numSteps; + public int radius, xCenter, yCenter, numSteps; private EnumFacing prevDir; private ModuleTextBox locationX, locationZ; - private ModuleText updateText; + private ModuleText updateText, positionText, xtext, ztext, no_targets_text; private MultiInventory inv; private MODE mode; - private Ticket ticket; + + private boolean terraformingstatus; + boolean client_first_loop = true; // for render bug on client + //private Ticket ticket; // this is useless anyway because it would not load the energy supply system and the laser would run out of energy + + int last_orbit_dim; + TerraformingHelper t; + WorldServer orbitWorld; + public TileOrbitalLaserDrill() { super(); - lens = ItemStack.EMPTY; + + terraformingstatus = false; + client_first_loop = true; radius = 0; xCenter = 0; yCenter = 0; numSteps = 0; prevDir = null; - + resetBtn = new ModuleButton(40, 20, 2, LibVulpes.proxy.getLocalizedString("msg.spacelaser.reset"), this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild, 34, 20); + positionText = new ModuleText(83, 63, "empty... shit!", 0x0b0b0b); + updateText = new ModuleText(83, 63, "also empty...", 0x0b0b0b); + xtext = new ModuleText(83, 33, "X:", 0x0b0b0b); + ztext = new ModuleText(83, 43, "Z:", 0x0b0b0b); + no_targets_text = new ModuleText(21, 43, "", 0x0b0b0b); + no_targets_text.setText("No target found!\nGo down and survey the area!"); + locationX = new ModuleNumericTextbox(this, 93, 31, 50, 10, 16); + locationZ = new ModuleNumericTextbox(this, 93, 41, 50, 10, 16); tickSinceLastOperation = 0; laserX = 0; laserZ = 0; inv = new MultiInventory(this.itemOutPorts); if (ARConfiguration.getCurrentConfig().laserDrillPlanet) - this.drill = new MiningDrill(); + this.miningDrill = new MiningDrill(); else - this.drill = new VoidDrill(); + this.miningDrill = new VoidDrill(); + this.terraformingDrill = new terraformingdrill(); + this.drill = miningDrill; isRunning = false; finished = false; @@ -143,38 +160,75 @@ public String getMachineName() { } /* - * ID 0: client changed xcoord in interface - * ID 1: client changed zcoord in interface * ID 2: sync whether the machine is running - * ID 3: sync Mode - * ID 4: jam reset + * ID 4: reset + * ID 1: send changes back to client + * ID 5 send only laser position to client + * ID 3: client requests update */ @Override public void writeDataToNetwork(ByteBuf out, byte id) { super.writeDataToNetwork(out, id); - if (id == 10) + if (id == 15) { out.writeInt(this.laserX); - else if (id == 11) out.writeInt(this.laserZ); - else if (id == 12) + }else if (id == 11){ + out.writeInt(mode.ordinal()); + out.writeInt(this.xCenter); + out.writeInt(this.yCenter); + out.writeInt(this.laserX); + out.writeInt(this.laserZ); + out.writeBoolean(this.isRunning); + out.writeBoolean(terraformingstatus); + } + else if (id == 12) { out.writeBoolean(isRunning); - else if (id == 13) + } + else if (id == 14){ out.writeInt(mode.ordinal()); + out.writeInt(this.xCenter); + out.writeInt(this.yCenter); + }else if (id == 16){ + out.writeBoolean(terraformingstatus); + } } @Override public void readDataFromNetwork(ByteBuf in, byte id, NBTTagCompound nbt) { super.readDataFromNetwork(in, id, nbt); - if (id == 10) - nbt.setInteger("laserX", in.readInt()); - else if (id == 11) - nbt.setInteger("laserZ", in.readInt()); - else if (id == 12) + if (id == 15){ + nbt.setInteger("currentX", in.readInt()); + nbt.setInteger("currentZ", in.readInt()); + } + else if (id == 11){ + nbt.setInteger("mode", in.readInt()); + nbt.setInteger("newX", in.readInt()); + nbt.setInteger("newZ", in.readInt()); + nbt.setInteger("currentX", in.readInt()); + nbt.setInteger("currentZ", in.readInt()); nbt.setBoolean("isRunning", in.readBoolean()); - else if (id == 13) + nbt.setBoolean("terraformingstatus", in.readBoolean()); + } + else if (id == 12) { + nbt.setBoolean("isRunning", in.readBoolean()); + } + else if (id == 14){ nbt.setInteger("mode", in.readInt()); + nbt.setInteger("newX", in.readInt()); + nbt.setInteger("newZ", in.readInt()); + }else if (id == 16){ + nbt.setBoolean("terraformingstatus", in.readBoolean()); + } + + } + public void client_update_tf_info(){ + if (!terraformingstatus && this.mode == MODE.T_FORM){ + this.no_targets_text.setVisible(true); + }else{ + this.no_targets_text.setVisible(false); + } } @Override @@ -182,27 +236,117 @@ public void useNetworkData(EntityPlayer player, Side side, byte id, NBTTagCompound nbt) { super.useNetworkData(player, side, id, nbt); - if (id == 10) { - this.laserX = nbt.getInteger("laserX"); - finished = false; + if (id == 15) { + laserZ = nbt.getInteger("currentZ"); + laserX = nbt.getInteger("currentX"); + positionText.setText("position:\n"+this.laserX+" : "+this.laserZ); + }else if (id == 11){ + resetSpiral(); + this.isRunning = nbt.getBoolean("isRunning"); + mode = MODE.values()[nbt.getInteger("mode")]; + xCenter = nbt.getInteger("newX"); + yCenter = nbt.getInteger("newZ"); + laserZ = nbt.getInteger("currentZ"); + laserX = nbt.getInteger("currentX"); + positionText.setText("position:\n"+this.laserX+" : "+this.laserZ); + updateText.setText(this.getMode().toString()); + locationX.setText(String.valueOf(this.xCenter)); + locationZ.setText(String.valueOf(this.yCenter)); + //System.out.println("reset client:"+xCenter+":"+yCenter+":"+mode); + resetBtn.setColor(0xf0f0f0); + check_is_terraforming_update_gui(); - if (mode == MODE.SPIRAL) - resetSpiral(); - } else if (id == 11) { - this.laserZ = nbt.getInteger("laserZ"); - finished = false; - if (mode == MODE.SPIRAL) - resetSpiral(); - } else if (id == 12) + this.terraformingstatus = nbt.getBoolean("terraformingstatus"); + client_update_tf_info(); + //System.out.println("is running: "+ isRunning); + + + } + else if (id == 12) { this.isRunning = nbt.getBoolean("isRunning"); - else if (id == 13 && !isRunning()) - this.mode = MODE.values()[nbt.getInteger("mode")]; - else if (id == 14) - this.checkjam(); + } + else if (id == 16){ + this.terraformingstatus = nbt.getBoolean("terraformingstatus"); + client_update_tf_info(); + + } + else if (id == 14){ + resetSpiral(); + mode = MODE.values()[nbt.getInteger("mode")]; + xCenter = nbt.getInteger("newX"); + yCenter = nbt.getInteger("newZ"); + laserZ = yCenter; + laserX = xCenter; + //System.out.println("reset:"+xCenter+":"+yCenter+":"+mode); + // do all the reset stuff + if (drill != null) { + drill.deactivate(); + } + finished = false; + setRunning(false); + + if (mode == MODE.T_FORM){ + this.drill = this.terraformingDrill; + }else { + this.drill = this.miningDrill; + } + + checkjam(); + checkCanRun(); + //update clients on new data + PacketHandler.sendToNearby(new PacketMachine(this, (byte) 11), this.world.provider.getDimension(), pos, 2048); + } + else if (id == 13) + //update clients on new data + PacketHandler.sendToNearby(new PacketMachine(this, (byte) 11), this.world.provider.getDimension(), pos, 2048); markDirty(); } + public void transferItems(IInventory inventorySource, IItemHandler inventoryTarget) { + for (int i = 0; i < inventorySource.getSizeInventory(); i++) { + ItemStack stack = inventorySource.getStackInSlot(i).copy(); + + if (!stack.isEmpty()) { + for (int j = 0; j < inventoryTarget.getSlots(); j++) { + // Try to insert the item + ItemStack remaining = inventoryTarget.insertItem(j, stack, false); + + // If the entire stack was inserted, remove it from the source inventory + if (remaining.isEmpty()) { + inventorySource.decrStackSize(i, stack.getCount()); + break; + } + + // Otherwise, update the stack to the remaining amount + stack.setCount(remaining.getCount()); + } + } + } + } + + + + + public void outputItems() { + // Loop over each output hatch in your inventory + for (int ic = 0; ic < this.getItemOutPorts().size(); ic++) { + + IInventory inventory = itemOutPorts.get(ic); + if (inventory instanceof TileEntity) { + + + for (EnumFacing direction : EnumFacing.values()) { + TileEntity tileEntity = world.getTileEntity(((TileEntity) inventory).getPos().offset(direction)); + if (tileEntity != null) { + if (tileEntity.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY,null)){ + transferItems(inventory, tileEntity.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY,null)); + } + } + } + } + } + } private void resetSpiral() { radius = 0; prevDir = null; @@ -216,9 +360,17 @@ public boolean isRunning() { } public void setRunning(boolean value) { + if (world.isRemote){ + System.out.println("client should not call setRunning"); + return; + } isRunning = value; + // this needs to be sent to all to update players on ground of change + // or you make 2 packages, one for space dim and one for ground dim at laser coords but this is more easy this way... + PacketHandler.sendToAll(new PacketMachine(this, (byte) 12)); + //PacketHandler.sendToNearby(new PacketMachine(this, (byte) 12), this.world.provider.getDimension(), pos, 128); + markDirty(); - //worldObj.notifyBlockUpdate(pos, worldObj.getBlockState(pos), worldObj.getBlockState(pos), 3); } public boolean isFinished() { @@ -238,9 +390,6 @@ public void setMode(MODE m) { } public void incrementMode() { - if (mode == MODE.SPIRAL) - resetSpiral(); - int num = mode.ordinal(); num++; @@ -251,9 +400,6 @@ public void incrementMode() { } public void decrementMode() { - if (mode == MODE.SPIRAL) - resetSpiral(); - int num = mode.ordinal(); num--; @@ -266,28 +412,38 @@ public void decrementMode() { @Override public void update() { + //Freaky janky crap to make sure the multiblock loads on chunkload etc + if (world.isRemote && client_first_loop) { + PacketHandler.sendToServer(new PacketMachine(this, (byte) 13)); + client_first_loop = false; + } if (timeAlive == 0 && !world.isRemote) { if (isComplete()) canRender = completeStructure = completeStructure(world.getBlockState(pos)); timeAlive = 0x1; checkCanRun(); + } if (!this.world.isRemote) { tickSinceLastOperation++; + if (mode != MODE.T_FORM) { checkjam(); - checkCanRun(); - if (this.hasPowerForOperation() && this.isReadyForOperation() && this.isRunning) { + } + checkCanRun(); + if (this.hasPowerForOperation() && this.isReadyForOperation() && this.isRunning) { - if (this.drill.needsRestart()) { - this.setRunning(false); - return; - } + if (this.drill.needsRestart()) { + this.setRunning(false); + return; + } - ItemStack[] stacks = this.drill.performOperation(); + ItemStack[] stacks = this.drill.performOperation(); + + if (stacks != null) { // is null during terraforming ZUtils.mergeInventory(stacks, this.inv); if (!ZUtils.isInvEmpty(stacks)) { @@ -295,45 +451,48 @@ public void update() { this.drill.deactivate(); this.isJammed = true; } - - this.batteries.setEnergyStored(this.batteries.getUniversalEnergyStored() - POWER_PER_OPERATION); - this.tickSinceLastOperation = 0; } - } + this.batteries.setEnergyStored(this.batteries.getUniversalEnergyStored() - POWER_PER_OPERATION); + this.tickSinceLastOperation = 0; + } - if (this.drill.isFinished()) { - setRunning(false); - this.drill.deactivate(); + if (!this.inv.isEmpty()) { + outputItems(); + } - if (!this.isJammed) { - if (this.mode == MODE.SINGLE) - this.finished = true; - - if (this.world.getStrongPower(getPos()) != 0) { - if (this.mode == MODE.LINE_X) { - this.laserX += 3; - } else if (this.mode == MODE.LINE_Z) { - this.laserZ += 3; - } else if (this.mode == MODE.SPIRAL) { - this.numSteps++; - if (this.radius < this.numSteps) { - this.numSteps = 0; - if (prevDir == EnumFacing.NORTH) - prevDir = EnumFacing.EAST; - else if (prevDir == EnumFacing.EAST) { - prevDir = EnumFacing.SOUTH; - radius++; - } else if (prevDir == EnumFacing.SOUTH) - prevDir = EnumFacing.WEST; - else { - prevDir = EnumFacing.NORTH; - radius++; + + if (this.drill.isFinished()) { + setRunning(false); + this.drill.deactivate(); + + if (!this.isJammed) { + if (this.mode == MODE.SINGLE) + this.finished = true; + + if (this.world.getStrongPower(getPos()) != 0) { + if (this.mode == MODE.SPIRAL) { + this.numSteps++; + if (this.radius < this.numSteps) { + this.numSteps = 0; + if (prevDir == EnumFacing.NORTH) + prevDir = EnumFacing.EAST; + else if (prevDir == EnumFacing.EAST) { + prevDir = EnumFacing.SOUTH; + radius++; + } else if (prevDir == EnumFacing.SOUTH) + prevDir = EnumFacing.WEST; + else { + prevDir = EnumFacing.NORTH; + radius++; + } } - } - this.laserX += 3 * prevDir.getFrontOffsetX(); - this.laserZ += 3 * prevDir.getFrontOffsetZ(); + this.laserX += 3 * prevDir.getFrontOffsetX(); + this.laserZ += 3 * prevDir.getFrontOffsetZ(); + PacketHandler.sendToNearby(new PacketMachine(this, (byte) 15), this.world.provider.getDimension(), pos, 128); + + } } } } @@ -341,6 +500,9 @@ else if (prevDir == EnumFacing.EAST) { } public boolean isReadyForOperation() { + + if (mode == MODE.T_FORM) return true; // every tick on terraforming + if (batteries.getUniversalEnergyStored() == 0) return false; @@ -351,7 +513,7 @@ public void onDestroy() { if (this.drill != null) { this.drill.deactivate(); } - ForgeChunkManager.releaseTicket(ticket); + //ForgeChunkManager.releaseTicket(ticket); } @Override @@ -366,36 +528,29 @@ public void onChunkUnload() { public SPacketUpdateTileEntity getUpdatePacket() { NBTTagCompound nbt = new NBTTagCompound(); this.writeToNBT(nbt); - - nbt.setBoolean("IsRunning", isRunning); - return new SPacketUpdateTileEntity(getPos(), 0, nbt); } @Override public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt) { this.readFromNBT(pkt.getNbtCompound()); - isRunning = pkt.getNbtCompound().getBoolean("IsRunning"); } @Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); - if (lens != null) { - NBTTagCompound tag = new NBTTagCompound(); - lens.writeToNBT(tag); - nbt.setTag("GlassPane", tag); - } + nbt.setInteger("laserX", laserX); nbt.setInteger("laserZ", laserZ); nbt.setByte("mode", (byte) mode.ordinal()); nbt.setBoolean("jammed", this.isJammed); + nbt.setInteger("CenterX", xCenter); + nbt.setInteger("CenterY", yCenter); + if (mode == MODE.SPIRAL && prevDir != null) { - nbt.setInteger("CenterX", xCenter); - nbt.setInteger("CenterY", yCenter); nbt.setInteger("radius", radius); nbt.setInteger("numSteps", numSteps); nbt.setInteger("prevDir", prevDir.ordinal()); @@ -407,23 +562,26 @@ public NBTTagCompound writeToNBT(NBTTagCompound nbt) { public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); - if (nbt.hasKey("GlassPane")) { - NBTTagCompound tag = nbt.getCompoundTag("GlassPane"); - lens = new ItemStack(tag); - } laserX = nbt.getInteger("laserX"); laserZ = nbt.getInteger("laserZ"); mode = MODE.values()[nbt.getByte("mode")]; this.isJammed = nbt.getBoolean("jammed"); + xCenter = nbt.getInteger("CenterX"); + yCenter = nbt.getInteger("CenterY"); + if (mode == MODE.SPIRAL && nbt.hasKey("prevDir")) { - xCenter = nbt.getInteger("CenterX"); - yCenter = nbt.getInteger("CenterY"); radius = nbt.getInteger("radius"); numSteps = nbt.getInteger("numSteps"); prevDir = EnumFacing.values()[nbt.getInteger("prevDir")]; } + + if (mode == MODE.T_FORM){ + this.drill = this.terraformingDrill; + }else { + this.drill = this.miningDrill; + } } /** @@ -453,167 +611,122 @@ private boolean canMachineSeeEarth() { } private boolean unableToRun() { - return lens.isEmpty() || !canMachineSeeEarth() || batteries.getUniversalEnergyStored() == 0 || !(this.world.provider instanceof WorldProviderSpace) || !zmaster587.advancedRocketry.dimension.DimensionManager.getInstance().canTravelTo(((WorldProviderSpace) this.world.provider).getDimensionProperties(getPos()).getParentPlanet()) || - ARConfiguration.getCurrentConfig().laserBlackListDims.contains(((WorldProviderSpace) this.world.provider).getDimensionProperties(getPos()).getParentPlanet()); + return !canMachineSeeEarth() || + batteries.getUniversalEnergyStored() == 0 || + !(this.world.provider instanceof WorldProviderSpace) || + !zmaster587.advancedRocketry.dimension.DimensionManager.getInstance().canTravelTo(((WorldProviderSpace) this.world.provider).getDimensionProperties(getPos()).getParentPlanet()) || + + (mode != MODE.T_FORM && ARConfiguration.getCurrentConfig().laserBlackListDims.contains(((WorldProviderSpace) this.world.provider).getDimensionProperties(getPos()).getParentPlanet())); } /** * Checks to see if the situation for firing the laser exists... and changes the state accordingly */ + + + public void checkCanRun() { - //Laser requires lense, redstone power, not be jammed, and be in orbit and energy to function - if (this.finished || this.isJammed || world.isBlockIndirectlyGettingPowered(getPos()) == 0 || unableToRun()) { + if (world.isRemote) return; // client has no business here + + ISpaceObject spaceObject = SpaceObjectManager.getSpaceManager().getSpaceStationFromBlockCoords(this.pos); + if(spaceObject == null){ if (isRunning) { drill.deactivate(); setRunning(false); - if (!this.world.isRemote) { - PacketHandler.sendToNearby(new PacketMachine(this, (byte) 12), 128, pos, this.world.provider.getDimension()); - IBlockState state = world.getBlockState(getPos()); - world.notifyBlockUpdate(pos, state, state, 2); - } } - } else if (world.isBlockIndirectlyGettingPowered(getPos()) > 0) { - - //Laser will be on at this point - int orbitDimId = SpaceObjectManager.getSpaceManager().getSpaceStationFromBlockCoords(this.pos).getOrbitingPlanetId(); - if (orbitDimId == SpaceObjectManager.WARPDIMID) + return; + } + int orbitDimId = spaceObject.getOrbitingPlanetId(); + + if (orbitDimId != last_orbit_dim ||orbitWorld== null || t == null){ + last_orbit_dim = orbitDimId; + if (!DimensionManager.isDimensionRegistered(orbitDimId)) { + if (isRunning) { + drill.deactivate(); + setRunning(false); + } return; - WorldServer orbitWorld = DimensionManager.getWorld(orbitDimId); + } + orbitWorld = DimensionManager.getWorld(orbitDimId); if (orbitWorld == null) { DimensionManager.initDimension(orbitDimId); orbitWorld = DimensionManager.getWorld(orbitDimId); - if (orbitWorld == null) + if (orbitWorld == null) { + if (isRunning) { + drill.deactivate(); + setRunning(false); + } return; - } - - - if (ticket == null) { - ticket = ForgeChunkManager.requestTicket(AdvancedRocketry.instance, this.world, Type.NORMAL); - if (ticket != null) - ForgeChunkManager.forceChunk(ticket, new ChunkPos(getPos().getX() / 16 - (getPos().getX() < 0 ? 1 : 0), getPos().getZ() / 16 - (getPos().getZ() < 0 ? 1 : 0))); - } - if (!isRunning) { - setRunning(drill.activate(orbitWorld, laserX, laserZ)); - if (!this.world.isRemote) { - PacketHandler.sendToNearby(new PacketMachine(this, (byte) 12), 128, pos, this.world.provider.getDimension()); - IBlockState state = world.getBlockState(getPos()); - world.notifyBlockUpdate(pos, state, state, 2); } } + t = terraformingDrill.get_my_helper(orbitWorld); } - } - - public int getEnergyPercentScaled(int max) { - return (int) (max * (batteries.getUniversalEnergyStored() / (float) batteries.getMaxEnergyStored())); - } - - public boolean hasEnergy() { - return batteries.getUniversalEnergyStored() != 0; - } - //InventoryHandling start - @Override - public int getSizeInventory() { - return inv.getSizeInventory(); - } + if (!t.has_blocks_in_tf_queue()) { + if (terraformingstatus) { + terraformingstatus = false; + PacketHandler.sendToAll(new PacketMachine(this, (byte) 16)); - @Override - @Nonnull - public ItemStack getStackInSlot(int i) { - if (i == 0) - return lens; - else { - i--; - return inv.getStackInSlot(i); + } + } else { + if (!terraformingstatus) { + terraformingstatus = true; + PacketHandler.sendToAll(new PacketMachine(this, (byte) 16)); + } } - } - @Override - @Nonnull - public ItemStack decrStackSize(int i, int j) { - ItemStack ret; - if (i == 0) { - ret = lens.copy(); - lens = ItemStack.EMPTY; - return ret; - } - return ItemStack.EMPTY; - } - - @Override - public void setInventorySlotContents(int i, @Nonnull ItemStack itemstack) { + //Laser redstone power, not be jammed, and be in orbit and energy to function + if ((mode == MODE.T_FORM && (t==null ||!t.has_blocks_in_tf_queue())) || this.finished || (this.isJammed && mode != MODE.T_FORM) || world.isBlockIndirectlyGettingPowered(getPos()) == 0 || unableToRun()) { + if (isRunning) { + drill.deactivate(); + setRunning(false); + } + } else if (world.isBlockIndirectlyGettingPowered(getPos()) > 0) { - //TODO: add gregcipies - if (i == 0) - lens = itemstack; - else { - if (InventoryCompat.canInjectItems(inv, itemstack)) - InventoryCompat.injectItem(inv, itemstack); + if (orbitDimId == SpaceObjectManager.WARPDIMID) + return; - this.checkCanRun(); - } - } - @Override - @Nonnull - public String getName() { - return getMachineName(); - } - @Override - public int getInventoryStackLimit() { - return 64; - } - @Override - public boolean isUsableByPlayer(EntityPlayer entityplayer) { - return entityplayer.getDistanceSq(pos) <= 64; - } + //Laser will be on at this point - @Override - public boolean isEmpty() { - return lens.isEmpty(); - } + //if (ticket == null) { + // ticket = ForgeChunkManager.requestTicket(AdvancedRocketry.instance, this.world, Type.NORMAL); + // if (ticket != null) + // ForgeChunkManager.forceChunk(ticket, new ChunkPos(getPos().getX() / 16 - (getPos().getX() < 0 ? 1 : 0), getPos().getZ() / 16 - (getPos().getZ() < 0 ? 1 : 0))); + //} + if (!isRunning) { - @Override - public void openInventory(EntityPlayer entity) { - // TODO Perhaps make sure laser isn't running - } + // load dimension i guess + orbitWorld = DimensionManager.getWorld(orbitDimId); + if (orbitWorld == null) { + DimensionManager.initDimension(orbitDimId); + orbitWorld = DimensionManager.getWorld(orbitDimId); + if (orbitWorld == null) + return; + } - @Override - public void closeInventory(EntityPlayer entity) { - // TODO Auto-generated method stub + setRunning(drill.activate(orbitWorld, laserX, laserZ)); + } + } - } - @Override - @Nonnull - public int[] getSlotsForFace(EnumFacing side) { - return new int[]{}; } - @Override - public boolean canInsertItem(int index, @Nonnull ItemStack itemStackIn, @Nullable EnumFacing direction) { - return false; + public int getEnergyPercentScaled(int max) { + return (int) (max * (batteries.getUniversalEnergyStored() / (float) batteries.getMaxEnergyStored())); } - @Override - public boolean canExtractItem(int index, @Nonnull ItemStack stack, @Nullable EnumFacing direction) { - return false; + public boolean hasEnergy() { + return batteries.getUniversalEnergyStored() != 0; } - @Override - public boolean isItemValidForSlot(int i, @Nonnull ItemStack itemstack) { - if (i == 0) - return AdvancedRocketryItems.itemLens == itemstack.getItem(); - - return inv.isItemValidForSlot(i, itemstack); - } /** * @return returns whether enough power is stored for the next operation @@ -643,26 +756,17 @@ public boolean isJammed() { public void setJammed(boolean b) { this.isJammed = b; } - - @Override - public boolean hasCustomName() { - return false; - } - @Override public void onModuleUpdated(ModuleBase module) { - + resetBtn.setColor(0x90ff90); if (module == locationX) { if (!((ModuleTextBox) module).getText().isEmpty() && !((ModuleTextBox) module).getText().contentEquals("-")) - laserX = Integer.parseInt(((ModuleTextBox) module).getText()); - PacketHandler.sendToServer(new PacketMachine(this, (byte) 10)); + xCenter = Integer.parseInt(((ModuleTextBox) module).getText()); } else if (module == locationZ) { if (!((ModuleTextBox) module).getText().isEmpty() && !((ModuleTextBox) module).getText().contentEquals("-")) - laserZ = Integer.parseInt(((ModuleTextBox) module).getText()); - PacketHandler.sendToServer(new PacketMachine(this, (byte) 11)); + yCenter = Integer.parseInt(((ModuleTextBox) module).getText()); } - } @Override @@ -670,25 +774,30 @@ public List getModules(int id, EntityPlayer player) { List modules = new LinkedList<>(); if (world.isRemote) { - modules.add(locationX = new ModuleNumericTextbox(this, 113, 31, 50, 10, 16)); - modules.add(locationZ = new ModuleNumericTextbox(this, 113, 41, 50, 10, 16)); + //request update on information + PacketHandler.sendToServer(new PacketMachine(this, (byte) 13)); + + modules.add(updateText = new ModuleText(110, 20, this.getMode().toString(), 0x0b0b0b, true)); + + + modules.add(locationX); + modules.add(locationZ); - locationX.setText(String.valueOf(this.laserX)); - locationZ.setText(String.valueOf(this.laserZ)); - modules.add(updateText = new ModuleText(130, 20, this.getMode().toString(), 0x0b0b0b, true)); - modules.add(new ModuleText(103, 33, "X:", 0x0b0b0b)); - modules.add(new ModuleText(103, 43, "Z:", 0x0b0b0b)); + modules.add(xtext); + modules.add(ztext); - modules.add(new ModuleImage(8, 16, TextureResources.laserGuiBG)); + modules.add(no_targets_text); + + modules.add(positionText); + + //modules.add(new ModuleImage(8, 16, TextureResources.laserGuiBG)); } - modules.add(new ModuleButton(103, 20, 0, "", this, zmaster587.libVulpes.inventory.TextureResources.buttonLeft, 5, 8)); - modules.add(new ModuleButton(157, 20, 1, "", this, zmaster587.libVulpes.inventory.TextureResources.buttonRight, 5, 8)); - modules.add(new ModuleButton(103, 62, 2, LibVulpes.proxy.getLocalizedString("msg.spacelaser.reset"), this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild, 34, 20)); + modules.add(new ModuleButton(83, 20, 0, "", this, zmaster587.libVulpes.inventory.TextureResources.buttonLeft, 5, 8)); + modules.add(new ModuleButton(137, 20, 1, "", this, zmaster587.libVulpes.inventory.TextureResources.buttonRight, 5, 8)); + modules.add(resetBtn); modules.add(new ModulePower(11, 25, batteries)); - modules.add(new ModuleSlotArray(56, 54, this, 0, 1)); - return modules; } @@ -703,55 +812,53 @@ public boolean canInteractWithContainer(EntityPlayer entity) { return true; } + void check_is_terraforming_update_gui() { + if (getMode() == MODE.T_FORM) { + locationX.setVisible(false); + locationZ.setVisible(false); + xtext.setVisible(false); + ztext.setVisible(false); + positionText.setVisible(false); + client_update_tf_info(); + //no_targets_text.setVisible(true); + }else{ + locationX.setVisible(true); + locationZ.setVisible(true); + xtext.setVisible(true); + ztext.setVisible(true); + positionText.setVisible(true); + no_targets_text.setVisible(false); + } + } @Override public void onInventoryButtonPressed(int buttonId) { - + if (buttonId!=2) + resetBtn.setColor(0x90ff90); if (buttonId == 0) { this.decrementMode(); updateText.setText(this.getMode().toString()); + check_is_terraforming_update_gui(); } else if (buttonId == 1) { this.incrementMode(); updateText.setText(this.getMode().toString()); + check_is_terraforming_update_gui(); } else if (buttonId == 2) { PacketHandler.sendToServer(new PacketMachine(this, (byte) 14)); return; } else return; - - if (!this.isRunning()) - PacketHandler.sendToServer(new PacketMachine(this, (byte) 13)); - } - - @Override - @Nonnull - public ItemStack removeStackFromSlot(int index) { - return ItemStack.EMPTY; - } - - @Override - public int getField(int id) { - return 0; - } - - @Override - public void setField(int id, int value) { - } @Override - public int getFieldCount() { - return 0; + @SideOnly(Side.CLIENT) + public double getMaxRenderDistanceSquared() { + return 320 * 320; } - @Override - public void clear() { - - } public enum MODE { SINGLE, - LINE_X, - LINE_Z, - SPIRAL + SPIRAL, + T_FORM } } \ No newline at end of file diff --git a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/orbitallaserdrill/terraformingdrill.java b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/orbitallaserdrill/terraformingdrill.java new file mode 100644 index 000000000..5a7e523f1 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/orbitallaserdrill/terraformingdrill.java @@ -0,0 +1,150 @@ +package zmaster587.advancedRocketry.tile.multiblock.orbitallaserdrill; + +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import net.minecraft.world.biome.BiomeProvider; +import net.minecraftforge.common.ForgeChunkManager; +import zmaster587.advancedRocketry.AdvancedRocketry; +import zmaster587.advancedRocketry.dimension.DimensionManager; +import zmaster587.advancedRocketry.dimension.DimensionProperties; +import zmaster587.advancedRocketry.entity.EntityLaserNode; +import zmaster587.advancedRocketry.util.BiomeHandler; +import zmaster587.advancedRocketry.util.TerraformingHelper; +import zmaster587.advancedRocketry.world.ChunkManagerPlanet; + +/** + * This drill is used if the laserDrillPlanet config option is disabled. It simply conjures ores from nowhere + */ +class terraformingdrill extends AbstractDrill{ + + + private ForgeChunkManager.Ticket ticketLaser; + private ChunkPos last_worked_chunk = null; + private EntityLaserNode laser; + + terraformingdrill(){ + + } + public TerraformingHelper get_my_helper() { + return get_my_helper(null); + } + public TerraformingHelper get_my_helper(World w){ + if (w == null) + w = laser.world; + + if (!DimensionProperties.proxylists.isinitialized(w.provider.getDimension())){ + DimensionProperties.proxylists.initdim(w.provider.getDimension()); + } + + TerraformingHelper t = DimensionProperties.proxylists.gethelper(w.provider.getDimension()); + + if (t == null) { + DimensionManager.getInstance().getDimensionProperties(w.provider.getDimension()).load_terraforming_helper(false); + t = DimensionProperties.proxylists.gethelper(w.provider.getDimension()); + } + return t; + } + + /** + * Performs a single drilling operation + * + * @return The ItemStacks produced by this tick of drilling + */ + ItemStack[] performOperation() { + try { + + + TerraformingHelper t = get_my_helper(); + BiomeProvider chunkmgr = t.chunkMgrTerraformed; + BlockPos next_block_pos = null; + Vec3d laserpos = null; + for (int i = 0; i<6;i++) { + next_block_pos = t.get_next_position(false); + + if (next_block_pos == null) { + //System.out.println("Queue empty - returning"); + return null; + } + + // blocks are usually added per chunk so it may be efficient to keep it loaded + // one chunk has to be loaded anyway to prevent dim unloading + + //System.out.println("terraform heightmap at "+next_block_pos.getX()+":"+next_block_pos.getZ()); + + + + ChunkPos currentChunk = t.getChunkPosFromBlockPos(next_block_pos); + if (last_worked_chunk != null) { + if (!currentChunk.equals(last_worked_chunk)) { + releaseticket(); + //just load chunk 0 0 to keep the dimension loaded + //System.out.println("request ticket at chunk " + currentChunk.x + ":" + currentChunk.z); + ticketLaser = ForgeChunkManager.requestTicket(AdvancedRocketry.instance, laser.world, ForgeChunkManager.Type.NORMAL); + if (ticketLaser != null) { + ForgeChunkManager.forceChunk(ticketLaser, new ChunkPos(currentChunk.x, currentChunk.z)); + } + } + } + last_worked_chunk = currentChunk; + + + BiomeHandler.terraform(laser.world, ((ChunkManagerPlanet) chunkmgr).getBiomeGenAt(next_block_pos.getX(), next_block_pos.getZ()), next_block_pos, false, laser.world.provider.getDimension()); + + //because it syncs entity position not every tick, just place it in the middle of the chunk it is currently working in + laserpos = new Vec3d(currentChunk.x*16+8, laser.world.getHeight(currentChunk.x*16+8, currentChunk.z*16+8), currentChunk.z*16+8); + + } + + laser.setPositionAndUpdate(laserpos.x,laserpos.y,laserpos.z); + + + //} catch (NullPointerException e) { + // e.printStackTrace(); + } catch (NoClassDefFoundError e){ + e.printStackTrace(); //WTF + } + return null; + } + + boolean activate(World world, int x, int z) { + + + + if (laser == null) { + laser = new EntityLaserNode(world, x, 0, z); + laser.markValid(); + laser.forceSpawn = true; + world.spawnEntity(laser); + } + return true; + + } + + void releaseticket(){ + if (ticketLaser != null) + ForgeChunkManager.releaseTicket(ticketLaser); + } + + void deactivate() { + if (laser != null) { + laser.setDead(); + laser = null; + } + + releaseticket(); + + + + } + + boolean isFinished() { + return laser==null || !get_my_helper().has_blocks_in_tf_queue(); + } + + boolean needsRestart() { + return this.laser == null; + } +} diff --git a/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteBuilder.java b/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteBuilder.java index b63c057b0..3d8847b2c 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteBuilder.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteBuilder.java @@ -14,6 +14,7 @@ import zmaster587.advancedRocketry.dimension.DimensionManager; import zmaster587.advancedRocketry.inventory.TextureResources; import zmaster587.advancedRocketry.item.*; +import zmaster587.advancedRocketry.util.WeightEngine; import zmaster587.libVulpes.LibVulpes; import zmaster587.libVulpes.client.util.ProgressBarImage; import zmaster587.libVulpes.inventory.modules.*; @@ -97,6 +98,7 @@ public boolean canAssembleSatellite() { public void assembleSatellite() { //Basic properties of the satellite int powerStorage = 0, powerGeneration = 0, maxData = 0; + float weight = 0; //Get the primary function from slot 0 String satType = SatelliteRegistry.getSatelliteProperty(getStackInSlot(primaryFunctionSlot)).getSatelliteType(); @@ -114,11 +116,13 @@ public void assembleSatellite() { if (SatelliteRegistry.getSatelliteProperty(stack).getPropertyFlag() == SatelliteProperties.Property.DATA.getFlag()) maxData += SatelliteRegistry.getSatelliteProperty(getStackInSlot(currentSlotIndex)).getMaxDataStorage(); } + + weight += WeightEngine.INSTANCE.getWeight(stack); } //Set final satellite properties //720 here is the base power buffer, so the satellite has SOMETHING to run on - SatelliteProperties properties = new SatelliteProperties(powerGeneration, powerStorage + 720, satType, maxData); + SatelliteProperties properties = new SatelliteProperties(powerGeneration, powerStorage + 720, satType, maxData, weight); properties.setId(DimensionManager.getInstance().getNextSatelliteId()); //Create the output item diff --git a/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileTerraformingTerminal.java b/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileTerraformingTerminal.java index 15a9a137e..27fd343aa 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileTerraformingTerminal.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileTerraformingTerminal.java @@ -1,53 +1,42 @@ package zmaster587.advancedRocketry.tile.satellite; import io.netty.buffer.ByteBuf; -import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.network.NetworkManager; -import net.minecraft.network.play.server.SPacketUpdateTileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; -import net.minecraft.world.WorldServer; import net.minecraft.world.biome.BiomeProvider; -import net.minecraft.world.chunk.Chunk; import net.minecraftforge.fml.relauncher.Side; -import zmaster587.advancedRocketry.api.*; -import zmaster587.advancedRocketry.api.DataStorage.DataType; +import zmaster587.advancedRocketry.api.ARConfiguration; +import zmaster587.advancedRocketry.api.AdvancedRocketryBlocks; +import zmaster587.advancedRocketry.api.AdvancedRocketryItems; +import zmaster587.advancedRocketry.api.SatelliteRegistry; import zmaster587.advancedRocketry.api.satellite.SatelliteBase; import zmaster587.advancedRocketry.dimension.DimensionManager; import zmaster587.advancedRocketry.dimension.DimensionProperties; -import zmaster587.advancedRocketry.inventory.modules.ModuleData; import zmaster587.advancedRocketry.inventory.modules.ModuleSatellite; import zmaster587.advancedRocketry.item.ItemBiomeChanger; -import zmaster587.advancedRocketry.item.ItemData; import zmaster587.advancedRocketry.item.ItemSatelliteIdentificationChip; import zmaster587.advancedRocketry.satellite.SatelliteBiomeChanger; -import zmaster587.advancedRocketry.satellite.SatelliteData; import zmaster587.advancedRocketry.util.BiomeHandler; -import zmaster587.advancedRocketry.util.IDataInventory; -import zmaster587.advancedRocketry.util.PlanetaryTravelHelper; +import zmaster587.advancedRocketry.util.TerraformingHelper; import zmaster587.advancedRocketry.world.ChunkManagerPlanet; -import zmaster587.advancedRocketry.world.provider.WorldProviderPlanet; import zmaster587.libVulpes.LibVulpes; import zmaster587.libVulpes.api.IUniversalEnergy; -import zmaster587.libVulpes.inventory.TextureResources; import zmaster587.libVulpes.inventory.modules.*; import zmaster587.libVulpes.network.PacketHandler; import zmaster587.libVulpes.network.PacketMachine; import zmaster587.libVulpes.tile.TileInventoriedRFConsumer; -import zmaster587.libVulpes.util.HashedBlockPosition; import zmaster587.libVulpes.util.INetworkMachine; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.math.BigDecimal; import java.math.RoundingMode; -import java.util.Collection; import java.util.LinkedList; import java.util.List; -import java.math.BigDecimal; @@ -140,7 +129,7 @@ public void setInventorySlotContents(int slot, @Nonnull ItemStack stack) { public void update() { super.update(); boolean has_redstone = world.isBlockIndirectlyGettingPowered(getPos()) != 0; - int powerrequired = 120; + int powerrequired = 80; //120; if (!world.isRemote) { if (world.getTotalWorldTime() % 20 == 0) @@ -175,33 +164,40 @@ public void update() { SatelliteBiomeChanger sat = (SatelliteBiomeChanger) ItemSatelliteIdentificationChip.getSatellite(getStackInSlot(0)); IUniversalEnergy battery = sat.getBattery(); - for (int i = 0; i < 10; i++) { + for (int i = 0; i < 1000; i++) { //TODO: Better imp if (battery.getUniversalEnergyStored() > powerrequired) { - if (battery.extractEnergy(powerrequired, false) == powerrequired) { try { - HashedBlockPosition next_block = DimensionManager.getInstance().getDimensionProperties(world.provider.getDimension()).get_next_terraforming_block(); - BiomeProvider chunkmgr = DimensionManager.getInstance().getDimensionProperties(world.provider.getDimension()).chunkMgrTerraformed; + TerraformingHelper t = DimensionProperties.proxylists.gethelper(world.provider.getDimension()); - // this chunkmgr is not initialized by default because dimensionproperties - // inits during the forge mod init phase and some stuff is not loaded at this time. - // I will make sure it will be initialized here - // I have no idea where else to put it :( - if (chunkmgr == null) - DimensionManager.getInstance().getDimensionProperties(world.provider.getDimension()).reset_chunkmgr(); + if (t == null) { + DimensionManager.getInstance().getDimensionProperties(world.provider.getDimension()).load_terraforming_helper(false); + t = DimensionProperties.proxylists.gethelper(world.provider.getDimension()); + } - BiomeHandler.changeBiome(world, ((ChunkManagerPlanet) chunkmgr).getBiomeGenAt(next_block.x, next_block.z), new BlockPos(next_block.x, 0, next_block.z), false); + BiomeProvider chunkmgr = t.chunkMgrTerraformed; + //BlockPos next_block_pos = t.get_next_position(false); + //BlockPos next_block_pos = t.get_next_position_biomechanging(false); + BlockPos next_block_pos = t.get_next_position_biomechanging(true); + if (next_block_pos != null) { // it is null when there is everything terraformed + battery.extractEnergy(powerrequired, false); + //BiomeHandler.terraform(world, ((ChunkManagerPlanet) chunkmgr).getBiomeGenAt(next_block_pos.getX(), next_block_pos.getZ()), next_block_pos, false, world.provider.getDimension()); + BiomeHandler.terraform_biomes(world, ((ChunkManagerPlanet) chunkmgr).getBiomeGenAt(next_block_pos.getX(), next_block_pos.getZ()), next_block_pos, world.provider.getDimension()); + }else{ + //System.out.println("nothing to terraform"); + break; // nothing to do, everything is terraformed + } - } catch (NullPointerException e) { - e.printStackTrace(); + //} catch (NullPointerException e) { + // e.printStackTrace(); } catch (NoClassDefFoundError e){ e.printStackTrace(); //WTF } - } + } else break; } diff --git a/src/main/java/zmaster587/advancedRocketry/tile/station/TileWarpController.java b/src/main/java/zmaster587/advancedRocketry/tile/station/TileWarpController.java index c9ba179b4..686d5f18b 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/station/TileWarpController.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/station/TileWarpController.java @@ -932,6 +932,15 @@ public void update() { @Override public boolean isPlanetKnown(IDimensionProperties properties) { + //okay so before i had if(dimId > 10000), but as marvin said it's dimOffset, so basically we can use it instead? idk, correct me and my code if i'm wrong + if (properties == null) return false; + + int dimId = properties.getId(); + + if (DimensionManager.getInstance().getDimensionProperties(dimId).isStar()) { + return true; + } + SpaceStationObject spaceStationObject = getSpaceObject(); if (spaceStationObject != null) return spaceStationObject.isPlanetKnown(properties); diff --git a/src/main/java/zmaster587/advancedRocketry/util/BiomeHandler.java b/src/main/java/zmaster587/advancedRocketry/util/BiomeHandler.java index 844f67178..d54098a87 100644 --- a/src/main/java/zmaster587/advancedRocketry/util/BiomeHandler.java +++ b/src/main/java/zmaster587/advancedRocketry/util/BiomeHandler.java @@ -2,79 +2,321 @@ import net.minecraft.block.*; import net.minecraft.block.state.IBlockState; -import net.minecraft.init.Biomes; import net.minecraft.init.Blocks; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; import net.minecraft.world.World; import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.BiomeDecorator; import net.minecraft.world.chunk.Chunk; -import net.minecraft.world.gen.feature.WorldGenAbstractTree; import net.minecraftforge.common.BiomeDictionary; -import net.minecraftforge.fml.common.Loader; -import zmaster587.advancedRocketry.api.IPlanetaryProvider; -import zmaster587.advancedRocketry.api.dimension.IDimensionProperties; import zmaster587.advancedRocketry.dimension.DimensionManager; import zmaster587.advancedRocketry.dimension.DimensionProperties; import zmaster587.advancedRocketry.network.PacketBiomeIDChange; import zmaster587.libVulpes.network.PacketHandler; import zmaster587.libVulpes.util.HashedBlockPosition; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.List; import java.util.Random; -import static zmaster587.advancedRocketry.util.AstronomicalBodyHelper.getAverageTemperature; public class BiomeHandler { + public static void decorate_simple(World world, Biome biomeId, Biome old_biome, BlockPos pos) { + BlockPos yy = world.getHeight(pos); + while (!world.getBlockState(yy.down()).isOpaqueCube() && yy.getY() > 0) + yy = yy.down(); - public static void changeBiome(World world, Biome biomeId, BlockPos pos, boolean regen_vegetation) { - Chunk chunk = world.getChunkFromBlockCoords(pos); - - Biome biome = world.getBiome(pos); - - if (biome != biomeId) { - BlockPos yy = world.getHeight(pos); - if (biome.topBlock != biomeId.topBlock) { - - while (!world.getBlockState(yy.down()).isOpaqueCube() && yy.getY() > 0) - yy = yy.down(); + if (old_biome.topBlock != biomeId.topBlock) { + if (world.getBlockState(yy.down()) == old_biome.topBlock) + world.setBlockState(yy.down(), biomeId.topBlock); + } - if (world.getBlockState(yy.down()) == biome.topBlock) - world.setBlockState(yy.down(), biomeId.topBlock); - } + decorateBiome(world, yy, biomeId); + } + // Bro I am sorry for changing this again and I know it will mess up your mixin but terraforming had a BIG update so.... + public static void changeBiome(World world, Biome biomeId, Biome old_biome, BlockPos pos) { + Chunk chunk = world.getChunkFromBlockCoords(pos); + if (old_biome != biomeId) { byte[] biomeArr = chunk.getBiomeArray(); try { biomeArr[(pos.getX() & 15) + (pos.getZ() & 15) * 16] = (byte) Biome.getIdForBiome(biomeId); } catch (IndexOutOfBoundsException e) { e.printStackTrace(); } - decorateBiome(world, yy, biomeId); + } + } - PacketHandler.sendToNearby(new PacketBiomeIDChange(chunk, world, new HashedBlockPosition(pos)), world.provider.getDimension(), pos, 256); + public static int get_height_blocks_only(IBlockState[] blocks) { + int h = blocks.length-1; + while (h>0 && (!blocks[h].isOpaqueCube())){ + h--; } - //for biome remote use - else if(regen_vegetation) { - BlockPos yy = world.getHeight(pos); + return h; + } + + public static int get_height_blocks_only(World world, BlockPos pos) { + BlockPos yy = world.getHeight(pos); + while ((!world.getBlockState(yy).isOpaqueCube()) && yy.getY() > 0) + yy = yy.down(); + return yy.getY(); + } + + public static void do_heavy_terraforming(World world, Biome biomeId, Biome old_biome, BlockPos pos, int dimId) { + + int inchunkx = ((pos.getX() % 16) + 16) % 16; + int inchunkz = ((pos.getZ() % 16) + 16) % 16; + + long startTime; + startTime = System.currentTimeMillis(); + DimensionProperties props = DimensionManager.getInstance().getDimensionProperties(dimId); + + ChunkPos cpos = DimensionProperties.proxylists.gethelper(props.getId()).getChunkPosFromBlockPos(pos); + + + IBlockState[] target_blocks = DimensionProperties.proxylists.gethelper(props.getId()).getBlocksAt(pos.getX(), pos.getZ()); + chunkdata data = DimensionProperties.proxylists.gethelper(props.getId()).getChunkFromList(cpos.x, cpos.z); + //System.out.println("d1"+(System.currentTimeMillis()-startTime)); + //startTime = System.currentTimeMillis(); + + //this should never be executed because it was removed from queue + //protected chunks will not be added to this queue again + if (data.type == TerraformingType.PROTECTED) { + //System.out.println("working protected"); + decorate_simple(world, biomeId, old_biome, pos); + DimensionProperties.proxylists.gethelper(props.getId()).getChunkFromList(cpos.x, cpos.z).set_position_fully_generated(inchunkx, inchunkz); + DimensionProperties.proxylists.gethelper(props.getId()).register_height_change(pos); // it does not really changetheheight but it will notify the border to update + } else if (data.type == TerraformingType.ALLOWED) { + //System.out.println("working full"); + + if (!data.fully_generated[inchunkx][inchunkz]) { + //fast replacing + //for (int i = 0; i < 255; i++) { + // world.setBlockState(new BlockPos(pos.getX(), i, pos.getZ()), target_blocks[i], 2); + //} + + + int target_height = 255; + for (int i = 255; i >= 0; i--) { + if(!target_blocks[i].equals(Blocks.AIR.getDefaultState())){ + target_height = i; + break; + } + } + int current_world_height = world.getHeight(pos.getX(), pos.getZ()); + + //slow replacing + int y_per_iteration = 3; + int blocks_replaced = 0; + //go up from 0 + for (int i = 0; i < 255; i++) { + if (i>target_height)break; + + if (blocks_replaced >= y_per_iteration) + break; + + if (!world.getBlockState(new BlockPos(pos.getX(), i, pos.getZ())).equals(target_blocks[i])) { + world.setBlockState(new BlockPos(pos.getX(), i, pos.getZ()), target_blocks[i], 2); + + //if both are underground player would not notice so only limit the actual height changes + if (i>=current_world_height) { + blocks_replaced += 1; + } + } + } + //now go down from 255 + for (int i = 255; i >=0; i--) { + if (i<=target_height)break; + + if (blocks_replaced >= y_per_iteration) + break; + + if (!world.getBlockState(new BlockPos(pos.getX(), i, pos.getZ())).equals(target_blocks[i])) { + world.setBlockState(new BlockPos(pos.getX(), i, pos.getZ()), target_blocks[i], 2); + blocks_replaced += 1; + } + } + + + + // as long as terrain does not match the target height, re-add position to queue + //System.out.println("heights:"+get_height_blocks_only(world, pos) +":"+ get_height_blocks_only(target_blocks)); + + // you need to check this for the entire chunk + // or the laser will reset on every new world load to its starting position and ignore the radius and iterate every chunk and skip over the ones that are already generated + // or make it like this: every time a single position is fully generated, check every chunk 3x3 around it and see if you can populate them + // use the chunk list again - replace spiral mod with global mode that scatters the chunks to make it a little more random. every new load it will start from its starting position again + if (get_height_blocks_only(world, pos) == get_height_blocks_only(target_blocks)) { + DimensionProperties.proxylists.gethelper(props.getId()).getChunkFromList(cpos.x, cpos.z).set_position_fully_generated(inchunkx, inchunkz); + } else { + DimensionProperties.proxylists.gethelper(props.getId()).add_position_to_queue(pos); + DimensionProperties.proxylists.gethelper(props.getId()).register_height_change(pos); + + //because height was changed, decorate the top block again + //this will update the top block and make some grass/flowers + world.setBlockState(world.getHeight(pos).down(),biomeId.topBlock); + //decorateBiome(world, pos, biomeId); //if we want to do grass and flowers - but this would not fit right after laser hits + } + } + } else if (data.type == TerraformingType.BORDER) { + + //this is to be sure the top block is changed even if the height matches already + BlockPos yy = world.getHeight(pos); while (!world.getBlockState(yy.down()).isOpaqueCube() && yy.getY() > 0) yy = yy.down(); - if (world.getBlockState(yy.down()) == biome.topBlock) - world.setBlockState(yy.down(), biomeId.topBlock); + if (old_biome.topBlock != biomeId.topBlock) { + if (world.getBlockState(yy.down()) == old_biome.topBlock) + world.setBlockState(yy.down(), biomeId.topBlock); + } + + + if (target_blocks != null) { + + int filter_size = 5; + //System.out.println("working border"); + + world.getChunkFromBlockCoords(pos.add(-filter_size, 0, 0)); // Ensure the chunk of the target positions are generated + world.getChunkFromBlockCoords(pos.add(filter_size, 0, 0)); // Ensure the chunk of the target positions are generated + world.getChunkFromBlockCoords(pos.add(0, 0, -filter_size)); // Ensure the chunk of the target positions are generated + world.getChunkFromBlockCoords(pos.add(0, 0, filter_size)); // Ensure the chunk of the target positions are generated + + + //this has to be weighted by distance + float heightsum = 0; + float num_samples = 0; + for (int x = -filter_size; x <= filter_size; x++) { + for (int z = -filter_size; z <= filter_size; z++) { + float w = (1.0f / (0.2f + x * x + z * z)); + heightsum += get_height_blocks_only(world, pos.add(x, 0, z)) * w; + num_samples += 1 * w; + } + } + + int avg_height = Math.round(heightsum / num_samples); + + int prev_height = get_height_blocks_only(world, pos); + if (avg_height == prev_height) { // nothing to do + return; + } + + //now we want to set the target height to >= sea level to fill it with the oceanblock + avg_height = Math.max(props.getSeaLevel(), avg_height); + + //fast replacing + for (int i = 0; i < 256; i++) { + IBlockState target = target_blocks[i]; + if (i < avg_height) + if (target == Blocks.AIR.getDefaultState()) + target = biomeId.topBlock; + if (i == avg_height) + target = biomeId.topBlock; + if (i > avg_height) + target = Blocks.AIR.getDefaultState(); + world.setBlockState(new BlockPos(pos.getX(), i, pos.getZ()), target, 2); + } + + int new_height = get_height_blocks_only(world, pos); + if (prev_height != new_height) { + DimensionProperties.proxylists.gethelper(props.getId()).register_height_change(pos); + DimensionProperties.proxylists.gethelper(props.getId()).add_position_to_queue(pos); + } else { + DimensionProperties.proxylists.gethelper(props.getId()).check_next_border_chunk_fully_generated(cpos.x, cpos.z); // maybe this was the last border block in queue? if yes, its terrain is done! + } + } else + DimensionProperties.proxylists.gethelper(props.getId()).check_next_border_chunk_fully_generated(cpos.x, cpos.z); // maybe this was the last border block in queue? if yes, its terrain is done! + } + } + + + public static void do_decoration(World world, BlockPos pos, int dimId){ + Biome biomeId = world.getBiome(pos); + int inchunkx = ((pos.getX() % 16) + 16) % 16; + int inchunkz = ((pos.getZ() % 16) + 16) % 16; - decorateBiome(world, yy, biomeId); + DimensionProperties props = DimensionManager.getInstance().getDimensionProperties(dimId); - PacketHandler.sendToNearby(new PacketBiomeIDChange(chunk, world, new HashedBlockPosition(pos)), world.provider.getDimension(), pos, 256); + ChunkPos cpos = DimensionProperties.proxylists.gethelper(props.getId()).getChunkPosFromBlockPos(pos); + + + int can_populate = DimensionProperties.proxylists.gethelper(props.getId()).can_populate(cpos.x, cpos.z); + if (can_populate == -1){ + //because it can never be populated, it is considered "done with population" + DimensionProperties.proxylists.gethelper(props.getId()).getChunkFromList(cpos.x, cpos.z).set_position_decorated(inchunkx, inchunkz); + } + if (can_populate == 1) { + + // we do some hacky tricks here to ensure that trees can fully generate + // we shift the actual tree generation by 8 blocks so that it overlaps with the chunks next to it + // can_populate() ensures that the chunks next to it are ready for decoration + + if (!DimensionProperties.proxylists.gethelper(props.getId()).getChunkFromList(cpos.x,cpos.z).fully_decorated[inchunkx][inchunkz]) { + //System.out.println("decorate block"); + int treegen = biomeId.decorator.treesPerChunk; + if (world.rand.nextInt(16 * 16) < treegen) { + biomeId.getRandomTreeFeature(world.rand).generate(world, world.rand, world.getHeight(pos.add(8, 0, 8))); + } + + //some more flowers, grass, .... + BlockPos yy = world.getHeight(pos); + while (!world.getBlockState(yy.down()).isOpaqueCube() && yy.getY() > 0) + yy = yy.down(); + decorateBiome(world, yy, biomeId); + + DimensionProperties.proxylists.gethelper(props.getId()).getChunkFromList(cpos.x, cpos.z).set_position_decorated(inchunkx, inchunkz); + } + } + } + + + + public static void terraform_biomes(World world, Biome biomeId, BlockPos pos, int dimId) { + Biome old_biome = world.getBiome(pos); + changeBiome(world,biomeId, old_biome, pos); + decorate_simple(world, biomeId, old_biome, pos); + + DimensionProperties props = DimensionManager.getInstance().getDimensionProperties(dimId); + ChunkPos cpos = DimensionProperties.proxylists.gethelper(props.getId()).getChunkPosFromBlockPos(pos); + chunkdata data = DimensionProperties.proxylists.gethelper(props.getId()).getChunkFromList(cpos.x, cpos.z); + + int inchunkx = ((pos.getX() % 16) + 16) % 16; + int inchunkz = ((pos.getZ() % 16) + 16) % 16; + if (data == null){ + DimensionProperties.proxylists.gethelper(props.getId()).generate_new_chunkdata(new ChunkPos(cpos.x, cpos.z)); + data = DimensionProperties.proxylists.gethelper(props.getId()).getChunkFromList(cpos.x, cpos.z); + } + data.set_position_biomechanged(inchunkx,inchunkz); + + Chunk chunk = world.getChunkFromBlockCoords(pos); + PacketHandler.sendToNearby(new PacketBiomeIDChange(chunk, world, new HashedBlockPosition(pos)), world.provider.getDimension(), pos, 1024); + + } + + public static void terraform(World world, Biome biomeId, BlockPos pos, boolean was_biome_remote, int dimId) { + Chunk chunk = world.getChunkFromBlockCoords(pos); + if (biomeId == null)return; + + Biome old_biome = world.getBiome(pos); + + + //for biome remote use, only change top block and do simple decoration + if(was_biome_remote) { + changeBiome(world,biomeId, old_biome, pos); // this should not be needed in heavy terraforming because it should have already been done before + decorate_simple(world, biomeId, old_biome, pos); + PacketHandler.sendToNearby(new PacketBiomeIDChange(chunk, world, new HashedBlockPosition(pos)), world.provider.getDimension(), pos, 1024); + } + + if (!was_biome_remote) { // heavy terraforming here... + do_heavy_terraforming(world, biomeId,old_biome,pos,dimId); } + + } private static void spawn_decoration_block(World world, BlockPos pos, IBlockState state, int p){ @@ -143,4 +385,3 @@ private static void decorateBiome(World world, BlockPos pos, Biome biome) { } - diff --git a/src/main/java/zmaster587/advancedRocketry/util/GraphicsHelper.java b/src/main/java/zmaster587/advancedRocketry/util/GraphicsHelper.java new file mode 100644 index 000000000..5f966181c --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/util/GraphicsHelper.java @@ -0,0 +1,102 @@ +package zmaster587.advancedRocketry.util; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import org.lwjgl.opengl.GL11; + +public final class GraphicsHelper { + + public static void drawCenteredScaledString(String text, int x, int y, float scale, int color) { + drawCenteredScaledString(Minecraft.getMinecraft().fontRenderer, text, x, y, scale, color); + } + + public static void drawCenteredScaledString(FontRenderer fontRenderer, String text, int x, int y, float scale, int color) { + GlStateManager.pushMatrix(); + GlStateManager.scale(scale, scale, 1.0F); + drawCenteredString(fontRenderer, text, (int) (x / scale), (int) (y / scale), color); + GlStateManager.popMatrix(); + } + + public static void drawScaledString(String text, int x, int y, float scale, int color) { + drawScaledString(Minecraft.getMinecraft().fontRenderer, text, x, y, scale, color); + } + + public static void drawScaledString(FontRenderer fontRenderer, String text, int x, int y, float scale, int color) { + GlStateManager.pushMatrix(); + GlStateManager.scale(scale, scale, 1.0F); + drawString(fontRenderer, text, (int) (x / scale), (int) (y / scale), color); + GlStateManager.popMatrix(); + } + + public static void drawCenteredString(String text, int x, int y, int color) { + drawCenteredString(Minecraft.getMinecraft().fontRenderer, text, x, y, color); + } + + public static void drawCenteredString(FontRenderer fontRenderer, String text, int x, int y, int color) { + drawString(text, x - fontRenderer.getStringWidth(text) / 2, y, color); + } + + public static void drawString(String text, int x, int y, int color) { + drawString(Minecraft.getMinecraft().fontRenderer, text, x, y, color); + } + + public static void drawString(FontRenderer fontRenderer, String text, int x, int y, int color) { + fontRenderer.drawString(text, x, y, color); + } + + /** + * Represents the GUI adaptation of glScissor mechanism + * Given coordinates are from up-left corner + * + * @param x start X coordinate + * @param y start Y coordinate + * @param width new window width + * @param height new window height + */ + public static void glScissor(int x, int y, int width, int height) { + GL11.glScissor(x, Minecraft.getMinecraft().displayHeight - (y + height), width, height); + } + + public static void drawTexturedModalRect(int x, int y, int width, int height, int u, int v, int textureWidth, int textureHeight, int textureSizeX, int textureSizeY, float zLevel) { + float f = 1.0F / textureSizeX; + float f1 = 1.0F / textureSizeY; + + GlStateManager.enableTexture2D(); + + Tessellator tess = Tessellator.getInstance(); + BufferBuilder bb = tess.getBuffer(); + bb.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); + + bb.pos(x, y + height, zLevel).tex(u * f, (v + textureHeight) * f1).endVertex(); + bb.pos(x + width, y + height, zLevel).tex((u + textureWidth) * f, (v + textureHeight) * f1).endVertex(); + bb.pos(x + width, y, zLevel).tex((u + textureWidth) * f, v * f1).endVertex(); + bb.pos(x, y, zLevel).tex(u * f, v * f1).endVertex(); + + tess.draw(); + } + + public static void drawTexturedModalRect(int x, int y, int textureX, int textureY, int width, int height, float zLevel) { + drawTexturedModalRect(x, y, width, height, textureX, textureY, width, height, 256, 256, zLevel); + } + + public static void drawColoredModalRect(int x, int y, int width, int height, float r, float g, float b, float a, float zLevel) { + drawColoredModalRect(x, y, width, height, (int) (r * 255), (int) (g * 255), (int) (b * 255), (int) (a * 255), zLevel); + } + + public static void drawColoredModalRect(int x, int y, int width, int height, int r, int g, int b, int a, float zLevel) { + Tessellator tess = Tessellator.getInstance(); + BufferBuilder bb = tess.getBuffer(); + bb.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR); + + bb.pos(x, y + height, zLevel).color(r, g, b, a).endVertex(); + bb.pos(x + width, y + height, zLevel).color(r, g, b, a).endVertex(); + bb.pos(x + width, y, zLevel).color(r, g, b, a).endVertex(); + bb.pos(x, y, zLevel).color(r, g, b, a).endVertex(); + + tess.draw(); + } +} diff --git a/src/main/java/zmaster587/advancedRocketry/util/IBreakable.java b/src/main/java/zmaster587/advancedRocketry/util/IBreakable.java new file mode 100644 index 000000000..70d02f6da --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/util/IBreakable.java @@ -0,0 +1,8 @@ +package zmaster587.advancedRocketry.util; + +public interface IBreakable { + + float getBreakingProbability(); + + boolean shouldBreak(); +} diff --git a/src/main/java/zmaster587/advancedRocketry/util/IBrokenPartBlock.java b/src/main/java/zmaster587/advancedRocketry/util/IBrokenPartBlock.java new file mode 100644 index 000000000..73b57568f --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/util/IBrokenPartBlock.java @@ -0,0 +1,13 @@ +package zmaster587.advancedRocketry.util; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import zmaster587.advancedRocketry.tile.TileBrokenPart; + +import javax.annotation.Nullable; + +public interface IBrokenPartBlock { + + ItemStack getDropItem(final IBlockState state, final World world, final @Nullable TileBrokenPart te); +} diff --git a/src/main/java/zmaster587/advancedRocketry/util/InventoryUtil.java b/src/main/java/zmaster587/advancedRocketry/util/InventoryUtil.java new file mode 100644 index 000000000..5e4e6062e --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/util/InventoryUtil.java @@ -0,0 +1,47 @@ +package zmaster587.advancedRocketry.util; + +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; + +public class InventoryUtil { + + public static boolean hasItemInInventories(Iterable invs, String substr, boolean consume) { + for (IInventory inv : invs) { + if (hasItemInInventory(inv, substr, consume)) { + return true; + } + } + return false; + } + + public static boolean hasItemInInventory(IInventory inv, String substr, boolean consume) { + for (int i = 0; i < inv.getSizeInventory(); i++) { + if (inv.getStackInSlot(i).getUnlocalizedName().toLowerCase().contains(substr.toLowerCase())) { + if (consume) { + inv.setInventorySlotContents(i, ItemStack.EMPTY); + } + return true; + } + } + return false; + } + + public static boolean addItemToOneOfTheInventories(Iterable invs, ItemStack stack) { + for (IInventory inv : invs) { + if (addItemToInventory(inv, stack)) { + return true; + } + } + return false; + } + + public static boolean addItemToInventory(IInventory inv, ItemStack stack) { + for (int i = 0; i < inv.getSizeInventory(); i++) { + if (inv.getStackInSlot(i).isEmpty()) { + inv.setInventorySlotContents(i, stack); + return true; + } + } + return false; + } +} diff --git a/src/main/java/zmaster587/advancedRocketry/util/StorageChunk.java b/src/main/java/zmaster587/advancedRocketry/util/StorageChunk.java index 55cbe0c10..48dd09f56 100644 --- a/src/main/java/zmaster587/advancedRocketry/util/StorageChunk.java +++ b/src/main/java/zmaster587/advancedRocketry/util/StorageChunk.java @@ -33,10 +33,12 @@ import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.items.CapabilityItemHandler; import zmaster587.advancedRocketry.AdvancedRocketry; -import zmaster587.advancedRocketry.api.Constants; -import zmaster587.advancedRocketry.api.EntityRocketBase; +import zmaster587.advancedRocketry.api.*; +import zmaster587.advancedRocketry.api.fuel.FuelRegistry; import zmaster587.advancedRocketry.api.satellite.SatelliteBase; import zmaster587.advancedRocketry.api.stations.IStorageChunk; +import zmaster587.advancedRocketry.block.*; +import zmaster587.advancedRocketry.item.ItemPackedStructure; import zmaster587.advancedRocketry.tile.TileBrokenPart; import zmaster587.advancedRocketry.tile.TileGuidanceComputer; import zmaster587.advancedRocketry.tile.hatch.TileSatelliteHatch; @@ -47,12 +49,9 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; +import java.util.*; -public class StorageChunk implements IBlockAccess, IStorageChunk, IWeighted { +public class StorageChunk implements IBlockAccess, IStorageChunk, IWeighted, IBreakable { public Chunk chunk; public WorldDummy world; @@ -60,16 +59,22 @@ public class StorageChunk implements IBlockAccess, IStorageChunk, IWeighted { private Block[][][] blocks; public int sizeX, sizeY, sizeZ; private short[][][] metas; + private Map pos2te = new HashMap<>(); private ArrayList tileEntities; //To store inventories (All inventories) private ArrayList inventoryTiles; private ArrayList liquidTiles; private Entity entity; private float weight; + private boolean hasServiceMonitor; - public Block[][][] getblocks(){ - return blocks; -} + public Block[][][] getblocks() { + return blocks; + } + + public boolean hasServiceMonitor() { + return hasServiceMonitor; + } public StorageChunk() { sizeX = 0; @@ -125,7 +130,10 @@ public float recalculateWeight() { for (int x = 0; x < this.sizeX; x++) { for (int y = 0; y < this.sizeY; y++) { for (int z = 0; z < this.sizeZ; z++) { - this.weight += WeightEngine.INSTANCE.getWeight(null, this.blocks[x][y][z]); + Block block = this.blocks[x][y][z]; + if (block != null) { + this.weight += WeightEngine.INSTANCE.getWeight(null, block); + } } } } @@ -133,11 +141,148 @@ public float recalculateWeight() { // TEs for (TileEntity te : this.tileEntities) { this.weight += WeightEngine.INSTANCE.getTEWeight(te); - } + if (te instanceof TileSatelliteHatch) { + TileSatelliteHatch hatch = (TileSatelliteHatch) te; + if (hatch.getSatellite() != null) { + weight += hatch.getSatellite().getProperties().getWeight(); + } else if (hatch.getStackInSlot(0).getItem() instanceof ItemPackedStructure) { + ItemPackedStructure struct = (ItemPackedStructure) hatch.getStackInSlot(0).getItem(); + weight += struct.getStructure(hatch.getStackInSlot(0)).getWeight(); + } + } + } return this.weight; } + public void recalculateStats(StatsRocket stats) { + int thrustMonopropellant = 0; + int thrustBipropellant = 0; + int thrustNuclearNozzleLimit = 0; + int thrustNuclearReactorLimit = 0; + int thrustNuclearTotalLimit = 0; + int monopropellantfuelUse = 0; + int bipropellantfuelUse = 0; + int nuclearWorkingFluidUseMax = 0; + int fuelCapacityMonopropellant = 0; + int fuelCapacityBipropellant = 0; + int fuelCapacityOxidizer = 0; + int fuelCapacityNuclearWorkingFluid = 0; + + float drillPower = 0f; + //stats.reset_no_fuel(); + stats.reset_no_fuel();// Oh Quarter... you can not keep adding engine and seat locations every launch + + float weight = 0; + + for (int yCurr = 0; yCurr <= this.sizeY; yCurr++) { + for (int xCurr = 0; xCurr <= this.sizeX; xCurr++) { + for (int zCurr = 0; zCurr <= this.sizeZ; zCurr++) { + BlockPos currBlockPos = new BlockPos(xCurr, yCurr, zCurr); + BlockPos abovePos = new BlockPos(xCurr, yCurr + 1, zCurr); + BlockPos belowPos = new BlockPos(xCurr, yCurr - 1, zCurr); + + if (this.getBlockState(currBlockPos).getBlock() != Blocks.AIR) { + IBlockState state = world.getBlockState(currBlockPos); + Block block = state.getBlock(); + + if (ARConfiguration.getCurrentConfig().advancedWeightSystem) { + weight += WeightEngine.INSTANCE.getWeight(world, currBlockPos); + } else { + weight += 1; + } + + //If rocketEngine increaseThrust + if (block instanceof IRocketEngine && (world.getBlockState(belowPos).getBlock().isAir(world.getBlockState(belowPos), world, belowPos) || world.getBlockState(belowPos).getBlock() instanceof BlockLandingPad || world.getBlockState(belowPos).getBlock() == AdvancedRocketryBlocks.blockLaunchpad)) { + if (block instanceof BlockNuclearRocketMotor) { + nuclearWorkingFluidUseMax += ((IRocketEngine) block).getFuelConsumptionRate(world, xCurr, yCurr, zCurr); + thrustNuclearNozzleLimit += ((IRocketEngine) block).getThrust(world, currBlockPos); + } else if (block instanceof BlockBipropellantRocketMotor) { + bipropellantfuelUse += ((IRocketEngine) block).getFuelConsumptionRate(world, xCurr, yCurr, zCurr); + thrustBipropellant += ((IRocketEngine) block).getThrust(world, currBlockPos); + } else if (block instanceof BlockRocketMotor) { + monopropellantfuelUse += ((IRocketEngine) block).getFuelConsumptionRate(world, xCurr, yCurr, zCurr); + thrustMonopropellant += ((IRocketEngine) block).getThrust(world, currBlockPos); + } + stats.addEngineLocation(xCurr - (float) this.sizeX /2+0.5f, yCurr+0.5f, zCurr- (float) this.sizeZ /2+0.5f); + } + + if (block instanceof IFuelTank) { + if (block instanceof BlockBipropellantFuelTank) { + fuelCapacityBipropellant += (((IFuelTank) block).getMaxFill(world, currBlockPos, state) * ARConfiguration.getCurrentConfig().fuelCapacityMultiplier); + } else if (block instanceof BlockOxidizerFuelTank) { + fuelCapacityOxidizer += (((IFuelTank) block).getMaxFill(world, currBlockPos, state) * ARConfiguration.getCurrentConfig().fuelCapacityMultiplier); + } else if (block instanceof BlockNuclearFuelTank) { + fuelCapacityNuclearWorkingFluid += (((IFuelTank) block).getMaxFill(world, currBlockPos, state) * ARConfiguration.getCurrentConfig().fuelCapacityMultiplier); + }else if (block instanceof BlockFuelTank) { + fuelCapacityMonopropellant += (((IFuelTank) block).getMaxFill(world, currBlockPos, state) * ARConfiguration.getCurrentConfig().fuelCapacityMultiplier); + } + } + + if (block instanceof IRocketNuclearCore && ((world.getBlockState(belowPos).getBlock() instanceof IRocketNuclearCore) || (world.getBlockState(belowPos).getBlock() instanceof IRocketEngine))) { + thrustNuclearReactorLimit += ((IRocketNuclearCore) block).getMaxThrust(world, currBlockPos); + } + + if (block instanceof BlockSeat && world.getBlockState(abovePos).getBlock().isPassable(world, abovePos)) { + stats.addPassengerSeat((int) (xCurr - (float) this.sizeX / 2 + 0.5f), yCurr, (int) (zCurr - (float) this.sizeZ / 2 + 0.5f)); + } + + if (block instanceof IMiningDrill) { + drillPower += ((IMiningDrill) block).getMiningSpeed(world, currBlockPos); + } + + if (block.getUnlocalizedName().contains("servicemonitor")) { + hasServiceMonitor = true; + } + + TileEntity tile = world.getTileEntity(currBlockPos); + if (tile instanceof TileSatelliteHatch) { + if (ARConfiguration.getCurrentConfig().advancedWeightSystem) { + TileSatelliteHatch hatch = (TileSatelliteHatch) tile; + if (hatch.getSatellite() != null) { + weight += hatch.getSatellite().getProperties().getWeight(); + } else if (hatch.getStackInSlot(0).getItem() instanceof ItemPackedStructure) { + ItemPackedStructure struct = (ItemPackedStructure) hatch.getStackInSlot(0).getItem(); + weight += struct.getStructure(hatch.getStackInSlot(0)).getWeight(); + } + } + } + } + } + } + } + + int nuclearWorkingFluidUse = 0; + if (thrustNuclearNozzleLimit > 0) { + //Only run the number of engines our cores can support - we can't throttle these effectively because they're small, so they shut off if they don't get full power + thrustNuclearTotalLimit = Math.min(thrustNuclearNozzleLimit, thrustNuclearReactorLimit); + nuclearWorkingFluidUse = (int) (nuclearWorkingFluidUseMax * (thrustNuclearTotalLimit / (float) thrustNuclearNozzleLimit)); + thrustNuclearTotalLimit = (nuclearWorkingFluidUse * thrustNuclearNozzleLimit) / nuclearWorkingFluidUseMax; + } + + //Set fuel stats + //Thrust depending on rocket type + stats.setBaseFuelRate(FuelRegistry.FuelType.LIQUID_MONOPROPELLANT, monopropellantfuelUse); + stats.setBaseFuelRate(FuelRegistry.FuelType.LIQUID_BIPROPELLANT, bipropellantfuelUse); + stats.setBaseFuelRate(FuelRegistry.FuelType.LIQUID_OXIDIZER, bipropellantfuelUse); + stats.setBaseFuelRate(FuelRegistry.FuelType.NUCLEAR_WORKING_FLUID, nuclearWorkingFluidUse); + //Fuel storage depending on rocket type + stats.setFuelCapacity(FuelRegistry.FuelType.LIQUID_MONOPROPELLANT, fuelCapacityMonopropellant); + stats.setFuelCapacity(FuelRegistry.FuelType.LIQUID_BIPROPELLANT, fuelCapacityBipropellant); + stats.setFuelCapacity(FuelRegistry.FuelType.LIQUID_OXIDIZER, fuelCapacityOxidizer); + stats.setFuelCapacity(FuelRegistry.FuelType.NUCLEAR_WORKING_FLUID, fuelCapacityNuclearWorkingFluid); + + //Non-fuel stats + stats.setWeight(weight); + stats.setThrust(Math.max(Math.max(thrustMonopropellant, thrustBipropellant), thrustNuclearTotalLimit)); + stats.setDrillingPower(drillPower); + } + + public void addTileEntity(TileEntity te) { + pos2te.put(te.getPos(), te); + tileEntities.add(te); + } + public static StorageChunk copyWorldBB(World world, AxisAlignedBB bb) { int actualMinX = (int) bb.maxX, actualMinY = (int) bb.maxY, @@ -188,6 +333,10 @@ public static StorageChunk copyWorldBB(World world, AxisAlignedBB bb) { ret.blocks[x - actualMinX][y - actualMinY][z - actualMinZ] = state.getBlock(); ret.metas[x - actualMinX][y - actualMinY][z - actualMinZ] = (short) state.getBlock().getMetaFromState(state); + if (state.getBlock() == AdvancedRocketryBlocks.blockServiceMonitor) { + ret.hasServiceMonitor = true; + } + TileEntity entity = world.getTileEntity(pos); if (entity != null) { NBTTagCompound nbt = new NBTTagCompound(); @@ -214,7 +363,7 @@ public static StorageChunk copyWorldBB(World world, AxisAlignedBB bb) { ret.liquidTiles.add(newTile); } - ret.tileEntities.add(newTile); + ret.addTileEntity(newTile); } } } @@ -229,15 +378,11 @@ public static StorageChunk copyWorldBB(World world, AxisAlignedBB bb) { public static StorageChunk cutWorldBB(World worldObj, AxisAlignedBB bb) { StorageChunk chunk = StorageChunk.copyWorldBB(worldObj, bb); - float weight = 0; - for (int x = (int) bb.minX; x <= bb.maxX; x++) { for (int z = (int) bb.minZ; z <= bb.maxZ; z++) { for (int y = (int) bb.minY; y <= bb.maxY; y++) { BlockPos pos = new BlockPos(x, y, z); - weight += WeightEngine.INSTANCE.getWeight(worldObj, pos); - //Workaround for dupe TileEntity tile = worldObj.getTileEntity(pos); if (tile instanceof IInventory) { @@ -252,8 +397,6 @@ public static StorageChunk cutWorldBB(World worldObj, AxisAlignedBB bb) { } } - chunk.weight = (int) weight; - //Carpenter's block's dupe for (Entity entity : worldObj.getEntitiesWithinAABB(EntityItem.class, bb.grow(5, 5, 5))) { entity.setDead(); @@ -323,7 +466,7 @@ public IBlockState getBlockState(BlockPos pos) { public void setBlockState(BlockPos pos, IBlockState state) { - System.out.println("Block "+pos.getX()+":"+pos.getY()+":"+pos.getZ()+" set to "+state.getBlock().getUnlocalizedName()); +// System.out.println("Block "+pos.getX()+":"+pos.getY()+":"+pos.getZ()+" set to "+state.getBlock().getUnlocalizedName()); int x = pos.getX(); int y = pos.getY(); @@ -333,85 +476,6 @@ public void setBlockState(BlockPos pos, IBlockState state) { metas[x][y][z] = (short) state.getBlock().getMetaFromState(state); } - //TODO: optimize the F*** out of this - public void writeToNBT(NBTTagCompound nbt) { - - if (world.isRemote) return; //client has no business writing here - - nbt.setInteger("xSize", sizeX); - nbt.setInteger("ySize", sizeY); - nbt.setInteger("zSize", sizeZ); - nbt.setFloat("weight", weight); - - Iterator tileEntityIterator = tileEntities.iterator(); - NBTTagList tileList = new NBTTagList(); - while (tileEntityIterator.hasNext()) { - TileEntity tile = tileEntityIterator.next(); - try { - NBTTagCompound tileNbt = new NBTTagCompound(); - tile.writeToNBT(tileNbt); - tileList.appendTag(tileNbt); - } catch (RuntimeException e) { - AdvancedRocketry.logger.warn("A tile entity has thrown an error: " + tile.getClass().getCanonicalName()); - blocks[tile.getPos().getX()][tile.getPos().getY()][tile.getPos().getZ()] = Blocks.AIR; - metas[tile.getPos().getX()][tile.getPos().getY()][tile.getPos().getZ()] = 0; - tileEntityIterator.remove(); - } - } - - int[] blockId = new int[sizeX * sizeY * sizeZ]; - int[] metasId = new int[sizeX * sizeY * sizeZ]; - for (int x = 0; x < sizeX; x++) { - for (int y = 0; y < sizeY; y++) { - for (int z = 0; z < sizeZ; z++) { - blockId[z + (sizeZ * y) + (sizeZ * sizeY * x)] = Block.getIdFromBlock(blocks[x][y][z]); - metasId[z + (sizeZ * y) + (sizeZ * sizeY * x)] = metas[x][y][z]; - } - } - } - - NBTTagIntArray idList = new NBTTagIntArray(blockId); - NBTTagIntArray metaList = new NBTTagIntArray(metasId); - - nbt.setTag("idList", idList); - nbt.setTag("metaList", metaList); - nbt.setTag("tiles", tileList); - - - /*for(int x = 0; x < sizeX; x++) { - for(int y = 0; y < sizeY; y++) { - for(int z = 0; z < sizeZ; z++) { - - idList.appendTag(new NBTTagInt(Block.getIdFromBlock(blocks[x][y][z]))); - metaList.appendTag(new NBTTagInt(metas[x][y][z])); - - //NBTTagCompound tag = new NBTTagCompound(); - tag.setInteger("block", Block.getIdFromBlock(blocks[x][y][z])); - tag.setShort("meta", metas[x][y][z]); - - NBTTagCompound tileNbtData = null; - - for(TileEntity tile : tileEntities) { - NBTTagCompound tileNbt = new NBTTagCompound(); - - tile.writeToNBT(tileNbt); - - if(tileNbt.getInteger("x") == x && tileNbt.getInteger("y") == y && tileNbt.getInteger("z") == z){ - tileNbtData = tileNbt; - break; - } - } - - if(tileNbtData != null) - tag.setTag("tile", tileNbtData); - - nbt.setTag(String.format("%d.%d.%d", x,y,z), tag); - } - - } - }*/ - } - public void rotateBy(EnumFacing dir) { HashedBlockPosition newSizes = new HashedBlockPosition(getSizeX(), getSizeY(), getSizeZ()); @@ -513,6 +577,86 @@ public HashedBlockPosition getNewCoord(HashedBlockPosition in, EnumFacing dir) { return out; } + //TODO: optimize the F*** out of this + public void writeToNBT(NBTTagCompound nbt) { + + if (world.isRemote) return; //client has no business writing here + + nbt.setInteger("xSize", sizeX); + nbt.setInteger("ySize", sizeY); + nbt.setInteger("zSize", sizeZ); + nbt.setFloat("weight", weight); + nbt.setBoolean("hasServiceMonitor", hasServiceMonitor); + + Iterator tileEntityIterator = tileEntities.iterator(); + NBTTagList tileList = new NBTTagList(); + while (tileEntityIterator.hasNext()) { + TileEntity tile = tileEntityIterator.next(); + try { + NBTTagCompound tileNbt = new NBTTagCompound(); + tile.writeToNBT(tileNbt); + tileList.appendTag(tileNbt); + } catch (RuntimeException e) { + AdvancedRocketry.logger.warn("A tile entity has thrown an error: " + tile.getClass().getCanonicalName()); + blocks[tile.getPos().getX()][tile.getPos().getY()][tile.getPos().getZ()] = Blocks.AIR; + metas[tile.getPos().getX()][tile.getPos().getY()][tile.getPos().getZ()] = 0; + tileEntityIterator.remove(); + } + } + + int[] blockId = new int[sizeX * sizeY * sizeZ]; + int[] metasId = new int[sizeX * sizeY * sizeZ]; + for (int x = 0; x < sizeX; x++) { + for (int y = 0; y < sizeY; y++) { + for (int z = 0; z < sizeZ; z++) { + blockId[z + (sizeZ * y) + (sizeZ * sizeY * x)] = Block.getIdFromBlock(blocks[x][y][z]); + metasId[z + (sizeZ * y) + (sizeZ * sizeY * x)] = metas[x][y][z]; + } + } + } + + NBTTagIntArray idList = new NBTTagIntArray(blockId); + NBTTagIntArray metaList = new NBTTagIntArray(metasId); + + nbt.setTag("idList", idList); + nbt.setTag("metaList", metaList); + nbt.setTag("tiles", tileList); + + + /*for(int x = 0; x < sizeX; x++) { + for(int y = 0; y < sizeY; y++) { + for(int z = 0; z < sizeZ; z++) { + + idList.appendTag(new NBTTagInt(Block.getIdFromBlock(blocks[x][y][z]))); + metaList.appendTag(new NBTTagInt(metas[x][y][z])); + + //NBTTagCompound tag = new NBTTagCompound(); + tag.setInteger("block", Block.getIdFromBlock(blocks[x][y][z])); + tag.setShort("meta", metas[x][y][z]); + + NBTTagCompound tileNbtData = null; + + for(TileEntity tile : tileEntities) { + NBTTagCompound tileNbt = new NBTTagCompound(); + + tile.writeToNBT(tileNbt); + + if(tileNbt.getInteger("x") == x && tileNbt.getInteger("y") == y && tileNbt.getInteger("z") == z){ + tileNbtData = tileNbt; + break; + } + } + + if(tileNbtData != null) + tag.setTag("tile", tileNbtData); + + nbt.setTag(String.format("%d.%d.%d", x,y,z), tag); + } + + } + }*/ + } + public void readFromNBT(NBTTagCompound nbt) { //System.out.println("read from nbt"); @@ -521,6 +665,7 @@ public void readFromNBT(NBTTagCompound nbt) { sizeY = nbt.getInteger("ySize"); sizeZ = nbt.getInteger("zSize"); weight = nbt.getFloat("weight"); + hasServiceMonitor = nbt.getBoolean("hasServiceMonitor"); blocks = new Block[sizeX][sizeY][sizeZ]; metas = new short[sizeX][sizeY][sizeZ]; @@ -534,7 +679,6 @@ public void readFromNBT(NBTTagCompound nbt) { int[] metasId = nbt.getIntArray("metaList"); - for (int x = 0; x < sizeX; x++) { for (int y = 0; y < sizeY; y++) { for (int z = 0; z < sizeZ; z++) { @@ -542,7 +686,7 @@ public void readFromNBT(NBTTagCompound nbt) { metas[x][y][z] = (short) metasId[z + (sizeZ * y) + (sizeZ * sizeY * x)]; chunk.setBlockState(new BlockPos(x, y, z), this.blocks[x][y][z].getStateFromMeta(this.metas[x][y][z])); - world.checkLightFor(EnumSkyBlock.BLOCK,new BlockPos(x, y, z)); + world.checkLightFor(EnumSkyBlock.BLOCK, new BlockPos(x, y, z)); } } } @@ -563,7 +707,7 @@ public void readFromNBT(NBTTagCompound nbt) { liquidTiles.add(tile); } - tileEntities.add(tile); + this.addTileEntity(tile); tile.setWorld(world); chunk.addTileEntity(tile); @@ -613,13 +757,9 @@ else if(tag.hasKey("tile")) { this.chunk.generateSkylightMap(); } + //pass the coords of the xmin, ymin, zmin as well as the world to move the rocket @Override public void pasteInWorld(World world, int xCoord, int yCoord, int zCoord) { - this.pasteInWorld(world, xCoord, yCoord, zCoord, false); - } - - //pass the coords of the xmin, ymin, zmin as well as the world to move the rocket - public void pasteInWorld(World world, int xCoord, int yCoord, int zCoord, boolean damage) { //Set all the blocks for (int x = 0; x < sizeX; x++) { @@ -657,20 +797,20 @@ public void pasteInWorld(World world, int xCoord, int yCoord, int zCoord, boolea if (entity != null) entity.readFromNBT(nbt); + } + } - if (damage && entity instanceof TileBrokenPart) { - ((TileBrokenPart) entity).transition(); + public void damageParts() { + for (TileEntity tile : tileEntities) { + if (tile instanceof TileBrokenPart) { + ((TileBrokenPart) tile).transition(); } } } - @Override + @Nullable public TileEntity getTileEntity(@Nonnull BlockPos pos) { - for (TileEntity tileE : tileEntities) { - if (tileE.getPos().compareTo(pos) == 0) - return tileE; - } - return null; + return pos2te.getOrDefault(pos, null); } @Override @@ -741,6 +881,45 @@ public TileGuidanceComputer getGuidanceComputer() { return null; } + public float getBreakingProbability() { + float prob = 0; + + for (TileEntity te : tileEntities) { + if (te instanceof TileBrokenPart) { + TileBrokenPart brokenPart = (TileBrokenPart) te; + float additionalProb = 0; + + if (te.getBlockType() instanceof BlockNuclearRocketMotor) { + additionalProb = 1F; + } else if (te.getBlockType() instanceof BlockRocketMotor || te.getBlockType() instanceof BlockBipropellantRocketMotor) { + additionalProb = 0.2F; + } + prob += additionalProb * brokenPart.getStage() / 10; + if (prob >= 1) { + return Math.min(1, prob); + } + } + } + + return prob; + } + + public List getBrokenBlocks() { + List res = new ArrayList<>(); + + for (TileEntity te : tileEntities) { + if (te instanceof TileBrokenPart) { + res.add((TileBrokenPart) te); + } + } + + return res; + } + + public boolean shouldBreak() { + return world.rand.nextFloat() < this.getBreakingProbability(); + } + /** * @return destination ID or Constants.INVALID_PLANET if none */ @@ -826,7 +1005,8 @@ public void readtiles(ByteBuf in) { } } } - public void writetiles(ByteBuf out){ + + public void writetiles(ByteBuf out) { PacketBuffer buffer = new PacketBuffer(out); buffer.writeShort(tileEntities.size()); Iterator tileIterator = tileEntities.iterator(); @@ -854,7 +1034,7 @@ public void writetiles(ByteBuf out){ public void writeToNetwork(ByteBuf out) { - if (DimensionManager.getWorld(0).isRemote)System.out.println("This should have never been called!"); + if (DimensionManager.getWorld(0).isRemote) System.out.println("This should have never been called!"); PacketBuffer buffer = new PacketBuffer(out); @@ -893,10 +1073,11 @@ public void writeToNetwork(ByteBuf out) { tileIterator.remove(); } } + + buffer.writeBoolean(hasServiceMonitor); } public void readFromNetwork(ByteBuf in) { - //System.out.println("read from network"); finalized = false; @@ -912,7 +1093,6 @@ public void readFromNetwork(ByteBuf in) { chunk = new Chunk(world, 0, 0); - for (int x = 0; x < sizeX; x++) { for (int y = 0; y < sizeY; y++) { for (int z = 0; z < sizeZ; z++) { @@ -921,7 +1101,7 @@ public void readFromNetwork(ByteBuf in) { this.metas[x][y][z] = buffer.readShort(); chunk.setBlockState(new BlockPos(x, y, z), this.blocks[x][y][z].getStateFromMeta(this.metas[x][y][z])); - //world.checkLightFor(EnumSkyBlock.BLOCK,new BlockPos(x, y, z)); + world.checkLightFor(EnumSkyBlock.BLOCK,new BlockPos(x, y, z)); } } } @@ -932,7 +1112,7 @@ public void readFromNetwork(ByteBuf in) { TileEntity tile = ZUtils.createTile(nbt); tile.setWorld(world); - tileEntities.add(tile); + this.addTileEntity(tile); if (isInventoryBlock(tile)) { inventoryTiles.add(tile); @@ -948,6 +1128,9 @@ public void readFromNetwork(ByteBuf in) { e.printStackTrace(); } } + + hasServiceMonitor = buffer.readBoolean(); + //We are now ready to render this.chunk.generateSkylightMap(); finalized = true; diff --git a/src/main/java/zmaster587/advancedRocketry/util/TerraformingHelper.java b/src/main/java/zmaster587/advancedRocketry/util/TerraformingHelper.java new file mode 100644 index 000000000..20ab6d6e4 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/util/TerraformingHelper.java @@ -0,0 +1,383 @@ +package zmaster587.advancedRocketry.util; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.math.Vec3i; +import net.minecraft.world.World; +import net.minecraft.world.biome.BiomeProvider; +import net.minecraft.world.chunk.ChunkPrimer; +import net.minecraftforge.common.BiomeManager; +import zmaster587.advancedRocketry.dimension.DimensionManager; +import zmaster587.advancedRocketry.dimension.DimensionProperties; +import zmaster587.advancedRocketry.world.ChunkManagerPlanet; +import zmaster587.advancedRocketry.world.ChunkProviderPlanet; + +import java.util.*; + +import static org.apache.commons.lang3.RandomUtils.nextInt; + +enum TerraformingType{ + ALLOWED, BORDER, PROTECTED +} + +public class TerraformingHelper { + public BiomeProvider chunkMgrTerraformed; + public int dimId; + public List biomeList; + public World world; + public ChunkProviderPlanet generator; + private DimensionProperties props; + + private Map chunkDataMap = new HashMap<>(); + + + // A block is placed in queue if (OR) + // - Initial block placements - both only set blocks if the terrain at the BlockPos is not fully generated in the "real" world + // - The TerraformingHelper is created ( causes all loaded chunks to place their blocks here, from DimProps ) + // - A new chunk is loaded ( called from PlanetEventHandler ) + // - After the BiomeHandler has made a change at a BlockPos + // - For type ALLOWED: if the terrain heigt does not match the target, re-add the block to the queue + // - For type BORDER: if BiomeHandler has made a change of the height at BlockPos re-add to queue + // - For type BORDER: if a type.ALLOWED has changed its height it will add blocks next to it (if type==BORDER) to the queue + // - For type PROTECTED: the block is never re-added to queue because it will change its biome only once + // - When a protecting Block has been removed and chunk status is re-calculated + // add every chunk that was PROTECTED and no longer is PROTECTED to the queue for terraforming. + // doesn't matter if it is type ALLOWED or type BORDER + private List terraformingqueue; + private List decorationqueue; + private List biomechangingqueue; + + int safe_zone_radius = 3; // radius for protected zone + int border_zone = 3; // border zone size + + public boolean has_blocks_in_tf_queue(){ + return !terraformingqueue.isEmpty(); + } + public boolean has_blocks_in_dec_queue(){ + return !decorationqueue.isEmpty(); + } + + public TerraformingHelper(int dimension, List biomes, HashSet generated_chunks, HashSet biomechanged_chunks){ + this.dimId = dimension; + this.props = DimensionManager.getInstance().getDimensionProperties(dimension); + this.biomeList = biomes; + this.world = net.minecraftforge.common.DimensionManager.getWorld(dimId); + this.chunkMgrTerraformed = new ChunkManagerPlanet(world, world.getWorldInfo().getGeneratorOptions(), biomeList); + this.terraformingqueue = new ArrayList<>(); + this.biomechangingqueue = new ArrayList<>(); + this.decorationqueue = new ArrayList<>(); + chunkDataMap = new HashMap<>(); + generator = new ChunkProviderPlanet(world, world.getSeed(), world.getWorldInfo().isMapFeaturesEnabled(), world.getWorldInfo().getGeneratorOptions()); + + System.out.println("register generated chunks..."); + for (ChunkPos i:generated_chunks){ + chunkdata data = new chunkdata(i.x,i.z,null, world, this); + data.chunk_fully_generated = true; + chunkDataMap.put(new ChunkPos(data.x,data.z), data); + } + System.out.println("register biome changed chunks..."); + for (ChunkPos i:biomechanged_chunks){ + + generate_new_chunkdata(new ChunkPos(i.x, i.z)); + chunkdata data = getChunkFromList(i.x,i.z); + data.chunk_fully_biomechanged = true; + } + + System.out.println("recalculate chunk types..."); + recalculate_chunk_status(); + System.out.println("ok!"); + } + + //0 = no + //1 = yes + // -1 = never (if it includes a type.PROTECTED chunk + public int can_populate(int x, int z){ + chunkdata currentchunk = getChunkFromList(x,z); + chunkdata currentchunkx1 = getChunkFromList(x+1,z); + chunkdata currentchunkz1 = getChunkFromList(x,z+1); + chunkdata currentchunkx1z1 = getChunkFromList(x+1,z+1); + + if (currentchunk != null && currentchunkz1 != null && currentchunkx1 != null && currentchunkx1z1 != null){ + + if (currentchunk.type == TerraformingType.PROTECTED || currentchunkz1.type == TerraformingType.PROTECTED ||currentchunkx1.type == TerraformingType.PROTECTED ||currentchunkx1z1.type == TerraformingType.PROTECTED) + return -1; // chunks contain a protected chunk + + if (currentchunkz1.terrain_fully_generated && currentchunkx1.terrain_fully_generated && currentchunkx1z1.terrain_fully_generated && currentchunk.terrain_fully_generated) { + currentchunk.populate_chunk_if_not_already_done(); + return 1; + } + } + return 0; + } + + /* + used to add BORDER type block positions to queue for updating again + */ + public void register_height_change_actual(BlockPos pos){ + ChunkPos cpos = getChunkPosFromBlockPos(pos); + chunkdata data= getChunkFromList(cpos.x,cpos.z); + if (data !=null && data.type == TerraformingType.BORDER) { + add_position_to_queue(pos); + //System.out.println("add position to queue again"); + } + } + public void register_height_change(BlockPos pos){ + register_height_change_actual(pos.add(1,0,0)); + register_height_change_actual(pos.add(-1,0,0)); + register_height_change_actual(pos.add(0,0,1)); + register_height_change_actual(pos.add(0,0,-1)); + } + + + /* + When a chunk is fully terrain-generated it will call this method to update border chunks next to it. + A Border chunk is considered fully generated when every type.ALLOWED chunks next to it are fully generated. + This is because a fully terrain generated chunk will no longer change its heightmap so it will not modify the heightmap of the border chunk next to it + */ + public synchronized void check_next_border_chunk_fully_generated(int px, int pz) { + + for (int x = -1; x <= 1; x++) { + for (int z = -1; z <= 1; z++) { + chunkdata data = getChunkFromList(px + x, pz + z); + if (data == null)continue; + if (data != null && !data.terrain_fully_generated && data.type == TerraformingType.BORDER) { + int chunkposxlow = data.x * 16; + int chunkposzlow = data.z * 16; + int chunkposxhigh = chunkposxlow + 16; + int chunkposzhigh = chunkposzlow + 16; + + + for(Vec3i p : terraformingqueue){ + if (p.getX() >= chunkposxlow && p.getX() < chunkposxhigh) { + if (p.getZ() >= chunkposzlow && p.getZ() < chunkposzhigh) { + return; + } + } + } + + + for (int x2 = -1; x2 <= 1; x2++) { + for (int z2 = -1; z2 <= 1; z2++) { + chunkdata data2 = getChunkFromList(px + x + x2, pz + z + z2); + if (data2 == null) return; + if (data2.type == TerraformingType.ALLOWED) { + if (!data2.terrain_fully_generated) { + return; + } + } + } + } + System.out.println("border chunk terrain fully generated"); + data.terrain_fully_generated = true; + data.blockStates = null; // no longer needed, gc should collect them now - actually, these are never needed but who cares... + check_next_border_chunk_fully_generated(data.x, data.z); // update border chunks next to this one to check if they can decorate + check_can_decorate(data.x, data.z); + + } + } + } + } + public void check_can_decorate(int px, int pz){ + // for every chunk next to this one, check if it can decorate (except for if it is already decorated) + for (int x = -1; x <= 1; x++) { + for (int z = -1; z <= 1; z++) { + if (getChunkFromList(px+x,pz+z) != null && !getChunkFromList(px+x,pz+z).chunk_fully_generated){ + if (can_populate(px+x,pz+z) != 0){ + //re-add all position to queue for decoration + System.out.println("chunk can populate now: "+(px+x)+":"+(pz+z)); + for (int bx = 0; bx < 16; bx++) { + for (int bz = 0; bz < 16; bz++) { + add_position_to_decoration_queue(new BlockPos((px+x)*16+bx, 0, (pz+z)*16+bz)); + } + } + } + } + } + } + + } + public ChunkPos getChunkPosFromBlockPos(BlockPos pos) { + return new ChunkPos(pos.getX() >> 4, pos.getZ() >> 4); + } + + + + public TerraformingType get_chunk_type(int x, int z) { + + TerraformingType type = TerraformingType.ALLOWED; + for (BlockPos i : DimensionProperties.proxylists.getProtectingBlocksForDimension(props.getId())) { + //System.out.println("found protecting block at "+i.getX()+":"+i.getY()+":"+i.getZ()); + ChunkPos cpos = getChunkPosFromBlockPos(i); + int dx = cpos.x - x; + int dz = cpos.z - z; + if (Math.abs(dx) <= safe_zone_radius && Math.abs(dz) <= safe_zone_radius) + return TerraformingType.PROTECTED; + else if (Math.abs(dx) <= safe_zone_radius + border_zone && Math.abs(dz) <= safe_zone_radius + border_zone) { + type = TerraformingType.BORDER; + } + } + return type; + } + + public void recalculate_chunk_status() { + Iterator> iterator = chunkDataMap.entrySet().iterator(); + + while (iterator.hasNext()) { + + Map.Entry entry = iterator.next(); + + chunkdata data = entry.getValue(); + + TerraformingType prevtype = data.type; + + data.type = get_chunk_type(data.x, data.z); + + if (prevtype != TerraformingType.ALLOWED) + if (data.type == TerraformingType.ALLOWED || data.type == TerraformingType.BORDER) + if (data.terrain_fully_generated) + iterator.remove(); + + } + } + + + + + + public chunkdata getChunkFromList(int x, int z){ + ChunkPos key = new ChunkPos(x,z); + return chunkDataMap.get(key); + } + + + + public synchronized void add_position_to_queue(BlockPos p){ + //System.out.println("add position: "+p.getX()+":"+p.getZ()); + if (p == null){ + System.out.print("ERROR POSITION IS NULL"); + return; + } + + //if on protected chunk, instantly add to decoration queue as it will not work protected chunks + ChunkPos cp = getChunkPosFromBlockPos(p); + if(get_chunk_type(cp.x,cp.z) == TerraformingType.PROTECTED){ + int inchunkx = ((p.getX() % 16) + 16) % 16; + int inchunkz = ((p.getZ() % 16) + 16) % 16; + getChunkFromList(cp.x, cp.z).set_position_fully_generated(inchunkx, inchunkz); + }else { + terraformingqueue.add(new Vec3i(p.getX(), p.getY(), p.getZ())); + } + } + + public synchronized void add_position_to_biomechanging_queue(BlockPos p){ + //System.out.println("add position: "+p.getX()+":"+p.getZ()); + if (p == null){ + System.out.print("ERROR POSITION IS NULL"); + return; + } + biomechangingqueue.add(new Vec3i(p.getX(),p.getY(),p.getZ())); + } + + public synchronized void add_position_to_decoration_queue(BlockPos p){ + //System.out.println("add position: "+p.getX()+":"+p.getZ()); + if (p == null){ + System.out.print("ERROR POSITION IS NULL"); + return; + } + int insertionIndex = 0; + if (decorationqueue.size() > 0) { + insertionIndex = new Random().nextInt(Math.min(decorationqueue.size(), 1000)); + } + decorationqueue.add(insertionIndex, new Vec3i(p.getX(),p.getY(),p.getZ())); + } + + + public synchronized BlockPos get_next_position(boolean random){ + if (terraformingqueue.isEmpty()) + return null; + int index = 0; + if (random) + index = nextInt(0,terraformingqueue.size()); + + Vec3i pos = terraformingqueue.remove(index); + return new BlockPos(pos); + } + public synchronized BlockPos get_next_position_biomechanging(boolean random) { + if (biomechangingqueue.isEmpty()) { + return null; + } + + int index; + if (random) { + index = new Random().nextInt(Math.min(8192, biomechangingqueue.size())); + } else { + index = 0; // Default to the first element if not random mode + } + + Vec3i pos = biomechangingqueue.remove(index); + return new BlockPos(pos); + } + + public synchronized BlockPos get_next_position_decoration(boolean random){ + if (decorationqueue.isEmpty()) + return null; + int index = 0; + if (random) + index = nextInt(0,decorationqueue.size()); + + Vec3i pos = decorationqueue.remove(index); + return new BlockPos(pos); + } + + public void set_chunk_biomechanged(ChunkPos pos){ // mark a chunk ready for terraforming + props.add_chunk_to_terraforming_list_but_this_time_real_terraforming_and_not_biomechanging(pos); + DimensionProperties.proxylists.getChunksFullyBiomeChanged(props.getId()).add(pos); // set it fully biome changed + + } + public void generate_new_chunkdata(ChunkPos cpos){ + chunkdata data; + + + + data = new chunkdata(cpos.x,cpos.z, null, world, this); + data.type = get_chunk_type(data.x,data.z); + chunkDataMap.put(new ChunkPos(data.x,data.z),data); + } + + public IBlockState[] getBlocksAt(int x, int z){ + ChunkPos cpos = getChunkPosFromBlockPos(new BlockPos(x,0,z)); + chunkdata data = getChunkFromList(cpos.x,cpos.z); + if (data == null){ + System.out.println("generate new chunk: "+cpos.x+":"+cpos.z); + generate_new_chunkdata(new ChunkPos(cpos.x, cpos.z)); + data = getChunkFromList(cpos.x,cpos.z); + } + if (data.blockStates == null){ + System.out.println("generate new blockstates: "+cpos.x+":"+cpos.z); + ChunkPrimer primer = generator.getChunkPrimer(cpos.x, cpos.z, chunkMgrTerraformed); + IBlockState[][][] blockStates = new IBlockState[16][16][256]; + for (int px = 0; px < 16; px++) { + for (int pz = 0; pz < 16; pz++) { + for (int py = 0; py < 256; py++) { + blockStates[px][pz][py] = primer.getBlockState(px,py,pz); + } + } + } + data.blockStates = blockStates; + } + int chunkx = ((x % 16) + 16) % 16; + int chunkz = ((z % 16) + 16) % 16; + + if (data.blockStates == null) + return null; + + return data.blockStates[chunkx][chunkz]; + } + + + public void setChunkFullyGenerated(int x, int z) { + getChunkFromList(x,z).chunk_fully_generated = true; + DimensionProperties.proxylists.getChunksFullyTerraformed(props.getId()).add(new ChunkPos(x,z)); + } +} diff --git a/src/main/java/zmaster587/advancedRocketry/util/WeightEngine.java b/src/main/java/zmaster587/advancedRocketry/util/WeightEngine.java index e76c4555b..61e2452ba 100644 --- a/src/main/java/zmaster587/advancedRocketry/util/WeightEngine.java +++ b/src/main/java/zmaster587/advancedRocketry/util/WeightEngine.java @@ -4,12 +4,23 @@ import com.google.gson.GsonBuilder; import com.google.gson.JsonObject; import net.minecraft.block.Block; +import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.IFluidTankProperties; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; +import zmaster587.advancedRocketry.api.ARConfiguration; +import zmaster587.advancedRocketry.block.BlockBipropellantRocketMotor; +import zmaster587.advancedRocketry.block.BlockFuelTank; +import zmaster587.advancedRocketry.block.BlockPressurizedFluidTank; +import zmaster587.advancedRocketry.block.BlockRocketMotor; import java.io.File; import java.io.FileReader; @@ -31,13 +42,47 @@ public enum WeightEngine { } public float getWeight(ItemStack stack) { - if (stack.isEmpty()) { + if (stack.isEmpty() || stack.getItem().getRegistryName()==null) { return 0; } double weight = weights.getOrDefault(stack.getItem().getRegistryName().toString(), -1.0) * stack.getCount(); if (weight >= 0) { return (float) weight; } + + double tankWeight = 0.2; + double motorWeight = 2; + double guidanceComputerWeight = 1.8; + + double pressureTankWeight = 5; + double satelliteHatchWeight = 5; + + // TODO Rewrite!!!! + if (stack.getItem() instanceof ItemBlock) { + Block block = ((ItemBlock) stack.getItem()).getBlock(); + + if (block instanceof BlockFuelTank){ + weights.put(stack.getItem().getRegistryName().toString(), (double) tankWeight); + return (float) tankWeight; + } + if (block instanceof BlockRocketMotor || block instanceof BlockBipropellantRocketMotor){ + weights.put(stack.getItem().getRegistryName().toString(), (double) motorWeight); + return (float) motorWeight; + } + if (block instanceof BlockPressurizedFluidTank){ + weights.put(stack.getItem().getRegistryName().toString(), (double) pressureTankWeight); + return (float) pressureTankWeight; + } + if (stack.getItem().getRegistryName().toString().equals("advancedrocketry:guidancecomputer")){ + weights.put(stack.getItem().getRegistryName().toString(), (double) guidanceComputerWeight); + return (float) guidanceComputerWeight; + } + if (stack.getItem().getRegistryName().toString().equals("advancedrocketry:loader")){ + weights.put(stack.getItem().getRegistryName().toString(), (double) satelliteHatchWeight); + return (float) satelliteHatchWeight; + } + } + weights.put(stack.getItem().getRegistryName().toString(), 0.1); return 0.1F; // TODO Make weight selection by regular expressions @@ -51,7 +96,26 @@ public float getWeight(World world, BlockPos pos) { return getWeight(world.getTileEntity(pos), world.getBlockState(pos).getBlock()); } + public float getWeight(FluidStack stack) { + return getWeight(stack.getFluid(), stack.amount); + } + + public float getWeight(Fluid fluid, float amount) { + double weight = weights.getOrDefault(fluid.getUnlocalizedName(), -1.0) * amount; + if (weight >= 0) { + return (float) weight; + } + + weight = 0.001 * amount; + + weights.put(fluid.getUnlocalizedName(), 0.001); + return (float) weight; + } + public float getTEWeight(TileEntity te) { + + if(!ARConfiguration.getCurrentConfig().advancedWeightSystemInventories) return 0; + float weight = 0; if (te == null) { @@ -59,12 +123,22 @@ public float getTEWeight(TileEntity te) { } IItemHandler capability = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null); - if (capability == null) { - return weight; + if (capability != null) { + for (int i = 0; i < capability.getSlots(); i++) { + weight += getWeight(capability.getStackInSlot(i)); + } } - for (int i = 0; i < capability.getSlots(); i++) { - weight += getWeight(capability.getStackInSlot(i)); + + + IFluidHandler fluidHandler = te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, null); + if (fluidHandler != null) { + for (IFluidTankProperties info : fluidHandler.getTankProperties()) { + if (info != null && info.getContents() != null) { + weight += getWeight(info.getContents()); + } + } } + return weight; } @@ -99,7 +173,7 @@ public void load() { public void save() { try (FileWriter w = new FileWriter(file)) { - Gson GSON = new GsonBuilder().disableHtmlEscaping().create(); + Gson GSON = new GsonBuilder().disableHtmlEscaping().setPrettyPrinting().create(); JsonObject json = new JsonObject(); json.add("individual", GSON.toJsonTree(weights)); w.write(GSON.toJson(json)); diff --git a/src/main/java/zmaster587/advancedRocketry/util/XMLPlanetLoader.java b/src/main/java/zmaster587/advancedRocketry/util/XMLPlanetLoader.java index e65e4a18c..97cc635a3 100644 --- a/src/main/java/zmaster587/advancedRocketry/util/XMLPlanetLoader.java +++ b/src/main/java/zmaster587/advancedRocketry/util/XMLPlanetLoader.java @@ -103,6 +103,14 @@ public class XMLPlanetLoader { private static final String ATTR_GROUPMIN = "groupMin"; private static final String ATTR_GROUPMAX = "groupMax"; private static final String ATTR_NBT = "nbt"; + // Weather + private static final String ELEMENT_RAIN_START_LENGTH = "rainStartLength"; + private static final String ELEMENT_THUNDER_START_LENGTH = "thunderStartLength"; + private static final String ELEMENT_RAIN_PROLONGATION_LENGTH = "rainProlongationLength"; + private static final String ELEMENT_THUNDER_PROLONGATION_LENGTH = "thunderProlongationLength"; + private static final String ELEMENT_RAIN_MARKER = "rainMarker"; + private static final String ELEMENT_THUNDER_MARKER = "thunderMarker"; + NodeList currentList; private Document doc; private int currentNodeIndex; @@ -261,12 +269,21 @@ private static Node writePlanet(Document doc, DimensionProperties properties) { nodePlanet.appendChild(createTextNode(doc, AVG_TEMPERATURE, properties.averageTemperature)); nodePlanet.appendChild(createTextNode(doc, ELEMENT_PERIOD, properties.rotationalPeriod)); nodePlanet.appendChild(createTextNode(doc, ELEMENT_ATMDENSITY, properties.getAtmosphereDensity())); + // Custom weather properties + nodePlanet.appendChild(createTextNode(doc, ELEMENT_RAIN_START_LENGTH, properties.rainStartLength)); + nodePlanet.appendChild(createTextNode(doc, ELEMENT_RAIN_PROLONGATION_LENGTH, properties.rainProlongationLength)); + nodePlanet.appendChild(createTextNode(doc, ELEMENT_THUNDER_START_LENGTH, properties.thunderStartLength)); + nodePlanet.appendChild(createTextNode(doc, ELEMENT_THUNDER_PROLONGATION_LENGTH, properties.thunderProlongationLength)); + nodePlanet.appendChild(createTextNode(doc, ELEMENT_RAIN_MARKER, properties.getRainMarker())); + nodePlanet.appendChild(createTextNode(doc, ELEMENT_THUNDER_MARKER, properties.getThunderMarker())); + nodePlanet.appendChild(createTextNode(doc, GENERATECRATERS, properties.canGenerateCraters())); nodePlanet.appendChild(createTextNode(doc, GENERATECAVES, properties.canGenerateCaves())); nodePlanet.appendChild(createTextNode(doc, GENERATEVOLCANOS, properties.canGenerateVolcanos())); nodePlanet.appendChild(createTextNode(doc, GENERATESTRUCTURES, properties.canGenerateStructures())); nodePlanet.appendChild(createTextNode(doc, GENERATEGEODES, properties.canGenerateGeodes())); + if (properties.canGenerateCraters() && !(properties.getCraterMultiplier() == 1)) nodePlanet.appendChild(createTextNode(doc, ELEMENT_CRATER_MULTIPLIER, properties.getCraterMultiplier())); @@ -584,6 +601,19 @@ else if (planetPropertyNode.getNodeName().equalsIgnoreCase(ELEMENT_COLOR_OVERRID properties.colorOverride = Boolean.parseBoolean(planetPropertyNode.getTextContent()); else if (planetPropertyNode.getNodeName().equalsIgnoreCase(ELEMENT_SKYOVERRIDE)) properties.skyRenderOverride = Boolean.parseBoolean(planetPropertyNode.getTextContent()); + else if (planetPropertyNode.getNodeName().equalsIgnoreCase(ELEMENT_RAIN_START_LENGTH)) + properties.rainStartLength = Integer.parseInt(planetPropertyNode.getTextContent()); + // TODO Create default values for new fields + else if (planetPropertyNode.getNodeName().equalsIgnoreCase(ELEMENT_RAIN_PROLONGATION_LENGTH)) + properties.rainProlongationLength = Integer.parseInt(planetPropertyNode.getTextContent()); + else if (planetPropertyNode.getNodeName().equalsIgnoreCase(ELEMENT_THUNDER_START_LENGTH)) + properties.thunderStartLength = Integer.parseInt(planetPropertyNode.getTextContent()); + else if (planetPropertyNode.getNodeName().equalsIgnoreCase(ELEMENT_THUNDER_PROLONGATION_LENGTH)) + properties.thunderProlongationLength = Integer.parseInt(planetPropertyNode.getTextContent()); + else if (planetPropertyNode.getNodeName().equalsIgnoreCase(ELEMENT_RAIN_MARKER)) + properties.setRainMarker(Integer.parseInt(planetPropertyNode.getTextContent())); + else if (planetPropertyNode.getNodeName().equalsIgnoreCase(ELEMENT_THUNDER_MARKER)) + properties.setThunderMarker(Integer.parseInt(planetPropertyNode.getTextContent())); else if (planetPropertyNode.getNodeName().equalsIgnoreCase(ELEMENT_ATMDENSITY)) { try { diff --git a/src/main/java/zmaster587/advancedRocketry/util/chunkdata.java b/src/main/java/zmaster587/advancedRocketry/util/chunkdata.java new file mode 100644 index 000000000..66b0b19b0 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/util/chunkdata.java @@ -0,0 +1,143 @@ +package zmaster587.advancedRocketry.util; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.World; + +public class chunkdata { + public int x; + public int z; + public TerraformingType type; + + + // chunk can be populated if itself and the 3 chunks with (x+1), (z+1) and (x+1,z+1) are fully generated in the world + + + // if a chunks terrain is fully generated and does not need any future updates - causes it to set the IBlockState[][][] to null to free memory + // if the terrain is fully generated it allows for calling populate() + public boolean terrain_fully_generated; + + // will be set by BiomeHandler after calling the populate method, makes the chunk fully generated and it does not need any future updates + // as long as the atmosphere does not change, chunks that are fully generated will not register their blocks in the terraforming queue + public boolean chunk_fully_generated; + + public boolean chunk_populated; + + public boolean chunk_fully_biomechanged; + + // if the y values of new chunk and chunk in world match, terrain at this position is considered fully generated + public boolean[][] fully_generated; + + // if all positions have been decorated + public boolean[][] fully_decorated; + + // if all positions have been biomechanged + public boolean[][] fully_biomechanged; + + + public IBlockState[][][] blockStates; + + World world; // used to call populate after decoration is finished + TerraformingHelper helper; + + public chunkdata(int x, int z, IBlockState[][][] blockStates, World world, TerraformingHelper helper) { + this.x = x; + this.world = world; + this.helper = helper; + this.z = z; + this.blockStates = blockStates; + this.type = TerraformingType.ALLOWED; + chunk_fully_generated = false; + terrain_fully_generated = false; + chunk_populated = false; + fully_generated = new boolean[16][16]; + fully_decorated = new boolean[16][16]; + fully_biomechanged = new boolean[16][16]; + } + + /* + sets if a blockpos is fully generated and computed if the chunk is fully generated + called from BiomeHandler + */ + public void set_position_fully_generated(int x, int z){ + fully_generated[x][z] = true; + boolean all_generated = true; + for (int i = 0; i < 16; i++) { + for (int j = 0; j < 16; j++) { + if (fully_generated[i][j] == false) { + all_generated = false; + } + } + } + if (all_generated){ + System.out.println("chunk fully generated: "+this.x+":"+this.z); + terrain_fully_generated = true; + this.blockStates = null; // no longer needed, gc should collect them now + helper.check_next_border_chunk_fully_generated(this.x,this.z); // update border chunks next to this one to check if they can decorate + helper.check_can_decorate(this.x,this.z); + + } + } + + + public void set_position_biomechanged(int x, int z){ + fully_biomechanged[x][z] = true; + boolean all_generated = true; + for (int i = 0; i < 16; i++) { + for (int j = 0; j < 16; j++) { + if (fully_biomechanged[i][j] == false) { + all_generated = false; + } + } + } + if (all_generated){ + System.out.println("chunk fully biomechanged: "+this.x+":"+this.z); + chunk_fully_biomechanged = true; + + /// add chunk to terraforming queue now + helper.set_chunk_biomechanged(new ChunkPos(this.x, this.z)); + + } + } + + public void populate_chunk_if_not_already_done() { + // populate uses the biome at blockpos 0,0, in the chunk x+1,z+1, that's why we need the chunks next to it generated + if (!chunk_fully_generated && !chunk_populated) { + + //2 times i want more population! + world.provider.createChunkGenerator().populate(this.x, this.z); + world.provider.createChunkGenerator().populate(this.x, this.z); + + System.out.println("populate chunk " + this.x + ":" + this.z); + chunk_populated = true; + //make a biome lasers here + // no - looks bad + //for (int i = 0; i < 32; i++) { + // int bx = world.rand.nextInt(16); + // int bz = world.rand.nextInt(16); + // BlockPos pos = new BlockPos(this.x*16+bx,0,this.z*16+bz); + // PacketHandler.sendToNearby(new PacketBiomeIDChange(world.getChunkFromChunkCoords(this.x,this.z), world, new HashedBlockPosition(pos)), world.provider.getDimension(), pos, 1024); + //} + } + } + + public void set_position_decorated(int x, int z){ + + fully_decorated[x][z] = true; + boolean all_decorated = true; + for (int i = 0; i < 16; i++) { + for (int j = 0; j < 16; j++) { + if (fully_decorated[i][j] == false) { + all_decorated = false; + } + } + } + if (all_decorated){ + + helper.setChunkFullyGenerated(this.x,this.z); + } + + + } + +} diff --git a/src/main/java/zmaster587/advancedRocketry/util/nbt/Factory.java b/src/main/java/zmaster587/advancedRocketry/util/nbt/Factory.java new file mode 100644 index 000000000..f31c09a3c --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/util/nbt/Factory.java @@ -0,0 +1,6 @@ +package zmaster587.advancedRocketry.util.nbt; + +public interface Factory { + + T create(); +} diff --git a/src/main/java/zmaster587/advancedRocketry/util/nbt/NBTHelper.java b/src/main/java/zmaster587/advancedRocketry/util/nbt/NBTHelper.java new file mode 100644 index 000000000..573911ce8 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/util/nbt/NBTHelper.java @@ -0,0 +1,257 @@ +package zmaster587.advancedRocketry.util.nbt; + +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityList; +import net.minecraft.nbt.*; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.common.util.INBTSerializable; +import net.minecraftforge.fml.common.registry.ForgeRegistries; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * Tool for NBT serializing and deserializing collections and other stuff + */ +@SuppressWarnings("unchecked") +public class NBTHelper { + + public static NBTBase NBT_NULL = new NBTTagString("null"); + + public static void writeCollection(String name, NBTTagCompound compound, Collection> collection) { + compound.setTag(name, collectionToNBT(collection)); + } + + public static void writeCollection(String name, NBTTagCompound compound, Collection collection, ParametrizedFactory serializer) { + compound.setTag(name, collectionToNBT(collection, serializer)); + } + + public static > C readCollection(String name, NBTTagCompound compound, Factory collectionFactory, ParametrizedFactory deserializer) { + return collectionFromNBT(getTagList(name, compound), collectionFactory, deserializer); + } + + public static NBTTagList collectionToNBT(Collection> collection) { + NBTTagList tag = new NBTTagList(); + collection.stream().map(INBTSerializable::serializeNBT).forEach(tag::appendTag); + return tag; + } + + public static NBTTagList collectionToNBT(Collection collection, ParametrizedFactory serializer) { + NBTTagList tag = new NBTTagList(); + collection.stream().map(serializer::create).forEach(tag::appendTag); + return tag; + } + + public static > C collectionFromNBT(NBTTagList tag, Factory collectionFactory, ParametrizedFactory deserializer) { + C collection = collectionFactory.create(); + tag.iterator().forEachRemaining(item -> collection.add(deserializer.create((NBT_T) item))); + return collection; + } + + public static void writeMap(String name, NBTTagCompound compound, Map> map) { + compound.setTag(name, mapToNBT(map)); + } + + public static void writeMap(String name, NBTTagCompound compound, Map map, ParametrizedFactory serializer) { + compound.setTag(name, mapToNBT(map, serializer)); + } + + public static Map readMap(String name, NBTTagCompound compound, ParametrizedFactory valueDeserializer) { + return readMap(name, compound, Objects::toString, valueDeserializer); + } + + public static Map readMap(String name, NBTTagCompound compound, ParametrizedFactory keyDeserializer, ParametrizedFactory valueDeserializer) { + return mapFromNBT(compound.getCompoundTag(name), HashMap::new, keyDeserializer, valueDeserializer); + } + + public static NBTTagCompound mapToNBT(Map> map) { + NBTTagCompound compound = new NBTTagCompound(); + map.forEach((key, value) -> write(key.toString(), value, compound)); + return compound; + } + + public static NBTTagCompound mapToNBT(Map map, ParametrizedFactory serializer) { + NBTTagCompound compound = new NBTTagCompound(); + map.forEach((key, value) -> write(key.toString(), serializer.create(value), compound)); + return compound; + } + + public static Map mapFromNBT(NBTTagCompound compound, ParametrizedFactory valueDeserializer) { + return mapFromNBT(compound, Objects::toString, valueDeserializer); + } + + public static Map mapFromNBT(NBTTagCompound compound, ParametrizedFactory keyDeserializer, ParametrizedFactory valueDeserializer) { + return mapFromNBT(compound, HashMap::new, keyDeserializer, valueDeserializer); + } + + public static Map mapFromNBT(NBTTagCompound compound, Factory> mapFactory, ParametrizedFactory keyDeserializer, ParametrizedFactory valueDeserializer) { + Map map = mapFactory.create(); + compound.getKeySet().forEach(key -> map.put(keyDeserializer.create(key), read(key, compound, valueDeserializer))); + return map; + } + + public static void write(String key, INBTSerializable value, NBTTagCompound compound) { + compound.setTag(key, value.serializeNBT()); + } + + public static void write(String key, Object value, NBTTagCompound compound) { + if (value instanceof Integer) { + compound.setInteger(key, (Integer) value); + } else if (value instanceof Long) { + compound.setLong(key, (Long) value); + } else if (value instanceof String) { + compound.setString(key, (String) value); + } else if (value instanceof Boolean) { + compound.setBoolean(key, (Boolean) value); + } else if (value instanceof Float) { + compound.setFloat(key, (Float) value); + } else if (value instanceof Double) { + compound.setDouble(key, (Double) value); + } else if (value instanceof Byte) { + compound.setByte(key, (Byte) value); + } else if (value instanceof NBTBase) { + compound.setTag(key, (NBTBase) value); + } else if (value instanceof byte[]) { + compound.setByteArray(key, (byte[]) value); + } else if (value instanceof int[]) { + compound.setIntArray(key, (int[]) value); + } + } + + public static T read(String key, NBTTagCompound compound, ParametrizedFactory factory) { + return factory.create((NBT_T) compound.getTag(key)); + } + + public static Object read(String key, NBTTagCompound compound) { + NBTBase tag = compound.getTag(key); + if (tag instanceof NBTTagInt) { + return ((NBTTagInt) tag).getInt(); + } else if (tag instanceof NBTTagLong) { + return ((NBTTagLong) tag).getLong(); + } else if (tag instanceof NBTTagString) { + return ((NBTTagString) tag).getString(); + } else if (tag instanceof NBTTagByte) { + return ((NBTTagByte) tag).getByte(); + } else if (tag instanceof NBTTagFloat) { + return ((NBTTagFloat) tag).getFloat(); + } else if (tag instanceof NBTTagDouble) { + return ((NBTTagDouble) tag).getDouble(); + } else if (tag instanceof NBTTagByteArray) { + return ((NBTTagByteArray) tag).getByteArray(); + } else if (tag instanceof NBTTagIntArray) { + return ((NBTTagIntArray) tag).getIntArray(); + } + return null; + } + + public static NBTTagList getTagList(String name, NBTTagCompound compound) { + NBTBase nbt = compound.tagMap.get(name); + if (!(nbt instanceof NBTTagList)) { + throw new IllegalArgumentException("Tag got by name " + name + "isn't NBTTagList!"); + } + return (NBTTagList) nbt; + } + + public static NBTBase writeBlockPos(BlockPos pos) { + return new NBTTagLong(pos.toLong()); + } + + public static BlockPos readBlockPos(NBTBase nbt) { + return BlockPos.fromLong(((NBTTagLong) nbt).getLong()); + } + + public static void writeBlockPos(String key, BlockPos pos, NBTTagCompound compound) { + compound.setLong(key, pos.toLong()); + } + + public static BlockPos readBlockPos(String key, NBTTagCompound compound) { + return BlockPos.fromLong(compound.getLong(key)); + } + + public static NBTBase writeState(IBlockState state) { + if (state == null) { + return NBT_NULL; + } + NBTTagCompound compound = new NBTTagCompound(); + compound.setString("name", state.getBlock().getRegistryName().toString()); + compound.setShort("meta", (short) state.getBlock().getMetaFromState(state)); + return compound; + } + + public static IBlockState readState(NBTBase nbt) { + if (nbt.equals(NBT_NULL)) { + return null; + } + NBTTagCompound compound = (NBTTagCompound) nbt; + String blockName = compound.getString("name"); + Block block = ForgeRegistries.BLOCKS.getValue(new ResourceLocation(blockName)); + return block.getStateFromMeta(compound.getShort("meta")); + } + + public static void writeAABB(String key, NBTTagCompound compound, AxisAlignedBB aabb) { + compound.setTag(key, NBTTagCompoundBuilder + .create() + .setDouble("minX", aabb.minX) + .setDouble("minY", aabb.minY) + .setDouble("minZ", aabb.minZ) + .setDouble("maxX", aabb.maxX) + .setDouble("maxY", aabb.maxY) + .setDouble("maxZ", aabb.maxZ) + .build()); + } + + public static AxisAlignedBB readAABB(String key, NBTTagCompound compound) { + NBTTagCompound tag = compound.getCompoundTag(key); + return new AxisAlignedBB( + tag.getDouble("minX"), + tag.getDouble("minY"), + tag.getDouble("minZ"), + tag.getDouble("maxX"), + tag.getDouble("maxY"), + tag.getDouble("maxZ") + ); + } + + public static NBTBase writeTileEntity(final TileEntity tileEntity) { + if (tileEntity == null) { + return NBT_NULL; + } + + final NBTTagCompound compound = new NBTTagCompound(); + tileEntity.writeToNBT(compound); + return compound; + } + + public static TileEntity readTileEntity(final NBTBase compound) { + return readTileEntity(compound, null); + } + + public static TileEntity readTileEntity(final NBTBase nbt, final World world) { + if (nbt.equals(NBT_NULL)) { + return null; + } + NBTTagCompound compound = (NBTTagCompound) nbt; + return TileEntity.create(world, compound); + } + + public static NBTTagCompound writeEntityToCompound(final Entity entity) { + final NBTTagCompound entityCompound = new NBTTagCompound(); + if (entity.writeToNBTOptional(entityCompound)) { + return entityCompound; + } + + return null; + } + + public static Entity readEntityFromCompound(final NBTTagCompound nbtTagCompound, final World world) { + return EntityList.createEntityFromNBT(nbtTagCompound, world); + } +} diff --git a/src/main/java/zmaster587/advancedRocketry/util/nbt/NBTTagCompoundBuilder.java b/src/main/java/zmaster587/advancedRocketry/util/nbt/NBTTagCompoundBuilder.java new file mode 100644 index 000000000..78dc6d011 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/util/nbt/NBTTagCompoundBuilder.java @@ -0,0 +1,161 @@ +package zmaster587.advancedRocketry.util.nbt; + +import net.minecraft.nbt.*; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.common.util.INBTSerializable; + +import java.util.Collection; +import java.util.Map; +import java.util.UUID; +import java.util.function.Consumer; + +/** + * An utility class to functionally construct NBTTagCompound. + * Potentially can provide the advanced serializing to it. + */ +public class NBTTagCompoundBuilder { + + private final NBTTagCompound instance; + + private NBTTagCompoundBuilder(NBTTagCompound instance) { + this.instance = instance; + } + + public static NBTTagCompoundBuilder create() { + return new NBTTagCompoundBuilder(new NBTTagCompound()); + } + + public static NBTTagCompoundBuilder create(NBTTagCompound instance) { + return new NBTTagCompoundBuilder(instance); + } + + public NBTTagCompoundBuilder setString(String key, String value) { + instance.setString(key, value); + return this; + } + + public NBTTagCompoundBuilder setInt(String key, int value) { + instance.setInteger(key, value); + return this; + } + + public NBTTagCompoundBuilder setShort(String key, short value) { + instance.setShort(key, value); + return this; + } + + public NBTTagCompoundBuilder setLong(String key, long value) { + instance.setLong(key, value); + return this; + } + + public NBTTagCompoundBuilder setFloat(String key, float value) { + instance.setFloat(key, value); + return this; + } + + public NBTTagCompoundBuilder setDouble(String key, double value) { + instance.setDouble(key, value); + return this; + } + + public NBTTagCompoundBuilder setBoolean(String key, boolean value) { + instance.setBoolean(key, value); + return this; + } + + public NBTTagCompoundBuilder setIntArray(String key, int[] value) { + instance.setIntArray(key, value); + return this; + } + + public NBTTagCompoundBuilder setByteArray(String key, byte[] value) { + instance.setByteArray(key, value); + return this; + } + + public NBTTagCompoundBuilder setUniqueID(String key, UUID value) { + instance.setUniqueId(key, value); + return this; + } + + public NBTTagCompoundBuilder setSerializable(String key, INBTSerializable serializable) { + return setTag(key, serializable.serializeNBT()); + } + + public NBTTagCompoundBuilder setBlockPos(String key, BlockPos value) { + NBTHelper.writeBlockPos(key, value, instance); + return this; + } + + public NBTTagCompoundBuilder setAABB(String key, AxisAlignedBB value) { + NBTHelper.writeAABB(key, instance, value); + return this; + } + + public NBTTagCompoundBuilder setTag(String key, NBTBase value) { + instance.setTag(key, value); + return this; + } + + public NBTTagCompoundBuilder setCollection(String key, Collection> collection) { + NBTHelper.writeCollection(key, instance, collection); + return this; + } + + public NBTTagCompoundBuilder setStringCollection(String key, Collection collection) { + NBTHelper.writeCollection(key, instance, collection, NBTTagString::new); + return this; + } + + public NBTTagCompoundBuilder setIntegerCollection(String key, Collection collection) { + NBTHelper.writeCollection(key, instance, collection, NBTTagInt::new); + return this; + } + + public NBTTagCompoundBuilder setFloatCollection(String key, Collection collection) { + NBTHelper.writeCollection(key, instance, collection, NBTTagFloat::new); + return this; + } + + public NBTTagCompoundBuilder setDoubleCollection(String key, Collection collection) { + NBTHelper.writeCollection(key, instance, collection, NBTTagDouble::new); + return this; + } + + public NBTTagCompoundBuilder setByteCollection(String key, Collection collection) { + NBTHelper.writeCollection(key, instance, collection, NBTTagByte::new); + return this; + } + + public NBTTagCompoundBuilder setCollection(String key, Collection collection, ParametrizedFactory serializer) { + NBTHelper.writeCollection(key, instance, collection, serializer); + return this; + } + + public NBTTagCompoundBuilder setResourceLocation(String key, ResourceLocation value) { + instance.setString(key, value.toString()); + return this; + } + + public NBTTagCompoundBuilder setMap(String key, Map> map) { + NBTHelper.writeMap(key, instance, map); + return this; + } + + public NBTTagCompoundBuilder setMap(String key, Map map, ParametrizedFactory serializer) { + NBTHelper.writeMap(key, instance, map, serializer); + return this; + } + + public NBTTagCompoundBuilder execute(Consumer action) { + action.accept(instance); + return this; + } + + public NBTTagCompound build() { + return instance; + } +} diff --git a/src/main/java/zmaster587/advancedRocketry/util/nbt/NBTTagListCollector.java b/src/main/java/zmaster587/advancedRocketry/util/nbt/NBTTagListCollector.java new file mode 100644 index 000000000..acc620c3f --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/util/nbt/NBTTagListCollector.java @@ -0,0 +1,48 @@ +package zmaster587.advancedRocketry.util.nbt; + +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagList; + +import java.util.Collections; +import java.util.EnumSet; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Collector; + +public class NBTTagListCollector implements Collector { + + static final Set CH_UNORDERED_ID + = Collections.unmodifiableSet(EnumSet.of(Characteristics.UNORDERED, + Characteristics.IDENTITY_FINISH)); + + @Override + public Supplier supplier() { + return NBTTagList::new; + } + + @Override + public BiConsumer accumulator() { + return NBTTagList::appendTag; + } + + @Override + public BinaryOperator combiner() { + return (o1, o2) -> { + o2.forEach(o1::appendTag); + return o1; + }; + } + + @Override + public Function finisher() { + return Function.identity(); + } + + @Override + public Set characteristics() { + return CH_UNORDERED_ID; + } +} diff --git a/src/main/java/zmaster587/advancedRocketry/util/nbt/ParametrizedFactory.java b/src/main/java/zmaster587/advancedRocketry/util/nbt/ParametrizedFactory.java new file mode 100644 index 000000000..87f6e5dc4 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/util/nbt/ParametrizedFactory.java @@ -0,0 +1,6 @@ +package zmaster587.advancedRocketry.util.nbt; + +public interface ParametrizedFactory { + + O create(I param); +} diff --git a/src/main/java/zmaster587/advancedRocketry/world/ChunkManagerPlanet.java b/src/main/java/zmaster587/advancedRocketry/world/ChunkManagerPlanet.java index eab63c020..6791c258c 100644 --- a/src/main/java/zmaster587/advancedRocketry/world/ChunkManagerPlanet.java +++ b/src/main/java/zmaster587/advancedRocketry/world/ChunkManagerPlanet.java @@ -12,6 +12,7 @@ import net.minecraft.world.gen.ChunkGeneratorSettings; import net.minecraft.world.gen.layer.*; import net.minecraftforge.common.BiomeManager.BiomeEntry; +import net.minecraftforge.fml.relauncher.ReflectionHelper; import zmaster587.advancedRocketry.AdvancedRocketry; import zmaster587.advancedRocketry.dimension.DimensionManager; import zmaster587.advancedRocketry.dimension.DimensionProperties; @@ -37,6 +38,10 @@ private void setup(long seed, WorldType default1, String str, DimensionPropertie agenlayer = getModdedBiomeGenerators(default1, seed, agenlayer); this.genBiomes = agenlayer[0]; this.biomeIndexLayer = agenlayer[1]; + + ReflectionHelper.setPrivateValue(BiomeProvider.class, this, this.genBiomes, "genBiomes", "field_76944_d"); + ReflectionHelper.setPrivateValue(BiomeProvider.class, this, this.biomeIndexLayer, "biomeIndexLayer", "field_76945_e"); + } long seed; diff --git a/src/main/java/zmaster587/advancedRocketry/world/ChunkProviderPlanet.java b/src/main/java/zmaster587/advancedRocketry/world/ChunkProviderPlanet.java index 29529069d..a5bb0f935 100644 --- a/src/main/java/zmaster587/advancedRocketry/world/ChunkProviderPlanet.java +++ b/src/main/java/zmaster587/advancedRocketry/world/ChunkProviderPlanet.java @@ -13,6 +13,7 @@ import net.minecraft.world.WorldType; import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.Biome.SpawnListEntry; +import net.minecraft.world.biome.BiomeProvider; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.ChunkPrimer; import net.minecraft.world.gen.*; @@ -153,8 +154,8 @@ public ChunkProviderPlanet(World worldIn, long seed, boolean mapFeaturesEnabledI this.mapFeaturesEnabled = dimProps.canGenerateStructures() && ARConfiguration.getCurrentConfig().generateVanillaStructures; //TODO: may break on little planets - float atmDensity = ((WorldProviderPlanet) worldObj.provider).getAtmosphereDensity(new BlockPos(0, 0, 0)); - habitable = ((WorldProviderPlanet) worldObj.provider).getAtmosphere(new BlockPos(0, 0, 0)).isBreathable(); + float atmDensity = dimProps.getAtmosphereDensity() / 100f; // this fucking shit does not belong here -> ((WorldProviderPlanet) worldObj.provider).getAtmosphereDensity(new BlockPos(0, 0, 0)); + habitable = dimProps.getAtmosphere().isBreathable(); if (ARConfiguration.getCurrentConfig().generateCraters && dimProps.canGenerateCraters() && atmDensity <= 0.05) @@ -193,11 +194,18 @@ public ChunkProviderPlanet(World worldIn, long seed, boolean mapFeaturesEnabledI } public void setBlocksInChunk(int x, int z, ChunkPrimer primer) { + setBlocksInChunk(x,z,primer,null); + } + public void setBlocksInChunk(int x, int z, ChunkPrimer primer, BiomeProvider bp) { byte b0 = 63; //TODO: may break for little planets - this.biomesForGeneration = this.worldObj.getBiomeProvider().getBiomesForGeneration(this.biomesForGeneration, x * 4 - 2, z * 4 - 2, 10, 10); - this.generateHeightmap(x * 4, 0, z * 4); - + if (bp == null) { + this.biomesForGeneration = this.worldObj.getBiomeProvider().getBiomesForGeneration(this.biomesForGeneration, x * 4 - 2, z * 4 - 2, 10, 10); + this.generateHeightmap(x * 4, 0, z * 4); + }else{ + this.biomesForGeneration = bp.getBiomesForGeneration(this.biomesForGeneration, x * 4 - 2, z * 4 - 2, 10, 10); + this.generateHeightmap(x * 4, 0, z * 4); + } for (int i = 0; i < 4; ++i) { int j = i * 5; int k = (i + 1) * 5; @@ -266,13 +274,28 @@ public void replaceBiomeBlocks(int x, int z, ChunkPrimer primer, Biome[] biomesI } } - protected ChunkPrimer getChunkPrimer(int x, int z) { + public ChunkPrimer getChunkPrimer(int x, int z) { + return getChunkPrimer(x,z,null); + } + public ChunkPrimer getChunkPrimer(int x, int z, BiomeProvider bp) { this.rand.setSeed((long) x * 341873128712L + (long) z * 132897987541L); ChunkPrimer chunkprimer = new ChunkPrimer(); - this.setBlocksInChunk(x, z, chunkprimer); - this.biomesForGeneration = this.worldObj.getBiomeProvider().getBiomes(this.biomesForGeneration, x * 16, z * 16, 16, 16); - this.replaceBiomeBlocks(x, z, chunkprimer, this.biomesForGeneration); + boolean is_terraforming = false; + if (bp == null) { + this.biomesForGeneration = this.worldObj.getBiomeProvider().getBiomes(this.biomesForGeneration, x * 16, z * 16, 16, 16); + this.setBlocksInChunk(x, z, chunkprimer); // this messes up biome generation, needs to reset biomes + this.biomesForGeneration = this.worldObj.getBiomeProvider().getBiomes(this.biomesForGeneration, x * 16, z * 16, 16, 16); + this.replaceBiomeBlocks(x, z, chunkprimer, this.biomesForGeneration); + } + else { + this.biomesForGeneration = bp.getBiomes(this.biomesForGeneration, x * 16, z * 16, 16, 16); + this.setBlocksInChunk(x, z, chunkprimer, bp); // this messes up biome generation, needs to reset biomes + this.biomesForGeneration = bp.getBiomes(this.biomesForGeneration, x * 16, z * 16, 16, 16); + this.replaceBiomeBlocks(x, z, chunkprimer, this.biomesForGeneration); + is_terraforming = true; + } + if (this.settings.useCaves && caveGenerator != null) { this.caveGenerator.generate(this.worldObj, x, z, chunkprimer); @@ -282,13 +305,13 @@ protected ChunkPrimer getChunkPrimer(int x, int z) { this.ravineGenerator.generate(this.worldObj, x, z, chunkprimer); } - if (this.craterGeneratorSmall != null) + if (this.craterGeneratorSmall != null && !is_terraforming) this.craterGeneratorSmall.generate(this.worldObj, x, z, chunkprimer); - if (this.craterGenerator != null) + if (this.craterGenerator != null && !is_terraforming) this.craterGenerator.generate(this.worldObj, x, z, chunkprimer); - if (this.craterGeneratorHuge != null) + if (this.craterGeneratorHuge != null && !is_terraforming) this.craterGeneratorHuge.generate(this.worldObj, x, z, chunkprimer); if (this.volcanoGenerator != null) @@ -300,7 +323,7 @@ protected ChunkPrimer getChunkPrimer(int x, int z) { //Trees are always this.swampTreeGenerator.generate(this.worldObj, x, z, chunkprimer); - if (this.mapFeaturesEnabled && habitable) { + if (this.mapFeaturesEnabled && habitable && !is_terraforming) { // terraforming would destroy it all... if (this.settings.useMineShafts) { this.mineshaftGenerator.generate(this.worldObj, x, z, chunkprimer); } @@ -308,7 +331,6 @@ protected ChunkPrimer getChunkPrimer(int x, int z) { if (this.settings.useVillages) { this.villageGenerator.generate(this.worldObj, x, z, chunkprimer); } - if (this.settings.useStrongholds) { this.strongholdGenerator.generate(this.worldObj, x, z, chunkprimer); } @@ -316,7 +338,6 @@ protected ChunkPrimer getChunkPrimer(int x, int z) { if (this.settings.useTemples) { this.scatteredFeatureGenerator.generate(this.worldObj, x, z, chunkprimer); } - if (this.settings.useMonuments) { this.oceanMonumentGenerator.generate(this.worldObj, x, z, chunkprimer); } @@ -493,7 +514,6 @@ public void populate(int x, int z) { if (this.settings.useTemples) { this.scatteredFeatureGenerator.generateStructure(this.worldObj, this.rand, chunkpos); } - if (this.settings.useMonuments) { this.oceanMonumentGenerator.generateStructure(this.worldObj, this.rand, chunkpos); } @@ -550,18 +570,6 @@ public void populate(int x, int z) { } }//Forge: End ICE - - //If a planet is terraformed chenge upper blocks - // NO - because it causes mega-lag! - /* - if (zmaster587.advancedRocketry.api.ARConfiguration.getCurrentConfig().enableTerraforming && worldObj.provider.getClass() == WorldProviderPlanet.class) { - - if (DimensionManager.getInstance().getDimensionProperties(worldObj.provider.getDimension()).isTerraformed()) { - Chunk chunk = worldObj.getChunkFromChunkCoords(x, z); - PlanetEventHandler.modifyChunk(worldObj, (WorldProviderPlanet) worldObj.provider, chunk); - } - } - */ net.minecraftforge.event.ForgeEventFactory.onChunkPopulate(false, this, this.worldObj, this.rand, x, z, flag); OreGenProperties oreGenProperties = DimensionManager.getInstance().getDimensionProperties(this.worldObj.provider.getDimension()).getOreGenProperties(this.worldObj); @@ -593,6 +601,7 @@ public boolean generateStructures(Chunk chunkIn, int x, int z) { @Override public void recreateStructures(Chunk chunkIn, int x, int z) { + if (this.mapFeaturesEnabled || !habitable) { if (this.settings.useMineShafts) { this.mineshaftGenerator.generate(this.worldObj, x, z, null); @@ -601,11 +610,11 @@ public void recreateStructures(Chunk chunkIn, int x, int z) { if (this.settings.useVillages) { this.villageGenerator.generate(this.worldObj, x, z, null); } - if (this.settings.useStrongholds) { this.strongholdGenerator.generate(this.worldObj, x, z, null); } + if (this.settings.useTemples) { this.scatteredFeatureGenerator.generate(this.worldObj, x, z, null); } @@ -613,6 +622,7 @@ public void recreateStructures(Chunk chunkIn, int x, int z) { if (this.settings.useMonuments) { this.oceanMonumentGenerator.generate(this.worldObj, x, z, null); } + } } diff --git a/src/main/java/zmaster587/advancedRocketry/world/CustomDerivedWorldInfo.java b/src/main/java/zmaster587/advancedRocketry/world/CustomDerivedWorldInfo.java new file mode 100644 index 000000000..71a5ba2bc --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/world/CustomDerivedWorldInfo.java @@ -0,0 +1,215 @@ +package zmaster587.advancedRocketry.world; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.*; +import net.minecraft.world.storage.WorldInfo; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import javax.annotation.Nullable; + +public class CustomDerivedWorldInfo extends WorldInfo { + + private final WorldInfo delegate; + private World world; + private WorldInfoSavedData saveHandler; + + public CustomDerivedWorldInfo(WorldInfo worldInfoIn) { + this.delegate = worldInfoIn; + } + + public void setWorld(World world) { + this.world = world; + } + + private WorldInfoSavedData getSaveHandler() { + if (saveHandler == null) { + saveHandler = (WorldInfoSavedData) world.getPerWorldStorage().getOrLoadData(WorldInfoSavedData.class, "WorldInfoSavedData"); + } + return saveHandler; + } + + public NBTTagCompound cloneNBTCompound(@Nullable NBTTagCompound nbt) { + return this.delegate.cloneNBTCompound(nbt); + } + + public long getSeed() { + return this.delegate.getSeed(); + } + + public int getSpawnX() { + return this.delegate.getSpawnX(); + } + + public int getSpawnY() { + return this.delegate.getSpawnY(); + } + + public int getSpawnZ() { + return this.delegate.getSpawnZ(); + } + + public long getWorldTotalTime() { + return this.delegate.getWorldTotalTime(); + } + + public long getWorldTime() { + return this.delegate.getWorldTime(); + } + + @SideOnly(Side.CLIENT) + public long getSizeOnDisk() { + return this.delegate.getSizeOnDisk(); + } + + public NBTTagCompound getPlayerNBTTagCompound() { + return this.delegate.getPlayerNBTTagCompound(); + } + + public String getWorldName() { + return this.delegate.getWorldName(); + } + + public int getSaveVersion() { + return this.delegate.getSaveVersion(); + } + + @SideOnly(Side.CLIENT) + public long getLastTimePlayed() { + return this.delegate.getLastTimePlayed(); + } + + public GameType getGameType() { + return this.delegate.getGameType(); + } + + @SideOnly(Side.CLIENT) + public void setSpawnX(int x) { + } + + @SideOnly(Side.CLIENT) + public void setSpawnY(int y) { + } + + public void setWorldTotalTime(long time) { + } + + @SideOnly(Side.CLIENT) + public void setSpawnZ(int z) { + } + + public void setSpawn(BlockPos spawnPoint) { + } + + public void setWorldName(String worldName) { + } + + public void setSaveVersion(int version) { + } + + public boolean isMapFeaturesEnabled() { + return this.delegate.isMapFeaturesEnabled(); + } + + public boolean isHardcoreModeEnabled() { + return this.delegate.isHardcoreModeEnabled(); + } + + public WorldType getTerrainType() { + return this.delegate.getTerrainType(); + } + + public void setTerrainType(WorldType type) { + } + + public boolean areCommandsAllowed() { + return this.delegate.areCommandsAllowed(); + } + + public void setAllowCommands(boolean allow) { + } + + public boolean isInitialized() { + return this.delegate.isInitialized(); + } + + public void setServerInitialized(boolean initializedIn) { + } + + public GameRules getGameRulesInstance() { + return this.delegate.getGameRulesInstance(); + } + + public EnumDifficulty getDifficulty() { + return this.delegate.getDifficulty(); + } + + public void setDifficulty(EnumDifficulty newDifficulty) { + } + + public boolean isDifficultyLocked() { + return this.delegate.isDifficultyLocked(); + } + + public void setDifficultyLocked(boolean locked) { + } + + @Deprecated + public void setDimensionData(DimensionType dimensionIn, NBTTagCompound compound) { + this.delegate.setDimensionData(dimensionIn, compound); + } + + @Deprecated + public NBTTagCompound getDimensionData(DimensionType dimensionIn) { + return this.delegate.getDimensionData(dimensionIn); + } + + public void setDimensionData(int dimensionID, NBTTagCompound compound) { + this.delegate.setDimensionData(dimensionID, compound); + } + + public NBTTagCompound getDimensionData(int dimensionID) { + return this.delegate.getDimensionData(dimensionID); + } + + // Custom + @Override + public void setCleanWeatherTime(int cleanWeatherTimeIn) { + super.setCleanWeatherTime(cleanWeatherTimeIn); + this.getSaveHandler().markDirty(); + } + + @Override + public void setRainTime(int time) { + super.setRainTime(time); + this.getSaveHandler().markDirty(); + } + + @Override + public void setThunderTime(int time) { + super.setThunderTime(time); + this.getSaveHandler().markDirty(); + } + + @Override + public void setRaining(boolean isRaining) { + super.setRaining(isRaining); + this.getSaveHandler().markDirty(); + } + + @Override + public void setThundering(boolean thunderingIn) { + super.setThundering(thunderingIn); + this.getSaveHandler().markDirty(); + } + + public NBTTagCompound addWeatherData(NBTTagCompound compound) { + compound.setInteger("clearWeatherTime", getCleanWeatherTime()); + compound.setInteger("rainTime", getRainTime()); + compound.setInteger("thunderTime", getThunderTime()); + compound.setBoolean("raining", isRaining()); + compound.setBoolean("thundering", isThundering()); + return compound; + } +} diff --git a/src/main/java/zmaster587/advancedRocketry/world/WorldInfoSavedData.java b/src/main/java/zmaster587/advancedRocketry/world/WorldInfoSavedData.java new file mode 100644 index 000000000..2f9832695 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/world/WorldInfoSavedData.java @@ -0,0 +1,49 @@ +package zmaster587.advancedRocketry.world; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.World; +import net.minecraft.world.storage.WorldInfo; +import net.minecraft.world.storage.WorldSavedData; + +public class WorldInfoSavedData extends WorldSavedData { + + private World world; + private WorldInfo readInfo; + + public WorldInfoSavedData(String name) { + super(name); + } + + public WorldInfoSavedData(World world) { + this("WorldInfoSavedData"); + this.world = world; + this.markDirty(); + } + + @Override + public void readFromNBT(NBTTagCompound nbt) { + readInfo = new WorldInfo(nbt); + } + + @Override + public NBTTagCompound writeToNBT(NBTTagCompound compound) { + return ((CustomDerivedWorldInfo) world.getWorldInfo()).addWeatherData(compound); + } + + public void updateWorldInfo(World world) { + if (readInfo == null) { + // WorldSavedData not loaded from NBT + return; + } + + this.world = world; + + WorldInfo target = world.getWorldInfo(); + + target.setCleanWeatherTime(readInfo.getCleanWeatherTime()); + target.setRaining(readInfo.isRaining()); + target.setRainTime(readInfo.getRainTime()); + target.setThundering(readInfo.isThundering()); + target.setThunderTime(readInfo.getThunderTime()); + } +} diff --git a/src/main/java/zmaster587/advancedRocketry/world/WorldServerNotMulti.java b/src/main/java/zmaster587/advancedRocketry/world/WorldServerNotMulti.java new file mode 100644 index 000000000..cf3f46408 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/world/WorldServerNotMulti.java @@ -0,0 +1,94 @@ +package zmaster587.advancedRocketry.world; + +import net.minecraft.profiler.Profiler; +import net.minecraft.server.MinecraftServer; +import net.minecraft.village.VillageCollection; +import net.minecraft.world.MinecraftException; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; +import net.minecraft.world.border.IBorderListener; +import net.minecraft.world.border.WorldBorder; +import net.minecraft.world.storage.ISaveHandler; + +public class WorldServerNotMulti extends WorldServer { + private final WorldServer delegate; + private final IBorderListener borderListener; + + public WorldServerNotMulti(MinecraftServer server, ISaveHandler saveHandlerIn, int dimensionId, WorldServer delegate, Profiler profilerIn) { + super(server, saveHandlerIn, new CustomDerivedWorldInfo(delegate.getWorldInfo()), dimensionId, profilerIn); + ((CustomDerivedWorldInfo) this.getWorldInfo()).setWorld(this); + this.delegate = delegate; + this.borderListener = new IBorderListener() { + public void onSizeChanged(WorldBorder border, double newSize) { + WorldServerNotMulti.this.getWorldBorder().setTransition(newSize); + } + + public void onTransitionStarted(WorldBorder border, double oldSize, double newSize, long time) { + WorldServerNotMulti.this.getWorldBorder().setTransition(oldSize, newSize, time); + } + + public void onCenterChanged(WorldBorder border, double x, double z) { + WorldServerNotMulti.this.getWorldBorder().setCenter(x, z); + } + + public void onWarningTimeChanged(WorldBorder border, int newTime) { + WorldServerNotMulti.this.getWorldBorder().setWarningTime(newTime); + } + + public void onWarningDistanceChanged(WorldBorder border, int newDistance) { + WorldServerNotMulti.this.getWorldBorder().setWarningDistance(newDistance); + } + + public void onDamageAmountChanged(WorldBorder border, double newAmount) { + WorldServerNotMulti.this.getWorldBorder().setDamageAmount(newAmount); + } + + public void onDamageBufferChanged(WorldBorder border, double newSize) { + WorldServerNotMulti.this.getWorldBorder().setDamageBuffer(newSize); + } + }; + this.delegate.getWorldBorder().addListener(this.borderListener); + } + + @Override + protected void saveLevel() throws MinecraftException { + this.perWorldStorage.saveAllData(); + } + + public World init() { + super.init(); + // load weather data from NBT + WorldInfoSavedData wi = (WorldInfoSavedData) perWorldStorage.getOrLoadData(WorldInfoSavedData.class, "WorldInfoSavedData"); + if (wi == null) { + wi = new WorldInfoSavedData(this); + this.perWorldStorage.setData("WorldInfoSavedData", wi); + } + wi.updateWorldInfo(this); + + this.mapStorage = this.delegate.getMapStorage(); + this.worldScoreboard = this.delegate.getScoreboard(); + this.lootTable = this.delegate.getLootTableManager(); + this.advancementManager = this.delegate.getAdvancementManager(); + String s = VillageCollection.fileNameForProvider(this.provider); + VillageCollection villagecollection = (VillageCollection) this.perWorldStorage.getOrLoadData(VillageCollection.class, s); + + if (villagecollection == null) { + this.villageCollection = new VillageCollection(this); + this.perWorldStorage.setData(s, this.villageCollection); + } else { + this.villageCollection = villagecollection; + this.villageCollection.setWorldsForAll(this); + } + + this.initCapabilities(); + return this; + } + + + @Override + public void flush() { + super.flush(); + this.delegate.getWorldBorder().removeListener(this.borderListener); // Unlink ourselves, to prevent world leak. + this.provider.onWorldSave(); + } +} diff --git a/src/main/java/zmaster587/advancedRocketry/world/biome/BiomeGenAlienForest.java b/src/main/java/zmaster587/advancedRocketry/world/biome/BiomeGenAlienForest.java index 1aaccaea9..25c669a3f 100644 --- a/src/main/java/zmaster587/advancedRocketry/world/biome/BiomeGenAlienForest.java +++ b/src/main/java/zmaster587/advancedRocketry/world/biome/BiomeGenAlienForest.java @@ -43,7 +43,7 @@ public void decorate(World worldIn, Random rand, BlockPos pos) { @Override @Nonnull public WorldGenAbstractTree getRandomTreeFeature(Random rand) { - return noTree; + return alienTree; } @Override diff --git a/src/main/java/zmaster587/advancedRocketry/world/decoration/MapGenGeode.java b/src/main/java/zmaster587/advancedRocketry/world/decoration/MapGenGeode.java index 1c03eff71..2636843a0 100644 --- a/src/main/java/zmaster587/advancedRocketry/world/decoration/MapGenGeode.java +++ b/src/main/java/zmaster587/advancedRocketry/world/decoration/MapGenGeode.java @@ -1,6 +1,7 @@ package zmaster587.advancedRocketry.world.decoration; import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; @@ -99,8 +100,10 @@ protected void recursiveGenerate(World world, int chunkX, int chunkZ, int p_1807 //Generates ore hanging from the ceiling if (x % 4 > 0 && z % 4 > 0) { - for (int i = 1; i < size; i++) - chunkPrimerIn.setBlockState(x, avgY + count - i, z, ores.get((x / 4 + z / 4) % ores.size()).getBlockState()); + IBlockState ore = ores.get(world.rand.nextInt(ores.size())).getBlockState(); + for (int i = 1; i < size; i++) { + chunkPrimerIn.setBlockState(x, avgY + count - i, z, ore); + } } else { size -= 2; for (int i = 1; i < size; i++) { @@ -110,10 +113,11 @@ protected void recursiveGenerate(World world, int chunkX, int chunkZ, int p_1807 //Generates ore in the floor if ((x + 2) % 4 > 0 && (z + 2) % 4 > 0) { - for (int i = 1; i < size; i++) - chunkPrimerIn.setBlockState(x, avgY - count + i, z, ores.get((x / 4 + z / 4) % ores.size()).getBlockState()); + IBlockState ore = ores.get(world.rand.nextInt(ores.size())).getBlockState(); + for (int i = 1; i < size; i++) { + chunkPrimerIn.setBlockState(x, avgY - count + i, z, ore); + } } - } chunkPrimerIn.setBlockState(x, avgY - count, z, AdvancedRocketryBlocks.blocksGeode.getDefaultState()); diff --git a/src/main/java/zmaster587/advancedRocketry/world/provider/WorldProviderPlanet.java b/src/main/java/zmaster587/advancedRocketry/world/provider/WorldProviderPlanet.java index 944c0b6bd..f71ef4689 100644 --- a/src/main/java/zmaster587/advancedRocketry/world/provider/WorldProviderPlanet.java +++ b/src/main/java/zmaster587/advancedRocketry/world/provider/WorldProviderPlanet.java @@ -11,13 +11,9 @@ import net.minecraft.util.math.Vec3d; import net.minecraft.world.DimensionType; import net.minecraft.world.WorldProvider; -import net.minecraft.world.biome.BiomeProvider; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.gen.IChunkGenerator; -import net.minecraft.world.storage.DerivedWorldInfo; -import net.minecraft.world.storage.WorldInfo; import net.minecraftforge.client.IRenderHandler; -import net.minecraftforge.fml.relauncher.ReflectionHelper; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import org.apache.commons.lang3.ArrayUtils; @@ -33,7 +29,6 @@ import zmaster587.advancedRocketry.client.render.planet.RenderPlanetarySky; import zmaster587.advancedRocketry.dimension.DimensionManager; import zmaster587.advancedRocketry.dimension.DimensionProperties; -import zmaster587.advancedRocketry.integration.CompatibilityMgr; import zmaster587.advancedRocketry.util.AstronomicalBodyHelper; import zmaster587.advancedRocketry.world.ChunkManagerPlanet; import zmaster587.advancedRocketry.world.ChunkProviderCavePlanet; @@ -75,7 +70,7 @@ public IRenderHandler getSkyRenderer() { if (!ARConfiguration.getCurrentConfig().planetSkyOverride || DimensionManager.getInstance().getDimensionProperties(world.provider.getDimension()).skyRenderOverride) return null; - int genType = DimensionManager.getInstance().getDimensionProperties(world.provider.getDimension()).getGenType(); +// int genType = DimensionManager.getInstance().getDimensionProperties(world.provider.getDimension()).getGenType(); if (super.getSkyRenderer() == null) @@ -119,26 +114,112 @@ public void calculateInitialWeather() { @Override public void updateWeather() { - super.updateWeather(); - doWeatherStuff(); - } + DimensionProperties props = getDimensionProperties(); + + // Totally override weather cycle + if (world.provider.hasSkyLight()) { + if (!world.isRemote) { + boolean flag = world.getGameRules().getBoolean("doWeatherCycle"); + + if (flag) { + if (props.getRainMarker() == -1 && props.getThunderMarker() == -1) { + world.getWorldInfo().setRaining(false); + world.getWorldInfo().setRainTime(0); + world.getWorldInfo().setThundering(false); + world.getWorldInfo().setThunderTime(0); + world.getWorldInfo().setCleanWeatherTime(20000); + } + + int j2 = world.getWorldInfo().getCleanWeatherTime(); + + if (j2 > 0) { + --j2; + world.getWorldInfo().setCleanWeatherTime(j2); + world.getWorldInfo().setThunderTime(world.getWorldInfo().isThundering() ? 1 : 2); + world.getWorldInfo().setRainTime(world.getWorldInfo().isRaining() ? 1 : 2); + } + if (props.getThunderMarker() == 1) { + world.getWorldInfo().setCleanWeatherTime(0); + world.getWorldInfo().setThundering(true); + } + if (props.getRainMarker() == 1) { + world.getWorldInfo().setCleanWeatherTime(0); + world.getWorldInfo().setRaining(true); + } + + int k2 = world.getWorldInfo().getThunderTime(); + + if (k2 <= 0) { + if (world.getWorldInfo().isThundering()) { + world.getWorldInfo().setThunderTime(world.rand.nextInt(getDimensionProperties().thunderProlongationLength) + 3600); + } else { + world.getWorldInfo().setThunderTime(world.rand.nextInt(getDimensionProperties().thunderStartLength) + 12000); + } + } else { + --k2; + world.getWorldInfo().setThunderTime(k2); + + if (props.getThunderMarker() == 0 && k2 <= 0) { + world.getWorldInfo().setThundering(!world.getWorldInfo().isThundering()); + } + } + + int l2 = world.getWorldInfo().getRainTime(); + + if (l2 <= 0) { + if (world.getWorldInfo().isRaining()) { + world.getWorldInfo().setRainTime(world.rand.nextInt(getDimensionProperties().rainProlongationLength) + 12000); + } else { + world.getWorldInfo().setRainTime(world.rand.nextInt(getDimensionProperties().rainStartLength) + 12000); + } + } else { + --l2; + world.getWorldInfo().setRainTime(l2); + + if (props.getRainMarker() == 0 && l2 <= 0) { + world.getWorldInfo().setRaining(!world.getWorldInfo().isRaining()); + } + } + } - private void doWeatherStuff() { - if (getAtmosphereDensity(new BlockPos(0, 0, 0)) <= 75 && world.isRaining()) { - if (!CompatibilityMgr.isSpongeInstalled) { - try { - WorldInfo worldInfo = ReflectionHelper.getPrivateValue(DerivedWorldInfo.class, (DerivedWorldInfo) this.world.getWorldInfo(), "delegate", "field_76115_a"); - worldInfo.setRaining(false); - } catch (ClassCastException e) { - //Fallback. Sometimes mods screw with worldInfo - this.world.getWorldInfo().setRaining(false); + world.prevThunderingStrength = world.thunderingStrength; + + if (world.getWorldInfo().isThundering()) { + world.thunderingStrength = (float) ((double) world.thunderingStrength + 0.01D); + } else { + world.thunderingStrength = (float) ((double) world.thunderingStrength - 0.01D); + } + + world.thunderingStrength = MathHelper.clamp(world.thunderingStrength, 0.0F, 1.0F); + world.prevRainingStrength = world.rainingStrength; + + if (world.getWorldInfo().isRaining()) { + world.rainingStrength = (float) ((double) world.rainingStrength + 0.01D); + } else { + world.rainingStrength = (float) ((double) world.rainingStrength - 0.01D); } - } else - //Hope that sponge cooperates - this.world.getWorldInfo().setRaining(false); + + world.rainingStrength = MathHelper.clamp(world.rainingStrength, 0.0F, 1.0F); + } } } + private void doWeatherStuff() { +// if (getAtmosphereDensity(new BlockPos(0, 0, 0)) <= 75 && world.isRaining()) { +// if (!CompatibilityMgr.isSpongeInstalled) { +// try { +// WorldInfo worldInfo = ReflectionHelper.getPrivateValue(DerivedWorldInfo.class, (DerivedWorldInfo) this.world.getWorldInfo(), "delegate", "field_76115_a"); +// worldInfo.setRaining(false); +// } catch (ClassCastException e) { +// //Fallback. Sometimes mods screw with worldInfo +// this.world.getWorldInfo().setRaining(false); +// } +// } else +// //Hope that sponge cooperates +// this.world.getWorldInfo().setRaining(false); +// } + } + @Override public int getRespawnDimension(@Nonnull EntityPlayerMP player) { if (ARConfiguration.getCurrentConfig().canPlayerRespawnInSpace) { @@ -280,7 +361,7 @@ private float eclipseValue(@Nonnull DimensionProperties properties, float lightV //No clouds @Override public float getCloudHeight() { - return getAtmosphereDensity(new BlockPos(0, 0, 0)) > .75f ? 128 : -2000; + return getAtmosphereDensity(new BlockPos(0, 0, 0)) > .75f ? 128 : -200000; } @Override @@ -430,6 +511,10 @@ public int getSolarOrbitalDistance(@Nullable BlockPos pos) { return getDimensionProperties(pos).getSolarOrbitalDistance(); } + public DimensionProperties getDimensionProperties() { + return this.getDimensionProperties(null); + } + @Override public DimensionProperties getDimensionProperties(@Nullable BlockPos pos) { DimensionProperties properties = DimensionManager.getInstance().getDimensionProperties(this.getDimension()); diff --git a/src/main/java/zmaster587/advancedRocketry/world/provider/WorldProviderSpace.java b/src/main/java/zmaster587/advancedRocketry/world/provider/WorldProviderSpace.java index 7f3c7c5c3..895c5317d 100755 --- a/src/main/java/zmaster587/advancedRocketry/world/provider/WorldProviderSpace.java +++ b/src/main/java/zmaster587/advancedRocketry/world/provider/WorldProviderSpace.java @@ -23,6 +23,8 @@ import zmaster587.advancedRocketry.util.AstronomicalBodyHelper; import zmaster587.advancedRocketry.world.ChunkProviderSpace; +import javax.annotation.Nullable; + public class WorldProviderSpace extends WorldProviderPlanet { private IRenderHandler skyRender; @@ -111,10 +113,12 @@ public ISpaceObject getSpaceObject(BlockPos pos) { } @Override - public DimensionProperties getDimensionProperties(BlockPos pos) { - ISpaceObject spaceObject = getSpaceObject(pos); - if (spaceObject != null) - return (DimensionProperties) spaceObject.getProperties(); + public DimensionProperties getDimensionProperties(@Nullable BlockPos pos) { + if (pos != null) { + ISpaceObject spaceObject = getSpaceObject(pos); + if (spaceObject != null) + return (DimensionProperties) spaceObject.getProperties(); + } return DimensionManager.defaultSpaceDimensionProperties; } } diff --git a/src/main/resources/META-INF/accessTransformer.cfg b/src/main/resources/META-INF/accessTransformer.cfg index f74b95b40..21b6200fa 100644 --- a/src/main/resources/META-INF/accessTransformer.cfg +++ b/src/main/resources/META-INF/accessTransformer.cfg @@ -1 +1,10 @@ -public net.minecraft.entity.Entity * \ No newline at end of file +public net.minecraft.entity.Entity * +public net.minecraft.nbt.NBTTagCompound * +public-f net.minecraft.inventory.InventoryBasic * +public net.minecraft.world.storage.MapStorage * + +public net.minecraft.server.MinecraftServer * +public net.minecraft.server.MinecraftServer *() + +public net.minecraft.server.integrated.IntegratedServer * +public net.minecraft.server.integrated.IntegratedServer *() diff --git a/src/main/resources/assets/advancedrocketry/advancements/normal/deathstar.json b/src/main/resources/assets/advancedrocketry/advancements/normal/deathstar.json new file mode 100644 index 000000000..1e06721b7 --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/advancements/normal/deathstar.json @@ -0,0 +1,20 @@ +{ + "display": { + "icon": { + "item": "advancedrocketry:lens" + }, + "title": { + "translate": "Space Laser" + }, + "description": { + "translate": "Construct a Space Laser" + }, + "frame": "challenge" + }, + "parent": "advancedrocketry:normal/root", + "criteria": { + "deathstar": { + "trigger": "deathstar" + } + } +} diff --git a/src/main/resources/assets/advancedrocketry/advancements/normal/pressurize.json b/src/main/resources/assets/advancedrocketry/advancements/normal/pressurize.json new file mode 100644 index 000000000..a384f044c --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/advancements/normal/pressurize.json @@ -0,0 +1,20 @@ +{ + "display": { + "icon": { + "item": "advancedrocketry:lens" + }, + "title": { + "translate": "Pressurized" + }, + "description": { + "translate": "Construct a Atmosphere Terraformer" + }, + "frame": "challenge" + }, + "parent": "advancedrocketry:normal/deathstar", + "criteria": { + "deathstar": { + "trigger": "pressurize" + } + } +} diff --git a/src/main/resources/assets/advancedrocketry/blockstates/advbipropellantrocketmotor.json b/src/main/resources/assets/advancedrocketry/blockstates/advbipropellantrocketmotor.json index 362c031ce..9c42ab421 100644 --- a/src/main/resources/assets/advancedrocketry/blockstates/advbipropellantrocketmotor.json +++ b/src/main/resources/assets/advancedrocketry/blockstates/advbipropellantrocketmotor.json @@ -4,16 +4,16 @@ "textures": { "#None": "advancedrocketry:/models/advbipropellantcombustion" }, - "model": "advancedrocketry:models/advbipropellantrocketmotor.obj", + "model": "advancedrocketry:models/advbipropellantrocket.obj", "transform": "forge:default-block" }, "variants": { - "facing=north": { "model": "advancedrocketry:models/advbipropellantrocketmotor.obj", "texture": "advancedrocketry:textures/models/advbipropellantcombustion", "x": 90 }, - "facing=south": { "model": "advancedrocketry:models/advbipropellantrocketmotor.obj", "texture": "advancedrocketry:textures/models/advbipropellantcombustion", "x": 90, "y": 180 }, - "facing=west": { "model": "advancedrocketry:models/advbipropellantrocketmotor.obj", "texture": "advancedrocketry:textures/models/advbipropellantcombustion", "x": 90, "y": 270 }, - "facing=east": { "model": "advancedrocketry:models/advbipropellantrocketmotor.obj", "texture": "advancedrocketry:textures/models/advbipropellantcombustion", "x": 90, "y": 90 }, - "facing=up": { "model": "advancedrocketry:models/advbipropellantrocketmotor.obj", "texture": "advancedrocketry:textures/models/advbipropellantcombustion", "x": 180 }, - "facing=down": { "model": "advancedrocketry:models/advbipropellantrocketmotor.obj", "texture": "advancedrocketry:textures/models/advbipropellantcombustion" }, - "inventory": { "model": "advancedrocketry:models/advbipropellantrocketmotor.obj", "texture": "advancedrocketry:textures/models/advbipropellantcombustion"} + "facing=north": { "model": "advancedrocketry:models/advbipropellantrocket.obj", "texture": "advancedrocketry:textures/models/advbipropellantcombustion", "x": 90 }, + "facing=south": { "model": "advancedrocketry:models/advbipropellantrocket.obj", "texture": "advancedrocketry:textures/models/advbipropellantcombustion", "x": 90, "y": 180 }, + "facing=west": { "model": "advancedrocketry:models/advbipropellantrocket.obj", "texture": "advancedrocketry:textures/models/advbipropellantcombustion", "x": 90, "y": 270 }, + "facing=east": { "model": "advancedrocketry:models/advbipropellantrocket.obj", "texture": "advancedrocketry:textures/models/advbipropellantcombustion", "x": 90, "y": 90 }, + "facing=up": { "model": "advancedrocketry:models/advbipropellantrocket.obj", "texture": "advancedrocketry:textures/models/advbipropellantcombustion", "x": 180 }, + "facing=down": { "model": "advancedrocketry:models/advbipropellantrocket.obj", "texture": "advancedrocketry:textures/models/advbipropellantcombustion" }, + "inventory": { "model": "advancedrocketry:models/advbipropellantrocket.obj", "texture": "advancedrocketry:textures/models/advbipropellantcombustion"} } } diff --git a/src/main/resources/assets/advancedrocketry/blockstates/advrocketmotor.json b/src/main/resources/assets/advancedrocketry/blockstates/advrocketmotor.json index f91ec760f..84ff1f773 100644 --- a/src/main/resources/assets/advancedrocketry/blockstates/advrocketmotor.json +++ b/src/main/resources/assets/advancedrocketry/blockstates/advrocketmotor.json @@ -4,16 +4,16 @@ "textures": { "#None": "advancedrocketry:/models/advcombustion" }, - "model": "advancedrocketry:models/advrocketmotor.obj", + "model": "advancedrocketry:models/advrocket.obj", "transform": "forge:default-block" }, "variants": { - "facing=north": { "model": "advancedrocketry:models/advrocketmotor.obj", "texture": "advancedrocketry:textures/models/advcombustion", "x": 90 }, - "facing=south": { "model": "advancedrocketry:models/advrocketmotor.obj", "texture": "advancedrocketry:textures/models/advcombustion", "x": 90, "y": 180 }, - "facing=west": { "model": "advancedrocketry:models/advrocketmotor.obj", "texture": "advancedrocketry:textures/models/advcombustion", "x": 90, "y": 270 }, - "facing=east": { "model": "advancedrocketry:models/advrocketmotor.obj", "texture": "advancedrocketry:textures/models/advcombustion", "x": 90, "y": 90 }, - "facing=up": { "model": "advancedrocketry:models/advrocketmotor.obj", "texture": "advancedrocketry:textures/models/advcombustion", "x": 180 }, - "facing=down": { "model": "advancedrocketry:models/advrocketmotor.obj", "texture": "advancedrocketry:textures/models/advcombustion" }, - "inventory": { "model": "advancedrocketry:models/advrocketmotor.obj", "texture": "advancedrocketry:textures/models/advcombustion"} + "facing=north": { "model": "advancedrocketry:models/advrocket.obj", "texture": "advancedrocketry:textures/models/advcombustion", "x": 90 }, + "facing=south": { "model": "advancedrocketry:models/advrocket.obj", "texture": "advancedrocketry:textures/models/advcombustion", "x": 90, "y": 180 }, + "facing=west": { "model": "advancedrocketry:models/advrocket.obj", "texture": "advancedrocketry:textures/models/advcombustion", "x": 90, "y": 270 }, + "facing=east": { "model": "advancedrocketry:models/advrocket.obj", "texture": "advancedrocketry:textures/models/advcombustion", "x": 90, "y": 90 }, + "facing=up": { "model": "advancedrocketry:models/advrocket.obj", "texture": "advancedrocketry:textures/models/advcombustion", "x": 180 }, + "facing=down": { "model": "advancedrocketry:models/advrocket.obj", "texture": "advancedrocketry:textures/models/advcombustion" }, + "inventory": { "model": "advancedrocketry:models/advrocket.obj", "texture": "advancedrocketry:textures/models/advcombustion"} } } diff --git a/src/main/resources/assets/advancedrocketry/blockstates/bipropellantfueltank.json b/src/main/resources/assets/advancedrocketry/blockstates/bipropellantfueltank.json index ad2fd5453..a9dcfb8c9 100644 --- a/src/main/resources/assets/advancedrocketry/blockstates/bipropellantfueltank.json +++ b/src/main/resources/assets/advancedrocketry/blockstates/bipropellantfueltank.json @@ -6,14 +6,32 @@ "transform": "forge:default-block" }, "variants": { - "tankstates=top": { "model": "advancedrocketry:models/toptank.obj" }, - "tankstates=middle": { "model": "advancedrocketry:models/middletank.obj" }, - "tankstates=bottom": { "model": "advancedrocketry:models/bottomtank.obj" }, "inventory": { "model": "advancedrocketry:models/middletank.obj", "textures": { "layer0": "advancedrocketry:textures/models/tank" } - } + }, + "facing=north,tankstates=middle": { "model": "advancedrocketry:models/middletank.obj", "x": 90 }, + "facing=south,tankstates=middle": { "model": "advancedrocketry:models/middletank.obj", "x": 90, "y": 180 }, + "facing=west,tankstates=middle": { "model": "advancedrocketry:models/middletank.obj", "x": 90, "y": 270 }, + "facing=east,tankstates=middle": { "model": "advancedrocketry:models/middletank.obj", "x": 90, "y": 90 }, + "facing=up,tankstates=middle": { "model": "advancedrocketry:models/middletank.obj"}, + "facing=down,tankstates=middle": { "model": "advancedrocketry:models/middletank.obj"}, + + "facing=north,tankstates=top": { "model": "advancedrocketry:models/toptank.obj", "x": 90 }, + "facing=south,tankstates=top": { "model": "advancedrocketry:models/toptank.obj", "x": 90, "y": 180 }, + "facing=west,tankstates=top": { "model": "advancedrocketry:models/toptank.obj", "x": 90, "y": 270 }, + "facing=east,tankstates=top": { "model": "advancedrocketry:models/toptank.obj", "x": 90, "y": 90 }, + "facing=up,tankstates=top": { "model": "advancedrocketry:models/toptank.obj"}, + "facing=down,tankstates=top": { "model": "advancedrocketry:models/toptank.obj"}, + + "facing=north,tankstates=bottom": { "model": "advancedrocketry:models/bottomtank.obj", "x": 90 }, + "facing=south,tankstates=bottom": { "model": "advancedrocketry:models/bottomtank.obj", "x": 90, "y": 180 }, + "facing=west,tankstates=bottom": { "model": "advancedrocketry:models/bottomtank.obj", "x": 90, "y": 270 }, + "facing=east,tankstates=bottom": { "model": "advancedrocketry:models/bottomtank.obj", "x": 90, "y": 90 }, + "facing=up,tankstates=bottom": { "model": "advancedrocketry:models/bottomtank.obj"}, + "facing=down,tankstates=bottom": { "model": "advancedrocketry:models/bottomtank.obj"} + } } diff --git a/src/main/resources/assets/advancedrocketry/blockstates/bipropellantrocketmotor.json b/src/main/resources/assets/advancedrocketry/blockstates/bipropellantrocketmotor.json index 3f744738c..36bea8b6a 100644 --- a/src/main/resources/assets/advancedrocketry/blockstates/bipropellantrocketmotor.json +++ b/src/main/resources/assets/advancedrocketry/blockstates/bipropellantrocketmotor.json @@ -4,18 +4,18 @@ "textures": { "#None": "advancedrocketry:/models/bipropellantcombustion" }, - "model": "advancedrocketry:models/bipropellantrocketmotor.obj", + "model": "advancedrocketry:models/bipropellantrocket.obj", "transform": "forge:default-block" }, "variants": { - "facing=north": { "model": "advancedrocketry:models/bipropellantrocketmotor.obj", "texture": "advancedrocketry:textures/models/bipropellantcombustion.png", "x": 90 }, - "facing=south": { "model": "advancedrocketry:models/bipropellantrocketmotor.obj", "texture": "advancedrocketry:textures/models/bipropellantcombustion.png", "x": 90, "y": 180 }, - "facing=west": { "model": "advancedrocketry:models/bipropellantrocketmotor.obj", "texture": "advancedrocketry:textures/models/bipropellantcombustion.png", "x": 90, "y": 270 }, - "facing=east": { "model": "advancedrocketry:models/bipropellantrocketmotor.obj", "texture": "advancedrocketry:textures/models/bipropellantcombustion.png", "x": 90, "y": 90 }, - "facing=up": { "model": "advancedrocketry:models/bipropellantrocketmotor.obj", "texture": "advancedrocketry:textures/models/bipropellantcombustion.png", "x": 180 }, - "facing=down": { "model": "advancedrocketry:models/bipropellantrocketmotor.obj", "texture": "advancedrocketry:textures/models/bipropellantcombustion.png" }, + "facing=north": { "model": "advancedrocketry:models/bipropellantrocket.obj", "texture": "advancedrocketry:textures/models/bipropellantcombustion.png", "x": 90 }, + "facing=south": { "model": "advancedrocketry:models/bipropellantrocket.obj", "texture": "advancedrocketry:textures/models/bipropellantcombustion.png", "x": 90, "y": 180 }, + "facing=west": { "model": "advancedrocketry:models/bipropellantrocket.obj", "texture": "advancedrocketry:textures/models/bipropellantcombustion.png", "x": 90, "y": 270 }, + "facing=east": { "model": "advancedrocketry:models/bipropellantrocket.obj", "texture": "advancedrocketry:textures/models/bipropellantcombustion.png", "x": 90, "y": 90 }, + "facing=up": { "model": "advancedrocketry:models/bipropellantrocket.obj", "texture": "advancedrocketry:textures/models/bipropellantcombustion.png", "x": 180 }, + "facing=down": { "model": "advancedrocketry:models/bipropellantrocket.obj", "texture": "advancedrocketry:textures/models/bipropellantcombustion.png" }, "inventory": { - "model": "advancedrocketry:models/bipropellantrocketmotor.obj", + "model": "advancedrocketry:models/bipropellantrocket.obj", "textures": { "layer0": "advancedrocketry:textures/models/bipropellantcombustion.png" } diff --git a/src/main/resources/assets/advancedrocketry/blockstates/invhatch.json b/src/main/resources/assets/advancedrocketry/blockstates/invhatch.json new file mode 100644 index 000000000..f468192c8 --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/blockstates/invhatch.json @@ -0,0 +1,7 @@ +{ + "variants": { + "default": { "model": "advancedrocketry:satelliteHatch" }, + "inventory": { "model": "advancedrocketry:satelliteHatch" }, + "normal": { "model": "advancedrocketry:satelliteHatch" } + } +} diff --git a/src/main/resources/assets/advancedrocketry/blockstates/nuclearfueltank.json b/src/main/resources/assets/advancedrocketry/blockstates/nuclearfueltank.json index ad2fd5453..a9dcfb8c9 100644 --- a/src/main/resources/assets/advancedrocketry/blockstates/nuclearfueltank.json +++ b/src/main/resources/assets/advancedrocketry/blockstates/nuclearfueltank.json @@ -6,14 +6,32 @@ "transform": "forge:default-block" }, "variants": { - "tankstates=top": { "model": "advancedrocketry:models/toptank.obj" }, - "tankstates=middle": { "model": "advancedrocketry:models/middletank.obj" }, - "tankstates=bottom": { "model": "advancedrocketry:models/bottomtank.obj" }, "inventory": { "model": "advancedrocketry:models/middletank.obj", "textures": { "layer0": "advancedrocketry:textures/models/tank" } - } + }, + "facing=north,tankstates=middle": { "model": "advancedrocketry:models/middletank.obj", "x": 90 }, + "facing=south,tankstates=middle": { "model": "advancedrocketry:models/middletank.obj", "x": 90, "y": 180 }, + "facing=west,tankstates=middle": { "model": "advancedrocketry:models/middletank.obj", "x": 90, "y": 270 }, + "facing=east,tankstates=middle": { "model": "advancedrocketry:models/middletank.obj", "x": 90, "y": 90 }, + "facing=up,tankstates=middle": { "model": "advancedrocketry:models/middletank.obj"}, + "facing=down,tankstates=middle": { "model": "advancedrocketry:models/middletank.obj"}, + + "facing=north,tankstates=top": { "model": "advancedrocketry:models/toptank.obj", "x": 90 }, + "facing=south,tankstates=top": { "model": "advancedrocketry:models/toptank.obj", "x": 90, "y": 180 }, + "facing=west,tankstates=top": { "model": "advancedrocketry:models/toptank.obj", "x": 90, "y": 270 }, + "facing=east,tankstates=top": { "model": "advancedrocketry:models/toptank.obj", "x": 90, "y": 90 }, + "facing=up,tankstates=top": { "model": "advancedrocketry:models/toptank.obj"}, + "facing=down,tankstates=top": { "model": "advancedrocketry:models/toptank.obj"}, + + "facing=north,tankstates=bottom": { "model": "advancedrocketry:models/bottomtank.obj", "x": 90 }, + "facing=south,tankstates=bottom": { "model": "advancedrocketry:models/bottomtank.obj", "x": 90, "y": 180 }, + "facing=west,tankstates=bottom": { "model": "advancedrocketry:models/bottomtank.obj", "x": 90, "y": 270 }, + "facing=east,tankstates=bottom": { "model": "advancedrocketry:models/bottomtank.obj", "x": 90, "y": 90 }, + "facing=up,tankstates=bottom": { "model": "advancedrocketry:models/bottomtank.obj"}, + "facing=down,tankstates=bottom": { "model": "advancedrocketry:models/bottomtank.obj"} + } } diff --git a/src/main/resources/assets/advancedrocketry/blockstates/nuclearrocketmotor.json b/src/main/resources/assets/advancedrocketry/blockstates/nuclearrocketmotor.json index 12ae68144..8b318ce39 100644 --- a/src/main/resources/assets/advancedrocketry/blockstates/nuclearrocketmotor.json +++ b/src/main/resources/assets/advancedrocketry/blockstates/nuclearrocketmotor.json @@ -4,18 +4,18 @@ "textures": { "#None": "advancedrocketry:/models/nuclearcombustion" }, - "model": "advancedrocketry:models/bipropellantrocketmotor.obj", + "model": "advancedrocketry:models/nuclearrocket.obj", "transform": "forge:default-block" }, "variants": { - "facing=north": { "model": "advancedrocketry:models/nuclearrocketmotor.obj", "texture": "advancedrocketry:textures/models/nuclearcombustion.png", "x": 90 }, - "facing=south": { "model": "advancedrocketry:models/nuclearrocketmotor.obj", "texture": "advancedrocketry:textures/models/nuclearcombustion.png", "x": 90, "y": 180 }, - "facing=west": { "model": "advancedrocketry:models/nuclearrocketmotor.obj", "texture": "advancedrocketry:textures/models/nuclearcombustion.png", "x": 90, "y": 270 }, - "facing=east": { "model": "advancedrocketry:models/nuclearrocketmotor.obj", "texture": "advancedrocketry:textures/models/nuclearcombustion.png", "x": 90, "y": 90 }, - "facing=up": { "model": "advancedrocketry:models/nuclearrocketmotor.obj", "texture": "advancedrocketry:textures/models/nuclearcombustion.png", "x": 180 }, - "facing=down": { "model": "advancedrocketry:models/nuclearrocketmotor.obj", "texture": "advancedrocketry:textures/models/nuclearcombustion.png" }, + "facing=north": { "model": "advancedrocketry:models/nuclearrocket.obj", "texture": "advancedrocketry:textures/models/nuclearcombustion.png", "x": 90 }, + "facing=south": { "model": "advancedrocketry:models/nuclearrocket.obj", "texture": "advancedrocketry:textures/models/nuclearcombustion.png", "x": 90, "y": 180 }, + "facing=west": { "model": "advancedrocketry:models/nuclearrocket.obj", "texture": "advancedrocketry:textures/models/nuclearcombustion.png", "x": 90, "y": 270 }, + "facing=east": { "model": "advancedrocketry:models/nuclearrocket.obj", "texture": "advancedrocketry:textures/models/nuclearcombustion.png", "x": 90, "y": 90 }, + "facing=up": { "model": "advancedrocketry:models/nuclearrocket.obj", "texture": "advancedrocketry:textures/models/nuclearcombustion.png", "x": 180 }, + "facing=down": { "model": "advancedrocketry:models/nuclearrocket.obj", "texture": "advancedrocketry:textures/models/nuclearcombustion.png" }, "inventory": { - "model": "advancedrocketry:models/bipropellantrocketmotor.obj", + "model": "advancedrocketry:models/nuclearrocket.obj", "textures": { "layer0": "advancedrocketry:textures/models/nuclearcombustion.png" } diff --git a/src/main/resources/assets/advancedrocketry/blockstates/oxidizerfueltank.json b/src/main/resources/assets/advancedrocketry/blockstates/oxidizerfueltank.json index ad2fd5453..a9dcfb8c9 100644 --- a/src/main/resources/assets/advancedrocketry/blockstates/oxidizerfueltank.json +++ b/src/main/resources/assets/advancedrocketry/blockstates/oxidizerfueltank.json @@ -6,14 +6,32 @@ "transform": "forge:default-block" }, "variants": { - "tankstates=top": { "model": "advancedrocketry:models/toptank.obj" }, - "tankstates=middle": { "model": "advancedrocketry:models/middletank.obj" }, - "tankstates=bottom": { "model": "advancedrocketry:models/bottomtank.obj" }, "inventory": { "model": "advancedrocketry:models/middletank.obj", "textures": { "layer0": "advancedrocketry:textures/models/tank" } - } + }, + "facing=north,tankstates=middle": { "model": "advancedrocketry:models/middletank.obj", "x": 90 }, + "facing=south,tankstates=middle": { "model": "advancedrocketry:models/middletank.obj", "x": 90, "y": 180 }, + "facing=west,tankstates=middle": { "model": "advancedrocketry:models/middletank.obj", "x": 90, "y": 270 }, + "facing=east,tankstates=middle": { "model": "advancedrocketry:models/middletank.obj", "x": 90, "y": 90 }, + "facing=up,tankstates=middle": { "model": "advancedrocketry:models/middletank.obj"}, + "facing=down,tankstates=middle": { "model": "advancedrocketry:models/middletank.obj"}, + + "facing=north,tankstates=top": { "model": "advancedrocketry:models/toptank.obj", "x": 90 }, + "facing=south,tankstates=top": { "model": "advancedrocketry:models/toptank.obj", "x": 90, "y": 180 }, + "facing=west,tankstates=top": { "model": "advancedrocketry:models/toptank.obj", "x": 90, "y": 270 }, + "facing=east,tankstates=top": { "model": "advancedrocketry:models/toptank.obj", "x": 90, "y": 90 }, + "facing=up,tankstates=top": { "model": "advancedrocketry:models/toptank.obj"}, + "facing=down,tankstates=top": { "model": "advancedrocketry:models/toptank.obj"}, + + "facing=north,tankstates=bottom": { "model": "advancedrocketry:models/bottomtank.obj", "x": 90 }, + "facing=south,tankstates=bottom": { "model": "advancedrocketry:models/bottomtank.obj", "x": 90, "y": 180 }, + "facing=west,tankstates=bottom": { "model": "advancedrocketry:models/bottomtank.obj", "x": 90, "y": 270 }, + "facing=east,tankstates=bottom": { "model": "advancedrocketry:models/bottomtank.obj", "x": 90, "y": 90 }, + "facing=up,tankstates=bottom": { "model": "advancedrocketry:models/bottomtank.obj"}, + "facing=down,tankstates=bottom": { "model": "advancedrocketry:models/bottomtank.obj"} + } } diff --git a/src/main/resources/assets/advancedrocketry/blockstates/rocketmotor.json b/src/main/resources/assets/advancedrocketry/blockstates/rocketmotor.json index d41bf7e67..a9acbbecc 100644 --- a/src/main/resources/assets/advancedrocketry/blockstates/rocketmotor.json +++ b/src/main/resources/assets/advancedrocketry/blockstates/rocketmotor.json @@ -4,18 +4,18 @@ "textures": { "#None": "advancedrocketry:/models/combustion" }, - "model": "advancedrocketry:models/rocketmotor.obj", + "model": "advancedrocketry:models/rocket.obj", "transform": "forge:default-block" }, "variants": { - "facing=north": { "model": "advancedrocketry:models/rocketmotor.obj", "texture": "advancedrocketry:textures/models/combustion.png", "x": 90 }, - "facing=south": { "model": "advancedrocketry:models/rocketmotor.obj", "texture": "advancedrocketry:textures/models/combustion.png", "x": 90, "y": 180 }, - "facing=west": { "model": "advancedrocketry:models/rocketmotor.obj", "texture": "advancedrocketry:textures/models/combustion.png", "x": 90, "y": 270 }, - "facing=east": { "model": "advancedrocketry:models/rocketmotor.obj", "texture": "advancedrocketry:textures/models/combustion.png", "x": 90, "y": 90 }, - "facing=up": { "model": "advancedrocketry:models/rocketmotor.obj", "texture": "advancedrocketry:textures/models/combustion.png", "x": 180 }, - "facing=down": { "model": "advancedrocketry:models/rocketmotor.obj", "texture": "advancedrocketry:textures/models/combustion.png" }, + "facing=north": { "model": "advancedrocketry:models/rocket.obj", "texture": "advancedrocketry:textures/models/combustion.png", "x": 90 }, + "facing=south": { "model": "advancedrocketry:models/rocket.obj", "texture": "advancedrocketry:textures/models/combustion.png", "x": 90, "y": 180 }, + "facing=west": { "model": "advancedrocketry:models/rocket.obj", "texture": "advancedrocketry:textures/models/combustion.png", "x": 90, "y": 270 }, + "facing=east": { "model": "advancedrocketry:models/rocket.obj", "texture": "advancedrocketry:textures/models/combustion.png", "x": 90, "y": 90 }, + "facing=up": { "model": "advancedrocketry:models/rocket.obj", "texture": "advancedrocketry:textures/models/combustion.png", "x": 180 }, + "facing=down": { "model": "advancedrocketry:models/rocket.obj", "texture": "advancedrocketry:textures/models/combustion.png" }, "inventory": { - "model": "advancedrocketry:models/rocketmotor.obj", + "model": "advancedrocketry:models/rocket.obj", "textures": { "layer0": "advancedrocketry:textures/models/combustion.png" } diff --git a/src/main/resources/assets/advancedrocketry/blockstates/servicemonitor.json b/src/main/resources/assets/advancedrocketry/blockstates/servicemonitor.json new file mode 100644 index 000000000..0b1a257ae --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/blockstates/servicemonitor.json @@ -0,0 +1,20 @@ +{ + "forge_marker": 1, + "defaults": { + "transform": "forge:default-block", + "model": "minecraft:orientable", + "textures": { + "top": "libvulpes:blocks/machinegeneric", + "front": "advancedrocketry:blocks/servicemonitor", + "side": "libvulpes:blocks/machinegeneric" + } + }, + "variants": { + "facing=north": [{}], + "facing=south": { "model": "minecraft:orientable", "y": 180}, + "facing=west": { "model": "minecraft:orientable", "y": 270 }, + "facing=east": { "model": "minecraft:orientable", "y": 90 }, + "normal": [{}], + "inventory" : [{}] + } +} diff --git a/src/main/resources/assets/advancedrocketry/blockstates/servicestation.json b/src/main/resources/assets/advancedrocketry/blockstates/servicestation.json new file mode 100644 index 000000000..42b0e7fbe --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/blockstates/servicestation.json @@ -0,0 +1,39 @@ +{ + "forge_marker": 1, + "defaults": { + "transform": "forge:default-block", + "model": "minecraft:orientable", + "textures": { + "top": "libvulpes:blocks/machinegeneric", + "front": "advancedrocketry:blocks/servicemachine", + "side": "libvulpes:blocks/machinegeneric" + } + }, + "variants": { + "facing=north,state=false": [{}], + "facing=south,state=false": { "model": "minecraft:orientable", "y": 180}, + "facing=west,state=false": { "model": "minecraft:orientable", "y": 270 }, + "facing=east,state=false": { "model": "minecraft:orientable", "y": 90 }, + "facing=north,state=true": { "model": "minecraft:orientable", "y": 0, + "textures": { + "front": "advancedrocketry:blocks/servicemachine_active_1" + } + }, + "facing=south,state=true": { "model": "minecraft:orientable", "y": 180, + "textures": { + "front": "advancedrocketry:blocks/servicemachine_active_2" + } + }, + "facing=west,state=true": { "model": "minecraft:orientable", "y": 270, + "textures": { + "front": "advancedrocketry:blocks/servicemachine_active_3" + } + }, + "facing=east,state=true": { "model": "minecraft:orientable", "y": 90, + "textures": { + "front": "advancedrocketry:blocks/servicemachine_active_4" + } + }, + "inventory" : [{}] + } +} diff --git a/src/main/resources/assets/advancedrocketry/lang/en_US.lang b/src/main/resources/assets/advancedrocketry/lang/en_US.lang index 07d489330..fc1e8d6b3 100644 --- a/src/main/resources/assets/advancedrocketry/lang/en_US.lang +++ b/src/main/resources/assets/advancedrocketry/lang/en_US.lang @@ -16,6 +16,9 @@ entity.hovercraft.name=Hovercraft tile.landingPad.name=Landing Pad tile.seat.name=Seat tile.pad.name=Launch Pad +tile.servicestation.name=Service station +tile.servicemonitor.name=Service monitor +tile.invhatch.name=Storage hatch tile.structuretower.name=Structure Tower tile.rocketAssembler.name=Rocket Assembling Machine tile.turf.name=Moon Turf @@ -135,6 +138,7 @@ tile.basalt.name=Basalt tile.landingfloat.name=Landing Float tile.solararray.name=Solar Array tile.solararraypanel.name=Solar Array Panel +tile.serviceStation.name=Service Station item.lens.0.name=Basic Lens item.wafer.0.name=Silicon Wafer @@ -199,6 +203,7 @@ item.elevatorChip.name=Space Elevator Chip container.satellite=Satellite Bay container.monitoringstation=Monitoring Station +container.invhatch=Storage hatch material.TitaniumAluminide.name=Titanium Aluminide material.TitaniumIridium.name=Titanium Iridium Alloy @@ -425,6 +430,16 @@ msg.itemplanetidchip.stationid=Station Id: msg.itemplanetidchip.artifacts=Artifacts: msg.vent.trace=Oxygen Trace +msg.serviceStation.destroyProbNA=Destroy probability: N/A +msg.serviceStation.destroyProb=Destroy probability +msg.serviceStation.serviceProgress=Service progress +msg.serviceStation.serviceProgressNA=Service progress: N/A +msg.serviceStation.wornMotorsText=Engines +msg.serviceStation.wornSeatsText=Seats +msg.serviceStation.wornTanksText=Tanks +msg.serviceStation.assemblerScan=Scan for assemblers +msg.serviceStation.link=You program the linker with the service station at + msg.itemsatellite.pwr=Power Storage: msg.itemsatellite.nopwr=No Power Storage msg.itemsatellite.pwrgen=Power Generation: @@ -433,6 +448,11 @@ msg.itemsatellite.microwavestatus=Collecting Power msg.itemsatellite.data=Data Storage: msg.itemsatellite.nodata=No Data Storage! msg.itemsatellite.empty=Empty Chassis +msg.itemsatellite.weight=Chassis weight: +msg.itemsatellite.noweight=Error in weight calculation + +msg.brokenstage.text=Destruction stage + msg.itemsatchip.id=ID: msg.itemsatchip.planet=Planet: msg.itemsatchip.planetunk=Planet: Unknown @@ -482,4 +502,8 @@ msg.muchTooDense=Warning: Atmosphere pressure critically dense! msg.chat.nostation1=You wake up on the space station with a lingering feeling that your far-reaching spacewalk was frowned upon by some elder fox deity, and that it would be foolish to attempt so again and to expect different results msg.chat.nostation2=Maybe you should think before overstepping clearly logical and absolute boundaries again then deciding it was a good idea and not your fault if things go wrong -msg.chat.nostation3=You must be on a space station to be in this dimension, and none have been created! \ No newline at end of file +msg.chat.nostation3=You must be on a space station to be in this dimension, and none have been created! + +commands.weather.always_not_clear=This planet is always not clear... +commands.weather.cannot_rain=Cannot start a rain here +commands.weather.cannot_thunder=Cannot start a thunder here diff --git a/src/main/resources/assets/advancedrocketry/lang/ru_RU.lang b/src/main/resources/assets/advancedrocketry/lang/ru_RU.lang index eacf1b5c5..9c25fc9d4 100644 --- a/src/main/resources/assets/advancedrocketry/lang/ru_RU.lang +++ b/src/main/resources/assets/advancedrocketry/lang/ru_RU.lang @@ -7,6 +7,9 @@ entity.advancedRocketry.rocket.name=Ракета entity.rocket.name=Ракета tile.landingPad.name=Посадочная площадка +tile.serviceStation.name=Станция техобслуживания +tile.servicemonitor.name=Монитор состояния +tile.invhatch.name=Отсек хранения tile.seat.name=Сиденье tile.pad.name=Стартовая площадка tile.structuretower.name=Структурная башня @@ -180,6 +183,8 @@ container.observatory=Обсерватория container.satellite=Отсек для спутника container.monitoringstation=Станция мониторинга container.satelliteMonitor=Спутниковый терминал +container.servicestation=Станция техобслуживания +container.invhatch=Отсек хранения enchantment.spaceBreathing=Герметичная изоляция @@ -265,6 +270,17 @@ msg.fuelingStation.link=Вы подключили частотный связы msg.monitoringStation.missionProgressNA=Прогресс миссии: Н/Д msg.monitoringStation.link=Вы подключили частотный связыватель к станции мониторинга на msg.monitoringStation.progress=Прогресс: + +msg.serviceStation.destroyProbNA=Вероятность разрушения: Н/Д +msg.serviceStation.destroyProb=Вероятность разрушения +msg.serviceStation.serviceProgress=Прогресс обслуживания +msg.serviceStation.serviceProgressNA=Прогресс обслуживания: Н/Д +msg.serviceStation.wornMotorsText=Двигатели +msg.serviceStation.wornSeatsText=Сиденья +msg.serviceStation.wornTanksText=Резервуары +msg.serviceStation.assemblerScan=Сканировать сборщики +msg.serviceStation.link=Вы подключили частотный связыватель к станции техобслуживания на + msg.guidanceComputerHatch.loadingState=Состояние загрузки: msg.guidanceComputerHatch.ejectonlanding=Автоматический выброс при посадке msg.guidanceComputerHatch.ejectonsatlanding=Разрешить выброс спутниковых чипов @@ -384,6 +400,11 @@ msg.itemsatellite.nopwrgen=Энергия не генерируется! msg.itemsatellite.data=Хранилище данных: msg.itemsatellite.nodata=Нет хранилища данных! msg.itemsatellite.empty=Пустое шасси +msg.itemsatellite.weight=Масса спутника: +msg.itemsatellite.noweight=Ошибка в подсчёте массы + +msg.brokenstage.text=Стадия повреждений + msg.itemsatchip.id=ID: msg.itemsatchip.planet=Планета: msg.itemsatchip.planetunk=Планета: Неизвестно @@ -423,3 +444,7 @@ msg.unprogrammed=Убрана программа msg.programfail=Ошибка программирования msg.modules=модулей msg.na=Н/Д + +commands.weather.always_not_clear=На этой планете не бывает сухо... +commands.weather.cannot_rain=Невозможно начать дождь, увы... +commands.weather.cannot_thunder=Невозможно включить грозу, увы... diff --git a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang index 16bfcac9e..1f9c728f4 100644 --- a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang +++ b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang @@ -1,16 +1,28 @@ itemGroup.advancedRocketry=高级火箭 itemGroup.advancedRocketryOres=高级火箭矿物 -death.attack.Vacuum=你被减压死了 -death.attack.Vacuum.player=减压死了 +death.attack.Vacuum=%1$s 因真空暴露死亡 +death.attack.Vacuum.player=%1$s 因真空暴露死亡 +death.attack.OxygenToxicity=%1$s 死于氧气中毒 +death.attack.OxygenToxicity.player=%1$s 死于氧气中毒 +death.attack.LowOxygen=%1$s 死于缺氧 +death.attack.LowOxygen.player=%1$s 死于缺氧 +death.attack.Heat=%1$s 死于高温暴露 +death.attack.Heat.player=%1$s 死于高温暴露 entity.advancedRocketry.rocket.name=火箭 entity.rocket.name=火箭 +entity.hovercraft.name=气垫船 +tile.landingPad.name=着陆平台 tile.seat.name=座位 tile.pad.name=发射台 +tile.servicestation.name=服务站 +tile.servicemonitor.name=服务监控器 +tile.invhatch.name=储物舱口 tile.structuretower.name=结构塔 tile.rocketAssembler.name=火箭组装机 tile.turf.name=月面土 +tile.turfDark.name=暗月面土 tile.cuttingMachine.name=切割机 tile.sawBlade.name=电锯 tile.controlComp.name=任务控制电脑 @@ -21,20 +33,29 @@ tile.blastBrick.name=隔热砖 tile.blastFurnaceController.name=隔热高炉控制器 tile.fuelStation.name=燃油站 tile.loader.0.name=数据总线 -tile.loader.1.name=卫星仓 +tile.loader.1.name=卫星舱 tile.loader.2.name=火箭卸载器 tile.loader.3.name=火箭装载器 tile.loader.4.name=火箭液体卸载器 tile.loader.5.name=火箭液体装载器 +tile.loader.6.name=导航电脑访问舱口 tile.observatory.name=瞭望台 tile.satelliteBuilder.name=卫星建造机 -tile.rocket.name=液体火箭发动机 -tile.advRocket.name=高级液体火箭发动机 +tile.rocket.name=单推进剂火箭发动机 +tile.bipropellantrocket.name=双燃料火箭发动机 +tile.nuclearrocket.name=核热火箭发动机 tile.fuelTank.name=液体燃料箱 +tile.bipropellantfueltank.name=双燃料燃料箱 +tile.oxidizerfueltank.name=氧化剂燃料箱 +tile.nuclearfueltank.name=核热工作燃料箱 +tile.nuclearcore.name=核热裂变核心 tile.monitoringstation.name=火箭监测站 tile.satelliteMonitor.name=卫星终端 +tile.terraformingTerminal.name=地形改造终端 +tile.lightwoodlog.name=轻木原木 tile.lightwoodsapling.name=轻木种子 tile.lightwoodleaves.name=轻木叶子 +tile.lightwoodplanks.name=轻木木板 tile.chipStorage.name=卫星ID储存器 tile.planetanalyser.name=天体数据处理器 tile.lunaranalyser.name=月球分析器 @@ -77,7 +98,6 @@ tile.gravityControl.name=重力控制器 tile.drill.name=钻头 tile.dataPipe.name=数据线 tile.liquidPipe.name=液体管道 -tile.energyPipe.name=能量管道 tile.rfOutput.name=RF输出端口 tile.microwaveReciever.name=微波接收器 tile.solarPanel.name=太阳能板 @@ -88,23 +108,37 @@ tile.atmoshereTerraformer.name=大气修改器 tile.deployableRocketAssembler.name=无人飞船组装器 tile.pressurizedTank.name=压力槽 tile.gasIntake.name=气体收集器 -tile.atmosphereTerraformer.name=大气修改器 +tile.atmosphereTerraformer.name=大气改造器 tile.circleLight.name=空间站光源 -tile.stationMarker.name=空间站停靠点 +tile.energyPipe.name=能量管道 tile.solarGenerator.name=太阳能发电机 +tile.stationMarker.name=空间站停靠点 +tile.qcrucible.name=石英坩埚 tile.altitudeController.name=海拔控制器 tile.railgun.name=轨道炮 +tile.advRocket.name=高级单推进剂火箭发动机 +tile.advbipropellantRocket.name=高级双推进剂火箭发动机 tile.planetHoloSelector.name=全息行星选择器 tile.lens.name=透镜 tile.forceField.name=力场方块 tile.forceFieldProjector.name=力场投射器 +tile.vacuumLaser.name=真空室高功率激光发射器 tile.gravityMachine.name=重力控制器 tile.pipeSeal.name=密封管 -tile.qcrucible.name=石英坩埚 - -tile.Dilithium.name=双锂矿 - -tile.coil.dilithium.name=双锂线圈 +tile.spaceElevatorController.name=太空电梯 +tile.beacon.name=灯塔 +tile.thermiteTorch.name=铝热管 +tile.wirelessTransciever.name=无线收发器 +tile.blackholegenerator.name=黑洞发生器 +tile.pump.name=流体泵 +tile.centrifuge.name=离心机 +tile.precisionlaseretcher.name=精密激光刻蚀机 +tile.enrichedLavaBlock.name=浓缩熔岩块 +tile.basalt.name=玄武岩 +tile.landingfloat.name=着陆浮标 +tile.solararray.name=太阳能电池 +tile.solararraypanel.name=太阳能电池板 +tile.serviceStation.name=服务站 item.lens.0.name=基础透镜 item.wafer.0.name=硅晶片 @@ -117,7 +151,7 @@ item.circuitIC.3.name=控制芯片板 item.circuitIC.4.name=物品IO芯片板 item.circuitIC.5.name=液体IO芯片板 item.OreScanner.name=矿物扫描仪 -item.dataUnit.0.name=数据存储单位 +item.dataUnit.0.name=数据存储单元 item.sawBlade.0.name=铁锯片 item.satellite.name=卫星 item.satellitePowerSource.0.name=基础太阳能板 @@ -128,18 +162,18 @@ item.satellitePrimaryFunction.2.name=质量检测器 item.satellitePrimaryFunction.3.name=微波传输器 item.satellitePrimaryFunction.4.name=矿物扫描仪 item.satellitePrimaryFunction.5.name=生物群落修改器 +item.satellitePrimaryFunction.6.name=天气控制器 item.satelliteIdChip.name=卫星ID芯片 item.planetIdChip.name=星球ID芯片 item.asteroidChip.name=小行星ID芯片 -item.battery.0.name=小号电池 -item.battery.1.name=2x小号电池 item.miscpart.0.name=用户界面 item.miscpart.1.name=碳砖 item.station.name=空间站容器 item.stationChip.name=空间站ID芯片 +item.stationchip.openmenu=蹲下右键打开配置菜单 item.spaceHelmet.name=太空头盔 -item.spaceLeggings.name=太空裤子 item.spaceChest.name=太空胸甲 +item.spaceLeggings.name=太空裤子 item.spaceBoots.name=太空鞋 item.smallAirlock.name=小气密门 item.carbonScrubberCartridge.name=碳收集器 @@ -150,27 +184,31 @@ item.itemUpgrade.1.name=飞行速度控制升级 item.itemUpgrade.2.name=仿生腿升级 item.itemUpgrade.3.name=降落缓冲鞋 item.itemUpgrade.4.name=雾镜 +item.itemUpgrade.5.name=地球反光遮挡板 item.atmAnalyser.name=大气分析器 item.biomeChanger.name=生物群系改变器遥控终端 +item.weatherController.name=气象卫星控制器 item.basicLaserGun.name=基础激光枪 +item.beaconFinder.name=灯塔探测器 +item.thermite.name=铝热剂 +item.hovercraft.name=气垫船 +item.hovercraft.tooltip=持久二锂电源,它可能会比你活得长 item.jetPack.name=飞行背包 item.pressureTank.0.name=低压槽 item.pressureTank.1.name=压力槽 item.pressureTank.2.name=高压槽 item.pressureTank.3.name=超高压槽 +item.elevatorChip.name=太空电梯芯片 + +container.satellite=卫星舱 +container.monitoringstation=监测站 +container.invhatch=储存舱口 -material.Dilithium.name=双锂 material.TitaniumAluminide.name=钛铝合金 material.TitaniumIridium.name=钛铱合金 -container.crystallizer=结晶器 -container.cuttingmachine=切割机 -container.precisionassemblingmachine=精确组装机 -container.observatory=瞭望台 -container.satellite=卫星仓 -container.monitoringstation=监测站 -container.satelliteMonitor=卫星终端 +enchantment.spaceBreathing=严实的封口 data.undefined.name=一些随机数据 data.distance.name=距离 @@ -184,6 +222,7 @@ fluid.oxygen=氧气 fluid.hydrogen=氢气 fluid.nitrogen=氮气 fluid.rocketFuel=火箭燃料 +fluid.enrichedLava=浓缩熔岩 mission.asteroidmining.name=小行星采矿 mission.gascollection.name=气体收集 @@ -212,7 +251,7 @@ advancement.moonLanding=登录月球 advancement.moonLanding.desc=登录月球 advancement.oneSmallStep=一小步 advancement.oneSmallStep.desc=第一个到达月球 -advancement.weReallyWentToTheMoon=我们真的想去月球 +advancement.weReallyWentToTheMoon=我们真的登上了月球! advancement.weReallyWentToTheMoon.desc=找到月球上的阿波罗11着陆点 advancement.dilithium=双锂 advancement.dilithium.desc=找到双锂矿 @@ -225,15 +264,246 @@ advancement.beerOnTheSun.desc=你需要更多的TNT才能到达轨道 advancement.suitedUp=穿好了 advancement.suitedUp.desc=穿好全套太空服 + + key.controls.advancedrocketry=高级火箭 key.openRocketUI=打开火箭界面 key.toggleJetpack=开关喷气背包 +key.togglercs=切换反作用控制系统 +key.turnRocketLeft=左转 +key.turnRocketRight=右转 +key.turnRocketUp=上移 +key.turnRocketDown=下移 +enchantment.advancedrocketry.spacebreathing.desc=可以让盔甲形成密封 + +machine.tooltip.smallplatepress=需要下面有两块黑曜石才能运作 + +msg.crystalliser.gravityTooHigh=重力不够低 msg.observetory.scan.tooltip=扫描新的小行星,将消耗100个距离数据 msg.observetory.scan.button=扫描! msg.observetory.text.asteroids=小行星 msg.observetory.text.composition=成分 msg.observetory.text.processdiscovery=扫描进度 -msg.observetory.text.observabledistance=可观测距离: +msg.observetory.text.observabledistance=可观测距离: +msg.observetory.text.missionTime=任务时间: msg.tooltip.data=数据 msg.tooltip.asteroidselection=小行星选择 +msg.label.name=名字 +msg.label.clear=发射 +msg.label.add=添加新的 +msg.label.rename=重命名 +msg.label.delete=删除 +msg.label.noneSelected=未选择目的地 +msg.label.selectDst=选择目的地 +msg.label.destName=目的地名称 +msg.label.coords=坐标 +msg.spaceElevator.button.summon=调运舱体 +msg.spaceElevator.sameDimensionError=无法连接同一星球上的两部电梯! +msg.spaceElevator.linkNotGeostationaryError=空间站未处于地球静止轨道! +msg.spaceElevator.tetherWouldBreakError=空间站必须直立静止才能接收系链! +msg.spaceElevator.linkCannotChangeError=已连接的电梯系链不能改变位置! +msg.spaceElevator.newDstAdded=锚定缆索连接成功! +msg.spaceElevator.ascentReady=准备升空 +msg.spaceElevator.warning.anchored0=该电梯锚定缆索已 +msg.spaceElevator.warning.anchored1=锚定了空间站! +msg.spaceElevator.warning.unanchored=该电梯没有锚定缆索 +msg.spaceElevator.turnedOff=电梯已关闭 +msg.fuelingStation.link=你将位于以下位置的燃油站对链接器进行编程 +msg.monitoringStation.missionProgressNA=任务进展: N/A +msg.monitoringStation.link=你将位于以下位置的监控站对链接器进行编程 +msg.monitoringStation.progress= 进度: +msg.guidanceComputerHatch.loadingState=加载状态: +msg.guidanceComputerHatch.ejectonlanding=着陆时自动弹射 +msg.guidanceComputerHatch.ejectonsatlanding=允许弹射卫星芯片 +msg.guidanceComputerHatch.ejectonplanetlanding=允许弹射行星芯片 +msg.guidanceComputerHatch.ejectonstationlanding=允许弹射空间站芯片 +msg.guidanceComputerHatch.link=你将位于以下位置的流体装载机对链接器进行编程 +msg.fluidLoader.loadingState=加载状态: +msg.fluidLoader.allowLoading=允许加载: +msg.fluidLoader.allowredstoneinput=允许红石输入 +msg.fluidLoader.allowredstoneoutput=允许红石输出 +msg.fluidLoader.none=无 +msg.fluidLoader.link=你将位于以下位置的流体装载机对链接器进行编程: +msg.rocketLoader.loadingState=载入状态: +msg.rocketLoader.allowLoading=允许加载: +msg.rocketLoader.allowredstoneinput=允许红石输入 +msg.rocketLoader.allowredstoneoutput=允许红石输出 +msg.rocketLoader.none=无 +msg.rocketLoader.link=你将位于以下位置的火箭加载器对链接器进行编程: +msg.microwaverec.notgenerating=生成 0 FE/t +msg.microwaverec.generating=正在生成 +msg.abdp.compositionresearch=合成研究 +msg.abdp.distanceresearch=距离研究 +msg.abdp.massresearch=质量研究 +msg.terraformer.atminc=增加大气压 +msg.terraformer.atmdec=减少大气压 +msg.terraformer.running=运行中 +msg.terraformer.missingbiome=缺少生物群落改变器链接 +msg.terraformer.outofgas=停止: 气体储备不足 +msg.terraformer.notrunning=未运行 +msg.terraformer.status=状态 +msg.terraformer.pressure=气压 +msg.biomescanner.gas=是啊,时髦,不是吗? +msg.biomescanner.star=如果我的传感器有遮阳帘就好了 +msg.gravitycontroller.radius=半径: +msg.gravitycontroller.targetgrav=目标重力: +msg.gravitycontroller.none=未设置 +msg.gravitycontroller.activeset=激活: 设置 +msg.gravitycontroller.activeadd=激活: 添加 +msg.gravitycontroller.targetdir.1=目标 -> +msg.gravitycontroller.targetdir.2=方向 +msg.railgun.transfermin=最小传送尺寸 +msg.spacelaser.reset=重置 +msg.satctrlcenter.toofar=太远 +msg.satctrlcenter.nolink=无链接... +msg.satctrlcenter.info=信息: +msg.satctrlcenter.destroysat=摧毁卫星 +msg.satctrlcenter.connect=连接! +msg.satbuilder.writesecondchip=写入第二芯片 +msg.dockingport.target=目标 Id +msg.dockingport.me=我的 Id +msg.planetholo.size=全息图尺寸: +msg.stationaltctrl.maxaltrate=最大高度变化率: +msg.stationaltctrl.tgtalt=目标高度: +msg.stationaltctrl.alt=高度: +msg.stationgravctrl.maxaltrate=最大重力变化率: +msg.stationgravctrl.tgtalt=目标重力: +msg.stationgravctrl.alt=模拟重力: +msg.stationorientctrl.alt=角速度: +msg.stationorientctrl.tgtalt=目标角速度: +msg.warpmon.tab.warp=跃迁选择 +msg.warpmon.tab.data=数据 +msg.warpmon.tab.tracking=行星跟踪 +msg.warpmon.selectplanet=选择行星 +msg.warpmon.corestatus=核心状态: +msg.warpmon.anchored=空间站已锚定! +msg.warpmon.nowhere=无处可去 +msg.warpmon.missingart=缺少工件 +msg.warpmon.ready=准备就绪! +msg.warpmon.notready=未就绪 +msg.warpmon.warp=跃迁! +msg.warpmon.fuelcost=燃料成本: +msg.warpmon.fuel=燃料: +msg.warpmon.dest=目的地: +msg.warpmon.na=N/A +msg.warpmon.search=搜索行星 +msg.warpmon.chip=芯片编程 +msg.warpmon.datareq=每种数据类型需要100个 +msg.warpmon.artifact=工件 +msg.rocketbuilder.success=可以发射了! +msg.rocketbuilder.nofuel=燃料容量不够! +msg.rocketbuilder.noseat=缺少座位或卫星舱! +msg.rocketbuilder.noengines=你没有足够的推力! +msg.rocketbuilder.noguidance=缺少导航电脑 +msg.rocketbuilder.unscanned=火箭未扫描 +msg.rocketbuilder.success_station=准备就绪! +msg.rocketbuilder.empty=这里什么都没有 +msg.rocketbuilder.finished=建造完成! +msg.rocketbuild.invalidblock=无效块! +msg.rocketbuilder.incompletestructure=无效的发射台结构! +msg.rocketbuilder.nosatellitehatch=缺少卫星舱 +msg.rocketbuilder.nosatellitechip=缺少芯片 +msg.rocketbuilder.outputblocked=输出槽被阻塞 +msg.rocketbuilder.thrust=推力 +msg.rocketbuilder.weight=重量 +msg.rocketbuilder.fuel=燃料 +msg.rocketbuilder.acc=飞行控制中心 +msg.rocketbuilder.build=建造 +msg.rocketbuilder.scan=扫描 +msg.rocketbuild.combinedthrust=燃料类型不能组合! +msg.solar.collectingEnergy=收集能量: +msg.solar.cannotcollectEnergy=无法收集能量 +msg.asteroidChip.asteroid=小行星 +msg.atmanal.atmtype=大气类型: +msg.atmanal.canbreathe=可呼吸: +msg.biomechanger.scan=扫描生物群系 +msg.biomechanger.nosat=卫星尚未发射 +msg.biomechanger.selBiome=选中生物群系: +msg.biomechanger.numBiome=扫描的生物群系数量: +msg.itemorescanner.nosat=卫星尚未发射 +msg.itemorescanner.maxzoom=最大缩放: +msg.itemorescanner.filter=可过滤矿石: +msg.itemorescanner.value=值: +msg.itemplanetidchip.planetname=星球名: +msg.itemplanetidchip.stationid=站台 Id: +msg.itemplanetidchip.artifacts=工件: +msg.vent.trace=氧迹检测 + +msg.serviceStation.destroyProbNA=销毁概率: N/A +msg.serviceStation.destroyProb=销毁概率 +msg.serviceStation.serviceProgress=服务进度 +msg.serviceStation.serviceProgressNA=服务进度: N/A +msg.serviceStation.wornMotorsText=引擎 +msg.serviceStation.wornSeatsText=座位 +msg.serviceStation.wornTanksText=油箱 +msg.serviceStation.assemblerScan=扫描装配器 +msg.serviceStation.link=你将位于以下位置的服务站对链接器进行编程: + +msg.itemsatellite.pwr=电源存储: +msg.itemsatellite.nopwr=无电源存储 +msg.itemsatellite.pwrgen=发电: +msg.itemsatellite.nopwrgen=无发电! +msg.itemsatellite.microwavestatus=收集电能 +msg.itemsatellite.data=数据存储: +msg.itemsatellite.nodata=无数据存储! +msg.itemsatellite.empty=空机箱 +msg.itemsatellite.weight=机箱重量: +msg.itemsatellite.noweight=重量计算错误 + +msg.brokenstage.text=销毁阶段 + +msg.itemsatchip.id=ID: +msg.itemsatchip.planet=行星: +msg.itemsatchip.planetunk=行星: 未知 +msg.itemsatchip.sat=卫星: +msg.itemsatchip.satlost=卫星: 失去联系 +msg.sealdetector.sealed=应能很好地密封 +msg.sealdetector.notsealmat=材料不会密封 +msg.sealdetector.notsealblock=阻挡物不会保持密封 +msg.sealdetector.notfullblock=空气会绕开此方块 +msg.sealdetector.fluid=空气会渗透此方块 +msg.sealdetector.other=空气会在此方块处泄露 +msg.stationchip.sation=站台 +msg.entity.rocket.descend.1=按空格键下降! +msg.entity.rocket.descend.2=自动下降 +msg.entity.rocket.ascend.1=按空格键起飞! +msg.entity.rocket.ascend.2=目的地: +msg.entity.rocket.launch=在T区发射 - +msg.entity.rocket.launch2=按空格键终止发射 +msg.entity.rocket.station=发射站 +msg.entity.rocket.pad=平台: +msg.entity.rocket.disass=解体 +msg.entity.rocket.seldst=选择目的地 +msg.entity.rocket.clear=发射 +msg.entity.rocket.rcs=反作用控制系统模式 +msg.entity.rocket.none=未选择 +msg.wirelessTransciever.extract=提取 + +msg.powerunit.rfpertick=FE/t +msg.linker.error.firstMachine=这必须是第一台要链接的机器! +msg.linker.program=坐标已编入链接器 +msg.linker.success=链接成功 +msg.notenoughpower=电量不足! +msg.empty=空 +msg.yes=是 +msg.no=否 +msg.connected=已连接 +msg.notconnected=未连接 +msg.unprogrammed=未编程 +msg.programfail=编程失败 +msg.modules=模块 +msg.na=N/A +msg.entityDeployedRocket.notGasGiant=这里没有气体 +msg.noOxygen=警告: 氧气浓度不足! +msg.tooHot=警告: 大气过热! +msg.tooDense=警告: 大气压过高! +msg.muchTooDense=警告: 大气压达到临界压力! + +msg.chat.nostation1=你在空间站醒来时,有一种挥之不去的感觉,那就是你那影响深远的太空行走遭到了某位狐神长老的鄙视,如果你再次尝试并期望得到不同的结果,那将是愚蠢的 +msg.chat.nostation2=也许你应该考虑一下,不要再逾越明确的逻辑和绝对的界限,然后决定这是个好主意,出了问题也不是你的错 +msg.chat.nostation3=你必须在空间站上才能来到这个时空,而现在还没有空间站! + +commands.weather.always_not_clear=这个星球的天气总是阴暗... +commands.weather.cannot_rain=这里无法启动降雨 +commands.weather.cannot_thunder=这里无法启动雷暴 diff --git a/src/main/resources/assets/advancedrocketry/models/block/models/advbipropellantrocketmotor.mtl b/src/main/resources/assets/advancedrocketry/models/block/models/advbipropellantrocket.mtl similarity index 52% rename from src/main/resources/assets/advancedrocketry/models/block/models/advbipropellantrocketmotor.mtl rename to src/main/resources/assets/advancedrocketry/models/block/models/advbipropellantrocket.mtl index 84466e27b..250c3c6ff 100644 --- a/src/main/resources/assets/advancedrocketry/models/block/models/advbipropellantrocketmotor.mtl +++ b/src/main/resources/assets/advancedrocketry/models/block/models/advbipropellantrocket.mtl @@ -2,4 +2,4 @@ # Material Count: 1 newmtl Material -map_Kd advancedrocketry:models/advbipropellantcombustion +map_Kd advancedrocketry:models/advbipropellantrocket diff --git a/src/main/resources/assets/advancedrocketry/models/block/models/advbipropellantrocketmotor.obj b/src/main/resources/assets/advancedrocketry/models/block/models/advbipropellantrocket.obj similarity index 99% rename from src/main/resources/assets/advancedrocketry/models/block/models/advbipropellantrocketmotor.obj rename to src/main/resources/assets/advancedrocketry/models/block/models/advbipropellantrocket.obj index bb2d98a50..e7a2a2b56 100644 --- a/src/main/resources/assets/advancedrocketry/models/block/models/advbipropellantrocketmotor.obj +++ b/src/main/resources/assets/advancedrocketry/models/block/models/advbipropellantrocket.obj @@ -1,6 +1,6 @@ # Blender v2.78 (sub 0) OBJ File: '' # www.blender.org -mtllib advbipropellantrocketmotor.mtl +mtllib advbipropellantrocket.mtl o Material v 0.050000 0.760000 0.400000 v 0.093301 0.577936 0.425000 diff --git a/src/main/resources/assets/advancedrocketry/models/block/models/advrocketmotor.mtl b/src/main/resources/assets/advancedrocketry/models/block/models/advrocket.mtl similarity index 58% rename from src/main/resources/assets/advancedrocketry/models/block/models/advrocketmotor.mtl rename to src/main/resources/assets/advancedrocketry/models/block/models/advrocket.mtl index afa57a192..9e0eaaefc 100644 --- a/src/main/resources/assets/advancedrocketry/models/block/models/advrocketmotor.mtl +++ b/src/main/resources/assets/advancedrocketry/models/block/models/advrocket.mtl @@ -2,4 +2,4 @@ # Material Count: 1 newmtl Material -map_Kd advancedrocketry:models/advcombustion +map_Kd advancedrocketry:models/advrocket diff --git a/src/main/resources/assets/advancedrocketry/models/block/models/advrocketmotor.obj b/src/main/resources/assets/advancedrocketry/models/block/models/advrocket.obj similarity index 99% rename from src/main/resources/assets/advancedrocketry/models/block/models/advrocketmotor.obj rename to src/main/resources/assets/advancedrocketry/models/block/models/advrocket.obj index 8def6833c..8ed8c0f4b 100644 --- a/src/main/resources/assets/advancedrocketry/models/block/models/advrocketmotor.obj +++ b/src/main/resources/assets/advancedrocketry/models/block/models/advrocket.obj @@ -1,6 +1,6 @@ # Blender v2.78 (sub 0) OBJ File: '' # www.blender.org -mtllib advrocketmotor.mtl +mtllib advrocket.mtl o Material v 0.050000 0.760000 0.400000 v 0.093301 0.577936 0.425000 diff --git a/src/main/resources/assets/advancedrocketry/models/block/models/bipropellantrocketmotor.mtl b/src/main/resources/assets/advancedrocketry/models/block/models/bipropellantrocket.mtl similarity index 58% rename from src/main/resources/assets/advancedrocketry/models/block/models/bipropellantrocketmotor.mtl rename to src/main/resources/assets/advancedrocketry/models/block/models/bipropellantrocket.mtl index 9c1dd0767..908e4affa 100644 --- a/src/main/resources/assets/advancedrocketry/models/block/models/bipropellantrocketmotor.mtl +++ b/src/main/resources/assets/advancedrocketry/models/block/models/bipropellantrocket.mtl @@ -2,4 +2,4 @@ # Material Count: 1 newmtl Material -map_Kd advancedrocketry:models/bipropellantcombustion +map_Kd advancedrocketry:models/bipropellantrocket diff --git a/src/main/resources/assets/advancedrocketry/models/block/models/bipropellantrocketmotor.obj b/src/main/resources/assets/advancedrocketry/models/block/models/bipropellantrocket.obj similarity index 99% rename from src/main/resources/assets/advancedrocketry/models/block/models/bipropellantrocketmotor.obj rename to src/main/resources/assets/advancedrocketry/models/block/models/bipropellantrocket.obj index 3a085169d..c8314220b 100644 --- a/src/main/resources/assets/advancedrocketry/models/block/models/bipropellantrocketmotor.obj +++ b/src/main/resources/assets/advancedrocketry/models/block/models/bipropellantrocket.obj @@ -1,6 +1,6 @@ # Blender v2.77 (sub 0) OBJ File: 'combustion.blend' # www.blender.org -mtllib bipropellantrocketmotor.mtl +mtllib bipropellantrocket.mtl o rocketmotor v 0.500000 0.456373 0.220000 v 0.302010 0.456373 0.302010 diff --git a/src/main/resources/assets/advancedrocketry/models/block/models/nuclearrocketmotor.mtl b/src/main/resources/assets/advancedrocketry/models/block/models/nuclearrocket.mtl similarity index 61% rename from src/main/resources/assets/advancedrocketry/models/block/models/nuclearrocketmotor.mtl rename to src/main/resources/assets/advancedrocketry/models/block/models/nuclearrocket.mtl index e9a9666f8..5c49b9236 100644 --- a/src/main/resources/assets/advancedrocketry/models/block/models/nuclearrocketmotor.mtl +++ b/src/main/resources/assets/advancedrocketry/models/block/models/nuclearrocket.mtl @@ -2,4 +2,4 @@ # Material Count: 2 newmtl Material -map_Kd advancedrocketry:models/nuclearengine +map_Kd advancedrocketry:models/nuclearrocket diff --git a/src/main/resources/assets/advancedrocketry/models/block/models/nuclearrocketmotor.obj b/src/main/resources/assets/advancedrocketry/models/block/models/nuclearrocket.obj similarity index 99% rename from src/main/resources/assets/advancedrocketry/models/block/models/nuclearrocketmotor.obj rename to src/main/resources/assets/advancedrocketry/models/block/models/nuclearrocket.obj index 66c8741c8..5e345e18b 100644 --- a/src/main/resources/assets/advancedrocketry/models/block/models/nuclearrocketmotor.obj +++ b/src/main/resources/assets/advancedrocketry/models/block/models/nuclearrocket.obj @@ -1,6 +1,6 @@ # Blender v2.79 (sub 0) OBJ File: 'rocket.blend' # www.blender.org -mtllib nuclearrocketmotor.mtl +mtllib nuclearrocket.mtl o rocketmotor v 0.302010 0.456373 0.302010 v 0.500000 0.005000 -0.000500 diff --git a/src/main/resources/assets/advancedrocketry/models/block/models/rocketmotor.mtl b/src/main/resources/assets/advancedrocketry/models/block/models/rocket.mtl similarity index 64% rename from src/main/resources/assets/advancedrocketry/models/block/models/rocketmotor.mtl rename to src/main/resources/assets/advancedrocketry/models/block/models/rocket.mtl index ff7f7bf57..b192a1f1f 100644 --- a/src/main/resources/assets/advancedrocketry/models/block/models/rocketmotor.mtl +++ b/src/main/resources/assets/advancedrocketry/models/block/models/rocket.mtl @@ -2,4 +2,4 @@ # Material Count: 1 newmtl Material -map_Kd advancedrocketry:models/combustion +map_Kd advancedrocketry:models/rocket diff --git a/src/main/resources/assets/advancedrocketry/models/block/models/rocketmotor.obj b/src/main/resources/assets/advancedrocketry/models/block/models/rocket.obj similarity index 99% rename from src/main/resources/assets/advancedrocketry/models/block/models/rocketmotor.obj rename to src/main/resources/assets/advancedrocketry/models/block/models/rocket.obj index ebe6651f0..64ca9614c 100644 --- a/src/main/resources/assets/advancedrocketry/models/block/models/rocketmotor.obj +++ b/src/main/resources/assets/advancedrocketry/models/block/models/rocket.obj @@ -1,6 +1,6 @@ # Blender v2.77 (sub 0) OBJ File: 'combustion.blend' # www.blender.org -mtllib rocketmotor.mtl +mtllib rocket.mtl o rocketmotor v 0.500000 0.456373 0.220000 v 0.302010 0.456373 0.302010 diff --git a/src/main/resources/assets/advancedrocketry/recipes/advbipropellantengine_repair_1.json b/src/main/resources/assets/advancedrocketry/recipes/advbipropellantengine_repair_1.json new file mode 100644 index 000000000..d83512cb3 --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/advbipropellantengine_repair_1.json @@ -0,0 +1,21 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotTitaniumIridium" + }, + { + "item": "advancedrocketry:advbipropellantrocketmotor", + "data": 1 + } + ], + "time": 900, + "energy": 100, + "itemresults": + { + "item": "advancedrocketry:advbipropellantrocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/advbipropellantengine_repair_2.json b/src/main/resources/assets/advancedrocketry/recipes/advbipropellantengine_repair_2.json new file mode 100644 index 000000000..49dd453d8 --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/advbipropellantengine_repair_2.json @@ -0,0 +1,21 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotTitaniumIridium" + }, + { + "item": "advancedrocketry:advbipropellantrocketmotor", + "data": 2 + } + ], + "time": 900, + "energy": 200, + "itemresults": + { + "item": "advancedrocketry:advbipropellantrocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/advbipropellantengine_repair_3.json b/src/main/resources/assets/advancedrocketry/recipes/advbipropellantengine_repair_3.json new file mode 100644 index 000000000..9d896d3c4 --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/advbipropellantengine_repair_3.json @@ -0,0 +1,21 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotTitaniumIridium" + }, + { + "item": "advancedrocketry:advbipropellantrocketmotor", + "data": 3 + } + ], + "time": 900, + "energy": 300, + "itemresults": + { + "item": "advancedrocketry:advbipropellantrocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/advbipropellantengine_repair_4.json b/src/main/resources/assets/advancedrocketry/recipes/advbipropellantengine_repair_4.json new file mode 100644 index 000000000..126633b4d --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/advbipropellantengine_repair_4.json @@ -0,0 +1,25 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotTitaniumIridium" + }, + { + "type": "forge:ore_dict", + "ore": "plateTitaniumAluminide" + }, + { + "item": "advancedrocketry:advbipropellantrocketmotor", + "data": 4 + } + ], + "time": 1800, + "energy": 400, + "itemresults": + { + "item": "advancedrocketry:advbipropellantrocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/advbipropellantengine_repair_5.json b/src/main/resources/assets/advancedrocketry/recipes/advbipropellantengine_repair_5.json new file mode 100644 index 000000000..65228913a --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/advbipropellantengine_repair_5.json @@ -0,0 +1,25 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotTitaniumIridium" + }, + { + "type": "forge:ore_dict", + "ore": "plateTitaniumAluminide" + }, + { + "item": "advancedrocketry:advbipropellantrocketmotor", + "data": 4 + } + ], + "time": 1800, + "energy": 500, + "itemresults": + { + "item": "advancedrocketry:advbipropellantrocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/advbipropellantengine_repair_6.json b/src/main/resources/assets/advancedrocketry/recipes/advbipropellantengine_repair_6.json new file mode 100644 index 000000000..637ff5f24 --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/advbipropellantengine_repair_6.json @@ -0,0 +1,25 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotTitaniumIridium" + }, + { + "type": "forge:ore_dict", + "ore": "plateTitaniumAluminide" + }, + { + "item": "advancedrocketry:advbipropellantrocketmotor", + "data": 4 + } + ], + "time": 1800, + "energy": 600, + "itemresults": + { + "item": "advancedrocketry:advbipropellantrocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/advbipropellantengine_repair_7.json b/src/main/resources/assets/advancedrocketry/recipes/advbipropellantengine_repair_7.json new file mode 100644 index 000000000..6028086a3 --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/advbipropellantengine_repair_7.json @@ -0,0 +1,26 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotTitaniumIridium", + "count": 2 + }, + { + "type": "forge:ore_dict", + "ore": "plateTitaniumAluminide" + }, + { + "item": "advancedrocketry:advbipropellantrocketmotor", + "data": 7 + } + ], + "time": 2700, + "energy": 700, + "itemresults": + { + "item": "advancedrocketry:advbipropellantrocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/advbipropellantengine_repair_8.json b/src/main/resources/assets/advancedrocketry/recipes/advbipropellantengine_repair_8.json new file mode 100644 index 000000000..f6b17f9c4 --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/advbipropellantengine_repair_8.json @@ -0,0 +1,27 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotTitaniumIridium", + "count": 2 + }, + { + "type": "forge:ore_dict", + "ore": "plateTitaniumAluminide", + "count": 2 + }, + { + "item": "advancedrocketry:advbipropellantrocketmotor", + "data": 8 + } + ], + "time": 2700, + "energy": 800, + "itemresults": + { + "item": "advancedrocketry:advbipropellantrocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/advbipropellantengine_repair_9.json b/src/main/resources/assets/advancedrocketry/recipes/advbipropellantengine_repair_9.json new file mode 100644 index 000000000..1b3ad83f0 --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/advbipropellantengine_repair_9.json @@ -0,0 +1,27 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotTitaniumIridium", + "count": 2 + }, + { + "type": "forge:ore_dict", + "ore": "plateTitaniumAluminide", + "count": 2 + }, + { + "item": "advancedrocketry:advbipropellantrocketmotor", + "data": 9 + } + ], + "time": 2700, + "energy": 900, + "itemresults": + { + "item": "advancedrocketry:advbipropellantrocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/advengine_repair_1.json b/src/main/resources/assets/advancedrocketry/recipes/advengine_repair_1.json new file mode 100644 index 000000000..d9d39a83d --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/advengine_repair_1.json @@ -0,0 +1,21 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotTitaniumIridium" + }, + { + "item": "advancedrocketry:advrocketmotor", + "data": 1 + } + ], + "time": 900, + "energy": 100, + "itemresults": + { + "item": "advancedrocketry:advrocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/advengine_repair_2.json b/src/main/resources/assets/advancedrocketry/recipes/advengine_repair_2.json new file mode 100644 index 000000000..75c0f7321 --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/advengine_repair_2.json @@ -0,0 +1,21 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotTitaniumIridium" + }, + { + "item": "advancedrocketry:advrocketmotor", + "data": 2 + } + ], + "time": 900, + "energy": 200, + "itemresults": + { + "item": "advancedrocketry:advrocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/advengine_repair_3.json b/src/main/resources/assets/advancedrocketry/recipes/advengine_repair_3.json new file mode 100644 index 000000000..6ef69df73 --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/advengine_repair_3.json @@ -0,0 +1,21 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotTitaniumIridium" + }, + { + "item": "advancedrocketry:advrocketmotor", + "data": 3 + } + ], + "time": 900, + "energy": 300, + "itemresults": + { + "item": "advancedrocketry:advrocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/advengine_repair_4.json b/src/main/resources/assets/advancedrocketry/recipes/advengine_repair_4.json new file mode 100644 index 000000000..f04a5a2cd --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/advengine_repair_4.json @@ -0,0 +1,25 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotTitaniumIridium" + }, + { + "type": "forge:ore_dict", + "ore": "plateTitaniumAluminide" + }, + { + "item": "advancedrocketry:advrocketmotor", + "data": 4 + } + ], + "time": 1800, + "energy": 400, + "itemresults": + { + "item": "advancedrocketry:advrocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/advengine_repair_5.json b/src/main/resources/assets/advancedrocketry/recipes/advengine_repair_5.json new file mode 100644 index 000000000..68169d40c --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/advengine_repair_5.json @@ -0,0 +1,25 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotTitaniumIridium" + }, + { + "type": "forge:ore_dict", + "ore": "plateTitaniumAluminide" + }, + { + "item": "advancedrocketry:advrocketmotor", + "data": 5 + } + ], + "time": 1800, + "energy": 500, + "itemresults": + { + "item": "advancedrocketry:advrocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/advengine_repair_6.json b/src/main/resources/assets/advancedrocketry/recipes/advengine_repair_6.json new file mode 100644 index 000000000..196ffd1ab --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/advengine_repair_6.json @@ -0,0 +1,25 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotTitaniumIridium" + }, + { + "type": "forge:ore_dict", + "ore": "plateTitaniumAluminide" + }, + { + "item": "advancedrocketry:advrocketmotor", + "data": 6 + } + ], + "time": 1800, + "energy": 600, + "itemresults": + { + "item": "advancedrocketry:advrocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/advengine_repair_7.json b/src/main/resources/assets/advancedrocketry/recipes/advengine_repair_7.json new file mode 100644 index 000000000..f7db81603 --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/advengine_repair_7.json @@ -0,0 +1,26 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotTitaniumIridium", + "count": 2 + }, + { + "type": "forge:ore_dict", + "ore": "plateTitaniumAluminide" + }, + { + "item": "advancedrocketry:advrocketmotor", + "data": 7 + } + ], + "time": 2700, + "energy": 700, + "itemresults": + { + "item": "advancedrocketry:advrocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/advengine_repair_8.json b/src/main/resources/assets/advancedrocketry/recipes/advengine_repair_8.json new file mode 100644 index 000000000..55f3a66bf --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/advengine_repair_8.json @@ -0,0 +1,26 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotTitaniumIridium", + "count": 2 + }, + { + "type": "forge:ore_dict", + "ore": "plateTitaniumAluminide" + }, + { + "item": "advancedrocketry:advrocketmotor", + "data": 8 + } + ], + "time": 2700, + "energy": 900, + "itemresults": + { + "item": "advancedrocketry:advrocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/advengine_repair_9.json b/src/main/resources/assets/advancedrocketry/recipes/advengine_repair_9.json new file mode 100644 index 000000000..97899a05e --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/advengine_repair_9.json @@ -0,0 +1,27 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotTitaniumIridium", + "count": 2 + }, + { + "type": "forge:ore_dict", + "ore": "plateTitaniumAluminide", + "count": 2 + }, + { + "item": "advancedrocketry:advrocketmotor", + "data": 9 + } + ], + "time": 2700, + "energy": 900, + "itemresults": + { + "item": "advancedrocketry:advrocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/engine_repair_1.json b/src/main/resources/assets/advancedrocketry/recipes/engine_repair_1.json new file mode 100644 index 000000000..9e1cd4453 --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/engine_repair_1.json @@ -0,0 +1,21 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotSteel" + }, + { + "item": "advancedrocketry:rocketmotor", + "data": 1 + } + ], + "time": 900, + "energy": 100, + "itemresults": + { + "item": "advancedrocketry:rocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/engine_repair_2.json b/src/main/resources/assets/advancedrocketry/recipes/engine_repair_2.json new file mode 100644 index 000000000..371c00ecd --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/engine_repair_2.json @@ -0,0 +1,21 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotSteel" + }, + { + "item": "advancedrocketry:rocketmotor", + "data": 2 + } + ], + "time": 900, + "energy": 200, + "itemresults": + { + "item": "advancedrocketry:rocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/engine_repair_3.json b/src/main/resources/assets/advancedrocketry/recipes/engine_repair_3.json new file mode 100644 index 000000000..fd9dfa1f4 --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/engine_repair_3.json @@ -0,0 +1,21 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotSteel" + }, + { + "item": "advancedrocketry:rocketmotor", + "data": 3 + } + ], + "time": 900, + "energy": 300, + "itemresults": + { + "item": "advancedrocketry:rocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/engine_repair_4.json b/src/main/resources/assets/advancedrocketry/recipes/engine_repair_4.json new file mode 100644 index 000000000..94b45834a --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/engine_repair_4.json @@ -0,0 +1,25 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotSteel" + }, + { + "type": "forge:ore_dict", + "ore": "plateTitanium" + }, + { + "item": "advancedrocketry:rocketmotor", + "data": 4 + } + ], + "time": 1800, + "energy": 400, + "itemresults": + { + "item": "advancedrocketry:rocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/engine_repair_5.json b/src/main/resources/assets/advancedrocketry/recipes/engine_repair_5.json new file mode 100644 index 000000000..31457d18a --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/engine_repair_5.json @@ -0,0 +1,25 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotSteel" + }, + { + "type": "forge:ore_dict", + "ore": "plateTitanium" + }, + { + "item": "advancedrocketry:rocketmotor", + "data": 5 + } + ], + "time": 1800, + "energy": 500, + "itemresults": + { + "item": "advancedrocketry:rocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/engine_repair_6.json b/src/main/resources/assets/advancedrocketry/recipes/engine_repair_6.json new file mode 100644 index 000000000..0b4450bc3 --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/engine_repair_6.json @@ -0,0 +1,25 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotSteel" + }, + { + "type": "forge:ore_dict", + "ore": "plateTitanium" + }, + { + "item": "advancedrocketry:rocketmotor", + "data": 6 + } + ], + "time": 1800, + "energy": 600, + "itemresults": + { + "item": "advancedrocketry:rocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/engine_repair_7.json b/src/main/resources/assets/advancedrocketry/recipes/engine_repair_7.json new file mode 100644 index 000000000..08cea1ca8 --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/engine_repair_7.json @@ -0,0 +1,26 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotSteel", + "count": 2 + }, + { + "type": "forge:ore_dict", + "ore": "plateTitanium" + }, + { + "item": "advancedrocketry:rocketmotor", + "data": 7 + } + ], + "time": 2700, + "energy": 700, + "itemresults": + { + "item": "advancedrocketry:rocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/engine_repair_8.json b/src/main/resources/assets/advancedrocketry/recipes/engine_repair_8.json new file mode 100644 index 000000000..3e0bd273d --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/engine_repair_8.json @@ -0,0 +1,26 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotSteel", + "count": 2 + }, + { + "type": "forge:ore_dict", + "ore": "plateTitanium" + }, + { + "item": "advancedrocketry:rocketmotor", + "data": 7 + } + ], + "time": 2700, + "energy": 800, + "itemresults": + { + "item": "advancedrocketry:rocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/engine_repair_9.json b/src/main/resources/assets/advancedrocketry/recipes/engine_repair_9.json new file mode 100644 index 000000000..f56951a72 --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/engine_repair_9.json @@ -0,0 +1,27 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotSteel", + "count": 2 + }, + { + "type": "forge:ore_dict", + "ore": "plateTitanium", + "count": 2 + }, + { + "item": "advancedrocketry:rocketmotor", + "data": 7 + } + ], + "time": 2700, + "energy": 900, + "itemresults": + { + "item": "advancedrocketry:rocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/nuclearengine.json b/src/main/resources/assets/advancedrocketry/recipes/nuclearengine.json index b29197cbd..6f27d0805 100644 --- a/src/main/resources/assets/advancedrocketry/recipes/nuclearengine.json +++ b/src/main/resources/assets/advancedrocketry/recipes/nuclearengine.json @@ -20,7 +20,8 @@ }, "d": { "type": "forge:ore_dict", - "ore": "gemDilithium"} + "ore": "gemDilithium" + } }, "result": { diff --git a/src/main/resources/assets/advancedrocketry/recipes/nuclearengine_repair_1.json b/src/main/resources/assets/advancedrocketry/recipes/nuclearengine_repair_1.json new file mode 100644 index 000000000..76b582ff6 --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/nuclearengine_repair_1.json @@ -0,0 +1,21 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotTitaniumIridium" + }, + { + "item": "advancedrocketry:nuclearrocketmotor", + "data": 1 + } + ], + "time": 2000, + "energy": 100, + "itemresults": + { + "item": "advancedrocketry:nuclearrocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/nuclearengine_repair_2.json b/src/main/resources/assets/advancedrocketry/recipes/nuclearengine_repair_2.json new file mode 100644 index 000000000..394decbae --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/nuclearengine_repair_2.json @@ -0,0 +1,21 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotTitaniumIridium" + }, + { + "item": "advancedrocketry:nuclearrocketmotor", + "data": 2 + } + ], + "time": 2000, + "energy": 200, + "itemresults": + { + "item": "advancedrocketry:nuclearrocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/nuclearengine_repair_3.json b/src/main/resources/assets/advancedrocketry/recipes/nuclearengine_repair_3.json new file mode 100644 index 000000000..85506af06 --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/nuclearengine_repair_3.json @@ -0,0 +1,22 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotTitaniumIridium", + "count": 2 + }, + { + "item": "advancedrocketry:nuclearrocketmotor", + "data": 3 + } + ], + "time": 2000, + "energy": 300, + "itemresults": + { + "item": "advancedrocketry:nuclearrocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/nuclearengine_repair_4.json b/src/main/resources/assets/advancedrocketry/recipes/nuclearengine_repair_4.json new file mode 100644 index 000000000..d85324b67 --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/nuclearengine_repair_4.json @@ -0,0 +1,26 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotTitaniumIridium", + "count": 2 + }, + { + "type": "forge:ore_dict", + "ore": "plateTitaniumAluminide" + }, + { + "item": "advancedrocketry:nuclearrocketmotor", + "data": 4 + } + ], + "time": 3000, + "energy": 400, + "itemresults": + { + "item": "advancedrocketry:nuclearrocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/nuclearengine_repair_5.json b/src/main/resources/assets/advancedrocketry/recipes/nuclearengine_repair_5.json new file mode 100644 index 000000000..d2514eee3 --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/nuclearengine_repair_5.json @@ -0,0 +1,26 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotTitaniumIridium", + "count": 2 + }, + { + "type": "forge:ore_dict", + "ore": "plateTitaniumAluminide" + }, + { + "item": "advancedrocketry:nuclearrocketmotor", + "data": 5 + } + ], + "time": 3000, + "energy": 500, + "itemresults": + { + "item": "advancedrocketry:nuclearrocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/nuclearengine_repair_6.json b/src/main/resources/assets/advancedrocketry/recipes/nuclearengine_repair_6.json new file mode 100644 index 000000000..6a5a18478 --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/nuclearengine_repair_6.json @@ -0,0 +1,27 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotTitaniumIridium", + "count": 2 + }, + { + "type": "forge:ore_dict", + "ore": "plateTitaniumAluminide", + "count": 2 + }, + { + "item": "advancedrocketry:nuclearrocketmotor", + "data": 4 + } + ], + "time": 3000, + "energy": 600, + "itemresults": + { + "item": "advancedrocketry:nuclearrocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/nuclearengine_repair_7.json b/src/main/resources/assets/advancedrocketry/recipes/nuclearengine_repair_7.json new file mode 100644 index 000000000..a4e6d86ea --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/nuclearengine_repair_7.json @@ -0,0 +1,27 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotTitaniumIridium", + "count": 2 + }, + { + "type": "forge:ore_dict", + "ore": "plateTitaniumAluminide", + "count": 2 + }, + { + "item": "advancedrocketry:nuclearrocketmotor", + "data": 7 + } + ], + "time": 4000, + "energy": 700, + "itemresults": + { + "item": "advancedrocketry:nuclearrocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/nuclearengine_repair_8.json b/src/main/resources/assets/advancedrocketry/recipes/nuclearengine_repair_8.json new file mode 100644 index 000000000..3269646ae --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/nuclearengine_repair_8.json @@ -0,0 +1,31 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotTitaniumIridium", + "count": 2 + }, + { + "type": "forge:ore_dict", + "ore": "plateTitaniumAluminide", + "count": 2 + }, + { + "type": "forge:ore_dict", + "ore": "gemDilithium" + }, + { + "item": "advancedrocketry:nuclearrocketmotor", + "data": 8 + } + ], + "time": 4000, + "energy": 800, + "itemresults": + { + "item": "advancedrocketry:nuclearrocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/recipes/nuclearengine_repair_9.json b/src/main/resources/assets/advancedrocketry/recipes/nuclearengine_repair_9.json new file mode 100644 index 000000000..a0b790dfc --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/nuclearengine_repair_9.json @@ -0,0 +1,31 @@ +{ + "type": "advancedrocketry:precisionassembler", + "itemingredients": + [ + { + "type": "forge:ore_dict", + "ore": "ingotTitaniumIridium", + "count": 2 + }, + { + "type": "forge:ore_dict", + "ore": "plateTitaniumAluminide", + "count": 2 + }, + { + "type": "forge:ore_dict", + "ore": "gemDilithium" + }, + { + "item": "advancedrocketry:nuclearrocketmotor", + "data": 9 + } + ], + "time": 4000, + "energy": 900, + "itemresults": + { + "item": "advancedrocketry:nuclearrocketmotor", + "count": 1 + } +} diff --git a/src/main/resources/assets/advancedrocketry/textures/blocks/servicemachine.png b/src/main/resources/assets/advancedrocketry/textures/blocks/servicemachine.png new file mode 100644 index 000000000..cb8dcf802 Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/blocks/servicemachine.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/blocks/servicemachine_active_1.png b/src/main/resources/assets/advancedrocketry/textures/blocks/servicemachine_active_1.png new file mode 100644 index 000000000..a91042c75 Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/blocks/servicemachine_active_1.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/blocks/servicemachine_active_2.png b/src/main/resources/assets/advancedrocketry/textures/blocks/servicemachine_active_2.png new file mode 100644 index 000000000..1a3ceba4c Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/blocks/servicemachine_active_2.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/blocks/servicemachine_active_3.png b/src/main/resources/assets/advancedrocketry/textures/blocks/servicemachine_active_3.png new file mode 100644 index 000000000..e541dde78 Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/blocks/servicemachine_active_3.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/blocks/servicemachine_active_4.png b/src/main/resources/assets/advancedrocketry/textures/blocks/servicemachine_active_4.png new file mode 100644 index 000000000..6c34c7949 Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/blocks/servicemachine_active_4.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/blocks/servicemonitor.png b/src/main/resources/assets/advancedrocketry/textures/blocks/servicemonitor.png new file mode 100644 index 000000000..58a981819 Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/blocks/servicemonitor.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/blocks/servicemonitormonitor.png b/src/main/resources/assets/advancedrocketry/textures/blocks/servicemonitormonitor.png new file mode 100644 index 000000000..58a981819 Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/blocks/servicemonitormonitor.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/gui/rockethud.png b/src/main/resources/assets/advancedrocketry/textures/gui/rockethud.png index 3d8e1ead3..456620d9d 100644 Binary files a/src/main/resources/assets/advancedrocketry/textures/gui/rockethud.png and b/src/main/resources/assets/advancedrocketry/textures/gui/rockethud.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/advbipropellantcombustion.png b/src/main/resources/assets/advancedrocketry/textures/models/advbipropellantcombustion.png deleted file mode 100644 index aa01bbb10..000000000 Binary files a/src/main/resources/assets/advancedrocketry/textures/models/advbipropellantcombustion.png and /dev/null differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/advbipropellantrocket.png b/src/main/resources/assets/advancedrocketry/textures/models/advbipropellantrocket.png new file mode 100644 index 000000000..86a9aefe1 Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/models/advbipropellantrocket.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/advbipropellantrocket_0.png b/src/main/resources/assets/advancedrocketry/textures/models/advbipropellantrocket_0.png new file mode 100644 index 000000000..b6e6db9f1 Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/models/advbipropellantrocket_0.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/advbipropellantrocket_1.png b/src/main/resources/assets/advancedrocketry/textures/models/advbipropellantrocket_1.png new file mode 100644 index 000000000..9c46e2794 Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/models/advbipropellantrocket_1.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/advbipropellantrocket_2.png b/src/main/resources/assets/advancedrocketry/textures/models/advbipropellantrocket_2.png new file mode 100644 index 000000000..f5dbc7f73 Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/models/advbipropellantrocket_2.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/advbipropellantrocket_3.png b/src/main/resources/assets/advancedrocketry/textures/models/advbipropellantrocket_3.png new file mode 100644 index 000000000..2b9480900 Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/models/advbipropellantrocket_3.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/advcombustion.png b/src/main/resources/assets/advancedrocketry/textures/models/advcombustion.png deleted file mode 100644 index 22d995ec5..000000000 Binary files a/src/main/resources/assets/advancedrocketry/textures/models/advcombustion.png and /dev/null differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/advrocket.png b/src/main/resources/assets/advancedrocketry/textures/models/advrocket.png new file mode 100644 index 000000000..479f8327c Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/models/advrocket.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/advrocket_0.png b/src/main/resources/assets/advancedrocketry/textures/models/advrocket_0.png new file mode 100644 index 000000000..2fbbbed0b Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/models/advrocket_0.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/advrocket_1.png b/src/main/resources/assets/advancedrocketry/textures/models/advrocket_1.png new file mode 100644 index 000000000..f54c5c75e Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/models/advrocket_1.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/advrocket_2.png b/src/main/resources/assets/advancedrocketry/textures/models/advrocket_2.png new file mode 100644 index 000000000..c45946c85 Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/models/advrocket_2.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/advrocket_3.png b/src/main/resources/assets/advancedrocketry/textures/models/advrocket_3.png new file mode 100644 index 000000000..34e237e11 Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/models/advrocket_3.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/bipropellantcombustion.png b/src/main/resources/assets/advancedrocketry/textures/models/bipropellantcombustion.png deleted file mode 100644 index aa01bbb10..000000000 Binary files a/src/main/resources/assets/advancedrocketry/textures/models/bipropellantcombustion.png and /dev/null differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/bipropellantrocket.png b/src/main/resources/assets/advancedrocketry/textures/models/bipropellantrocket.png new file mode 100644 index 000000000..86a9aefe1 Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/models/bipropellantrocket.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/bipropellantrocket_0.png b/src/main/resources/assets/advancedrocketry/textures/models/bipropellantrocket_0.png new file mode 100644 index 000000000..97ecac206 Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/models/bipropellantrocket_0.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/bipropellantrocket_1.png b/src/main/resources/assets/advancedrocketry/textures/models/bipropellantrocket_1.png new file mode 100644 index 000000000..58cf48378 Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/models/bipropellantrocket_1.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/bipropellantrocket_2.png b/src/main/resources/assets/advancedrocketry/textures/models/bipropellantrocket_2.png new file mode 100644 index 000000000..ec7a5225b Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/models/bipropellantrocket_2.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/bipropellantrocket_3.png b/src/main/resources/assets/advancedrocketry/textures/models/bipropellantrocket_3.png new file mode 100644 index 000000000..0718d1baf Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/models/bipropellantrocket_3.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/combustion.png b/src/main/resources/assets/advancedrocketry/textures/models/combustion.png deleted file mode 100644 index 22d995ec5..000000000 Binary files a/src/main/resources/assets/advancedrocketry/textures/models/combustion.png and /dev/null differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/nuclearengine.png b/src/main/resources/assets/advancedrocketry/textures/models/nuclearengine.png deleted file mode 100644 index e9db55903..000000000 Binary files a/src/main/resources/assets/advancedrocketry/textures/models/nuclearengine.png and /dev/null differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/nuclearrocket.png b/src/main/resources/assets/advancedrocketry/textures/models/nuclearrocket.png new file mode 100644 index 000000000..ad17768a9 Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/models/nuclearrocket.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/nuclearrocket_0.png b/src/main/resources/assets/advancedrocketry/textures/models/nuclearrocket_0.png new file mode 100644 index 000000000..6619d808f Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/models/nuclearrocket_0.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/nuclearrocket_1.png b/src/main/resources/assets/advancedrocketry/textures/models/nuclearrocket_1.png new file mode 100644 index 000000000..60d1874b0 Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/models/nuclearrocket_1.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/nuclearrocket_2.png b/src/main/resources/assets/advancedrocketry/textures/models/nuclearrocket_2.png new file mode 100644 index 000000000..8b60cb8eb Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/models/nuclearrocket_2.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/nuclearrocket_3.png b/src/main/resources/assets/advancedrocketry/textures/models/nuclearrocket_3.png new file mode 100644 index 000000000..a374ac44d Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/models/nuclearrocket_3.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/rocket.png b/src/main/resources/assets/advancedrocketry/textures/models/rocket.png new file mode 100644 index 000000000..dbae1fbc0 Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/models/rocket.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/rocket_0.png b/src/main/resources/assets/advancedrocketry/textures/models/rocket_0.png new file mode 100644 index 000000000..021874e43 Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/models/rocket_0.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/rocket_1.png b/src/main/resources/assets/advancedrocketry/textures/models/rocket_1.png new file mode 100644 index 000000000..018d13e03 Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/models/rocket_1.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/rocket_2.png b/src/main/resources/assets/advancedrocketry/textures/models/rocket_2.png new file mode 100644 index 000000000..951302374 Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/models/rocket_2.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/rocket_3.png b/src/main/resources/assets/advancedrocketry/textures/models/rocket_3.png new file mode 100644 index 000000000..de572cc32 Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/models/rocket_3.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/tank_0.png b/src/main/resources/assets/advancedrocketry/textures/models/tank_0.png new file mode 100644 index 000000000..4e715f296 Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/models/tank_0.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/tank_1.png b/src/main/resources/assets/advancedrocketry/textures/models/tank_1.png new file mode 100644 index 000000000..fd781cb93 Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/models/tank_1.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/tank_2.png b/src/main/resources/assets/advancedrocketry/textures/models/tank_2.png new file mode 100644 index 000000000..66e7bdb70 Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/models/tank_2.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/models/tank_3.png b/src/main/resources/assets/advancedrocketry/textures/models/tank_3.png new file mode 100644 index 000000000..d1a2152fe Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/models/tank_3.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/particle/soft1.png b/src/main/resources/assets/advancedrocketry/textures/particle/soft1.png new file mode 100644 index 000000000..162e02a8d Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/particle/soft1.png differ diff --git a/src/main/resources/assets/advancedrocketry/textures/particle/soft2.png b/src/main/resources/assets/advancedrocketry/textures/particle/soft2.png new file mode 100644 index 000000000..4341a90d4 Binary files /dev/null and b/src/main/resources/assets/advancedrocketry/textures/particle/soft2.png differ diff --git a/src/main/resources/methods.bin b/src/main/resources/methods.bin new file mode 100644 index 000000000..33c2f4c09 Binary files /dev/null and b/src/main/resources/methods.bin differ