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 374848f978
Author: simibubi <31564874+simibubi@users.noreply.github.com>
Date:   Fri May 12 13:22:29 2023 +0200

    Compilation dependency toggle

commit b2cd60b619
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 ee3a079bac
Author: Christian L.W <bebeu@bebeu.dk>
Date:   Thu Apr 13 00:55:20 2023 +0200

    Small tweaks to the wiki pages

commit 8e1e4e8bd3
Author: caelwarner <caelawarner@gmail.com>
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 952941e5fc
Author: caelwarner <caelawarner@gmail.com>
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 7f3ca1cfa0
Author: caelwarner <caelawarner@gmail.com>
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 fac1ebcd3f
Author: caelwarner <caelawarner@gmail.com>
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 3e21996984
Author: caelwarner <caelawarner@gmail.com>
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 7141c10025
Author: caelwarner <caelawarner@gmail.com>
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 909484ed5b
Author: caelwarner <caelawarner@gmail.com>
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 31ad3aa671
Author: caelwarner <caelawarner@gmail.com>
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 574cd93a89
Author: caelwarner <caelawarner@gmail.com>
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 94e3ed44ad
Author: caelwarner <caelawarner@gmail.com>
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 9afdcaded7
Author: caelwarner <caelawarner@gmail.com>
Date:   Thu Oct 20 10:18:37 2022 -0700

    Refactored PeripheralBase to SyncedPeripheral

commit 7d47fdcd06
Author: caelwarner <caelawarner@gmail.com>
Date:   Wed Oct 19 22:45:47 2022 -0700

    Made LuaFunction's final

commit 56a1210fff
Author: caelwarner <caelawarner@gmail.com>
Date:   Wed Oct 19 22:39:38 2022 -0700

    Created ComputerBehaviour behaviour

    - ComputerBehaviour replaces ComputerControllable and SyncedComputerControllable

commit 19d283b923
Author: caelwarner <caelawarner@gmail.com>
Date:   Wed Oct 19 16:05:48 2022 -0700

    Moved all peripheral classes to computercraft.peripherals package

commit ab18034b98
Author: caelwarner <caelawarner@gmail.com>
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 1091f3227c
Author: caelwarner <caelawarner@gmail.com>
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 18bfb216b1
Author: caelwarner <caelawarner@gmail.com>
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 96dc4db6dc
Author: caelwarner <caelawarner@gmail.com>
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 9a80781401
Author: caelwarner <caelawarner@gmail.com>
Date:   Tue Oct 4 19:36:08 2022 -0700

    Added PeripheralBase

commit d404f07319
Author: caelwarner <caelawarner@gmail.com>
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 654476d9f3
Author: caelwarner <caelawarner@gmail.com>
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 1420406ab7
Author: caelwarner <caelawarner@gmail.com>
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 47b8619d07
Author: caelwarner <caelawarner@gmail.com>
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 6591c2d46e
Author: caelwarner <caelawarner@gmail.com>
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
This commit is contained in:
simibubi 2023-05-12 13:41:28 +02:00
parent beb61708a0
commit 3ad4195dd6
57 changed files with 2152 additions and 158 deletions

View File

@ -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/'

View File

@ -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

View File

@ -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();

View File

@ -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));
}
}

View File

@ -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<AbstractComputerBehaviour> 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 <T> boolean isPeripheralCap(Capability<T> cap) {
return false;
}
public <T> LazyOptional<T> 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;
}
}

View File

@ -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<SyncedTileEntity> {
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);
}
}
}

View File

@ -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<SmartTileEntity, ? extends AbstractComputerBehaviour> fallbackFactory;
private static Function<SmartTileEntity, ? extends AbstractComputerBehaviour> computerFactory;
public static AbstractComputerBehaviour behaviour(SmartTileEntity ste) {
if (computerFactory == null)
return fallbackFactory.apply(ste);
return computerFactory.apply(ste);
}
}

View File

@ -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<Component> displayTitle;
private final RenderWindowFunction additional;
private final Screen previousScreen;
private final Supplier<Boolean> hasAttachedComputer;
private AbstractSimiWidget computerWidget;
private IconButton confirmButton;
public ComputerScreen(Component title, @Nullable RenderWindowFunction additional, Screen previousScreen, Supplier<Boolean> hasAttachedComputer) {
this(title, () -> title, additional, previousScreen, hasAttachedComputer);
}
public ComputerScreen(Component title, Supplier<Component> displayTitle, @Nullable RenderWindowFunction additional, Screen previousScreen, Supplier<Boolean> 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);
}
}

