diff --git a/build.gradle.kts b/build.gradle.kts index 5991c71..a1203d0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -26,7 +26,8 @@ version = metadata.version description = metadata.description toxopid { - compileVersion.set("v" + metadata.minGameVersion) + compileVersion.set("v140.4") + runtimeVersion.set("v140.4") platforms.set(setOf(ModPlatform.HEADLESS)) } diff --git a/src/main/java/fr/xpdustry/patches/FixedPayloadConveyor.java b/src/main/java/fr/xpdustry/patches/FixedPayloadConveyor.java new file mode 100644 index 0000000..2f1d9fe --- /dev/null +++ b/src/main/java/fr/xpdustry/patches/FixedPayloadConveyor.java @@ -0,0 +1,95 @@ +/* + * This file is part of NoPayloadConveyorCrashPlugin. No more payload conveyor crashes. + * + * MIT License + * + * Copyright (c) 2023 Xpdustry + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * 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. + */ +package fr.xpdustry.patches; + +import mindustry.world.blocks.payloads.PayloadBlock; +import mindustry.world.blocks.payloads.PayloadConveyor; + +public class FixedPayloadConveyor extends PayloadConveyor { + + public FixedPayloadConveyor(String name) { + super(name); + } + + public class FixedPayloadBuild extends PayloadConveyor.PayloadConveyorBuild { + + @Override + public void updateTile() { + if (!enabled) { + return; + } + + if (item != null) { + item.update(null, this); + } + + lastInterp = curInterp; + curInterp = fract(); + // rollover skip + if (lastInterp > curInterp) { + lastInterp = 0f; + } + progress = time() % moveTime; + + updatePayload(); + if (item != null && next == null) { + PayloadBlock.pushOutput(item, progress / moveTime); + } + + int curStep = curStep(); + if (curStep > step) { + boolean valid = step != -1; + step = curStep; + boolean had = item != null; + + if (valid && stepAccepted != curStep && item != null) { + if (next != null) { + // trigger update forward + next.updateTile(); + + // PATCH HERE + if (next != null && next.acceptPayload(this, item)) { + // move forward. + next.handlePayload(this, item); + item = null; + moved(); + } + } else if (!blocked) { + // dump item forward + if (item.dump()) { + item = null; + moved(); + } + } + } + + if (had && item != null) { + moveFailed(); + } + } + } + } +} diff --git a/src/main/java/fr/xpdustry/patches/FixedPayloadRouter.java b/src/main/java/fr/xpdustry/patches/FixedPayloadRouter.java new file mode 100644 index 0000000..c9b8a73 --- /dev/null +++ b/src/main/java/fr/xpdustry/patches/FixedPayloadRouter.java @@ -0,0 +1,99 @@ +/* + * This file is part of NoPayloadConveyorCrashPlugin. No more payload conveyor crashes. + * + * MIT License + * + * Copyright (c) 2023 Xpdustry + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * 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. + */ +package fr.xpdustry.patches; + +import arc.math.Mathf; +import arc.util.Time; +import mindustry.world.blocks.payloads.PayloadBlock; +import mindustry.world.blocks.payloads.PayloadRouter; + +public class FixedPayloadRouter extends PayloadRouter { + public FixedPayloadRouter(String name) { + super(name); + } + + public class FixedPayloadRouterBuild extends PayloadRouter.PayloadRouterBuild { + + @Override + public void updateTile() { + if (!enabled) { + return; + } + + if (item != null) { + item.update(null, this); + } + + lastInterp = curInterp; + curInterp = fract(); + // rollover skip + if (lastInterp > curInterp) { + lastInterp = 0f; + } + progress = time() % moveTime; + + updatePayload(); + if (item != null && next == null) { + PayloadBlock.pushOutput(item, progress / moveTime); + } + + int curStep = curStep(); + if (curStep > step) { + boolean valid = step != -1; + step = curStep; + boolean had = item != null; + + if (valid && stepAccepted != curStep && item != null) { + if (next != null) { + // trigger update forward + next.updateTile(); + + // PATCH HERE + if (next != null && next.acceptPayload(this, item)) { + // move forward. + next.handlePayload(this, item); + item = null; + moved(); + } + } else if (!blocked) { + // dump item forward + if (item.dump()) { + item = null; + moved(); + } + } + } + + if (had && item != null) { + moveFailed(); + } + } + + controlTime -= Time.delta; + smoothRot = Mathf.slerpDelta(smoothRot, rotdeg(), 0.2f); + } + } +} diff --git a/src/main/java/fr/xpdustry/patches/NoPayloadConveyorCrashPlugin.java b/src/main/java/fr/xpdustry/patches/NoPayloadConveyorCrashPlugin.java index 3f38d02..63764d1 100644 --- a/src/main/java/fr/xpdustry/patches/NoPayloadConveyorCrashPlugin.java +++ b/src/main/java/fr/xpdustry/patches/NoPayloadConveyorCrashPlugin.java @@ -25,30 +25,95 @@ */ package fr.xpdustry.patches; -import arc.util.CommandHandler; -import arc.util.Log; +import arc.struct.ObjectMap; +import arc.util.Strings; +import java.util.function.Consumer; +import java.util.function.Function; +import mindustry.Vars; +import mindustry.content.Blocks; +import mindustry.content.Items; +import mindustry.ctype.MappableContent; import mindustry.mod.Plugin; -import org.checkerframework.checker.nullness.qual.NonNull; +import mindustry.type.Category; +import mindustry.type.ItemStack; +import mindustry.world.Block; public final class NoPayloadConveyorCrashPlugin extends Plugin { - /** - * This method is called when game initializes. - */ - @Override - public void init() { - Log.info("Bonjour !"); + private final ObjectMap[] contentNameMap; + + @SuppressWarnings("unchecked") + public NoPayloadConveyorCrashPlugin() { + try { + final var field = Vars.content.getClass().getDeclaredField("contentNameMap"); + field.setAccessible(true); + this.contentNameMap = (ObjectMap[]) field.get(Vars.content); + } catch (final ReflectiveOperationException e) { + throw new RuntimeException(e); + } } - /** - * This method is called when the game register the server-side commands. - */ @Override - public void registerServerCommands(final @NonNull CommandHandler handler) {} + public void init() { + this.replaceBlock("payload-conveyor", FixedPayloadConveyor::new, block -> { + block.requirements(Category.units, ItemStack.with(Items.graphite, 10, Items.copper, 10)); + block.canOverdrive = false; + }); - /** - * This method is called when the game register the client-side commands. - */ - @Override - public void registerClientCommands(final @NonNull CommandHandler handler) {} + this.replaceBlock("payload-router", FixedPayloadRouter::new, block -> { + block.requirements(Category.units, ItemStack.with(Items.graphite, 15, Items.copper, 10)); + block.canOverdrive = false; + }); + + this.replaceBlock("reinforced-payload-conveyor", FixedPayloadConveyor::new, block -> { + block.requirements(Category.units, ItemStack.with(Items.tungsten, 10)); + block.moveTime = 35f; + block.canOverdrive = false; + block.health = 800; + block.researchCostMultiplier = 4f; + block.underBullets = true; + }); + + this.replaceBlock("reinforced-payload-router", FixedPayloadRouter::new, block -> { + block.requirements(Category.units, ItemStack.with(Items.tungsten, 15)); + block.moveTime = 35f; + block.health = 800; + block.canOverdrive = false; + block.researchCostMultiplier = 4f; + block.underBullets = true; + }); + } + + private void replaceBlock( + final String name, Function constructor, final Consumer modifiers) { + try { + // Get the corresponding field + final var field = Blocks.class.getField(Strings.kebabToCamel(name)); + final var block = (Block) field.get(null); + // Get the index of the block to replace + final var index = Vars.content.blocks().indexOf(block); + // Get the id of the block to replace + final var id = block.id; + // Remove the old block + this.contentNameMap[block.getContentType().ordinal()].remove(block.name); + Vars.content.blocks().remove(block); + // Creates the replacement, it will register itself in the contentNameMap + final var replacement = constructor.apply(name); + // Apply the modifiers of the replaced block + modifiers.accept(replacement); + replacement.id = id; + // Substitute the old block with the new one in the tech tree + replacement.techNode = block.techNode; + replacement.techNode.content = replacement; + // Since the block adds itself to the content list, remove to insert it to the right index + Vars.content.blocks().remove(replacement); + Vars.content.blocks().insert(index, replacement); + // Initialize the block + replacement.init(); + // Set the field to the new block + field.set(null, replacement); + } catch (final ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } }