From 3ad4195dd6865fb0994c37f9d95555aed35373e9 Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Fri, 12 May 2023 13:41:28 +0200 Subject: [PATCH] Squashed commit of the following: commit a162e18c9c4d91c4020e86cf718d59d3a33b2817 Merge: 374848f97 beb61708a Author: simibubi <31564874+simibubi@users.noreply.github.com> Date: Fri May 12 13:40:58 2023 +0200 Merge branch 'mc1.18/dev' into mc1.18/computercraft commit 374848f978cf0cc1d91ff0b98a8bd506f1b81130 Author: simibubi <31564874+simibubi@users.noreply.github.com> Date: Fri May 12 13:22:29 2023 +0200 Compilation dependency toggle commit b2cd60b6195bcbdacaa47c8b8a05929cb160fe5b Merge: 8e1e4e8bd ee3a079ba Author: simibubi <31564874+simibubi@users.noreply.github.com> Date: Wed May 10 14:37:32 2023 +0200 Merge pull request #4650 from ChristianLW/mc1.18/computercraft Small tweaks to the wiki pages for ComputerCraft integration commit ee3a079bacbee6fccdf14a356846e12d67edece6 Author: Christian L.W Date: Thu Apr 13 00:55:20 2023 +0200 Small tweaks to the wiki pages commit 8e1e4e8bd3beb310e4e114e7d36134caf1c7eb79 Author: caelwarner Date: Mon Mar 13 18:31:56 2023 -0700 Added computer to display source ponder tag - Added advanced computer to display source ponder tag - Added missing lang entry for computer display source commit 952941e5fc86036bf2c3555ead662cdb9ea9a29d Author: caelwarner Date: Mon Mar 13 16:31:16 2023 -0700 Added documentation for train station peripherals and train schedules - Added in depth documentation for working with train stations and train schedules in Lua - Fixed small formatting issues in Lua-Rotation-Speed-Controller.md and Lua-Sequenced-Gearshift.md commit 7f3ca1cfa06b227211a41503c4ae31c3cf854ba5 Author: caelwarner Date: Mon Mar 13 16:29:05 2023 -0700 Added isTrainEnroute to station peripheral API - isTrainEnroute checks if a train is currently navigating to the station - Reworded null station exception to "station is not connected to a track" - Refactored StationPeripheral#inAssemblyMode to StationPeripheral#isInAssemblyMode - Added a check to StationPeripheral#disassemble to make sure the station isn't in assembly mode commit fac1ebcd3f1d1d570735fa6b2d57641b20c4ad8d Author: caelwarner Date: Sat Mar 11 16:12:58 2023 -0800 Added documentation for most peripherals - Lua documentation has been added for all peripherals except the train station (not looking forward to writing that one) - This documentation will be added to the GitHub wiki pages commit 3e21996984febc8b256ac8abbb11df9dbe150630 Author: caelwarner Date: Sat Mar 11 15:54:36 2023 -0800 Updated DisplayLinkPeripheral#write to move cursor to the end of the text - This change was made to be more inline with ComputerCraft's builtin display API commit 7141c10025c948ce5a78f1d484964f4324ffb463 Author: caelwarner Date: Sat Mar 11 11:45:43 2023 -0800 Added isTrainImminent and hasSchedule to train station API - Added isTrainImminent to check if a train is incoming to the station and hasSchedule to check if the currently present train has a schedule - Added StationPeripheral#getTrainOrThrow to consolidate repetitive null checks commit 909484ed5b80ac1c397e04a1ad41acab6cc8e13a Author: caelwarner Date: Sat Mar 11 11:15:58 2023 -0800 Added getSchedule to train station lua API - Added getSchedule which serializes the currently present train's schedule into a lua table - Refactored StationPeripheral#setSchedule to use a more generic method of serializing NBT tags to lua tables - Moved schedule entry special data from root tag to "Data" - Added StringHelper#camelCaseToSnakeCase - Added variety of put methods to CreateLuaTable commit 31ad3aa671339e7642f1c89118a218ff7c7eec15 Author: caelwarner Date: Wed Mar 8 18:22:23 2023 -0800 Extended train station peripheral API - Train station peripherals can now assemble and disassemble trains, check if the station is in assembly mode, set the assembly mode of the station, get and change the station name, check if a train is present at the station and get and change the currently present train name. - Refactored StationEditPacket. Moved most of the logic that was previously in StationEditPacket to StationTileEntity. This allows us to call this logic without having to send a packet. - Made Train#owner nullable. This is needed so that computers can assemble trains. All Train#owner is currently used for is to display the train status to the correct play. commit 574cd93a89d49d8ac50b865b9b7f83955fa16ffc Author: caelwarner Date: Wed Nov 30 00:37:47 2022 -0800 Serialize hasAttachedComputer in ComputerBehaviour - This eliminates some edge cases were peripherals don't realize they're being controlled by a computer on a world save and load commit 94e3ed44ad1deaa383c8da61928f67697dc13273 Author: caelwarner Date: Wed Oct 26 16:57:12 2022 -0700 Added ComputerScreen - ComputerScreen shows that tile entity currently has computers attached and therefore cannot be controlled manually commit 9afdcaded7006c1c2671cd3070185d500c3a3dca Author: caelwarner Date: Thu Oct 20 10:18:37 2022 -0700 Refactored PeripheralBase to SyncedPeripheral commit 7d47fdcd061ca8efaab5688ac2724fec3e0bf1b7 Author: caelwarner Date: Wed Oct 19 22:45:47 2022 -0700 Made LuaFunction's final commit 56a1210fff386fd538733a0a0998dd1bc0bd060f Author: caelwarner Date: Wed Oct 19 22:39:38 2022 -0700 Created ComputerBehaviour behaviour - ComputerBehaviour replaces ComputerControllable and SyncedComputerControllable commit 19d283b92376da793e7c88c443adbb3cd70b2c43 Author: caelwarner Date: Wed Oct 19 16:05:48 2022 -0700 Moved all peripheral classes to computercraft.peripherals package commit ab18034b985fe9cecf4de5add48557371789d756 Author: caelwarner Date: Wed Oct 19 15:58:56 2022 -0700 Added Train Station as peripheral - Train station can set a new auto-schedule for the train currently at the station - Added CreateLuaTable to add helper functions for working with lua tables - Added StringHelper util class to convert snake case to camel case commit 1091f3227c806f09fb443320900f7563ed264655 Author: caelwarner Date: Thu Oct 6 21:11:24 2022 -0700 Changed Display Link Peripheral API - Changed the Display Link Peripheral API to be more in line with the Monitor API - Added write, setCursorPos, getCursorPos, getSize, isColor, isColour, clearLine - Removed void writeLine, setLine, writeLines, setLines commit 18bfb216b1bd5c1b6fab99370318536ccf27b069 Author: caelwarner Date: Thu Oct 6 02:50:41 2022 -0700 Changed method of checking if a computer attached - After talking with SquidDev from CC: Tweaked I've changed to monitoring IPeripheral#attach and IPeripheral#detach for changes in the number of computers connected to the network, then updating the client using AttachedComputerPacket - This works with wired full modems, wired cabled modems and directly connected computers - Added SyncedPeripheralBase and SyncedComputerControllable for TE's and peripherals that want to be aware of attached computers commit 96dc4db6dc6cbf6519725109dbaa69851dcb0dbb Author: caelwarner Date: Tue Oct 4 21:11:38 2022 -0700 Sequenced Gearshift screen "greys out" when being controlled by a computer - This is to stop players from trying to using both the builtin sequencing and a computer to control the Sequenced Gearshift at the same time, leading to undefined behaviour - The "greyed out" screen should have a message added explaining why it's greyed out. - Added ComputerControllable#isComputerControlled to check if a tile entity is connected to a modem commit 9a807814013e54f59230d7f57f4c212164311e64 Author: caelwarner Date: Tue Oct 4 19:36:08 2022 -0700 Added PeripheralBase commit d404f073196f43eff9c0c66485693b5aed68051a Author: caelwarner Date: Mon Oct 3 20:46:16 2022 -0700 Added invalidateCaps - Changed setRemoved to invalidateCaps. I don't know why I wasn't just using invalidateCaps from the beginning commit 654476d9f33b78eb05d620ed8dd318cc9244b670 Author: caelwarner Date: Mon Oct 3 20:05:25 2022 -0700 Added Rotation Speed Controller and Sequenced Gearshift as peripherals - Rotation Speed Controller can get and set targetSpeed - Sequenced Gearshift can rotate by a certain angle and move a certain distance commit 1420406ab72204a8e34043c64404a16990104d23 Author: caelwarner Date: Mon Oct 3 16:38:12 2022 -0700 Added Speedometer and Stressometer as peripherals - Speedometer can get current speed - Stressometer can get current stress level as well as network stress capacity - Made GaugeTileEntity abstract commit 47b8619d07c9f58e6c3a34a9db97aea53071b9bd Author: caelwarner Date: Mon Oct 3 16:17:05 2022 -0700 Refactored peripheralHandler to peripheral - peripheralHandler was the wrong name. It's just a peripheral. - Changed peripheral type from "cdl" to "Create_DisplayLink" - Added equals function to DisplayLinkPeripheral commit 6591c2d46efc74d91f9a0c3d3c2aa1679fe68790 Author: caelwarner Date: Mon Oct 3 14:29:04 2022 -0700 ComputerCraft integration for Display Links - CC computers can now control display links through a variety of functions - Added ComputerControllable interface to define a tile entity as controllable by CC computers - Added CC: Tweaked soft dependency --- build.gradle | 19 ++ gradle.properties | 4 + src/main/java/com/simibubi/create/Create.java | 2 + .../java/com/simibubi/create/compat/Mods.java | 9 + .../AbstractComputerBehaviour.java | 57 ++++ .../computercraft/AttachedComputerPacket.java | 37 +++ .../computercraft/ComputerCraftProxy.java | 30 ++ .../compat/computercraft/ComputerScreen.java | 96 +++++++ .../FallbackComputerBehaviour.java | 16 ++ .../implementation/ComputerBehaviour.java | 74 +++++ .../implementation/CreateLuaTable.java | 172 +++++++++++ .../peripherals/DisplayLinkPeripheral.java | 108 +++++++ .../SequencedGearshiftPeripheral.java | 54 ++++ .../SpeedControllerPeripheral.java | 35 +++ .../peripherals/SpeedGaugePeripheral.java | 26 ++ .../peripherals/StationPeripheral.java | 269 ++++++++++++++++++ .../peripherals/StressGaugePeripheral.java | 31 ++ .../peripherals/SyncedPeripheral.java | 50 ++++ .../advanced/SpeedControllerTileEntity.java | 29 +- .../ConfigureSequencedGearshiftPacket.java | 3 + .../advanced/sequencer/Instruction.java | 6 +- .../sequencer/InstructionSpeedModifiers.java | 8 + .../sequencer/SequencedGearshiftScreen.java | 33 ++- .../SequencedGearshiftTileEntity.java | 39 ++- .../relays/gauge/GaugeTileEntity.java | 3 +- .../relays/gauge/SpeedGaugeTileEntity.java | 32 +++ .../relays/gauge/StressGaugeTileEntity.java | 25 ++ .../block/display/AllDisplayBehaviours.java | 11 + .../block/display/DisplayLinkTileEntity.java | 47 ++- .../display/source/ComputerDisplaySource.java | 33 +++ .../block/display/source/DisplaySource.java | 4 + .../logistics/trains/entity/Train.java | 19 +- .../logistics/trains/entity/TrainPacket.java | 10 +- .../station/AbstractStationScreen.java | 20 +- .../edgePoint/station/StationEditPacket.java | 100 +------ .../edgePoint/station/StationScreen.java | 2 + .../edgePoint/station/StationTileEntity.java | 122 +++++++- .../management/schedule/IScheduleInput.java | 6 +- .../schedule/ScheduleDataEntry.java | 22 +- .../condition/FluidThresholdCondition.java | 5 +- .../condition/ItemThresholdCondition.java | 5 +- .../condition/RedstoneLinkCondition.java | 5 +- .../condition/ScheduleWaitCondition.java | 16 +- .../destination/ScheduleInstruction.java | 12 +- .../create/foundation/gui/AllGuiTextures.java | 7 +- .../foundation/networking/AllPackets.java | 3 +- .../ponder/content/PonderIndex.java | 10 + .../foundation/utility/StringHelper.java | 46 +++ .../assets/create/textures/gui/computer.png | Bin 0 -> 1016 bytes wiki/Lua-Display-Link.md | 88 ++++++ wiki/Lua-Rotation-Speed-Controller.md | 18 ++ wiki/Lua-Sequenced-Gearshift.md | 28 ++ wiki/Lua-Speedometer.md | 10 + wiki/Lua-Stressometer.md | 18 ++ wiki/Lua-Train-Schedule.md | 195 +++++++++++++ wiki/Lua-Train-Station.md | 179 ++++++++++++ wiki/README.md | 2 + 57 files changed, 2152 insertions(+), 158 deletions(-) create mode 100644 src/main/java/com/simibubi/create/compat/computercraft/AbstractComputerBehaviour.java create mode 100644 src/main/java/com/simibubi/create/compat/computercraft/AttachedComputerPacket.java create mode 100644 src/main/java/com/simibubi/create/compat/computercraft/ComputerCraftProxy.java create mode 100644 src/main/java/com/simibubi/create/compat/computercraft/ComputerScreen.java create mode 100644 src/main/java/com/simibubi/create/compat/computercraft/FallbackComputerBehaviour.java create mode 100644 src/main/java/com/simibubi/create/compat/computercraft/implementation/ComputerBehaviour.java create mode 100644 src/main/java/com/simibubi/create/compat/computercraft/implementation/CreateLuaTable.java create mode 100644 src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/DisplayLinkPeripheral.java create mode 100644 src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/SequencedGearshiftPeripheral.java create mode 100644 src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/SpeedControllerPeripheral.java create mode 100644 src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/SpeedGaugePeripheral.java create mode 100644 src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/StationPeripheral.java create mode 100644 src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/StressGaugePeripheral.java create mode 100644 src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/SyncedPeripheral.java create mode 100644 src/main/java/com/simibubi/create/content/logistics/block/display/source/ComputerDisplaySource.java create mode 100644 src/main/java/com/simibubi/create/foundation/utility/StringHelper.java create mode 100644 src/main/resources/assets/create/textures/gui/computer.png create mode 100644 wiki/Lua-Display-Link.md create mode 100644 wiki/Lua-Rotation-Speed-Controller.md create mode 100644 wiki/Lua-Sequenced-Gearshift.md create mode 100644 wiki/Lua-Speedometer.md create mode 100644 wiki/Lua-Stressometer.md create mode 100644 wiki/Lua-Train-Schedule.md create mode 100644 wiki/Lua-Train-Station.md create mode 100644 wiki/README.md diff --git a/build.gradle b/build.gradle index 05c9bdb9a..1ec83e22f 100644 --- a/build.gradle +++ b/build.gradle @@ -147,6 +147,14 @@ repositories { includeGroup "maven.modrinth" } } + maven { + // Location of maven for CC: Tweaked + name = "squiddev" + url = "https://squiddev.cc/maven/" + content { + includeGroup "org.squiddev" + } + } } dependencies { @@ -174,6 +182,11 @@ dependencies { compileOnly fg.deobf("top.theillusivec4.curios:curios-forge:${curios_minecraft_version}-${curios_version}:api") runtimeOnly fg.deobf("top.theillusivec4.curios:curios-forge:${curios_minecraft_version}-${curios_version}") + if (cc_tweaked_enable.toBoolean()) { + compileOnly fg.deobf("org.squiddev:cc-tweaked-${cc_tweaked_minecraft_version}:${cc_tweaked_version}:api") + runtimeOnly fg.deobf("org.squiddev:cc-tweaked-${cc_tweaked_minecraft_version}:${cc_tweaked_version}") + } + // implementation fg.deobf("curse.maven:druidcraft-340991:3101903") // implementation fg.deobf("com.ferreusveritas.dynamictrees:DynamicTrees-1.16.5:0.10.0-Beta25") // runtimeOnly fg.deobf("vazkii.arl:AutoRegLib:1.4-35.69") @@ -190,6 +203,12 @@ dependencies { } } +sourceSets.main.java { + if (!cc_tweaked_enable.toBoolean()) { + exclude 'com/simibubi/create/compat/computercraft/implementation/**' + } +} + sourceSets.main.resources { srcDir 'src/generated/resources' exclude '.cache/' diff --git a/gradle.properties b/gradle.properties index da1c49bc1..1615ed75c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -27,6 +27,10 @@ jei_version = 9.7.0.209 curios_minecraft_version = 1.18.2 curios_version = 5.0.7.0 +cc_tweaked_enable = true +cc_tweaked_minecraft_version = 1.18.2 +cc_tweaked_version = 1.100.10 + # curseforge information projectId = 328085 curse_type = beta diff --git a/src/main/java/com/simibubi/create/Create.java b/src/main/java/com/simibubi/create/Create.java index 420c74a30..67acdc81b 100644 --- a/src/main/java/com/simibubi/create/Create.java +++ b/src/main/java/com/simibubi/create/Create.java @@ -9,6 +9,7 @@ import com.google.gson.GsonBuilder; import com.mojang.logging.LogUtils; import com.simibubi.create.api.behaviour.BlockSpoutingBehaviour; import com.simibubi.create.compat.Mods; +import com.simibubi.create.compat.computercraft.ComputerCraftProxy; import com.simibubi.create.compat.curios.Curios; import com.simibubi.create.content.CreateItemGroup; import com.simibubi.create.content.contraptions.TorquePropagator; @@ -130,6 +131,7 @@ public class Create { ContraptionMovementSetting.registerDefaults(); AllArmInteractionPointTypes.register(); BlockSpoutingBehaviour.registerDefaults(); + ComputerCraftProxy.register(); ForgeMod.enableMilkFluid(); CopperRegistries.inject(); diff --git a/src/main/java/com/simibubi/create/compat/Mods.java b/src/main/java/com/simibubi/create/compat/Mods.java index 55fe10952..36bd60e52 100644 --- a/src/main/java/com/simibubi/create/compat/Mods.java +++ b/src/main/java/com/simibubi/create/compat/Mods.java @@ -5,7 +5,10 @@ import java.util.function.Supplier; import com.simibubi.create.foundation.utility.Lang; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.Block; import net.minecraftforge.fml.ModList; +import net.minecraftforge.registries.ForgeRegistries; /** * For compatibility with and without another mod present, we have to define load conditions of the specific code @@ -14,6 +17,8 @@ public enum Mods { DYNAMICTREES, TCONSTRUCT, CURIOS, + + COMPUTERCRAFT, STORAGEDRAWERS, XLPACKETS; @@ -51,4 +56,8 @@ public enum Mods { toExecute.get().run(); } } + + public Block getBlock(String id) { + return ForgeRegistries.BLOCKS.getValue(new ResourceLocation(asId(), id)); + } } diff --git a/src/main/java/com/simibubi/create/compat/computercraft/AbstractComputerBehaviour.java b/src/main/java/com/simibubi/create/compat/computercraft/AbstractComputerBehaviour.java new file mode 100644 index 000000000..a8620450b --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/computercraft/AbstractComputerBehaviour.java @@ -0,0 +1,57 @@ +package com.simibubi.create.compat.computercraft; + +import com.simibubi.create.foundation.tileEntity.SmartTileEntity; +import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; +import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType; + +import net.minecraft.nbt.CompoundTag; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; + +public class AbstractComputerBehaviour extends TileEntityBehaviour { + + public static final BehaviourType TYPE = new BehaviourType<>(); + + boolean hasAttachedComputer; + + public AbstractComputerBehaviour(SmartTileEntity te) { + super(te); + this.hasAttachedComputer = false; + } + + @Override + public void read(CompoundTag nbt, boolean clientPacket) { + hasAttachedComputer = nbt.getBoolean("HasAttachedComputer"); + super.read(nbt, clientPacket); + } + + @Override + public void write(CompoundTag nbt, boolean clientPacket) { + nbt.putBoolean("HasAttachedComputer", hasAttachedComputer); + super.write(nbt, clientPacket); + } + + public boolean isPeripheralCap(Capability cap) { + return false; + } + + public LazyOptional getPeripheralCapability() { + return LazyOptional.empty(); + } + + public void removePeripheral() {} + + public void setHasAttachedComputer(boolean hasAttachedComputer) { + this.hasAttachedComputer = hasAttachedComputer; + } + + public boolean hasAttachedComputer() { + return hasAttachedComputer; + } + + @Override + public BehaviourType getType() { + return TYPE; + } + +} diff --git a/src/main/java/com/simibubi/create/compat/computercraft/AttachedComputerPacket.java b/src/main/java/com/simibubi/create/compat/computercraft/AttachedComputerPacket.java new file mode 100644 index 000000000..3181217fe --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/computercraft/AttachedComputerPacket.java @@ -0,0 +1,37 @@ +package com.simibubi.create.compat.computercraft; + +import com.simibubi.create.foundation.networking.TileEntityDataPacket; +import com.simibubi.create.foundation.tileEntity.SmartTileEntity; +import com.simibubi.create.foundation.tileEntity.SyncedTileEntity; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; + +public class AttachedComputerPacket extends TileEntityDataPacket { + + private final boolean hasAttachedComputer; + + public AttachedComputerPacket(BlockPos tilePos, boolean hasAttachedComputer) { + super(tilePos); + this.hasAttachedComputer = hasAttachedComputer; + } + + public AttachedComputerPacket(FriendlyByteBuf buffer) { + super(buffer); + this.hasAttachedComputer = buffer.readBoolean(); + } + + @Override + protected void writeData(FriendlyByteBuf buffer) { + buffer.writeBoolean(hasAttachedComputer); + } + + @Override + protected void handlePacket(SyncedTileEntity tile) { + if (tile instanceof SmartTileEntity smartTile) { + smartTile.getBehaviour(AbstractComputerBehaviour.TYPE) + .setHasAttachedComputer(hasAttachedComputer); + } + } + +} diff --git a/src/main/java/com/simibubi/create/compat/computercraft/ComputerCraftProxy.java b/src/main/java/com/simibubi/create/compat/computercraft/ComputerCraftProxy.java new file mode 100644 index 000000000..e424bfdad --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/computercraft/ComputerCraftProxy.java @@ -0,0 +1,30 @@ +package com.simibubi.create.compat.computercraft; + +import java.util.function.Function; + +import com.simibubi.create.compat.Mods; +import com.simibubi.create.compat.computercraft.implementation.ComputerBehaviour; +import com.simibubi.create.foundation.tileEntity.SmartTileEntity; + +public class ComputerCraftProxy { + + public static void register() { + fallbackFactory = FallbackComputerBehaviour::new; + Mods.COMPUTERCRAFT.executeIfInstalled(() -> ComputerCraftProxy::registerWithDependency); + } + + private static void registerWithDependency() { + /* Comment if computercraft.implementation is not in the source set */ + computerFactory = ComputerBehaviour::new; + } + + private static Function fallbackFactory; + private static Function computerFactory; + + public static AbstractComputerBehaviour behaviour(SmartTileEntity ste) { + if (computerFactory == null) + return fallbackFactory.apply(ste); + return computerFactory.apply(ste); + } + +} diff --git a/src/main/java/com/simibubi/create/compat/computercraft/ComputerScreen.java b/src/main/java/com/simibubi/create/compat/computercraft/ComputerScreen.java new file mode 100644 index 000000000..2d55a2554 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/computercraft/ComputerScreen.java @@ -0,0 +1,96 @@ +package com.simibubi.create.compat.computercraft; + +import java.util.function.Supplier; + +import javax.annotation.Nullable; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.compat.Mods; +import com.simibubi.create.foundation.gui.AbstractSimiScreen; +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.gui.AllIcons; +import com.simibubi.create.foundation.gui.element.GuiGameElement; +import com.simibubi.create.foundation.gui.widget.AbstractSimiWidget; +import com.simibubi.create.foundation.gui.widget.ElementWidget; +import com.simibubi.create.foundation.gui.widget.IconButton; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; + +public class ComputerScreen extends AbstractSimiScreen { + + private final AllGuiTextures background = AllGuiTextures.COMPUTER; + + private final Supplier displayTitle; + private final RenderWindowFunction additional; + private final Screen previousScreen; + private final Supplier hasAttachedComputer; + + private AbstractSimiWidget computerWidget; + private IconButton confirmButton; + + public ComputerScreen(Component title, @Nullable RenderWindowFunction additional, Screen previousScreen, Supplier hasAttachedComputer) { + this(title, () -> title, additional, previousScreen, hasAttachedComputer); + } + + public ComputerScreen(Component title, Supplier displayTitle, @Nullable RenderWindowFunction additional, Screen previousScreen, Supplier hasAttachedComputer) { + super(title); + this.displayTitle = displayTitle; + this.additional = additional; + this.previousScreen = previousScreen; + this.hasAttachedComputer = hasAttachedComputer; + } + + @Override + public void tick() { + if (!hasAttachedComputer.get()) + minecraft.setScreen(previousScreen); + + super.tick(); + } + + @Override + protected void init() { + setWindowSize(background.width, background.height); + super.init(); + + int x = guiLeft; + int y = guiTop; + + Mods.COMPUTERCRAFT.executeIfInstalled(() -> () -> { + computerWidget = new ElementWidget(x + 33, y + 38) + .showingElement(GuiGameElement.of(Mods.COMPUTERCRAFT.getBlock("computer_advanced"))); + computerWidget.getToolTip().add(Lang.translate("gui.attached_computer.hint").component()); + addRenderableWidget(computerWidget); + }); + + confirmButton = new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM); + confirmButton.withCallback(this::onClose); + addRenderableWidget(confirmButton); + } + + + + @Override + protected void renderWindow(PoseStack ms, int mouseX, int mouseY, float partialTicks) { + int x = guiLeft; + int y = guiTop; + + background.render(ms, x, y, this); + + font.draw(ms, displayTitle.get(), x + background.width / 2.0F - font.width(displayTitle.get()) / 2.0F, y + 4, 0x442000); + font.drawWordWrap(Lang.translate("gui.attached_computer.controlled").component(), x + 55, y + 32, 111, 0x7A7A7A); + + if (additional != null) + additional.render(ms, mouseX, mouseY, partialTicks, x, y, background); + } + + @FunctionalInterface + public interface RenderWindowFunction { + + void render(PoseStack ms, int mouseX, int mouseY, float partialTicks, int guiLeft, int guiTop, AllGuiTextures background); + + } + +} diff --git a/src/main/java/com/simibubi/create/compat/computercraft/FallbackComputerBehaviour.java b/src/main/java/com/simibubi/create/compat/computercraft/FallbackComputerBehaviour.java new file mode 100644 index 000000000..2e1a3da77 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/computercraft/FallbackComputerBehaviour.java @@ -0,0 +1,16 @@ +package com.simibubi.create.compat.computercraft; + +import com.simibubi.create.foundation.tileEntity.SmartTileEntity; + +public class FallbackComputerBehaviour extends AbstractComputerBehaviour { + + public FallbackComputerBehaviour(SmartTileEntity te) { + super(te); + } + + @Override + public boolean hasAttachedComputer() { + return false; + } + +} diff --git a/src/main/java/com/simibubi/create/compat/computercraft/implementation/ComputerBehaviour.java b/src/main/java/com/simibubi/create/compat/computercraft/implementation/ComputerBehaviour.java new file mode 100644 index 000000000..dfe1f504d --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/computercraft/implementation/ComputerBehaviour.java @@ -0,0 +1,74 @@ +package com.simibubi.create.compat.computercraft.implementation; + +import com.simibubi.create.compat.computercraft.AbstractComputerBehaviour; +import com.simibubi.create.compat.computercraft.implementation.peripherals.DisplayLinkPeripheral; +import com.simibubi.create.compat.computercraft.implementation.peripherals.SequencedGearshiftPeripheral; +import com.simibubi.create.compat.computercraft.implementation.peripherals.SpeedControllerPeripheral; +import com.simibubi.create.compat.computercraft.implementation.peripherals.SpeedGaugePeripheral; +import com.simibubi.create.compat.computercraft.implementation.peripherals.StationPeripheral; +import com.simibubi.create.compat.computercraft.implementation.peripherals.StressGaugePeripheral; +import com.simibubi.create.content.contraptions.relays.advanced.SpeedControllerTileEntity; +import com.simibubi.create.content.contraptions.relays.advanced.sequencer.SequencedGearshiftTileEntity; +import com.simibubi.create.content.contraptions.relays.gauge.SpeedGaugeTileEntity; +import com.simibubi.create.content.contraptions.relays.gauge.StressGaugeTileEntity; +import com.simibubi.create.content.logistics.block.display.DisplayLinkTileEntity; +import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationTileEntity; +import com.simibubi.create.foundation.tileEntity.SmartTileEntity; + +import dan200.computercraft.api.peripheral.IPeripheral; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.CapabilityManager; +import net.minecraftforge.common.capabilities.CapabilityToken; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.common.util.NonNullSupplier; + +public class ComputerBehaviour extends AbstractComputerBehaviour { + + protected static final Capability PERIPHERAL_CAPABILITY = + CapabilityManager.get(new CapabilityToken<>() { + }); + LazyOptional peripheral; + NonNullSupplier peripheralSupplier; + + public ComputerBehaviour(SmartTileEntity te) { + super(te); + this.peripheralSupplier = getPeripheralFor(te); + } + + public static NonNullSupplier getPeripheralFor(SmartTileEntity te) { + if (te instanceof SpeedControllerTileEntity scte) + return () -> new SpeedControllerPeripheral(scte, scte.targetSpeed); + if (te instanceof DisplayLinkTileEntity dlte) + return () -> new DisplayLinkPeripheral(dlte); + if (te instanceof SequencedGearshiftTileEntity sgte) + return () -> new SequencedGearshiftPeripheral(sgte); + if (te instanceof SpeedGaugeTileEntity sgte) + return () -> new SpeedGaugePeripheral(sgte); + if (te instanceof StressGaugeTileEntity sgte) + return () -> new StressGaugePeripheral(sgte); + if (te instanceof StationTileEntity ste) + return () -> new StationPeripheral(ste); + + throw new IllegalArgumentException("No peripheral available for " + te.getType() + .getRegistryName()); + } + + @Override + public boolean isPeripheralCap(Capability cap) { + return cap == PERIPHERAL_CAPABILITY; + } + + @Override + public LazyOptional getPeripheralCapability() { + if (peripheral == null || !peripheral.isPresent()) + peripheral = LazyOptional.of(peripheralSupplier); + return peripheral.cast(); + } + + @Override + public void removePeripheral() { + if (peripheral != null) + peripheral.invalidate(); + } + +} diff --git a/src/main/java/com/simibubi/create/compat/computercraft/implementation/CreateLuaTable.java b/src/main/java/com/simibubi/create/compat/computercraft/implementation/CreateLuaTable.java new file mode 100644 index 000000000..3c957274e --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/computercraft/implementation/CreateLuaTable.java @@ -0,0 +1,172 @@ +package com.simibubi.create.compat.computercraft.implementation; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.LuaTable; +import dan200.computercraft.api.lua.LuaValues; + +public class CreateLuaTable implements LuaTable { + + private final Map map; + + public CreateLuaTable() { + this.map = new HashMap<>(); + } + + public CreateLuaTable(Map map) { + this.map = new HashMap<>(map); + } + + public boolean getBoolean(String key) throws LuaException { + Object value = get(key); + + if (!(value instanceof Boolean)) + throw LuaValues.badField(key, "boolean", LuaValues.getType(value)); + + return (Boolean) value; + } + + public String getString(String key) throws LuaException { + Object value = get(key); + + if (!(value instanceof String)) + throw LuaValues.badField(key, "string", LuaValues.getType(value)); + + return (String) value; + } + + public CreateLuaTable getTable(String key) throws LuaException { + Object value = get(key); + + if (!(value instanceof Map)) + throw LuaValues.badField(key, "table", LuaValues.getType(value)); + + return new CreateLuaTable((Map) value); + } + + public Optional getOptBoolean(String key) throws LuaException { + Object value = get(key); + + if (value == null) + return Optional.empty(); + + if (!(value instanceof Boolean)) + throw LuaValues.badField(key, "boolean", LuaValues.getType(value)); + + return Optional.of((Boolean) value); + } + + public Set stringKeySet() throws LuaException { + Set stringSet = new HashSet<>(); + + for (Object key : keySet()) { + if (!(key instanceof String)) + throw new LuaException("key " + key + " is not string (got " + LuaValues.getType(key) + ")"); + + stringSet.add((String) key); + } + + return Collections.unmodifiableSet(stringSet); + } + + public Collection tableValues() throws LuaException { + List tables = new ArrayList<>(); + + for (int i = 1; i <= size(); i++) { + Object value = get((double) i); + + if (!(value instanceof Map)) + throw new LuaException("value " + value + " is not table (got " + LuaValues.getType(value) + ")"); + + tables.add(new CreateLuaTable((Map) value)); + } + + return Collections.unmodifiableList(tables); + } + + public Map getMap() { + return map; + } + + @Nullable + @Override + public Object put(Object key, Object value) { + return map.put(key, value); + } + + public void putBoolean(String key, boolean value) { + map.put(key, value); + } + + public void putDouble(String key, double value) { + map.put(key, value); + } + + public void putString(String key, String value) { + map.put(key, value); + } + + public void putTable(String key, CreateLuaTable value) { + map.put(key, value); + } + + public void putTable(int i, CreateLuaTable value) { + map.put(i, value); + } + + @Override + public int size() { + return map.size(); + } + + @Override + public boolean isEmpty() { + return map.isEmpty(); + } + + @Override + public boolean containsKey(Object o) { + return map.containsKey(o); + } + + @Override + public boolean containsValue(Object o) { + return map.containsValue(o); + } + + @Override + public Object get(Object o) { + return map.get(o); + } + + @NotNull + @Override + public Set keySet() { + return map.keySet(); + } + + @NotNull + @Override + public Collection values() { + return map.values(); + } + + @NotNull + @Override + public Set> entrySet() { + return map.entrySet(); + } + +} diff --git a/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/DisplayLinkPeripheral.java b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/DisplayLinkPeripheral.java new file mode 100644 index 000000000..0e9275227 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/DisplayLinkPeripheral.java @@ -0,0 +1,108 @@ +package com.simibubi.create.compat.computercraft.implementation.peripherals; + +import java.util.concurrent.atomic.AtomicInteger; + +import org.jetbrains.annotations.NotNull; + +import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; +import com.simibubi.create.content.logistics.block.display.DisplayLinkTileEntity; +import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats; + +import dan200.computercraft.api.lua.LuaFunction; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.StringTag; +import net.minecraft.nbt.Tag; + +public class DisplayLinkPeripheral extends SyncedPeripheral { + + public static final String TAG_KEY = "ComputerSourceList"; + private final AtomicInteger cursorX = new AtomicInteger(); + private final AtomicInteger cursorY = new AtomicInteger(); + + public DisplayLinkPeripheral(DisplayLinkTileEntity tile) { + super(tile); + } + + @LuaFunction + public final void setCursorPos(int x, int y) { + cursorX.set(x - 1); + cursorY.set(y - 1); + } + + @LuaFunction + public final Object[] getCursorPos() { + return new Object[] {cursorX.get() + 1, cursorY.get() + 1}; + } + + @LuaFunction(mainThread = true) + public final Object[] getSize() { + DisplayTargetStats stats = tile.activeTarget.provideStats(new DisplayLinkContext(tile.getLevel(), tile)); + return new Object[]{stats.maxRows(), stats.maxColumns()}; + } + + @LuaFunction + public final boolean isColor() { + return false; + } + + @LuaFunction + public final boolean isColour() { + return false; + } + + @LuaFunction + public final void write(String text) { + ListTag tag = tile.getSourceConfig().getList(TAG_KEY, Tag.TAG_STRING); + + int x = cursorX.get(); + int y = cursorY.get(); + + for (int i = tag.size(); i <= y; i++) { + tag.add(StringTag.valueOf("")); + } + + StringBuilder builder = new StringBuilder(tag.getString(y)); + + builder.append(" ".repeat(Math.max(0, x - builder.length()))); + builder.replace(x, x + text.length(), text); + + tag.set(y, StringTag.valueOf(builder.toString())); + + synchronized (tile) { + tile.getSourceConfig().put(TAG_KEY, tag); + } + + cursorX.set(x + text.length()); + } + + @LuaFunction + public final void clearLine() { + ListTag tag = tile.getSourceConfig().getList(TAG_KEY, Tag.TAG_STRING); + + if (tag.size() > cursorY.get()) + tag.set(cursorY.get(), StringTag.valueOf("")); + + synchronized (tile) { + tile.getSourceConfig().put(TAG_KEY, tag); + } + } + + @LuaFunction + public final void clear() { + synchronized (tile) { + tile.getSourceConfig().put(TAG_KEY, new ListTag()); + } + } + + @LuaFunction(mainThread = true) + public final void update() { + tile.tickSource(); + } + + @NotNull + @Override + public String getType() { + return "Create_DisplayLink"; + } + +} diff --git a/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/SequencedGearshiftPeripheral.java b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/SequencedGearshiftPeripheral.java new file mode 100644 index 000000000..8addb181e --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/SequencedGearshiftPeripheral.java @@ -0,0 +1,54 @@ +package com.simibubi.create.compat.computercraft.implementation.peripherals; + +import org.jetbrains.annotations.NotNull; + +import com.simibubi.create.content.contraptions.relays.advanced.sequencer.Instruction; +import com.simibubi.create.content.contraptions.relays.advanced.sequencer.InstructionSpeedModifiers; +import com.simibubi.create.content.contraptions.relays.advanced.sequencer.SequencedGearshiftTileEntity; +import com.simibubi.create.content.contraptions.relays.advanced.sequencer.SequencerInstructions; + +import dan200.computercraft.api.lua.IArguments; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.LuaFunction; + +public class SequencedGearshiftPeripheral extends SyncedPeripheral { + + public SequencedGearshiftPeripheral(SequencedGearshiftTileEntity tile) { + super(tile); + } + + @LuaFunction(mainThread = true) + public final void rotate(IArguments arguments) throws LuaException { + runInstruction(arguments, SequencerInstructions.TURN_ANGLE); + } + + @LuaFunction(mainThread = true) + public final void move(IArguments arguments) throws LuaException { + runInstruction(arguments, SequencerInstructions.TURN_DISTANCE); + } + + @LuaFunction + public final boolean isRunning() { + return !this.tile.isIdle(); + } + + private void runInstruction(IArguments arguments, SequencerInstructions instructionType) throws LuaException { + int speedModifier = arguments.count() > 1 ? arguments.getInt(1) : 1; + this.tile.getInstructions().clear(); + + this.tile.getInstructions().add(new Instruction( + instructionType, + InstructionSpeedModifiers.getByModifier(speedModifier), + Math.abs(arguments.getInt(0)))); + this.tile.getInstructions().add(new Instruction(SequencerInstructions.END)); + + this.tile.run(0); + } + + @NotNull + @Override + public String getType() { + return "Create_SequencedGearshift"; + } + +} diff --git a/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/SpeedControllerPeripheral.java b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/SpeedControllerPeripheral.java new file mode 100644 index 000000000..2aba811f0 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/SpeedControllerPeripheral.java @@ -0,0 +1,35 @@ +package com.simibubi.create.compat.computercraft.implementation.peripherals; + +import org.jetbrains.annotations.NotNull; + +import com.simibubi.create.content.contraptions.relays.advanced.SpeedControllerTileEntity; +import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueBehaviour; + +import dan200.computercraft.api.lua.LuaFunction; + +public class SpeedControllerPeripheral extends SyncedPeripheral { + + private final ScrollValueBehaviour targetSpeed; + + public SpeedControllerPeripheral(SpeedControllerTileEntity tile, ScrollValueBehaviour targetSpeed) { + super(tile); + this.targetSpeed = targetSpeed; + } + + @LuaFunction(mainThread = true) + public final void setTargetSpeed(int speed) { + this.targetSpeed.setValue(speed); + } + + @LuaFunction + public final float getTargetSpeed() { + return this.targetSpeed.getValue(); + } + + @NotNull + @Override + public String getType() { + return "Create_RotationSpeedController"; + } + +} diff --git a/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/SpeedGaugePeripheral.java b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/SpeedGaugePeripheral.java new file mode 100644 index 000000000..a13b02cd5 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/SpeedGaugePeripheral.java @@ -0,0 +1,26 @@ +package com.simibubi.create.compat.computercraft.implementation.peripherals; + +import org.jetbrains.annotations.NotNull; + +import com.simibubi.create.content.contraptions.relays.gauge.SpeedGaugeTileEntity; + +import dan200.computercraft.api.lua.LuaFunction; + +public class SpeedGaugePeripheral extends SyncedPeripheral { + + public SpeedGaugePeripheral(SpeedGaugeTileEntity tile) { + super(tile); + } + + @LuaFunction + public final float getSpeed() { + return this.tile.getSpeed(); + } + + @NotNull + @Override + public String getType() { + return "Create_Speedometer"; + } + +} diff --git a/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/StationPeripheral.java b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/StationPeripheral.java new file mode 100644 index 000000000..3de8e979b --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/StationPeripheral.java @@ -0,0 +1,269 @@ +package com.simibubi.create.compat.computercraft.implementation.peripherals; + +import java.util.Map; + +import javax.annotation.Nullable; + +import org.jetbrains.annotations.NotNull; + +import com.simibubi.create.compat.computercraft.implementation.CreateLuaTable; +import com.simibubi.create.content.logistics.trains.entity.Train; +import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation; +import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationTileEntity; +import com.simibubi.create.content.logistics.trains.management.edgePoint.station.TrainEditPacket; +import com.simibubi.create.content.logistics.trains.management.schedule.Schedule; +import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.StringHelper; + +import dan200.computercraft.api.lua.IArguments; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.LuaFunction; +import net.minecraft.nbt.ByteTag; +import net.minecraft.nbt.CollectionTag; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.DoubleTag; +import net.minecraft.nbt.IntTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.NumericTag; +import net.minecraft.nbt.StringTag; +import net.minecraft.nbt.Tag; +import net.minecraftforge.network.PacketDistributor; + +public class StationPeripheral extends SyncedPeripheral { + + public StationPeripheral(StationTileEntity tile) { + super(tile); + } + + @LuaFunction(mainThread = true) + public final void assemble() throws LuaException { + if (!tile.isAssembling()) + throw new LuaException("station must be in assembly mode"); + + tile.assemble(null); + + if (tile.getStation() == null || tile.getStation().getPresentTrain() == null) + throw new LuaException("failed to assemble train"); + + if (!tile.exitAssemblyMode()) + throw new LuaException("failed to exit assembly mode"); + } + + @LuaFunction(mainThread = true) + public final void disassemble() throws LuaException { + if (tile.isAssembling()) + throw new LuaException("station must not be in assembly mode"); + + getTrainOrThrow(); + + if (!tile.enterAssemblyMode(null)) + throw new LuaException("could not disassemble train"); + } + + @LuaFunction(mainThread = true) + public final void setAssemblyMode(boolean assemblyMode) throws LuaException { + if (assemblyMode) { + if (!tile.enterAssemblyMode(null)) + throw new LuaException("failed to enter assembly mode"); + } else { + if (!tile.exitAssemblyMode()) + throw new LuaException("failed to exit assembly mode"); + } + } + + @LuaFunction + public final boolean isInAssemblyMode() { + return tile.isAssembling(); + } + + @LuaFunction + public final String getStationName() throws LuaException { + GlobalStation station = tile.getStation(); + if (station == null) + throw new LuaException("station is not connected to a track"); + + return station.name; + } + + @LuaFunction(mainThread = true) + public final void setStationName(String name) throws LuaException { + if (!tile.updateName(name)) + throw new LuaException("could not set station name"); + } + + @LuaFunction + public final boolean isTrainPresent() throws LuaException { + GlobalStation station = tile.getStation(); + if (station == null) + throw new LuaException("station is not connected to a track"); + + return station.getPresentTrain() != null; + } + + @LuaFunction + public final boolean isTrainImminent() throws LuaException { + GlobalStation station = tile.getStation(); + if (station == null) + throw new LuaException("station is not connected to a track"); + + return station.getImminentTrain() != null; + } + + @LuaFunction + public final boolean isTrainEnroute() throws LuaException { + GlobalStation station = tile.getStation(); + if (station == null) + throw new LuaException("station is not connected to a track"); + + return station.getNearestTrain() != null; + } + + @LuaFunction + public final String getTrainName() throws LuaException { + Train train = getTrainOrThrow(); + return train.name.getString(); + } + + @LuaFunction(mainThread = true) + public final void setTrainName(String name) throws LuaException { + Train train = getTrainOrThrow(); + train.name = Components.literal(name); + AllPackets.channel.send(PacketDistributor.ALL.noArg(), new TrainEditPacket.TrainEditReturnPacket(train.id, name, train.icon.getId())); + } + + @LuaFunction + public final boolean hasSchedule() throws LuaException { + Train train = getTrainOrThrow(); + return train.runtime.getSchedule() != null; + } + + @LuaFunction + public final CreateLuaTable getSchedule() throws LuaException { + Train train = getTrainOrThrow(); + + Schedule schedule = train.runtime.getSchedule(); + if (schedule == null) + throw new LuaException("train doesn't have a schedule"); + + return fromCompoundTag(schedule.write()); + } + + @LuaFunction(mainThread = true) + public final void setSchedule(IArguments arguments) throws LuaException { + Train train = getTrainOrThrow(); + Schedule schedule = Schedule.fromTag(toCompoundTag(new CreateLuaTable(arguments.getTable(0)))); + boolean autoSchedule = train.runtime.getSchedule() == null || train.runtime.isAutoSchedule; + train.runtime.setSchedule(schedule, autoSchedule); + } + + private @NotNull Train getTrainOrThrow() throws LuaException { + GlobalStation station = tile.getStation(); + if (station == null) + throw new LuaException("station is not connected to a track"); + + Train train = station.getPresentTrain(); + if (train == null) + throw new LuaException("there is no train present"); + + return train; + } + + private static @NotNull CreateLuaTable fromCompoundTag(CompoundTag tag) throws LuaException { + return (CreateLuaTable) fromNBTTag(null, tag); + } + + private static @NotNull Object fromNBTTag(@Nullable String key, Tag tag) throws LuaException { + byte type = tag.getId(); + + if (type == Tag.TAG_BYTE && key != null && key.equals("Count")) + return ((NumericTag) tag).getAsByte(); + else if (type == Tag.TAG_BYTE) + return ((NumericTag) tag).getAsByte() != 0; + else if (type == Tag.TAG_SHORT || type == Tag.TAG_INT || type == Tag.TAG_LONG) + return ((NumericTag) tag).getAsLong(); + else if (type == Tag.TAG_FLOAT || type == Tag.TAG_DOUBLE) + return ((NumericTag) tag).getAsDouble(); + else if (type == Tag.TAG_STRING) + return tag.getAsString(); + else if (type == Tag.TAG_LIST || type == Tag.TAG_BYTE_ARRAY || type == Tag.TAG_INT_ARRAY || type == Tag.TAG_LONG_ARRAY) { + CreateLuaTable list = new CreateLuaTable(); + CollectionTag listTag = (CollectionTag) tag; + + for (int i = 0; i < listTag.size(); i++) { + list.put(i + 1, fromNBTTag(null, listTag.get(i))); + } + + return list; + + } else if (type == Tag.TAG_COMPOUND) { + CreateLuaTable table = new CreateLuaTable(); + CompoundTag compoundTag = (CompoundTag) tag; + + for (String compoundKey : compoundTag.getAllKeys()) { + table.put( + StringHelper.camelCaseToSnakeCase(compoundKey), + fromNBTTag(compoundKey, compoundTag.get(compoundKey)) + ); + } + + return table; + } + + throw new LuaException("unknown tag type " + tag.getType().getName()); + } + + private static @NotNull CompoundTag toCompoundTag(CreateLuaTable table) throws LuaException { + return (CompoundTag) toNBTTag(null, table.getMap()); + } + + private static @NotNull Tag toNBTTag(@Nullable String key, Object value) throws LuaException { + if (value instanceof Boolean v) + return ByteTag.valueOf(v); + else if (value instanceof Byte || (key != null && key.equals("count"))) + return ByteTag.valueOf(((Number) value).byteValue()); + else if (value instanceof Number v) { + // If number is numerical integer + if (v.intValue() == v.doubleValue()) + return IntTag.valueOf(v.intValue()); + else + return DoubleTag.valueOf(v.doubleValue()); + + } else if (value instanceof String v) + return StringTag.valueOf(v); + else if (value instanceof Map v && v.containsKey(1.0)) { // List + ListTag list = new ListTag(); + for (Object o : v.values()) { + list.add(toNBTTag(null, o)); + } + + return list; + + } else if (value instanceof Map v) { // Table/Map + CompoundTag compound = new CompoundTag(); + for (Object objectKey : v.keySet()) { + if (!(objectKey instanceof String compoundKey)) + throw new LuaException("table key is not of type string"); + + compound.put( + // Items serialize their resource location as "id" and not as "Id". + // This check is needed to see if the 'i' should be left lowercase or not. + // Items store "count" in the same compound tag, so we can check for its presence to see if this is a serialized item + compoundKey.equals("id") && v.containsKey("count") ? "id" : StringHelper.snakeCaseToCamelCase(compoundKey), + toNBTTag(compoundKey, v.get(compoundKey)) + ); + } + + return compound; + } + + throw new LuaException("unknown object type " + value.getClass().getName()); + } + + @NotNull + @Override + public String getType() { + return "Create_Station"; + } + +} diff --git a/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/StressGaugePeripheral.java b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/StressGaugePeripheral.java new file mode 100644 index 000000000..b712bd6da --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/StressGaugePeripheral.java @@ -0,0 +1,31 @@ +package com.simibubi.create.compat.computercraft.implementation.peripherals; + +import org.jetbrains.annotations.NotNull; + +import com.simibubi.create.content.contraptions.relays.gauge.StressGaugeTileEntity; + +import dan200.computercraft.api.lua.LuaFunction; + +public class StressGaugePeripheral extends SyncedPeripheral { + + public StressGaugePeripheral(StressGaugeTileEntity tile) { + super(tile); + } + + @LuaFunction + public final float getStress() { + return this.tile.getNetworkStress(); + } + + @LuaFunction + public final float getStressCapacity() { + return this.tile.getNetworkCapacity(); + } + + @NotNull + @Override + public String getType() { + return "Create_Stressometer"; + } + +} diff --git a/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/SyncedPeripheral.java b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/SyncedPeripheral.java new file mode 100644 index 000000000..a6371063d --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/SyncedPeripheral.java @@ -0,0 +1,50 @@ +package com.simibubi.create.compat.computercraft.implementation.peripherals; + +import java.util.concurrent.atomic.AtomicInteger; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.compat.computercraft.AttachedComputerPacket; +import com.simibubi.create.compat.computercraft.implementation.ComputerBehaviour; +import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.foundation.tileEntity.SmartTileEntity; + +import dan200.computercraft.api.peripheral.IComputerAccess; +import dan200.computercraft.api.peripheral.IPeripheral; +import net.minecraftforge.network.PacketDistributor; + +public abstract class SyncedPeripheral implements IPeripheral { + + protected final T tile; + private final AtomicInteger computers = new AtomicInteger(); + + public SyncedPeripheral(T tile) { + this.tile = tile; + } + + @Override + public void attach(@NotNull IComputerAccess computer) { + computers.incrementAndGet(); + updateTile(); + } + + @Override + public void detach(@NotNull IComputerAccess computer) { + computers.decrementAndGet(); + updateTile(); + } + + private void updateTile() { + boolean hasAttachedComputer = computers.get() > 0; + + tile.getBehaviour(ComputerBehaviour.TYPE).setHasAttachedComputer(hasAttachedComputer); + AllPackets.channel.send(PacketDistributor.ALL.noArg(), new AttachedComputerPacket(tile.getBlockPos(), hasAttachedComputer)); + } + + @Override + public boolean equals(@Nullable IPeripheral other) { + return this == other; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/SpeedControllerTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/SpeedControllerTileEntity.java index 9238ed52e..37385e92b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/SpeedControllerTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/SpeedControllerTileEntity.java @@ -2,6 +2,11 @@ package com.simibubi.create.content.contraptions.relays.advanced; import java.util.List; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.compat.computercraft.AbstractComputerBehaviour; +import com.simibubi.create.compat.computercraft.ComputerCraftProxy; import com.simibubi.create.content.contraptions.RotationPropagator; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.components.motor.CreativeMotorTileEntity; @@ -20,11 +25,14 @@ import net.minecraft.core.Direction; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; public class SpeedControllerTileEntity extends KineticTileEntity { public static final int DEFAULT_SPEED = 16; - protected ScrollValueBehaviour targetSpeed; + public ScrollValueBehaviour targetSpeed; + public AbstractComputerBehaviour computerBehaviour; boolean hasBracket; @@ -53,7 +61,8 @@ public class SpeedControllerTileEntity extends KineticTileEntity { targetSpeed.withCallback(i -> this.updateTargetRotation()); targetSpeed.withStepFunction(CreativeMotorTileEntity::step); behaviours.add(targetSpeed); - + behaviours.add(computerBehaviour = ComputerCraftProxy.behaviour(this)); + registerAwardables(behaviours, AllAdvancements.SPEED_CONTROLLER); } @@ -63,7 +72,7 @@ public class SpeedControllerTileEntity extends KineticTileEntity { RotationPropagator.handleRemoved(level, worldPosition, this); removeSource(); attachKinetics(); - + if (isCogwheelPresent() && getSpeed() != 0) award(AllAdvancements.SPEED_CONTROLLER); } @@ -127,6 +136,20 @@ public class SpeedControllerTileEntity extends KineticTileEntity { && stateAbove.getValue(CogWheelBlock.AXIS).isHorizontal(); } + @NotNull + @Override + public LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) { + if (computerBehaviour.isPeripheralCap(cap)) + return computerBehaviour.getPeripheralCapability(); + return super.getCapability(cap, side); + } + + @Override + public void invalidateCaps() { + super.invalidateCaps(); + computerBehaviour.removePeripheral(); + } + private class ControllerValueBoxTransform extends ValueBoxTransform.Sided { @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/ConfigureSequencedGearshiftPacket.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/ConfigureSequencedGearshiftPacket.java index 75fb4ca84..fa77415c4 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/ConfigureSequencedGearshiftPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/ConfigureSequencedGearshiftPacket.java @@ -35,6 +35,9 @@ public class ConfigureSequencedGearshiftPacket extends TileEntityConfigurationPa @Override protected void applySettings(SequencedGearshiftTileEntity te) { + if (te.computerBehaviour.hasAttachedComputer()) + return; + te.run(-1); te.instructions = Instruction.deserializeAll(instructions); te.sendData(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/Instruction.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/Instruction.java index 9335285d1..a7b91a04a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/Instruction.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/Instruction.java @@ -19,8 +19,12 @@ public class Instruction { } public Instruction(SequencerInstructions instruction, int value) { + this(instruction, InstructionSpeedModifiers.FORWARD, value); + } + + public Instruction(SequencerInstructions instruction, InstructionSpeedModifiers speedModifier, int value) { this.instruction = instruction; - speedModifier = InstructionSpeedModifiers.FORWARD; + this.speedModifier = speedModifier; this.value = value; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/InstructionSpeedModifiers.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/InstructionSpeedModifiers.java index 93713d075..b1a1f236a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/InstructionSpeedModifiers.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/InstructionSpeedModifiers.java @@ -1,6 +1,7 @@ package com.simibubi.create.content.contraptions.relays.advanced.sequencer; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import com.simibubi.create.foundation.utility.Components; @@ -36,4 +37,11 @@ public enum InstructionSpeedModifiers { return options; } + public static InstructionSpeedModifiers getByModifier(int modifier) { + return Arrays.stream(InstructionSpeedModifiers.values()) + .filter(speedModifier -> speedModifier.value == modifier) + .findAny() + .orElse(InstructionSpeedModifiers.FORWARD); + } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftScreen.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftScreen.java index 7f2c86ab4..1cf8e7259 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftScreen.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftScreen.java @@ -4,6 +4,7 @@ import java.util.Vector; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllBlocks; +import com.simibubi.create.compat.computercraft.ComputerScreen; import com.simibubi.create.foundation.gui.AbstractSimiScreen; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; @@ -15,7 +16,6 @@ import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Lang; -import net.minecraft.core.BlockPos; import net.minecraft.nbt.ListTag; import net.minecraft.network.chat.Component; import net.minecraft.world.item.ItemStack; @@ -25,22 +25,26 @@ public class SequencedGearshiftScreen extends AbstractSimiScreen { private final ItemStack renderedItem = AllBlocks.SEQUENCED_GEARSHIFT.asStack(); private final AllGuiTextures background = AllGuiTextures.SEQUENCER; private IconButton confirmButton; + private SequencedGearshiftTileEntity te; private ListTag compareTag; private Vector instructions; - private BlockPos pos; private Vector> inputs; public SequencedGearshiftScreen(SequencedGearshiftTileEntity te) { super(Lang.translateDirect("gui.sequenced_gearshift.title")); this.instructions = te.instructions; - this.pos = te.getBlockPos(); + this.te = te; compareTag = Instruction.serializeAll(instructions); } @Override protected void init() { + if (te.computerBehaviour.hasAttachedComputer()) + minecraft.setScreen(new ComputerScreen(title, this::renderAdditional, + this, te.computerBehaviour::hasAttachedComputer)); + setWindowSize(background.width, background.height); setWindowOffset(-20, 0); super.init(); @@ -127,6 +131,15 @@ public class SequencedGearshiftScreen extends AbstractSimiScreen { modifier.setState(instruction.speedModifier.ordinal()); } + @Override + public void tick() { + super.tick(); + + if (te.computerBehaviour.hasAttachedComputer()) + minecraft.setScreen(new ComputerScreen(title, this::renderAdditional, + this, te.computerBehaviour::hasAttachedComputer)); + } + @Override protected void renderWindow(PoseStack ms, int mouseX, int mouseY, float partialTicks) { int x = guiLeft; @@ -134,6 +147,13 @@ public class SequencedGearshiftScreen extends AbstractSimiScreen { background.render(ms, x, y, this); + for (int row = 0; row < instructions.capacity(); row++) { + AllGuiTextures toDraw = AllGuiTextures.SEQUENCER_EMPTY; + int yOffset = toDraw.height * row; + + toDraw.render(ms, x, y + 14 + yOffset, this); + } + for (int row = 0; row < instructions.capacity(); row++) { AllGuiTextures toDraw = AllGuiTextures.SEQUENCER_EMPTY; int yOffset = toDraw.height * row; @@ -156,10 +176,13 @@ public class SequencedGearshiftScreen extends AbstractSimiScreen { label(ms, 127, yOffset - 3, instruction.speedModifier.label); } + renderAdditional(ms, mouseX, mouseY, partialTicks, x, y, background); drawCenteredString(ms, font, title, x + (background.width - 8) / 2, y + 3, 0xFFFFFF); + } + private void renderAdditional(PoseStack ms, int mouseX, int mouseY, float partialTicks, int guiLeft, int guiTop, AllGuiTextures background) { GuiGameElement.of(renderedItem) - .at(x + background.width + 6, y + background.height - 56, -200) + .at(guiLeft + background.width + 6, guiTop + background.height - 56, 100) .scale(5) .render(ms); } @@ -172,7 +195,7 @@ public class SequencedGearshiftScreen extends AbstractSimiScreen { ListTag serialized = Instruction.serializeAll(instructions); if (serialized.equals(compareTag)) return; - AllPackets.channel.sendToServer(new ConfigureSequencedGearshiftPacket(pos, serialized)); + AllPackets.channel.sendToServer(new ConfigureSequencedGearshiftPacket(te.getBlockPos(), serialized)); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftTileEntity.java index 9c595af72..2fd02b095 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftTileEntity.java @@ -1,8 +1,15 @@ package com.simibubi.create.content.contraptions.relays.advanced.sequencer; +import java.util.List; import java.util.Vector; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.compat.computercraft.AbstractComputerBehaviour; +import com.simibubi.create.compat.computercraft.ComputerCraftProxy; import com.simibubi.create.content.contraptions.relays.encased.SplitShaftTileEntity; +import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -10,6 +17,8 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { @@ -20,6 +29,8 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { int timer; boolean poweredPreviously; + public AbstractComputerBehaviour computerBehaviour; + public SequencedGearshiftTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); instructions = Instruction.createDefault(); @@ -30,6 +41,12 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { poweredPreviously = false; } + @Override + public void addBehaviours(List behaviours) { + super.addBehaviours(behaviours); + behaviours.add(computerBehaviour = ComputerCraftProxy.behaviour(this)); + } + @Override public void tick() { super.tick(); @@ -72,6 +89,8 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { } public void onRedstoneUpdate(boolean isPowered, boolean isRunning) { + if (computerBehaviour.hasAttachedComputer()) + return; if (!poweredPreviously && isPowered) risingFlank(); poweredPreviously = isPowered; @@ -105,7 +124,7 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { } } - protected void run(int instructionIndex) { + public void run(int instructionIndex) { Instruction instruction = getInstruction(instructionIndex); if (instruction == null || instruction.instruction == SequencerInstructions.END) { if (getModifier() != 0) @@ -156,6 +175,20 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { super.read(compound, clientPacket); } + @NotNull + @Override + public LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) { + if (computerBehaviour.isPeripheralCap(cap)) + return computerBehaviour.getPeripheralCapability(); + return super.getCapability(cap, side); + } + + @Override + public void invalidateCaps() { + super.invalidateCaps(); + computerBehaviour.removePeripheral(); + } + @Override public float getRotationSpeedModifier(Direction face) { if (isVirtual()) @@ -171,4 +204,8 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { .getSpeedModifier(); } + public Vector getInstructions() { + return this.instructions; + } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeTileEntity.java index bdd77ba69..bc320e85d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeTileEntity.java @@ -12,7 +12,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; -public class GaugeTileEntity extends KineticTileEntity implements IHaveGoggleInformation { +public abstract class GaugeTileEntity extends KineticTileEntity implements IHaveGoggleInformation { public float dialTarget; public float dialState; @@ -52,4 +52,5 @@ public class GaugeTileEntity extends KineticTileEntity implements IHaveGoggleInf return true; } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/SpeedGaugeTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/SpeedGaugeTileEntity.java index fb48c7209..5f853e7d9 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/SpeedGaugeTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/SpeedGaugeTileEntity.java @@ -2,24 +2,41 @@ package com.simibubi.create.content.contraptions.relays.gauge; import java.util.List; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.compat.computercraft.AbstractComputerBehaviour; +import com.simibubi.create.compat.computercraft.ComputerCraftProxy; import com.simibubi.create.content.contraptions.base.IRotate.SpeedLevel; import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; import net.minecraft.network.chat.Component; import net.minecraft.util.Mth; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; public class SpeedGaugeTileEntity extends GaugeTileEntity { + public AbstractComputerBehaviour computerBehaviour; + public SpeedGaugeTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); } + @Override + public void addBehaviours(List behaviours) { + super.addBehaviours(behaviours); + behaviours.add(computerBehaviour = ComputerCraftProxy.behaviour(this)); + } + @Override public void onSpeedChanged(float prevSpeed) { super.onSpeedChanged(prevSpeed); @@ -62,4 +79,19 @@ public class SpeedGaugeTileEntity extends GaugeTileEntity { .forGoggles(tooltip); return true; } + + @NotNull + @Override + public LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) { + if (computerBehaviour.isPeripheralCap(cap)) + return computerBehaviour.getPeripheralCapability(); + return super.getCapability(cap, side); + } + + @Override + public void invalidateCaps() { + super.invalidateCaps(); + computerBehaviour.removePeripheral(); + } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/StressGaugeTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/StressGaugeTileEntity.java index 665226cb1..8eb5c9d0e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/StressGaugeTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/StressGaugeTileEntity.java @@ -2,6 +2,11 @@ package com.simibubi.create.content.contraptions.relays.gauge; import java.util.List; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.compat.computercraft.AbstractComputerBehaviour; +import com.simibubi.create.compat.computercraft.ComputerCraftProxy; import com.simibubi.create.content.contraptions.base.IRotate.StressImpact; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.item.ItemDescription; @@ -13,14 +18,19 @@ import com.simibubi.create.foundation.utility.LangBuilder; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.util.Mth; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; public class StressGaugeTileEntity extends GaugeTileEntity { + public AbstractComputerBehaviour computerBehaviour; + static BlockPos lastSent; public StressGaugeTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { @@ -30,6 +40,7 @@ public class StressGaugeTileEntity extends GaugeTileEntity { @Override public void addBehaviours(List behaviours) { super.addBehaviours(behaviours); + behaviours.add(computerBehaviour = ComputerCraftProxy.behaviour(this)); registerAwardables(behaviours, AllAdvancements.STRESSOMETER, AllAdvancements.STRESSOMETER_MAXED); } @@ -141,4 +152,18 @@ public class StressGaugeTileEntity extends GaugeTileEntity { award(AllAdvancements.STRESSOMETER_MAXED); } + @NotNull + @Override + public LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) { + if (computerBehaviour.isPeripheralCap(cap)) + return computerBehaviour.getPeripheralCapability(); + return super.getCapability(cap, side); + } + + @Override + public void invalidateCaps() { + super.invalidateCaps(); + computerBehaviour.removePeripheral(); + } + } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/AllDisplayBehaviours.java b/src/main/java/com/simibubi/create/content/logistics/block/display/AllDisplayBehaviours.java index 55637bae2..5f73512f2 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/AllDisplayBehaviours.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/display/AllDisplayBehaviours.java @@ -9,6 +9,8 @@ import java.util.Map; import javax.annotation.Nullable; import com.simibubi.create.Create; +import com.simibubi.create.compat.Mods; +import com.simibubi.create.content.logistics.block.display.source.ComputerDisplaySource; import com.simibubi.create.content.logistics.block.display.source.DeathCounterDisplaySource; import com.simibubi.create.content.logistics.block.display.source.DisplaySource; import com.simibubi.create.content.logistics.block.display.source.EnchantPowerDisplaySource; @@ -237,5 +239,14 @@ public class AllDisplayBehaviours { assignTile(register(Create.asResource("scoreboard_display_source"), new ScoreboardDisplaySource()), BlockEntityType.COMMAND_BLOCK); assignTile(register(Create.asResource("enchant_power_display_source"), new EnchantPowerDisplaySource()), BlockEntityType.ENCHANTING_TABLE); assignBlock(register(Create.asResource("redstone_power_display_source"), new RedstonePowerDisplaySource()), Blocks.TARGET); + + Mods.COMPUTERCRAFT.executeIfInstalled(() -> () -> { + DisplayBehaviour computerDisplaySource = register(Create.asResource("computer_display_source"), new ComputerDisplaySource()); + + assignTile(computerDisplaySource, new ResourceLocation(Mods.COMPUTERCRAFT.asId(), "wired_modem_full")); + assignTile(computerDisplaySource, new ResourceLocation(Mods.COMPUTERCRAFT.asId(), "computer_normal")); + assignTile(computerDisplaySource, new ResourceLocation(Mods.COMPUTERCRAFT.asId(), "computer_advanced")); + assignTile(computerDisplaySource, new ResourceLocation(Mods.COMPUTERCRAFT.asId(), "computer_command")); + }); } } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/DisplayLinkTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/display/DisplayLinkTileEntity.java index 9d9a5f606..448afed55 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/DisplayLinkTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/display/DisplayLinkTileEntity.java @@ -2,6 +2,11 @@ package com.simibubi.create.content.logistics.block.display; import java.util.List; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.compat.computercraft.AbstractComputerBehaviour; +import com.simibubi.create.compat.computercraft.ComputerCraftProxy; import com.simibubi.create.content.logistics.block.display.source.DisplaySource; import com.simibubi.create.content.logistics.block.display.target.DisplayTarget; import com.simibubi.create.foundation.advancement.AllAdvancements; @@ -18,6 +23,8 @@ import net.minecraft.nbt.NbtUtils; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; public class DisplayLinkTileEntity extends SmartTileEntity { @@ -31,9 +38,11 @@ public class DisplayLinkTileEntity extends SmartTileEntity { public LerpedFloat glow; private boolean sendPulse; - + public int refreshTicks; + public AbstractComputerBehaviour computerBehaviour; + public DisplayLinkTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); targetOffset = BlockPos.ZERO; @@ -44,10 +53,16 @@ public class DisplayLinkTileEntity extends SmartTileEntity { glow.chase(0, 0.5f, Chaser.EXP); } + @Override + public void addBehaviours(List behaviours) { + behaviours.add(computerBehaviour = ComputerCraftProxy.behaviour(this)); + registerAwardables(behaviours, AllAdvancements.DISPLAY_LINK, AllAdvancements.DISPLAY_BOARD); + } + @Override public void tick() { super.tick(); - + if (isVirtual()) { glow.tickChaser(); return; @@ -59,9 +74,9 @@ public class DisplayLinkTileEntity extends SmartTileEntity { glow.tickChaser(); return; } - + refreshTicks++; - if (refreshTicks < activeSource.getPassiveRefreshTicks()) + if (refreshTicks < activeSource.getPassiveRefreshTicks() || !activeSource.shouldPassiveReset()) return; tickSource(); } @@ -114,13 +129,8 @@ public class DisplayLinkTileEntity extends SmartTileEntity { activeSource.transferData(context, activeTarget, targetLine); sendPulse = true; sendData(); - - award(AllAdvancements.DISPLAY_LINK); - } - @Override - public void addBehaviours(List behaviours) { - registerAwardables(behaviours, AllAdvancements.DISPLAY_LINK, AllAdvancements.DISPLAY_BOARD); + award(AllAdvancements.DISPLAY_LINK); } @Override @@ -133,7 +143,7 @@ public class DisplayLinkTileEntity extends SmartTileEntity { protected void write(CompoundTag tag, boolean clientPacket) { super.write(tag, clientPacket); writeGatheredData(tag); - if (clientPacket && activeTarget != null) + if (clientPacket && activeTarget != null) tag.putString("TargetType", activeTarget.id.toString()); if (clientPacket && sendPulse) { sendPulse = false; @@ -173,6 +183,21 @@ public class DisplayLinkTileEntity extends SmartTileEntity { sourceConfig = data.copy(); } + @NotNull + @Override + public LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) { + if (computerBehaviour.isPeripheralCap(cap)) + return computerBehaviour.getPeripheralCapability(); + + return super.getCapability(cap, side); + } + + @Override + public void invalidateCaps() { + super.invalidateCaps(); + computerBehaviour.removePeripheral(); + } + public void target(BlockPos targetPosition) { this.targetOffset = targetPosition.subtract(worldPosition); } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/ComputerDisplaySource.java b/src/main/java/com/simibubi/create/content/logistics/block/display/source/ComputerDisplaySource.java new file mode 100644 index 000000000..e3e988143 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/block/display/source/ComputerDisplaySource.java @@ -0,0 +1,33 @@ +package com.simibubi.create.content.logistics.block.display.source; + +import java.util.ArrayList; +import java.util.List; + +import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; +import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats; +import com.simibubi.create.foundation.utility.Components; + +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.MutableComponent; + +public class ComputerDisplaySource extends DisplaySource { + + @Override + public List provideText(DisplayLinkContext context, DisplayTargetStats stats) { + List components = new ArrayList<>(); + ListTag tag = context.sourceConfig().getList("ComputerSourceList", Tag.TAG_STRING); + + for (int i = 0; i < tag.size(); i++) { + components.add(Components.literal(tag.getString(i))); + } + + return components; + } + + @Override + public boolean shouldPassiveReset() { + return false; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/DisplaySource.java b/src/main/java/com/simibubi/create/content/logistics/block/display/source/DisplaySource.java index 5b9877273..d844a1ed1 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/DisplaySource.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/display/source/DisplaySource.java @@ -49,6 +49,10 @@ public abstract class DisplaySource extends DisplayBehaviour { return 100; }; + public boolean shouldPassiveReset() { + return true; + } + protected String getTranslationKey() { return id.getPath(); } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/Train.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/Train.java index a5a371013..8c237ceaf 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/Train.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/Train.java @@ -15,8 +15,6 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiConsumer; import java.util.function.Consumer; -import javax.annotation.Nullable; - import org.apache.commons.lang3.mutable.MutableBoolean; import org.apache.commons.lang3.mutable.MutableObject; @@ -51,7 +49,7 @@ import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.Pair; import com.simibubi.create.foundation.utility.VecHelper; - +import javax.annotation.Nullable; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -67,6 +65,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Explosion.BlockInteraction; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.common.ForgeHooks; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; @@ -86,6 +85,7 @@ public class Train { public boolean honk = false; public UUID id; + @Nullable public UUID owner; public TrackGraph graph; public Navigation navigation; @@ -124,7 +124,7 @@ public class Train { public int honkPitch; public float accumulatedSteamRelease; - + int tickOffset; double[] stress; @@ -277,7 +277,7 @@ public class Train { int carriageCount = carriages.size(); boolean stalled = false; double maxStress = 0; - + if (carriageWaitingForChunks != -1) distance = 0; @@ -317,7 +317,7 @@ public class Train { entries++; } } - + if (entries > 0) actual = total / entries; @@ -369,7 +369,7 @@ public class Train { .getLeadingPoint(); double totalStress = derailed ? 0 : leadingStress + trailingStress; - + boolean first = i == 0; boolean last = i == carriageCount - 1; int carriageType = first ? last ? Carriage.BOTH : Carriage.FIRST : last ? Carriage.LAST : Carriage.MIDDLE; @@ -1087,7 +1087,8 @@ public class Train { public CompoundTag write(DimensionPalette dimensions) { CompoundTag tag = new CompoundTag(); tag.putUUID("Id", id); - tag.putUUID("Owner", owner); + if (owner != null) + tag.putUUID("Owner", owner); if (graph != null) tag.putUUID("Graph", graph.id); tag.put("Carriages", NBTHelper.writeCompoundList(carriages, c -> c.write(dimensions))); @@ -1133,7 +1134,7 @@ public class Train { public static Train read(CompoundTag tag, Map trackNetworks, DimensionPalette dimensions) { UUID id = tag.getUUID("Id"); - UUID owner = tag.getUUID("Owner"); + UUID owner = tag.contains("Owner") ? tag.getUUID("Owner") : null; UUID graphId = tag.contains("Graph") ? tag.getUUID("Graph") : null; TrackGraph graph = graphId == null ? null : trackNetworks.get(graphId); List carriages = new ArrayList<>(); diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainPacket.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainPacket.java index 479b2699e..ec43cd9f9 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainPacket.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainPacket.java @@ -12,7 +12,6 @@ import com.simibubi.create.foundation.networking.SimplePacketBase; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.RegisteredObjects; - import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.Component; import net.minecraft.world.level.block.Block; @@ -37,7 +36,10 @@ public class TrainPacket extends SimplePacketBase { if (!add) return; - UUID owner = buffer.readUUID(); + UUID owner = null; + if (buffer.readBoolean()) + owner = buffer.readUUID(); + List carriages = new ArrayList<>(); List carriageSpacing = new ArrayList<>(); @@ -73,7 +75,9 @@ public class TrainPacket extends SimplePacketBase { if (!add) return; - buffer.writeUUID(train.owner); + buffer.writeBoolean(train.owner != null); + if (train.owner != null) + buffer.writeUUID(train.owner); buffer.writeVarInt(train.carriages.size()); for (Carriage carriage : train.carriages) { diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/AbstractStationScreen.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/AbstractStationScreen.java index ed32075ae..a1d5ea049 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/AbstractStationScreen.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/AbstractStationScreen.java @@ -7,6 +7,7 @@ import com.jozufozu.flywheel.core.PartialModel; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.CreateClient; +import com.simibubi.create.compat.computercraft.ComputerScreen; import com.simibubi.create.content.logistics.trains.entity.Carriage; import com.simibubi.create.content.logistics.trains.entity.Train; import com.simibubi.create.content.logistics.trains.entity.TrainIconType; @@ -15,6 +16,7 @@ import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.gui.element.GuiGameElement; import com.simibubi.create.foundation.gui.widget.IconButton; +import com.simibubi.create.foundation.utility.Components; import net.minecraft.world.level.block.state.properties.BlockStateProperties; @@ -39,6 +41,10 @@ public abstract class AbstractStationScreen extends AbstractSimiScreen { @Override protected void init() { + if (te.computerBehaviour.hasAttachedComputer()) + minecraft.setScreen(new ComputerScreen(title, () -> Components.literal(station.name), + this::renderAdditional, this, te.computerBehaviour::hasAttachedComputer)); + setWindowSize(background.width, background.height); super.init(); clearWidgets(); @@ -71,17 +77,29 @@ public abstract class AbstractStationScreen extends AbstractSimiScreen { return w; } + @Override + public void tick() { + super.tick(); + + if (te.computerBehaviour.hasAttachedComputer()) + minecraft.setScreen(new ComputerScreen(title, () -> Components.literal(station.name), + this::renderAdditional, this, te.computerBehaviour::hasAttachedComputer)); + } + @Override protected void renderWindow(PoseStack ms, int mouseX, int mouseY, float partialTicks) { int x = guiLeft; int y = guiTop; background.render(ms, x, y, this); + renderAdditional(ms, mouseX, mouseY, partialTicks, x, y, background); + } + private void renderAdditional(PoseStack ms, int mouseX, int mouseY, float partialTicks, int guiLeft, int guiTop, AllGuiTextures background) { ms.pushPose(); TransformStack msr = TransformStack.cast(ms); msr.pushPose() - .translate(x + background.width + 4, y + background.height + 4, 100) + .translate(guiLeft + background.width + 4, guiTop + background.height + 4, 100) .scale(40) .rotateX(-22) .rotateY(63); diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationEditPacket.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationEditPacket.java index e1ec084c7..2028aca9d 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationEditPacket.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationEditPacket.java @@ -1,19 +1,11 @@ package com.simibubi.create.content.logistics.trains.management.edgePoint.station; -import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.GraphLocation; -import com.simibubi.create.content.logistics.trains.entity.Train; import com.simibubi.create.foundation.networking.TileEntityConfigurationPacket; -import com.simibubi.create.foundation.utility.VecHelper; - import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; public class StationEditPacket extends TileEntityConfigurationPacket { @@ -92,18 +84,12 @@ public class StationEditPacket extends TileEntityConfigurationPacket station.assembling = true); + GlobalStation station = getStation(); + if (station != null) { + for (Train train : Create.RAILWAYS.sided(level).trains.values()) { + if (train.navigation.destination != station) + continue; + + GlobalStation preferredDestination = train.runtime.startCurrentInstruction(); + train.navigation.startNavigation(preferredDestination != null ? preferredDestination : station, Double.MAX_VALUE, false); + } + } + + return true; + } + + public boolean exitAssemblyMode() { + if (!isAssembling()) + return false; + + cancelAssembly(); + BlockState newState = getBlockState().setValue(StationBlock.ASSEMBLING, false); + level.setBlock(getBlockPos(), newState, 3); + refreshBlockState(); + + return updateStationState(station -> station.assembling = false); + } + + public boolean tryDisassembleTrain(@Nullable ServerPlayer sender) { + GlobalStation station = getStation(); + if (station == null) + return false; + + Train train = station.getPresentTrain(); + if (train == null) + return false; + + BlockPos trackPosition = edgePoint.getGlobalPosition(); + if (!train.disassemble(getAssemblyDirection(), trackPosition.above())) + return false; + + dropSchedule(sender); + return true; + } + public boolean isAssembling() { BlockState state = getBlockState(); return state.hasProperty(StationBlock.ASSEMBLING) && state.getValue(StationBlock.ASSEMBLING); @@ -341,6 +409,42 @@ public class StationTileEntity extends SmartTileEntity implements ITransformable return true; } + public void dropSchedule(@Nullable ServerPlayer sender) { + GlobalStation station = getStation(); + if (station == null) + return; + + Train train = station.getPresentTrain(); + if (train == null) + return; + + ItemStack schedule = train.runtime.returnSchedule(); + if (schedule.isEmpty()) + return; + if (sender != null && sender.getMainHandItem().isEmpty()) { + sender.getInventory() + .placeItemBackInInventory(schedule); + return; + } + + Vec3 v = VecHelper.getCenterOf(getBlockPos()); + ItemEntity itemEntity = new ItemEntity(getLevel(), v.x, v.y, v.z, schedule); + itemEntity.setDeltaMovement(Vec3.ZERO); + getLevel().addFreshEntity(itemEntity); + } + + private boolean updateStationState(Consumer updateState) { + GlobalStation station = getStation(); + GraphLocation graphLocation = edgePoint.determineGraphLocation(); + if (station == null || graphLocation == null) + return false; + + updateState.accept(station); + Create.RAILWAYS.sync.pointAdded(graphLocation.graph, station); + Create.RAILWAYS.markTracksDirty(); + return true; + } + public void refreshAssemblyInfo() { if (!edgePoint.hasValidTrack()) return; @@ -409,6 +513,14 @@ public class StationTileEntity extends SmartTileEntity implements ITransformable map.put(worldPosition, BoundingBox.fromCorners(startPosition, trackEnd)); } + public boolean updateName(String name) { + if (!updateStationState(station -> station.name = name)) + return false; + notifyUpdate(); + + return true; + } + public boolean isValidBogeyOffset(int i) { if ((i < 3 || bogeyCount == 0) && i != 0) return false; @@ -698,12 +810,20 @@ public class StationTileEntity extends SmartTileEntity implements ITransformable } @Override - public LazyOptional getCapability(Capability cap, Direction side) { + public @NotNull LazyOptional getCapability(@NotNull Capability cap, Direction side) { if (isItemHandlerCap(cap)) return depotBehaviour.getItemCapability(cap, side); + if (computerBehaviour.isPeripheralCap(cap)) + return computerBehaviour.getPeripheralCapability(); return super.getCapability(cap, side); } + @Override + public void invalidateCaps() { + super.invalidateCaps(); + computerBehaviour.removePeripheral(); + } + private void applyAutoSchedule() { ItemStack stack = getAutoSchedule(); if (!AllItems.SCHEDULE.isIn(stack)) diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/IScheduleInput.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/IScheduleInput.java index 4858e0974..41392f608 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/IScheduleInput.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/IScheduleInput.java @@ -25,6 +25,8 @@ public interface IScheduleInput { public abstract CompoundTag getData(); + public abstract void setData(CompoundTag data); + public default int slotsTargeted() { return 0; } @@ -40,7 +42,7 @@ public interface IScheduleInput { } public default void setItem(int slot, ItemStack stack) {} - + public default ItemStack getItem(int slot) { return ItemStack.EMPTY; } @@ -58,4 +60,4 @@ public interface IScheduleInput { return false; } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleDataEntry.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleDataEntry.java index 58b2eae7a..c2c7144c7 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleDataEntry.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleDataEntry.java @@ -3,33 +3,39 @@ package com.simibubi.create.content.logistics.trains.management.schedule; import net.minecraft.nbt.CompoundTag; public abstract class ScheduleDataEntry implements IScheduleInput { - + protected CompoundTag data; - + public ScheduleDataEntry() { data = new CompoundTag(); } - + @Override public CompoundTag getData() { return data; } - + + @Override + public void setData(CompoundTag data) { + this.data = data; + readAdditional(data); + } + protected void writeAdditional(CompoundTag tag) {}; protected void readAdditional(CompoundTag tag) {}; - + protected T enumData(String key, Class enumClass) { T[] enumConstants = enumClass.getEnumConstants(); return enumConstants[data.getInt(key) % enumConstants.length]; } - + protected String textData(String key) { return data.getString(key); } - + protected int intData(String key) { return data.getInt(key); } - + } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/FluidThresholdCondition.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/FluidThresholdCondition.java index 0c3f25f55..f9ab12a18 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/FluidThresholdCondition.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/FluidThresholdCondition.java @@ -68,7 +68,8 @@ public class FluidThresholdCondition extends CargoThresholdCondition { @Override protected void readAdditional(CompoundTag tag) { super.readAdditional(tag); - compareStack = ItemStack.of(tag.getCompound("Bucket")); + if (tag.contains("Bucket")) + compareStack = ItemStack.of(tag.getCompound("Bucket")); } @Override @@ -139,4 +140,4 @@ public class FluidThresholdCondition extends CargoThresholdCondition { Math.max(0, getThreshold() + offset), Lang.translateDirect("schedule.condition.threshold.buckets")); } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/ItemThresholdCondition.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/ItemThresholdCondition.java index 78905d201..81122ad73 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/ItemThresholdCondition.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/ItemThresholdCondition.java @@ -69,7 +69,8 @@ public class ItemThresholdCondition extends CargoThresholdCondition { @Override protected void readAdditional(CompoundTag tag) { super.readAdditional(tag); - stack = ItemStack.of(tag.getCompound("Item")); + if (tag.contains("Item")) + stack = ItemStack.of(tag.getCompound("Item")); } @Override @@ -131,4 +132,4 @@ public class ItemThresholdCondition extends CargoThresholdCondition { Math.max(0, getThreshold() + offset), Lang.translateDirect("schedule.condition.threshold." + (inStacks() ? "stacks" : "items"))); } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/RedstoneLinkCondition.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/RedstoneLinkCondition.java index 9bb8f4190..896c9a23f 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/RedstoneLinkCondition.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/RedstoneLinkCondition.java @@ -107,7 +107,8 @@ public class RedstoneLinkCondition extends ScheduleWaitCondition { @Override protected void readAdditional(CompoundTag tag) { - freq = Couple.deserializeEach(tag.getList("Frequency", Tag.TAG_COMPOUND), c -> Frequency.of(ItemStack.of(c))); + if (tag.contains("Frequency")) + freq = Couple.deserializeEach(tag.getList("Frequency", Tag.TAG_COMPOUND), c -> Frequency.of(ItemStack.of(c))); } @Override @@ -118,7 +119,7 @@ public class RedstoneLinkCondition extends ScheduleWaitCondition { .titled(Lang.translateDirect("schedule.condition.redstone_link.frequency_state")), "Inverted"); } - + @Override public MutableComponent getWaitingStatus(Level level, Train train, CompoundTag tag) { return Lang.translateDirect("schedule.condition.redstone_link.status"); diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/ScheduleWaitCondition.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/ScheduleWaitCondition.java index a8e307d6a..7da150cce 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/ScheduleWaitCondition.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/ScheduleWaitCondition.java @@ -16,16 +16,17 @@ import net.minecraft.world.level.Level; public abstract class ScheduleWaitCondition extends ScheduleDataEntry { public abstract boolean tickCompletion(Level level, Train train, CompoundTag context); - + protected void requestStatusToUpdate(CompoundTag context) { context.putInt("StatusVersion", context.getInt("StatusVersion") + 1); } - + public final CompoundTag write() { CompoundTag tag = new CompoundTag(); + CompoundTag dataCopy = data.copy(); + writeAdditional(dataCopy); tag.putString("Id", getId().toString()); - tag.put("Data", data.copy()); - writeAdditional(tag); + tag.put("Data", dataCopy); return tag; } @@ -43,11 +44,14 @@ public abstract class ScheduleWaitCondition extends ScheduleDataEntry { } ScheduleWaitCondition condition = supplier.get(); - condition.data = tag.getCompound("Data"); + // Left around for migration purposes. Data added in writeAdditional has moved into the "Data" tag condition.readAdditional(tag); + CompoundTag data = tag.getCompound("Data"); + condition.readAdditional(data); + condition.data = data; return condition; } public abstract MutableComponent getWaitingStatus(Level level, Train train, CompoundTag tag); -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/destination/ScheduleInstruction.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/destination/ScheduleInstruction.java index cc3554094..6e1e56354 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/destination/ScheduleInstruction.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/destination/ScheduleInstruction.java @@ -16,9 +16,10 @@ public abstract class ScheduleInstruction extends ScheduleDataEntry { public final CompoundTag write() { CompoundTag tag = new CompoundTag(); + CompoundTag dataCopy = data.copy(); + writeAdditional(dataCopy); tag.putString("Id", getId().toString()); - tag.put("Data", data.copy()); - writeAdditional(tag); + tag.put("Data", dataCopy); return tag; } @@ -36,9 +37,12 @@ public abstract class ScheduleInstruction extends ScheduleDataEntry { } ScheduleInstruction scheduleDestination = supplier.get(); - scheduleDestination.data = tag.getCompound("Data"); + // Left around for migration purposes. Data added in writeAdditional has moved into the "Data" tag scheduleDestination.readAdditional(tag); + CompoundTag data = tag.getCompound("Data"); + scheduleDestination.readAdditional(data); + scheduleDestination.data = data; return scheduleDestination; } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java b/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java index 53f9571e8..71946bbe2 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java +++ b/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java @@ -163,7 +163,7 @@ public enum AllGuiTextures implements ScreenElement { SPEECH_TOOLTIP_BACKGROUND("widgets", 0, 24, 8, 8), SPEECH_TOOLTIP_COLOR("widgets", 8, 24, 8, 8), - + TRAIN_HUD_SPEED_BG("widgets", 0, 190, 182, 5), TRAIN_HUD_SPEED("widgets", 0, 185, 182, 5), TRAIN_HUD_THROTTLE("widgets", 0, 195, 182, 5), @@ -175,7 +175,10 @@ public enum AllGuiTextures implements ScreenElement { TRAIN_PROMPT("widgets", 0, 230, 256, 16), // PlacementIndicator - PLACEMENT_INDICATOR_SHEET("placement_indicator", 0, 0, 16, 256); + PLACEMENT_INDICATOR_SHEET("placement_indicator", 0, 0, 16, 256), + + // ComputerCraft + COMPUTER("computer", 200, 102); ; diff --git a/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java b/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java index 10c6a635f..634fd8ec0 100644 --- a/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java +++ b/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java @@ -8,6 +8,7 @@ import java.util.function.Function; import java.util.function.Supplier; import com.simibubi.create.Create; +import com.simibubi.create.compat.computercraft.AttachedComputerPacket; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionBlockChangedPacket; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionDisassemblyPacket; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionRelocationPacket; @@ -184,7 +185,7 @@ public enum AllPackets { S_TRAIN_PROMPT(TrainPromptPacket.class, TrainPromptPacket::new, PLAY_TO_CLIENT), CONTRAPTION_RELOCATION(ContraptionRelocationPacket.class, ContraptionRelocationPacket::new, PLAY_TO_CLIENT), TRACK_GRAPH_ROLL_CALL(TrackGraphRollCallPacket.class, TrackGraphRollCallPacket::new, PLAY_TO_CLIENT), - + ATTACHED_COMPUTER(AttachedComputerPacket.class, AttachedComputerPacket::new, PLAY_TO_CLIENT), ; public static final ResourceLocation CHANNEL_NAME = Create.asResource("main"); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndex.java b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndex.java index ed44673e8..5abcce458 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndex.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndex.java @@ -3,6 +3,7 @@ package com.simibubi.create.foundation.ponder.content; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; import com.simibubi.create.Create; +import com.simibubi.create.compat.Mods; import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.ponder.PonderRegistrationHelper; import com.simibubi.create.foundation.ponder.PonderRegistry; @@ -20,8 +21,11 @@ import com.simibubi.create.foundation.ponder.content.trains.TrainScenes; import com.simibubi.create.foundation.ponder.content.trains.TrainSignalScenes; import com.simibubi.create.foundation.ponder.content.trains.TrainStationScenes; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.DyeColor; +import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; +import net.minecraftforge.registries.ForgeRegistries; public class PonderIndex { @@ -548,6 +552,12 @@ public class PonderIndex { .add(Blocks.COMMAND_BLOCK) .add(Blocks.TARGET); + Mods.COMPUTERCRAFT.executeIfInstalled(() -> () -> { + Block computer = ForgeRegistries.BLOCKS.getValue(new ResourceLocation(Mods.COMPUTERCRAFT.asId(), "computer_advanced")); + if (computer != null) + PonderRegistry.TAGS.forTag(PonderTag.DISPLAY_SOURCES).add(computer); + }); + PonderRegistry.TAGS.forTag(PonderTag.DISPLAY_TARGETS) .add(AllBlocks.ORANGE_NIXIE_TUBE) .add(AllBlocks.DISPLAY_BOARD) diff --git a/src/main/java/com/simibubi/create/foundation/utility/StringHelper.java b/src/main/java/com/simibubi/create/foundation/utility/StringHelper.java new file mode 100644 index 000000000..78521b4e5 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/StringHelper.java @@ -0,0 +1,46 @@ +package com.simibubi.create.foundation.utility; + +import java.util.Locale; + +public class StringHelper { + + public static String snakeCaseToCamelCase(String text) { + StringBuilder builder = new StringBuilder(); + builder.append(text.substring(0, 1).toUpperCase(Locale.ROOT)); + + for (int i = 1; i < text.length(); i++) { + int j = text.indexOf('_', i); + + if (j == -1) { + builder.append(text.substring(i)); + break; + } + + builder.append(text.substring(i, j).toLowerCase(Locale.ROOT)); + builder.append(text.substring(j + 1, j + 2).toUpperCase(Locale.ROOT)); + + i = j + 1; + } + + return builder.toString(); + } + + public static String camelCaseToSnakeCase(String text) { + StringBuilder builder = new StringBuilder(); + + for (char c : text.toCharArray()) { + if (Character.isUpperCase(c)) { + builder.append('_'); + builder.append(Character.toLowerCase(c)); + } else { + builder.append(c); + } + } + + if (builder.length() > 0 && builder.charAt(0) == '_') + builder.deleteCharAt(0); + + return builder.toString(); + } + +} diff --git a/src/main/resources/assets/create/textures/gui/computer.png b/src/main/resources/assets/create/textures/gui/computer.png new file mode 100644 index 0000000000000000000000000000000000000000..293bedad784f171501f1983784abcf863ba62ae0 GIT binary patch literal 1016 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911MRQ8&P5D>38$lZxy-8q?;K+f|3pAc6d z{r~^}M~@!exN-BwjT_gmUq5r^%%_97$BrG_v17-QB}*1BUc7&n%Y+FNy1ToZnwlyq zDoRR9^7Hf4($d1i!$U(u9UL6uj2JB~En^KCVhtE#fJmRg+}u1`pCMY0Aqt3e8KQI; zB6S!%^~EE#86tp4iy<6{G#LyG3|zED_4M@YHH7Wdg>BS@t<{9ARD~>6fJo3nS`oN+#hRG+_7|fh9KU{vh z{rl>?&(*(cqIT_^>9>47cX@fdSN#5|`~GX(z5ie5kJg`gfA9agr6nGCn5oH||AXF^ zC?=l6QvIwR`~`)Ed}s6zK4F;q=g%+yE5|E&pX)Pisq1T&H)YNEE5mNDbATy}bHn>| z`NeAD9|~H&iBxQ6jj^w>vEo0gx8UvLcbgcvH^5Lv7322M$ZW=2kq2_WI<1qk{T7wY zy&}$|nh|IUCYlxHP!@VMs-aA*z+{hF2BTO47+tu+)EBUr+rn*k_)B}&zspy!UJ+XG zwOHm4(4G~_2cEWX(0g5RI-uYs9d3@9zXff`dYdd7&r}=IWDX{bt>Io(;;l) z^z(gg=_gs8*d^x8{Tjr5gwNm&kYeGV5T}sT@F@I2al;cPM&^?3OgzjYh4EYm z#!bDS*E27<=c5tSkW>5bIm1cwU@p;w@A?P7%=SFW7jXFO7AN)!-+aKopOC}t+<|