View File

@ -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;
}
}

View File

@ -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<IPeripheral> PERIPHERAL_CAPABILITY =
CapabilityManager.get(new CapabilityToken<>() {
});
LazyOptional<IPeripheral> peripheral;
NonNullSupplier<IPeripheral> peripheralSupplier;
public ComputerBehaviour(SmartTileEntity te) {
super(te);
this.peripheralSupplier = getPeripheralFor(te);
}
public static NonNullSupplier<IPeripheral> 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 <T> boolean isPeripheralCap(Capability<T> cap) {
return cap == PERIPHERAL_CAPABILITY;
}
@Override
public <T> LazyOptional<T> getPeripheralCapability() {
if (peripheral == null || !peripheral.isPresent())
peripheral = LazyOptional.of(peripheralSupplier);
return peripheral.cast();
}
@Override
public void removePeripheral() {
if (peripheral != null)
peripheral.invalidate();
}
}

View File

@ -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<Object, Object> {
private final Map<Object, Object> 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<Boolean> 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<String> stringKeySet() throws LuaException {
Set<String> 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<CreateLuaTable> tableValues() throws LuaException {
List<CreateLuaTable> 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<Object, Object> 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<Object> keySet() {
return map.keySet();
}
@NotNull
@Override
public Collection<Object> values() {
return map.values();
}
@NotNull
@Override
public Set<Entry<Object, Object>> entrySet() {
return map.entrySet();
}
}

View File

@ -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<DisplayLinkTileEntity> {
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";
}
}

View File

@ -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<SequencedGearshiftTileEntity> {
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";
}
}

View File

@ -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<SpeedControllerTileEntity> {
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";
}
}

View File

@ -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<SpeedGaugeTileEntity> {
public SpeedGaugePeripheral(SpeedGaugeTileEntity tile) {
super(tile);
}
@LuaFunction
public final float getSpeed() {
return this.tile.getSpeed();
}
@NotNull
@Override
public String getType() {
return "Create_Speedometer";
}
}

View File

@ -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<StationTileEntity> {
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";
}
}

View File

@ -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<StressGaugeTileEntity> {
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";
}
}

View File

@ -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<T extends SmartTileEntity> 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;
}
}

View File

@ -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 <T> LazyOptional<T> getCapability(@NotNull Capability<T> 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

View File

@ -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();

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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<Instruction> instructions;
private BlockPos pos;
private Vector<Vector<ScrollInput>> 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)
.<GuiGameElement.GuiRenderBuilder>at(x + background.width + 6, y + background.height - 56, -200)
.<GuiGameElement.GuiRenderBuilder>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

View File

@ -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<TileEntityBehaviour> 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 <T> LazyOptional<T> getCapability(@NotNull Capability<T> 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<Instruction> getInstructions() {
return this.instructions;
}
}

View File

@ -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;
}
}

View File

@ -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<TileEntityBehaviour> 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 <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) {
if (computerBehaviour.isPeripheralCap(cap))
return computerBehaviour.getPeripheralCapability();
return super.getCapability(cap, side);
}
@Override
public void invalidateCaps() {
super.invalidateCaps();
computerBehaviour.removePeripheral();
}
}

View File

@ -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<TileEntityBehaviour> 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 <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) {
if (computerBehaviour.isPeripheralCap(cap))
return computerBehaviour.getPeripheralCapability();
return super.getCapability(cap, side);
}
@Override
public void invalidateCaps() {
super.invalidateCaps();
computerBehaviour.removePeripheral();
}
}

View File

@ -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"));
});
}
}

View File

@ -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<TileEntityBehaviour> 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<TileEntityBehaviour> 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 <T> LazyOptional<T> getCapability(@NotNull Capability<T> 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);
}

View File

@ -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<MutableComponent> provideText(DisplayLinkContext context, DisplayTargetStats stats) {
List<MutableComponent> 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;
}
}

View File

@ -49,6 +49,10 @@ public abstract class DisplaySource extends DisplayBehaviour {
return 100;
};
public boolean shouldPassiveReset() {
return true;
}
protected String getTranslationKey() {
return id.getPath();
}

View File

@ -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<UUID, TrackGraph> 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<Carriage> carriages = new ArrayList<>();

View File

@ -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<Carriage> carriages = new ArrayList<>();
List<Integer> 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) {

View File

@ -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);

View File

@ -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<StationTileEntity> {
@ -92,18 +84,12 @@ public class StationEditPacket extends TileEntityConfigurationPacket<StationTile
BlockState blockState = level.getBlockState(blockPos);
if (dropSchedule) {
scheduleDropRequested(player, te);
te.dropSchedule(player);
return;
}
if (!name.isBlank()) {
GlobalStation station = te.getStation();
GraphLocation graphLocation = te.edgePoint.determineGraphLocation();
if (station != null && graphLocation != null) {
station.name = name;
Create.RAILWAYS.sync.pointAdded(graphLocation.graph, station);
Create.RAILWAYS.markTracksDirty();
}
te.updateName(name);
}
if (!(blockState.getBlock() instanceof StationBlock))
@ -120,89 +106,17 @@ public class StationEditPacket extends TileEntityConfigurationPacket<StationTile
assemblyComplete = te.getStation() != null && te.getStation()
.getPresentTrain() != null;
} else {
if (disassembleAndEnterMode(player, te))
if (te.tryDisassembleTrain(player) && te.tryEnterAssemblyMode())
te.refreshAssemblyInfo();
}
if (!assemblyComplete)
return;
}
if (isAssemblyMode == assemblyMode)
return;
BlockState newState = blockState.cycle(StationBlock.ASSEMBLING);
Boolean nowAssembling = newState.getValue(StationBlock.ASSEMBLING);
if (nowAssembling) {
if (!disassembleAndEnterMode(player, te))
return;
} else {
te.cancelAssembly();
}
level.setBlock(blockPos, newState, 3);
te.refreshBlockState();
if (nowAssembling)
te.refreshAssemblyInfo();
GlobalStation station = te.getStation();
GraphLocation graphLocation = te.edgePoint.determineGraphLocation();
if (station != null && graphLocation != null) {
station.assembling = nowAssembling;
Create.RAILWAYS.sync.pointAdded(graphLocation.graph, station);
Create.RAILWAYS.markTracksDirty();
if (nowAssembling)
for (Train train : Create.RAILWAYS.sided(level).trains.values()) {
if (train.navigation.destination != station)
continue;
GlobalStation preferredDestination = train.runtime.startCurrentInstruction();
if (preferredDestination != null)
train.navigation.startNavigation(preferredDestination, Double.MAX_VALUE, false);
else
train.navigation.startNavigation(station, Double.MAX_VALUE, false);
}
}
}
private void scheduleDropRequested(ServerPlayer sender, StationTileEntity te) {
GlobalStation station = te.getStation();
if (station == null)
return;
Train train = station.getPresentTrain();
if (train == null)
return;
ItemStack schedule = train.runtime.returnSchedule();
dropSchedule(sender, te, schedule);
}
private boolean disassembleAndEnterMode(ServerPlayer sender, StationTileEntity te) {
GlobalStation station = te.getStation();
if (station != null) {
Train train = station.getPresentTrain();
BlockPos trackPosition = te.edgePoint.getGlobalPosition();
ItemStack schedule = train == null ? ItemStack.EMPTY : train.runtime.returnSchedule();
if (train != null && !train.disassemble(te.getAssemblyDirection(), trackPosition.above()))
return false;
dropSchedule(sender, te, schedule);
}
return te.tryEnterAssemblyMode();
}
private void dropSchedule(ServerPlayer sender, StationTileEntity te, ItemStack schedule) {
if (schedule.isEmpty())
return;
if (sender.getMainHandItem()
.isEmpty()) {
sender.getInventory()
.placeItemBackInInventory(schedule);
return;
}
Vec3 v = VecHelper.getCenterOf(te.getBlockPos());
ItemEntity itemEntity = new ItemEntity(te.getLevel(), v.x, v.y, v.z, schedule);
itemEntity.setDeltaMovement(Vec3.ZERO);
te.getLevel()
.addFreshEntity(itemEntity);
if (assemblyMode)
te.enterAssemblyMode(player);
else
te.exitAssemblyMode();
}
@Override

View File

@ -345,6 +345,8 @@ public class StationScreen extends AbstractStationScreen {
@Override
public void removed() {
super.removed();
if (nameBox == null || trainNameBox == null)
return;
AllPackets.channel
.sendToServer(StationEditPacket.configure(te.getBlockPos(), switchingToAssemblyMode, nameBox.getValue()));
Train train = displayedTrain.get();

View File

@ -9,18 +9,24 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.UUID;
import java.util.function.Consumer;
import javax.annotation.Nullable;
import org.jetbrains.annotations.NotNull;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems;
import com.simibubi.create.AllSoundEvents;
import com.simibubi.create.Create;
import com.simibubi.create.compat.computercraft.AbstractComputerBehaviour;
import com.simibubi.create.compat.computercraft.ComputerCraftProxy;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.ITransformableTE;
import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform;
import com.simibubi.create.content.logistics.block.depot.DepotBehaviour;
import com.simibubi.create.content.logistics.block.display.DisplayLinkBlock;
import com.simibubi.create.content.logistics.trains.GraphLocation;
import com.simibubi.create.content.logistics.trains.IBogeyBlock;
import com.simibubi.create.content.logistics.trains.ITrackBlock;
import com.simibubi.create.content.logistics.trains.TrackEdge;
@ -47,6 +53,7 @@ import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.NBTHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.WorldAttached;
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser;
@ -60,9 +67,11 @@ import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.Mth;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.SoundType;
@ -85,6 +94,7 @@ public class StationTileEntity extends SmartTileEntity implements ITransformable
protected int failedCarriageIndex;
protected AssemblyException lastException;
protected DepotBehaviour depotBehaviour;
public AbstractComputerBehaviour computerBehaviour;
// for display
UUID imminentTrain;
@ -116,6 +126,7 @@ public class StationTileEntity extends SmartTileEntity implements ITransformable
depotBehaviour.addSubBehaviours(behaviours);
registerAwardables(behaviours, AllAdvancements.CONTRAPTION_ACTORS, AllAdvancements.TRAIN,
AllAdvancements.LONG_TRAIN, AllAdvancements.CONDUCTOR);
behaviours.add(computerBehaviour = ComputerCraftProxy.behaviour(this));
}
@Override
@ -314,6 +325,63 @@ public class StationTileEntity extends SmartTileEntity implements ITransformable
return true;
}
public boolean enterAssemblyMode(@Nullable ServerPlayer sender) {
if (isAssembling())
return false;
tryDisassembleTrain(sender);
if (!tryEnterAssemblyMode())
return false;
BlockState newState = getBlockState().setValue(StationBlock.ASSEMBLING, true);
level.setBlock(getBlockPos(), newState, 3);
refreshBlockState();
refreshAssemblyInfo();
updateStationState(station -> 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<GlobalStation> 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 <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
public <T> @NotNull LazyOptional<T> getCapability(@NotNull Capability<T> 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))

View File

@ -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;
}
}
}

View File

@ -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> T enumData(String key, Class<T> 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);
}
}

View File

@ -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"));
}
}
}

View File

@ -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")));
}
}
}

View File

@ -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");

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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);
;

View File

@ -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");

View File

@ -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)

View File

@ -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();
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1016 B

88
wiki/Lua-Display-Link.md Normal file
View File

@ -0,0 +1,88 @@
| Method | Description |
|---------------------------------------|------------------------------------------------------|
| [`setCursorPos(x, y)`](#setCursorPos) | Sets the cursor position |
| [`getCursorPos()`](#getCursorPos) | Gets the current cursor position |
| [`getSize()`](#getSize) | Gets the display size of the connected target |
| [`isColor()`](#isColor) | Whether the connected display target supports color |
| [`isColour()`](#isColour) | Whether the connected display target supports colour |
| [`write(text)`](#writetext) | Writes text at the current cursor position |
| [`clearLine()`](#clearLine) | Clears the line at the current cursor position |
| [`clear()`](#clear) | Clears the whole display |
| [`update()`](#update) | Pushes an update to the display target |
---
### `setCursorPos(x, y)`
Sets the cursor position. Can be outside the bounds of the connected display.
**Parameters**
- _x:_ `number` The cursor x position.
- _y:_ `number` The cursor y position.
---
### `getCursorPos()`
Gets the current cursor position.
**Returns**
- `number` The cursor x position.
- `number` The cursor y position.
---
### `getSize()`
Gets the size of the connected display target.
**Returns**
- `number` The width of the display.
- `number` The height of the display.
---
### `isColor()`
Checks whether the connected display target supports color.
**Returns**
- `boolean` Whether the display supports color.
---
### `isColour()`
Checks whether the connected display target supports colour.
**Returns**
- `boolean` Whether the display supports colour.
---
### `write(text)`
Writes text at the current cursor position, moving the cursor to the end of the text.
This only writes to an internal buffer. For the changes to show up on the display [`update()`](#update) must be used.
If the cursor is outside the bounds of the connected display, the text will not show up on the display.
This will overwrite any text currently at the cursor position.
**Parameters**
- _text:_ `string` The text to write.
**See also**
- [`update()`](#update) To push the changes to the display target.
---
### `clearLine()`
Clears the line at the current cursor position.
**See also**
- [`update()`](#update) To push the changes to the display target.
---
### `clear()`
Clears the whole display.
**See also**
- [`update()`](#update) To push the changes to the display target.
---
### `update()`
Pushes any changes to the connected display target.
Any changes made are only made to an internal buffer.
For them to show up on the display they must be pushed to the display using this function.
This allows for this peripheral to be better multithreaded and for users to be able to change multiple lines at once by
using multiple [`write(text)`](#writetext) calls and then one [`update()`](#update) call.
**See also**
- [`write(text)`](#writetext) To write text to the display target.

View File

@ -0,0 +1,18 @@
| Method | Description |
|-------------------------------------------------|----------------------------------------|
| [`setTargetSpeed(speed)`](#setTargetSpeedspeed) | Sets the target rotation speed |
| [`getTargetSpeed()`](#getTargetSpeed) | Gets the current target rotation speed |
---
### `setTargetSpeed(speed)`
Sets the rotation speed controller's target speed.
**Parameters**
- _speed:_ `number` The target speed in RPM. Must be an integer within the range of [-256..256]. Values outside of this range will be clamped.
---
### `getTargetSpeed()`
Gets the rotation speed controller's current target speed.
**Returns**
- `number` The current target rotation speed in RPM.

View File

@ -0,0 +1,28 @@
| Method | Description |
|--------------------------------------------------------|--------------------------------------------------------------|
| [`rotate(angle, [modifier])`](#rotateangle-modifier) | Rotates shaft by a set angle |
| [`move(distance, [modifier])`](#movedistance-modifier) | Rotates shaft to move Piston/Pulley/Gantry by a set distance |
| [`isRunning()`](#isRunning) | Whether the gearshift is currently spinning |
---
### `rotate(angle, [modifier])`
Rotates connected components by a set angle.
**Parameters**
- _angle:_ `number` Angle to rotate the shaft by in degrees. Must be a positive integer. To do backwards rotation, set _modifier_ to a negative value.
- _modifier?:_ `number = 1` Speed modifier which can be used to reverse rotation. Must be an integer within the range of [-2..2]. Values out of this range are ignored and the default of 1 is used.
---
### `move(distance, [modifier])`
Rotates connected components to move connected piston, pulley or gantry contractions by a set distance.
**Parameters**
- _distance:_ `number` Distance to move connected piston, pulley or gantry contraptions by. Must be a positive integer. To do backwards movement, set _modifier_ to a negative value.
- _modifier?:_ `number = 1` Speed modifier which can be used to reverse direction. Must be an integer within the range of [-2..2]. Values out of this range are ignored and the default of 1 is used.
---
### `isRunning()`
Checks if the sequenced gearshift is currently spinning.
**Returns**
- `boolean` Whether the sequenced gearshift is currently spinning.

10
wiki/Lua-Speedometer.md Normal file
View File

@ -0,0 +1,10 @@
| Method | Description |
|---------------------------|---------------------------------|
| [`getSpeed()`](#getSpeed) | Gets the current rotation speed |
---
### `getSpeed()`
Gets the current rotation speed of the attached components.
**Returns**
- `number` The current rotation speed in RPM.

18
wiki/Lua-Stressometer.md Normal file
View File

@ -0,0 +1,18 @@
| Method | Description |
|---------------------------------------------|--------------------------------|
| [`getStress()`](#getStress) | Gets the current stress level |
| [`getStressCapacity()`](#getStressCapacity) | Gets the total stress capacity |
---
### `getStress()`
Gets the connected network's current stress level.
**Returns**
- `number` The current stress level in SU.
---
### `getStressCapacity()`
Gets the connected network's total stress capacity.
**Returns**
- `number` The total stress capacity in SU.

195
wiki/Lua-Train-Schedule.md Normal file
View File

@ -0,0 +1,195 @@
Train schedules are represented by a table in Lua. The table contains a list of entries where each entry has a single instruction and multiple conditions.
Each instruction and condition has a `data` table that stores specific data about the instruction or condition.
```lua
schedule = {
cyclic = true, -- Does the schedule repeat itself after the end has been reached?
entries = { -- List of entries, each entry contains a single instruction and multiple conditions.
{
instruction = {
id = "create:destination", -- The different instructions are described below.
data = { -- Data that is stored about the instruction. Different for each instruction type.
text = "Station 1",
},
},
conditions = { -- List of lists of conditions. The outer list is the "OR" list
{ -- and the inner lists are "AND" lists.
{
id = "create:delay", -- The different conditions are described below.
data = { -- Data that is stored about the condition. Different for each condition type.
value = 5,
time_unit = 1,
},
},
{
id = "create:powered",
data = {},
},
},
{
{
id = "create:time_of_day",
data = {
rotation = 0,
hour = 14,
minute = 0,
},
},
},
},
},
},
}
```
---
## Instructions
| ID | Description |
|----------------------------------------------|---------------------------------|
| [`"create:destination"`](#createdestination) | Move to a certain train station |
| [`"create:rename"`](#createrename) | Change the schedule title |
| [`"create:throttle"`](#createthrottle) | Change the train's throttle |
---
### `"create:destination"`
Moves the train to the chosen train station. This instruction must have at least one condition.
**Data**
- _text:_ `string` The name of the station to travel to. Can include * as a wildcard.
---
### `"create:rename"`
Renames the schedule. This name shows up on display link targets. This instruction cannot have conditions.
**Data**
- _text:_ `string` The name to rename the schedule to.
---
### `"create:throttle"`
Changes the throttle of the train. This instruction cannot have conditions.
**Data**
- _value:_ `number` The throttle to set the train to. Must be an integer within the range of [5..100].
---
## Conditions
Conditions are stored in a list of lists of conditions. The inner lists contain conditions that get `AND`'ed together. They must all be met for that group to be true.
The outer list contains the `AND`'ed groups of conditions that get `OR`'ed together. Only one of the groups needs to be true for the schedule to move onto the next instruction.
| ID | Description |
|-----------------------------------------------------|-----------------------------------------------------|
| [`"create:delay"`](#createdelay) | Wait for a certain delay |
| [`"create:time_of_day"`](#createtimeofday) | Wait for a specific time of day |
| [`"create:fluid_threshold"`](#createfluidthreshold) | Wait for a certain amount of fluid to be on board |
| [`"create:item_threshold"`](#createitemthreshold) | Wait for a certain amount of items to be on board |
| [`"create:redstone_link"`](#createredstonelink) | Wait for a redstone link to be powered |
| [`"create:player_count"`](#createplayercount) | Wait for a certain amount of players to be on board |
| [`"create:idle"`](#createidle) | Wait for cargo loading inactivity |
| [`"create:unloaded"`](#createunloaded) | Wait for the current chunk to be unloaded |
| [`"create:powered"`](#createpowered) | Wait for the station to be powered |
---
### `"create:delay"`
Wait for a set delay. Can be measured in ticks, seconds or minutes.
**Data**
- _value:_ `number` The amount of time to wait for.
- _time_unit:_ `number` The unit of time. 0 for ticks, 1 for seconds and 2 for minutes.
---
### `"create:time_of_day"`
Wait for a time of day, then repeat at a specified interval.
**Data**
- _hour:_ `number` The hour of the day to wait for in a 24-hour format. Must be an integer within the range of [0..23].
- _minute:_ `number` The minute of the hour to wait for. Must be an integer within the range of [0..59].
- _rotation:_ `number` The interval to repeat at after the time of day has been met. Check the rotation table below for valid values. Must be an integer within the range of [0..9].
**Rotation**
| Rotation | Time Interval |
|----------|------------------|
| 0 | Every Day |
| 1 | Every 12 Hours |
| 2 | Every 6 Hours |
| 3 | Every 4 Hours |
| 4 | Every 3 Hours |
| 5 | Every 2 Hours |
| 6 | Every Hour |
| 7 | Every 45 Minutes |
| 8 | Every 30 Minutes |
| 9 | Every 15 Minutes |
---
### `"create:fluid_threshold"`
Wait for a certain amount of a specific fluid to be loaded onto the train.
**Data**
- _bucket:_ `table` The bucket item of the fluid.
- _threshold:_ `number` The threshold in number of buckets of fluid. Must be a positive integer.
- _operator:_ `number` Whether the condition should wait for the train to be loaded above the threshold, below the threshold or exactly at the threshold. 0 for greater than, 1 for less than, 2 for equal to.
- _measure:_ `number` The unit to measure the fluid in. This condition supports buckets as the only unit. Set to 0.
**See also**
- [Items](#items) How items are represented in Lua.
---
### `"create:item_threshold"`
Wait for a certain amount of a specific item to be loaded onto the train.
**Data**
- _item:_ `table` The item.
- _threshold:_ `number` The threshold of items. Must be a positive integer.
- _operator:_ `number` Whether the condition should wait for the train to be loaded above the threshold, below the threshold or exactly at the threshold. 0 for greater than, 1 for less than, 2 for equal to.
- _measure:_ `number` The unit to measure the items in. 0 for items. 1 for stacks of items.
**See also**
- [Items](#items) How items are represented in Lua.
---
### `"create:redstone_link"`
Wait for a redstone link to be powered.
**Data**
- _frequency:_ `{ table... }` A list of the two items making up the redstone link frequency.
- _inverted:_ `number` Whether the redstone link should be powered or not to meet the condition. 0 for powered. 1 for not powered.
**See also**
- [Items](#items) How items are represented in Lua.
---
### `"create:player_count"`
Wait for a certain amount of players to be seated on the train.
**Data**
- _count:_ `number` The number of players to be seated on the train. Must be a positive integer.
- _exact:_ `number` Whether the seated player count has to be exact to meet the condition. 0 for the exact amount of players seated, 1 for a greater than or equal amount of seated players.
---
### `"create:idle"`
Wait for a period of inactivity in loading or unloading the train. Can be measured in ticks, seconds or minutes.
**Data**
- _value:_ `number` The amount of idle time to meet the condition. Must be a positive integer.
- _time_unit:_ `number` The unit of time. 0 for ticks, 1 for seconds and 2 for minutes.
---
### `"create:unloaded"`
Wait for the chunk the train is in to be unloaded.
---
### `"create:powered"`
Wait for the station to be powered with a redstone signal.
---
## Items
In Lua, items are represented with an ID and a count.
```lua
item = {
id = "minecraft:stone",
count = 1,
}
```
- _id:_ `string` The ID of the item.
- _count:_ `number` The amount of items in the stack. For the purposes of working with train schedules the count should always be 1. Must be an integer.

179
wiki/Lua-Train-Station.md Normal file
View File

@ -0,0 +1,179 @@
| Method | Description |
|-----------------------------------------------------------------|----------------------------------------------------|
| [`assemble()`](#assemble) | Assembles a new train at the station |
| [`disassemble()`](#disassemble) | Disassembles the currently present train |
| [`setAssemblyMode(assemblyMode)`](#setAssemblyModeassemblyMode) | Sets the station's assembly mode |
| [`isInAssemblyMode()`](#isInAssemblyMode) | Whether the station is in assembly mode |
| [`getStationName()`](#getStationName) | Gets the station's current name |
| [`setStationName(name)`](#setStationNamename) | Sets the station's name |
| [`isTrainPresent()`](#isTrainPresent) | Whether a train is present at the station |
| [`isTrainImminent()`](#isTrainImminent) | Whether a train is imminent to the station |
| [`isTrainEnroute()`](#isTrainEnroute) | Whether a train is enroute to the station |
| [`getTrainName()`](#getTrainName) | Gets the currently present train's name |
| [`setTrainName(name)`](#setTrainNamename) | Sets the currently present train's name |
| [`hasSchedule()`](#hasSchedule) | Whether the currently present train has a schedule |
| [`getSchedule()`](#getSchedule) | Gets the currently present train's schedule |
| [`setSchedule(schedule)`](#setScheduleschedule) | Sets the currently present train's schedule |
---
### `assemble()`
Assembles a new train at the station. The station must be in assembly mode prior to calling this function.
This function also causes the station to exit assembly mode after the train is done assembing.
**Throws**
- If the station is not in assembly mode.
- If the station is not connected to a track.
- If the train failed to assemble.
- If the station failed to exit assembly mode.
**See also**
- [`setAssemblyMode(assemblyMode)`](#setAssemblyModeassemblyMode) To set the assembly mode of the station.
---
### `disassemble()`
Disassembles the station's currently present train. The station must not be in assembly mode.
**Throws**
- If the station is in assembly mode.
- If the station is not connected to a track.
- If there is currently no train present at the station.
- If the train failed to disassemble.
**See also**
- [`setAssemblyMode(assemblyMode)`](#setAssemblyModeassemblyMode) To set the assembly mode of the station.
---
### `setAssemblyMode(assemblyMode)`
Sets the station's assembly mode.
**Parameters**
- _assemblyMode:_ `boolean` Whether the station should be in assembly mode.
**Throws**
- If the station fails to enter or exit assembly mode.
- If the station is not connected to a track.
---
### `isInAssemblyMode()`
Checks whether the station is in assembly mode.
**Returns**
- `boolean` Whether the station is in assembly mode.
---
### `getStationName()`
Gets the station's current name.
**Returns**
- `string` The station's current name.
**Throws**
- If the station is not connected to a track.
---
### `setStationName(name)`
Sets the station's name.
**Parameters**
- _name:_ `string` What to set the station's name to.
**Throws**
- If the station name fails to be set.
- If the station is not connected to a track.
---
### `isTrainPresent()`
Checks whether a train is currently present at the station.
**Returns**
- `boolean` Whether a train is present at the station.
**Throws**
- If the station is not connected to a track.
---
### `isTrainImminent()`
Checks whether a train is imminently arriving at the station.
Imminent is defined as being within 30 blocks of the station.
This will not be true if the train has arrived and stopped at the station.
**Returns**
- `boolean` Whether a train is imminent to the station.
**Throws**
- If the station is not connected to a track.
**See also**
- [`isTrainPresent()`](#isTrainPresent) To check if a train is present at the station.
---
### `isTrainEnroute()`
Checks whether a train is enroute and navigating to the station.
**Returns**
- `boolean` Whether a train is enroute to the station.
**Throws**
- If the station is not connected to a track.
---
### `getTrainName()`
Gets the currently present train's name.
**Returns**
- `string` The currently present train's name.
**Throws**
- If the station is not connected to a track.
- If there is currently no train present at the station.
---
### `setTrainName(name)`
Sets the currently present train's name.
**Parameters**
- _name:_ `string` What to set the currently present train's name to.
**Throws**
- If the station is not connected to a track.
- If there is currently no train present at the station.
---
### `hasSchedule()`
Checks whether the currently present train has a schedule.
**Returns**
- `boolean` Whether the currently present train has a schedule.
**Throws**
- If the station is not connected to a track.
- If there is currently no train present at the station.
---
### `getSchedule()`
Gets the currently present train's schedule.
**Returns**
- `table` The train's schedule
**Throws**
- If the station is not connected to a track.
- If there is currently no train present at the station.
- If the present train doesn't have a schedule.
**See also**
- [Lua Train Schedules](#Lua-Train-Schedules) How train schedules are represented in Lua.
---
### `setSchedule(schedule)`
Sets the currently present train's schedule. This will overwrite the currently set schedule.
**Parameters**
- _schedule:_ `table` The schedule to set the present train to.
**Throws**
- If the station is not connected to a track.
- If there is currently no train present at the station.
**See also**
- [Lua Train Schedules](#Lua-Train-Schedules) How train schedules are represented in Lua.

2
wiki/README.md Normal file
View File

@ -0,0 +1,2 @@
Just before this PR is about to be merged this /wiki folder will be removed from the PR and the pages will be added to
the wiki section of the Create GitHub under API Reference