2023-03-15 21:52:13 +00:00
|
|
|
// Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
|
|
|
//
|
|
|
|
// SPDX-License-Identifier: LicenseRef-CCPL
|
|
|
|
|
2017-05-01 13:32:39 +00:00
|
|
|
package dan200.computercraft.shared.computer.blocks;
|
|
|
|
|
2022-11-08 17:44:06 +00:00
|
|
|
import com.google.common.base.Strings;
|
2022-10-21 18:51:23 +00:00
|
|
|
import dan200.computercraft.api.ComputerCraftAPI;
|
2022-11-08 17:44:06 +00:00
|
|
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
2019-04-09 09:02:54 +00:00
|
|
|
import dan200.computercraft.core.computer.ComputerSide;
|
2022-11-09 23:58:56 +00:00
|
|
|
import dan200.computercraft.impl.BundledRedstone;
|
2024-04-25 19:17:43 +00:00
|
|
|
import dan200.computercraft.shared.ModRegistry;
|
2017-05-01 13:32:39 +00:00
|
|
|
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
Update CC: Tweaked to 1.13
Look, I originally had this split into several commits, but lots of
other cleanups got mixed in. I then backported some of the cleanups to
1.12, did other tidy ups there, and eventually the web of merges was
unreadable.
Yes, this is a horrible mess, but it's still nicer than it was. Anyway,
changes:
- Flatten everything. For instance, there are now three instances of
BlockComputer, two BlockTurtle, ItemPocketComputer. There's also no
more BlockPeripheral (thank heavens) - there's separate block classes
for each peripheral type.
- Remove pretty much all legacy code. As we're breaking world
compatibility anyway, we can remove all the code to load worlds from
1.4 days.
- The command system is largely rewriten to take advantage of 1.13's
new system. It's very fancy!
- WidgetTerminal now uses Minecraft's "GUI listener" system.
- BREAKING CHANGE: All the codes in keys.lua are different, due to the
move to LWJGL 3. Hopefully this won't have too much of an impact.
I don't want to map to the old key codes on the Java side, as there
always ends up being small but slight inconsistencies. IMO it's
better to make a clean break - people should be using keys rather
than hard coding the constants anyway.
- commands.list now allows fetching sub-commands. The ROM has already
been updated to allow fancy usage such as commands.time.set("noon").
- Turtles, modems and cables can be waterlogged.
2019-04-02 12:27:27 +00:00
|
|
|
import dan200.computercraft.shared.computer.core.ComputerState;
|
2017-05-01 13:32:39 +00:00
|
|
|
import dan200.computercraft.shared.computer.core.ServerComputer;
|
2022-10-21 20:01:01 +00:00
|
|
|
import dan200.computercraft.shared.computer.core.ServerContext;
|
2022-11-08 17:44:06 +00:00
|
|
|
import dan200.computercraft.shared.platform.ComponentAccess;
|
|
|
|
import dan200.computercraft.shared.platform.PlatformHelper;
|
2024-04-25 19:17:43 +00:00
|
|
|
import dan200.computercraft.shared.util.*;
|
2021-08-03 20:46:53 +00:00
|
|
|
import net.minecraft.core.BlockPos;
|
|
|
|
import net.minecraft.core.Direction;
|
2024-04-25 19:17:43 +00:00
|
|
|
import net.minecraft.core.HolderLookup;
|
|
|
|
import net.minecraft.core.component.DataComponentMap;
|
|
|
|
import net.minecraft.core.component.DataComponents;
|
2021-08-03 20:46:53 +00:00
|
|
|
import net.minecraft.nbt.CompoundTag;
|
|
|
|
import net.minecraft.network.chat.Component;
|
2021-11-30 22:37:07 +00:00
|
|
|
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
2024-04-25 17:21:23 +00:00
|
|
|
import net.minecraft.world.Container;
|
2024-04-17 14:00:43 +00:00
|
|
|
import net.minecraft.world.LockCode;
|
|
|
|
import net.minecraft.world.MenuProvider;
|
|
|
|
import net.minecraft.world.Nameable;
|
2021-08-03 20:46:53 +00:00
|
|
|
import net.minecraft.world.entity.player.Player;
|
2022-05-27 21:28:55 +00:00
|
|
|
import net.minecraft.world.level.block.entity.BaseContainerBlockEntity;
|
2022-11-10 15:48:26 +00:00
|
|
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
2021-08-03 20:46:53 +00:00
|
|
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
|
|
|
import net.minecraft.world.level.block.state.BlockState;
|
2017-05-01 13:32:39 +00:00
|
|
|
|
2019-03-27 18:59:02 +00:00
|
|
|
import javax.annotation.Nullable;
|
2018-12-29 12:38:19 +00:00
|
|
|
import java.util.Objects;
|
Replace integer instance IDs with UUIDs
Here's a fun bug you can try at home:
- Create a new world
- Spawn in a pocket computer, turn it on, and place it in a chest.
- Reload the world - the pocket computer in the chest should now be
off.
- Spawn in a new pocket computer, and turn it on. The computer in chest
will also appear to be on!
This bug has been present since pocket computers were added (27th March,
2024).
When a pocket computer is added to a player's inventory, it is assigned
a unique *per-session* "instance id" , which is used to find the
associated computer. Note the "per-session" there - these ids will be
reused if you reload the world (or restart the server).
In the above bug, we see the following:
- The first pocket computer is assigned an instance id of 0.
- After reloading, the second pocket computer is assigned an instance
id of 0.
- If the first pocket computer was in our inventory, it'd be ticked and
assigned a new instance id. However, because it's in an inventory, it
keeps its old one.
- Both computers look up their client-side computer state and get the
same value, meaning the first pocket computer mirrors the second!
To fix this, we now ensure instance ids are entirely unique (not just
per-session). Rather than sequentially assigning an int, we now use a
random UUID (we probably could get away with a random long, but this
feels more idiomatic).
This has a couple of user-visible changes:
- /computercraft no longer lists instance ids outside of dumping an
individual computer.
- The @c[instance=...] selector uses UUIDs. We still use int instance
ids for the legacy selector, but that'll be removed in a later MC
version.
- Pocket computers now store a UUID rather than an int.
Related to this change (I made this change first, but then they got
kinda mixed up together), we now only create PocketComputerData when
receiving server data. This makes the code a little uglier in some
places (the data may now be null), but means we don't populate the
client-side pocket computer map with computers the server doesn't know
about.
2024-03-17 12:21:21 +00:00
|
|
|
import java.util.UUID;
|
2017-05-06 23:07:42 +00:00
|
|
|
|
2022-11-10 15:48:26 +00:00
|
|
|
public abstract class AbstractComputerBlockEntity extends BlockEntity implements IComputerBlockEntity, Nameable, MenuProvider {
|
Update CC: Tweaked to 1.13
Look, I originally had this split into several commits, but lots of
other cleanups got mixed in. I then backported some of the cleanups to
1.12, did other tidy ups there, and eventually the web of merges was
unreadable.
Yes, this is a horrible mess, but it's still nicer than it was. Anyway,
changes:
- Flatten everything. For instance, there are now three instances of
BlockComputer, two BlockTurtle, ItemPocketComputer. There's also no
more BlockPeripheral (thank heavens) - there's separate block classes
for each peripheral type.
- Remove pretty much all legacy code. As we're breaking world
compatibility anyway, we can remove all the code to load worlds from
1.4 days.
- The command system is largely rewriten to take advantage of 1.13's
new system. It's very fancy!
- WidgetTerminal now uses Minecraft's "GUI listener" system.
- BREAKING CHANGE: All the codes in keys.lua are different, due to the
move to LWJGL 3. Hopefully this won't have too much of an impact.
I don't want to map to the old key codes on the Java side, as there
always ends up being small but slight inconsistencies. IMO it's
better to make a clean break - people should be using keys rather
than hard coding the constants anyway.
- commands.list now allows fetching sub-commands. The ROM has already
been updated to allow fancy usage such as commands.time.set("noon").
- Turtles, modems and cables can be waterlogged.
2019-04-02 12:27:27 +00:00
|
|
|
private static final String NBT_ID = "ComputerId";
|
|
|
|
private static final String NBT_LABEL = "Label";
|
|
|
|
private static final String NBT_ON = "On";
|
|
|
|
|
Replace integer instance IDs with UUIDs
Here's a fun bug you can try at home:
- Create a new world
- Spawn in a pocket computer, turn it on, and place it in a chest.
- Reload the world - the pocket computer in the chest should now be
off.
- Spawn in a new pocket computer, and turn it on. The computer in chest
will also appear to be on!
This bug has been present since pocket computers were added (27th March,
2024).
When a pocket computer is added to a player's inventory, it is assigned
a unique *per-session* "instance id" , which is used to find the
associated computer. Note the "per-session" there - these ids will be
reused if you reload the world (or restart the server).
In the above bug, we see the following:
- The first pocket computer is assigned an instance id of 0.
- After reloading, the second pocket computer is assigned an instance
id of 0.
- If the first pocket computer was in our inventory, it'd be ticked and
assigned a new instance id. However, because it's in an inventory, it
keeps its old one.
- Both computers look up their client-side computer state and get the
same value, meaning the first pocket computer mirrors the second!
To fix this, we now ensure instance ids are entirely unique (not just
per-session). Rather than sequentially assigning an int, we now use a
random UUID (we probably could get away with a random long, but this
feels more idiomatic).
This has a couple of user-visible changes:
- /computercraft no longer lists instance ids outside of dumping an
individual computer.
- The @c[instance=...] selector uses UUIDs. We still use int instance
ids for the legacy selector, but that'll be removed in a later MC
version.
- Pocket computers now store a UUID rather than an int.
Related to this change (I made this change first, but then they got
kinda mixed up together), we now only create PocketComputerData when
receiving server data. This makes the code a little uglier in some
places (the data may now be null), but means we don't populate the
client-side pocket computer map with computers the server doesn't know
about.
2024-03-17 12:21:21 +00:00
|
|
|
private @Nullable UUID instanceID = null;
|
2021-01-15 16:35:49 +00:00
|
|
|
private int computerID = -1;
|
2022-11-09 18:58:31 +00:00
|
|
|
protected @Nullable String label = null;
|
2021-01-15 16:35:49 +00:00
|
|
|
private boolean on = false;
|
|
|
|
boolean startOn = false;
|
|
|
|
private boolean fresh = false;
|
2021-11-28 20:03:27 +00:00
|
|
|
|
|
|
|
private int invalidSides = 0;
|
2024-01-14 17:46:37 +00:00
|
|
|
private final ComponentAccess<IPeripheral> peripherals = PlatformHelper.get().createPeripheralAccess(this, d -> invalidSides |= 1 << d.ordinal());
|
2017-05-01 13:32:39 +00:00
|
|
|
|
2022-05-27 18:16:45 +00:00
|
|
|
private LockCode lockCode = LockCode.NO_LOCK;
|
|
|
|
|
Update CC: Tweaked to 1.13
Look, I originally had this split into several commits, but lots of
other cleanups got mixed in. I then backported some of the cleanups to
1.12, did other tidy ups there, and eventually the web of merges was
unreadable.
Yes, this is a horrible mess, but it's still nicer than it was. Anyway,
changes:
- Flatten everything. For instance, there are now three instances of
BlockComputer, two BlockTurtle, ItemPocketComputer. There's also no
more BlockPeripheral (thank heavens) - there's separate block classes
for each peripheral type.
- Remove pretty much all legacy code. As we're breaking world
compatibility anyway, we can remove all the code to load worlds from
1.4 days.
- The command system is largely rewriten to take advantage of 1.13's
new system. It's very fancy!
- WidgetTerminal now uses Minecraft's "GUI listener" system.
- BREAKING CHANGE: All the codes in keys.lua are different, due to the
move to LWJGL 3. Hopefully this won't have too much of an impact.
I don't want to map to the old key codes on the Java side, as there
always ends up being small but slight inconsistencies. IMO it's
better to make a clean break - people should be using keys rather
than hard coding the constants anyway.
- commands.list now allows fetching sub-commands. The ROM has already
been updated to allow fancy usage such as commands.time.set("noon").
- Turtles, modems and cables can be waterlogged.
2019-04-02 12:27:27 +00:00
|
|
|
private final ComputerFamily family;
|
|
|
|
|
2022-11-10 15:48:26 +00:00
|
|
|
public AbstractComputerBlockEntity(BlockEntityType<? extends AbstractComputerBlockEntity> type, BlockPos pos, BlockState state, ComputerFamily family) {
|
2021-08-03 20:46:53 +00:00
|
|
|
super(type, pos, state);
|
Update CC: Tweaked to 1.13
Look, I originally had this split into several commits, but lots of
other cleanups got mixed in. I then backported some of the cleanups to
1.12, did other tidy ups there, and eventually the web of merges was
unreadable.
Yes, this is a horrible mess, but it's still nicer than it was. Anyway,
changes:
- Flatten everything. For instance, there are now three instances of
BlockComputer, two BlockTurtle, ItemPocketComputer. There's also no
more BlockPeripheral (thank heavens) - there's separate block classes
for each peripheral type.
- Remove pretty much all legacy code. As we're breaking world
compatibility anyway, we can remove all the code to load worlds from
1.4 days.
- The command system is largely rewriten to take advantage of 1.13's
new system. It's very fancy!
- WidgetTerminal now uses Minecraft's "GUI listener" system.
- BREAKING CHANGE: All the codes in keys.lua are different, due to the
move to LWJGL 3. Hopefully this won't have too much of an impact.
I don't want to map to the old key codes on the Java side, as there
always ends up being small but slight inconsistencies. IMO it's
better to make a clean break - people should be using keys rather
than hard coding the constants anyway.
- commands.list now allows fetching sub-commands. The ROM has already
been updated to allow fancy usage such as commands.time.set("noon").
- Turtles, modems and cables can be waterlogged.
2019-04-02 12:27:27 +00:00
|
|
|
this.family = family;
|
2017-05-01 13:32:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
protected void unload() {
|
Remove ClientComputer
Historically CC has maintained two computer registries; one on the
server (which runs the actual computer) and one on the client (which
stores the terminal and some small bits of additional data).
This means when a user opens the computer UI, we send the terminal
contents and store it in the client computer registry. We then send the
instance id alongside the "open container" packet, which is used to look
up the client computer (and thus terminal) in our client-side registry.
This patch makes the computer menu syncing behaviour more consistent
with vanilla. The initial terminal contents is sent alongside the "open
container" packet, and subsequent terminal changes apply /just/ to the
open container. Computer on/off state is synced via a vanilla
ContainerData/IIntArray.
Likewise, sending user input to the server now targets the open
container, rather than an arbitrary instance id.
The one remaining usage of ClientComputer is for pocket computers. For
these, we still need to sync the current on/off/blinking state and the
pocket computer light.
We don't need the full ClientComputer interface for this case (after
all, you can't send input to a pocket computer someone else is
holding!). This means we can tear out ClientComputer and
ClientComputerRegistry, replacing it with a much simpler
ClientPocketComputers store.
This in turn allows the following changes:
- Remove IComputer, as we no longer need to abstract over client and
server computers.
- Likewise, we can merge ComputerRegistry into the server
registry. This commit also cleans up the handling of instance IDs a
little bit: ServerComputers are now responsible for generating their
ID and adding/removing themselves from the registry.
- As the client-side terminal will never be null, we can remove a whole
bunch of null checks throughout the codebase.
- As the terminal is available immediately, we don't need to explicitly
pass in terminal sizes to the computer GUIs. This means we're no
longer reliant on those config values on the client side!
- Remove the "request computer state" packet. Pocket computers now
store which players need to know the computer state, automatically
sending data when a new player starts tracking the computer.
2022-10-21 17:17:42 +00:00
|
|
|
if (getLevel().isClientSide) return;
|
|
|
|
|
|
|
|
var computer = getServerComputer();
|
|
|
|
if (computer != null) computer.close();
|
Replace integer instance IDs with UUIDs
Here's a fun bug you can try at home:
- Create a new world
- Spawn in a pocket computer, turn it on, and place it in a chest.
- Reload the world - the pocket computer in the chest should now be
off.
- Spawn in a new pocket computer, and turn it on. The computer in chest
will also appear to be on!
This bug has been present since pocket computers were added (27th March,
2024).
When a pocket computer is added to a player's inventory, it is assigned
a unique *per-session* "instance id" , which is used to find the
associated computer. Note the "per-session" there - these ids will be
reused if you reload the world (or restart the server).
In the above bug, we see the following:
- The first pocket computer is assigned an instance id of 0.
- After reloading, the second pocket computer is assigned an instance
id of 0.
- If the first pocket computer was in our inventory, it'd be ticked and
assigned a new instance id. However, because it's in an inventory, it
keeps its old one.
- Both computers look up their client-side computer state and get the
same value, meaning the first pocket computer mirrors the second!
To fix this, we now ensure instance ids are entirely unique (not just
per-session). Rather than sequentially assigning an int, we now use a
random UUID (we probably could get away with a random long, but this
feels more idiomatic).
This has a couple of user-visible changes:
- /computercraft no longer lists instance ids outside of dumping an
individual computer.
- The @c[instance=...] selector uses UUIDs. We still use int instance
ids for the legacy selector, but that'll be removed in a later MC
version.
- Pocket computers now store a UUID rather than an int.
Related to this change (I made this change first, but then they got
kinda mixed up together), we now only create PocketComputerData when
receiving server data. This makes the code a little uglier in some
places (the data may now be null), but means we don't populate the
client-side pocket computer map with computers the server doesn't know
about.
2024-03-17 12:21:21 +00:00
|
|
|
instanceID = null;
|
2017-05-01 13:32:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2021-01-09 19:22:58 +00:00
|
|
|
public void setRemoved() {
|
|
|
|
super.setRemoved();
|
2022-11-10 15:48:26 +00:00
|
|
|
unload();
|
2017-05-01 13:32:39 +00:00
|
|
|
}
|
|
|
|
|
2024-04-25 19:17:43 +00:00
|
|
|
protected float getInteractRange() {
|
|
|
|
return Container.DEFAULT_DISTANCE_BUFFER;
|
2022-11-10 15:48:26 +00:00
|
|
|
}
|
|
|
|
|
2022-05-27 21:28:55 +00:00
|
|
|
public boolean isUsable(Player player) {
|
2022-11-10 15:48:26 +00:00
|
|
|
return BaseContainerBlockEntity.canUnlock(player, lockCode, getDisplayName())
|
2024-04-25 17:21:23 +00:00
|
|
|
&& Container.stillValidBlockEntity(this, player, getInteractRange());
|
2022-05-27 18:16:45 +00:00
|
|
|
}
|
|
|
|
|
2021-08-03 20:46:53 +00:00
|
|
|
protected void serverTick() {
|
2021-11-28 20:03:27 +00:00
|
|
|
if (getLevel().isClientSide) return;
|
2022-10-21 18:51:23 +00:00
|
|
|
if (computerID < 0 && !startOn) return; // Don't tick if we don't need a computer!
|
2021-11-28 20:03:27 +00:00
|
|
|
|
2021-08-03 20:46:53 +00:00
|
|
|
var computer = createServerComputer();
|
Update CC: Tweaked to 1.13
Look, I originally had this split into several commits, but lots of
other cleanups got mixed in. I then backported some of the cleanups to
1.12, did other tidy ups there, and eventually the web of merges was
unreadable.
Yes, this is a horrible mess, but it's still nicer than it was. Anyway,
changes:
- Flatten everything. For instance, there are now three instances of
BlockComputer, two BlockTurtle, ItemPocketComputer. There's also no
more BlockPeripheral (thank heavens) - there's separate block classes
for each peripheral type.
- Remove pretty much all legacy code. As we're breaking world
compatibility anyway, we can remove all the code to load worlds from
1.4 days.
- The command system is largely rewriten to take advantage of 1.13's
new system. It's very fancy!
- WidgetTerminal now uses Minecraft's "GUI listener" system.
- BREAKING CHANGE: All the codes in keys.lua are different, due to the
move to LWJGL 3. Hopefully this won't have too much of an impact.
I don't want to map to the old key codes on the Java side, as there
always ends up being small but slight inconsistencies. IMO it's
better to make a clean break - people should be using keys rather
than hard coding the constants anyway.
- commands.list now allows fetching sub-commands. The ROM has already
been updated to allow fancy usage such as commands.time.set("noon").
- Turtles, modems and cables can be waterlogged.
2019-04-02 12:27:27 +00:00
|
|
|
|
2024-03-06 18:56:40 +00:00
|
|
|
// Update any peripherals that have changed.
|
2021-11-28 20:03:27 +00:00
|
|
|
if (invalidSides != 0) {
|
|
|
|
for (var direction : DirectionUtil.FACINGS) {
|
2024-03-17 00:18:27 +00:00
|
|
|
if (DirectionUtil.isSet(invalidSides, direction)) refreshPeripheral(computer, direction);
|
2017-05-01 13:32:39 +00:00
|
|
|
}
|
2021-11-28 20:03:27 +00:00
|
|
|
}
|
Update CC: Tweaked to 1.13
Look, I originally had this split into several commits, but lots of
other cleanups got mixed in. I then backported some of the cleanups to
1.12, did other tidy ups there, and eventually the web of merges was
unreadable.
Yes, this is a horrible mess, but it's still nicer than it was. Anyway,
changes:
- Flatten everything. For instance, there are now three instances of
BlockComputer, two BlockTurtle, ItemPocketComputer. There's also no
more BlockPeripheral (thank heavens) - there's separate block classes
for each peripheral type.
- Remove pretty much all legacy code. As we're breaking world
compatibility anyway, we can remove all the code to load worlds from
1.4 days.
- The command system is largely rewriten to take advantage of 1.13's
new system. It's very fancy!
- WidgetTerminal now uses Minecraft's "GUI listener" system.
- BREAKING CHANGE: All the codes in keys.lua are different, due to the
move to LWJGL 3. Hopefully this won't have too much of an impact.
I don't want to map to the old key codes on the Java side, as there
always ends up being small but slight inconsistencies. IMO it's
better to make a clean break - people should be using keys rather
than hard coding the constants anyway.
- commands.list now allows fetching sub-commands. The ROM has already
been updated to allow fancy usage such as commands.time.set("noon").
- Turtles, modems and cables can be waterlogged.
2019-04-02 12:27:27 +00:00
|
|
|
|
2021-08-03 20:46:53 +00:00
|
|
|
// If the computer isn't on and should be, then turn it on
|
|
|
|
if (startOn || (fresh && on)) {
|
|
|
|
computer.turnOn();
|
|
|
|
startOn = false;
|
|
|
|
}
|
Update CC: Tweaked to 1.13
Look, I originally had this split into several commits, but lots of
other cleanups got mixed in. I then backported some of the cleanups to
1.12, did other tidy ups there, and eventually the web of merges was
unreadable.
Yes, this is a horrible mess, but it's still nicer than it was. Anyway,
changes:
- Flatten everything. For instance, there are now three instances of
BlockComputer, two BlockTurtle, ItemPocketComputer. There's also no
more BlockPeripheral (thank heavens) - there's separate block classes
for each peripheral type.
- Remove pretty much all legacy code. As we're breaking world
compatibility anyway, we can remove all the code to load worlds from
1.4 days.
- The command system is largely rewriten to take advantage of 1.13's
new system. It's very fancy!
- WidgetTerminal now uses Minecraft's "GUI listener" system.
- BREAKING CHANGE: All the codes in keys.lua are different, due to the
move to LWJGL 3. Hopefully this won't have too much of an impact.
I don't want to map to the old key codes on the Java side, as there
always ends up being small but slight inconsistencies. IMO it's
better to make a clean break - people should be using keys rather
than hard coding the constants anyway.
- commands.list now allows fetching sub-commands. The ROM has already
been updated to allow fancy usage such as commands.time.set("noon").
- Turtles, modems and cables can be waterlogged.
2019-04-02 12:27:27 +00:00
|
|
|
|
2021-08-03 20:46:53 +00:00
|
|
|
computer.keepAlive();
|
Update CC: Tweaked to 1.13
Look, I originally had this split into several commits, but lots of
other cleanups got mixed in. I then backported some of the cleanups to
1.12, did other tidy ups there, and eventually the web of merges was
unreadable.
Yes, this is a horrible mess, but it's still nicer than it was. Anyway,
changes:
- Flatten everything. For instance, there are now three instances of
BlockComputer, two BlockTurtle, ItemPocketComputer. There's also no
more BlockPeripheral (thank heavens) - there's separate block classes
for each peripheral type.
- Remove pretty much all legacy code. As we're breaking world
compatibility anyway, we can remove all the code to load worlds from
1.4 days.
- The command system is largely rewriten to take advantage of 1.13's
new system. It's very fancy!
- WidgetTerminal now uses Minecraft's "GUI listener" system.
- BREAKING CHANGE: All the codes in keys.lua are different, due to the
move to LWJGL 3. Hopefully this won't have too much of an impact.
I don't want to map to the old key codes on the Java side, as there
always ends up being small but slight inconsistencies. IMO it's
better to make a clean break - people should be using keys rather
than hard coding the constants anyway.
- commands.list now allows fetching sub-commands. The ROM has already
been updated to allow fancy usage such as commands.time.set("noon").
- Turtles, modems and cables can be waterlogged.
2019-04-02 12:27:27 +00:00
|
|
|
|
2021-08-03 20:46:53 +00:00
|
|
|
fresh = false;
|
|
|
|
computerID = computer.getID();
|
Update CC: Tweaked to 1.13
Look, I originally had this split into several commits, but lots of
other cleanups got mixed in. I then backported some of the cleanups to
1.12, did other tidy ups there, and eventually the web of merges was
unreadable.
Yes, this is a horrible mess, but it's still nicer than it was. Anyway,
changes:
- Flatten everything. For instance, there are now three instances of
BlockComputer, two BlockTurtle, ItemPocketComputer. There's also no
more BlockPeripheral (thank heavens) - there's separate block classes
for each peripheral type.
- Remove pretty much all legacy code. As we're breaking world
compatibility anyway, we can remove all the code to load worlds from
1.4 days.
- The command system is largely rewriten to take advantage of 1.13's
new system. It's very fancy!
- WidgetTerminal now uses Minecraft's "GUI listener" system.
- BREAKING CHANGE: All the codes in keys.lua are different, due to the
move to LWJGL 3. Hopefully this won't have too much of an impact.
I don't want to map to the old key codes on the Java side, as there
always ends up being small but slight inconsistencies. IMO it's
better to make a clean break - people should be using keys rather
than hard coding the constants anyway.
- commands.list now allows fetching sub-commands. The ROM has already
been updated to allow fancy usage such as commands.time.set("noon").
- Turtles, modems and cables can be waterlogged.
2019-04-02 12:27:27 +00:00
|
|
|
|
2024-03-06 18:56:40 +00:00
|
|
|
// If the on state has changed, mark as as dirty.
|
|
|
|
var newOn = computer.isOn();
|
|
|
|
if (on != newOn) {
|
|
|
|
on = newOn;
|
|
|
|
setChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the label has changed, mark as dirty and sync to client.
|
|
|
|
var newLabel = computer.getLabel();
|
|
|
|
if (!Objects.equals(label, newLabel)) {
|
|
|
|
label = newLabel;
|
|
|
|
BlockEntityHelpers.updateBlock(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update the block state if needed.
|
2021-08-03 20:46:53 +00:00
|
|
|
updateBlockState(computer.getState());
|
Update CC: Tweaked to 1.13
Look, I originally had this split into several commits, but lots of
other cleanups got mixed in. I then backported some of the cleanups to
1.12, did other tidy ups there, and eventually the web of merges was
unreadable.
Yes, this is a horrible mess, but it's still nicer than it was. Anyway,
changes:
- Flatten everything. For instance, there are now three instances of
BlockComputer, two BlockTurtle, ItemPocketComputer. There's also no
more BlockPeripheral (thank heavens) - there's separate block classes
for each peripheral type.
- Remove pretty much all legacy code. As we're breaking world
compatibility anyway, we can remove all the code to load worlds from
1.4 days.
- The command system is largely rewriten to take advantage of 1.13's
new system. It's very fancy!
- WidgetTerminal now uses Minecraft's "GUI listener" system.
- BREAKING CHANGE: All the codes in keys.lua are different, due to the
move to LWJGL 3. Hopefully this won't have too much of an impact.
I don't want to map to the old key codes on the Java side, as there
always ends up being small but slight inconsistencies. IMO it's
better to make a clean break - people should be using keys rather
than hard coding the constants anyway.
- commands.list now allows fetching sub-commands. The ROM has already
been updated to allow fancy usage such as commands.time.set("noon").
- Turtles, modems and cables can be waterlogged.
2019-04-02 12:27:27 +00:00
|
|
|
|
2024-03-06 18:56:40 +00:00
|
|
|
var changes = computer.pollAndResetChanges();
|
|
|
|
if (changes != 0) {
|
|
|
|
for (var direction : DirectionUtil.FACINGS) {
|
|
|
|
if ((changes & (1 << remapToLocalSide(direction).ordinal())) != 0) updateRedstoneTo(direction);
|
|
|
|
}
|
|
|
|
}
|
2017-05-01 13:32:39 +00:00
|
|
|
}
|
|
|
|
|
Update CC: Tweaked to 1.13
Look, I originally had this split into several commits, but lots of
other cleanups got mixed in. I then backported some of the cleanups to
1.12, did other tidy ups there, and eventually the web of merges was
unreadable.
Yes, this is a horrible mess, but it's still nicer than it was. Anyway,
changes:
- Flatten everything. For instance, there are now three instances of
BlockComputer, two BlockTurtle, ItemPocketComputer. There's also no
more BlockPeripheral (thank heavens) - there's separate block classes
for each peripheral type.
- Remove pretty much all legacy code. As we're breaking world
compatibility anyway, we can remove all the code to load worlds from
1.4 days.
- The command system is largely rewriten to take advantage of 1.13's
new system. It's very fancy!
- WidgetTerminal now uses Minecraft's "GUI listener" system.
- BREAKING CHANGE: All the codes in keys.lua are different, due to the
move to LWJGL 3. Hopefully this won't have too much of an impact.
I don't want to map to the old key codes on the Java side, as there
always ends up being small but slight inconsistencies. IMO it's
better to make a clean break - people should be using keys rather
than hard coding the constants anyway.
- commands.list now allows fetching sub-commands. The ROM has already
been updated to allow fancy usage such as commands.time.set("noon").
- Turtles, modems and cables can be waterlogged.
2019-04-02 12:27:27 +00:00
|
|
|
protected abstract void updateBlockState(ComputerState newState);
|
|
|
|
|
2017-05-01 13:32:39 +00:00
|
|
|
@Override
|
2024-04-25 19:17:43 +00:00
|
|
|
public void saveAdditional(CompoundTag nbt, HolderLookup.Provider registries) {
|
2017-05-01 13:32:39 +00:00
|
|
|
// Save ID, label and power state
|
2021-01-15 16:35:49 +00:00
|
|
|
if (computerID >= 0) nbt.putInt(NBT_ID, computerID);
|
2019-06-15 07:00:20 +00:00
|
|
|
if (label != null) nbt.putString(NBT_LABEL, label);
|
2021-01-15 16:35:49 +00:00
|
|
|
nbt.putBoolean(NBT_ON, on);
|
Update CC: Tweaked to 1.13
Look, I originally had this split into several commits, but lots of
other cleanups got mixed in. I then backported some of the cleanups to
1.12, did other tidy ups there, and eventually the web of merges was
unreadable.
Yes, this is a horrible mess, but it's still nicer than it was. Anyway,
changes:
- Flatten everything. For instance, there are now three instances of
BlockComputer, two BlockTurtle, ItemPocketComputer. There's also no
more BlockPeripheral (thank heavens) - there's separate block classes
for each peripheral type.
- Remove pretty much all legacy code. As we're breaking world
compatibility anyway, we can remove all the code to load worlds from
1.4 days.
- The command system is largely rewriten to take advantage of 1.13's
new system. It's very fancy!
- WidgetTerminal now uses Minecraft's "GUI listener" system.
- BREAKING CHANGE: All the codes in keys.lua are different, due to the
move to LWJGL 3. Hopefully this won't have too much of an impact.
I don't want to map to the old key codes on the Java side, as there
always ends up being small but slight inconsistencies. IMO it's
better to make a clean break - people should be using keys rather
than hard coding the constants anyway.
- commands.list now allows fetching sub-commands. The ROM has already
been updated to allow fancy usage such as commands.time.set("noon").
- Turtles, modems and cables can be waterlogged.
2019-04-02 12:27:27 +00:00
|
|
|
|
2022-05-27 18:16:45 +00:00
|
|
|
lockCode.addToTag(nbt);
|
|
|
|
|
2024-04-25 19:17:43 +00:00
|
|
|
super.saveAdditional(nbt, registries);
|
2017-05-01 13:32:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2024-04-25 19:17:43 +00:00
|
|
|
public final void loadAdditional(CompoundTag nbt, HolderLookup.Provider registries) {
|
|
|
|
super.loadAdditional(nbt, registries);
|
2022-11-10 15:48:26 +00:00
|
|
|
if (level != null && level.isClientSide) {
|
2024-04-25 19:17:43 +00:00
|
|
|
loadClient(nbt, registries);
|
2022-11-10 15:48:26 +00:00
|
|
|
} else {
|
2024-04-25 19:17:43 +00:00
|
|
|
loadServer(nbt, registries);
|
2022-11-10 15:48:26 +00:00
|
|
|
}
|
|
|
|
}
|
2017-05-01 13:32:39 +00:00
|
|
|
|
2024-04-25 19:17:43 +00:00
|
|
|
protected void loadServer(CompoundTag nbt, HolderLookup.Provider registries) {
|
Update CC: Tweaked to 1.13
Look, I originally had this split into several commits, but lots of
other cleanups got mixed in. I then backported some of the cleanups to
1.12, did other tidy ups there, and eventually the web of merges was
unreadable.
Yes, this is a horrible mess, but it's still nicer than it was. Anyway,
changes:
- Flatten everything. For instance, there are now three instances of
BlockComputer, two BlockTurtle, ItemPocketComputer. There's also no
more BlockPeripheral (thank heavens) - there's separate block classes
for each peripheral type.
- Remove pretty much all legacy code. As we're breaking world
compatibility anyway, we can remove all the code to load worlds from
1.4 days.
- The command system is largely rewriten to take advantage of 1.13's
new system. It's very fancy!
- WidgetTerminal now uses Minecraft's "GUI listener" system.
- BREAKING CHANGE: All the codes in keys.lua are different, due to the
move to LWJGL 3. Hopefully this won't have too much of an impact.
I don't want to map to the old key codes on the Java side, as there
always ends up being small but slight inconsistencies. IMO it's
better to make a clean break - people should be using keys rather
than hard coding the constants anyway.
- commands.list now allows fetching sub-commands. The ROM has already
been updated to allow fancy usage such as commands.time.set("noon").
- Turtles, modems and cables can be waterlogged.
2019-04-02 12:27:27 +00:00
|
|
|
// Load ID, label and power state
|
2021-01-15 16:35:49 +00:00
|
|
|
computerID = nbt.contains(NBT_ID) ? nbt.getInt(NBT_ID) : -1;
|
2019-06-15 07:00:20 +00:00
|
|
|
label = nbt.contains(NBT_LABEL) ? nbt.getString(NBT_LABEL) : null;
|
2021-01-15 16:35:49 +00:00
|
|
|
on = startOn = nbt.getBoolean(NBT_ON);
|
2022-05-27 18:16:45 +00:00
|
|
|
|
|
|
|
lockCode = LockCode.fromTag(nbt);
|
2017-05-01 13:32:39 +00:00
|
|
|
}
|
|
|
|
|
2024-04-25 19:17:43 +00:00
|
|
|
@Override
|
|
|
|
protected void applyImplicitComponents(DataComponentInput component) {
|
|
|
|
super.applyImplicitComponents(component);
|
|
|
|
label = DataComponentUtil.getCustomName(component.get(DataComponents.CUSTOM_NAME));
|
|
|
|
computerID = NonNegativeId.getId(component.get(ModRegistry.DataComponents.COMPUTER_ID.get()));
|
|
|
|
lockCode = component.getOrDefault(DataComponents.LOCK, LockCode.NO_LOCK);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void collectImplicitComponents(DataComponentMap.Builder builder) {
|
|
|
|
super.collectImplicitComponents(builder);
|
|
|
|
builder.set(ModRegistry.DataComponents.COMPUTER_ID.get(), NonNegativeId.of(computerID));
|
|
|
|
builder.set(DataComponents.CUSTOM_NAME, label == null ? null : Component.literal(label));
|
|
|
|
if (lockCode != LockCode.NO_LOCK) builder.set(DataComponents.LOCK, lockCode);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Deprecated
|
|
|
|
public void removeComponentsFromTag(CompoundTag tag) {
|
|
|
|
super.removeComponentsFromTag(tag);
|
|
|
|
tag.remove(NBT_ID);
|
|
|
|
tag.remove(NBT_LABEL);
|
|
|
|
tag.remove(LockCode.TAG_LOCK);
|
|
|
|
}
|
|
|
|
|
2019-04-09 09:02:54 +00:00
|
|
|
protected boolean isPeripheralBlockedOnSide(ComputerSide localSide) {
|
2017-05-01 13:32:39 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-06-08 12:36:31 +00:00
|
|
|
protected abstract Direction getDirection();
|
Update CC: Tweaked to 1.13
Look, I originally had this split into several commits, but lots of
other cleanups got mixed in. I then backported some of the cleanups to
1.12, did other tidy ups there, and eventually the web of merges was
unreadable.
Yes, this is a horrible mess, but it's still nicer than it was. Anyway,
changes:
- Flatten everything. For instance, there are now three instances of
BlockComputer, two BlockTurtle, ItemPocketComputer. There's also no
more BlockPeripheral (thank heavens) - there's separate block classes
for each peripheral type.
- Remove pretty much all legacy code. As we're breaking world
compatibility anyway, we can remove all the code to load worlds from
1.4 days.
- The command system is largely rewriten to take advantage of 1.13's
new system. It's very fancy!
- WidgetTerminal now uses Minecraft's "GUI listener" system.
- BREAKING CHANGE: All the codes in keys.lua are different, due to the
move to LWJGL 3. Hopefully this won't have too much of an impact.
I don't want to map to the old key codes on the Java side, as there
always ends up being small but slight inconsistencies. IMO it's
better to make a clean break - people should be using keys rather
than hard coding the constants anyway.
- commands.list now allows fetching sub-commands. The ROM has already
been updated to allow fancy usage such as commands.time.set("noon").
- Turtles, modems and cables can be waterlogged.
2019-04-02 12:27:27 +00:00
|
|
|
|
2019-06-08 12:36:31 +00:00
|
|
|
protected ComputerSide remapToLocalSide(Direction globalSide) {
|
Update CC: Tweaked to 1.13
Look, I originally had this split into several commits, but lots of
other cleanups got mixed in. I then backported some of the cleanups to
1.12, did other tidy ups there, and eventually the web of merges was
unreadable.
Yes, this is a horrible mess, but it's still nicer than it was. Anyway,
changes:
- Flatten everything. For instance, there are now three instances of
BlockComputer, two BlockTurtle, ItemPocketComputer. There's also no
more BlockPeripheral (thank heavens) - there's separate block classes
for each peripheral type.
- Remove pretty much all legacy code. As we're breaking world
compatibility anyway, we can remove all the code to load worlds from
1.4 days.
- The command system is largely rewriten to take advantage of 1.13's
new system. It's very fancy!
- WidgetTerminal now uses Minecraft's "GUI listener" system.
- BREAKING CHANGE: All the codes in keys.lua are different, due to the
move to LWJGL 3. Hopefully this won't have too much of an impact.
I don't want to map to the old key codes on the Java side, as there
always ends up being small but slight inconsistencies. IMO it's
better to make a clean break - people should be using keys rather
than hard coding the constants anyway.
- commands.list now allows fetching sub-commands. The ROM has already
been updated to allow fancy usage such as commands.time.set("noon").
- Turtles, modems and cables can be waterlogged.
2019-04-02 12:27:27 +00:00
|
|
|
return remapLocalSide(DirectionUtil.toLocal(getDirection(), globalSide));
|
|
|
|
}
|
|
|
|
|
2019-04-09 09:02:54 +00:00
|
|
|
protected ComputerSide remapLocalSide(ComputerSide localSide) {
|
2017-05-01 13:32:39 +00:00
|
|
|
return localSide;
|
|
|
|
}
|
|
|
|
|
2024-03-06 18:56:40 +00:00
|
|
|
/**
|
|
|
|
* Update the redstone input on a particular side.
|
|
|
|
* <p>
|
|
|
|
* This is called <em>immediately</em> when a neighbouring block changes (see {@link #neighborChanged(BlockPos)}).
|
|
|
|
*
|
|
|
|
* @param computer The current server computer.
|
|
|
|
* @param dir The direction to update in.
|
|
|
|
* @param targetPos The position of the adjacent block, equal to {@code getBlockPos().offset(dir)}.
|
|
|
|
*/
|
2022-11-09 18:58:31 +00:00
|
|
|
private void updateRedstoneInput(ServerComputer computer, Direction dir, BlockPos targetPos) {
|
2019-06-08 12:36:31 +00:00
|
|
|
var offsetSide = dir.getOpposite();
|
2019-04-09 10:11:12 +00:00
|
|
|
var localDir = remapToLocalSide(dir);
|
2019-04-22 10:40:19 +00:00
|
|
|
|
2024-04-06 07:38:44 +00:00
|
|
|
computer.setRedstoneInput(localDir, RedstoneUtil.getRedstoneInput(getLevel(), targetPos, dir));
|
2021-11-28 20:03:27 +00:00
|
|
|
computer.setBundledRedstoneInput(localDir, BundledRedstone.getOutput(getLevel(), targetPos, offsetSide));
|
2017-05-03 09:14:39 +00:00
|
|
|
}
|
|
|
|
|
2024-03-06 18:56:40 +00:00
|
|
|
/**
|
|
|
|
* Update the peripheral on a particular side.
|
|
|
|
* <p>
|
|
|
|
* This is called from {@link #serverTick()}, after a peripheral has been marked as invalid (such as in
|
|
|
|
* {@link #neighborChanged(BlockPos)})
|
|
|
|
*
|
|
|
|
* @param computer The current server computer.
|
|
|
|
* @param dir The direction to update in.
|
|
|
|
*/
|
2022-11-09 18:58:31 +00:00
|
|
|
private void refreshPeripheral(ServerComputer computer, Direction dir) {
|
2021-11-28 20:03:27 +00:00
|
|
|
invalidSides &= ~(1 << dir.ordinal());
|
2019-04-22 10:52:01 +00:00
|
|
|
|
2021-11-28 20:03:27 +00:00
|
|
|
var localDir = remapToLocalSide(dir);
|
|
|
|
if (isPeripheralBlockedOnSide(localDir)) return;
|
2019-04-22 10:52:01 +00:00
|
|
|
|
2024-01-14 17:46:37 +00:00
|
|
|
var peripheral = peripherals.get(dir);
|
2021-11-28 20:03:27 +00:00
|
|
|
computer.setPeripheral(localDir, peripheral);
|
2019-04-22 10:52:01 +00:00
|
|
|
}
|
|
|
|
|
2021-11-28 20:03:27 +00:00
|
|
|
public void updateInputsImmediately() {
|
2017-05-03 09:14:39 +00:00
|
|
|
var computer = getServerComputer();
|
2021-11-28 20:03:27 +00:00
|
|
|
if (computer != null) updateInputsImmediately(computer);
|
|
|
|
}
|
2019-04-02 10:50:13 +00:00
|
|
|
|
2021-11-28 20:03:27 +00:00
|
|
|
/**
|
|
|
|
* Update all redstone and peripherals.
|
2022-10-25 18:17:55 +00:00
|
|
|
* <p>
|
2021-11-28 20:03:27 +00:00
|
|
|
* This should only be really be called when the computer is being ticked (though there are some cases where it
|
|
|
|
* won't be), as peripheral scanning requires adjacent tiles to be in a "correct" state - which may not be the case
|
|
|
|
* if they're still updating!
|
|
|
|
*
|
|
|
|
* @param computer The current computer instance.
|
|
|
|
*/
|
2022-11-09 18:58:31 +00:00
|
|
|
private void updateInputsImmediately(ServerComputer computer) {
|
2021-11-28 20:03:27 +00:00
|
|
|
var pos = getBlockPos();
|
2019-06-08 12:36:31 +00:00
|
|
|
for (var dir : DirectionUtil.FACINGS) {
|
2021-11-28 20:03:27 +00:00
|
|
|
updateRedstoneInput(computer, dir, pos.relative(dir));
|
|
|
|
refreshPeripheral(computer, dir);
|
2017-05-03 09:14:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-06 18:56:40 +00:00
|
|
|
/**
|
|
|
|
* Called when a neighbour block changes.
|
|
|
|
* <p>
|
|
|
|
* This finds the side the neighbour block is on, and updates the inputs accordingly.
|
|
|
|
* <p>
|
|
|
|
* We do <strong>NOT</strong> update the peripheral immediately. Blocks and block entities are sometimes
|
|
|
|
* inconsistent at the point where an update is received, and so we instead just mark that side as dirty (see
|
|
|
|
* {@link #invalidSides}) and refresh it {@linkplain #serverTick() next tick}.
|
|
|
|
*
|
|
|
|
* @param neighbour The position of the neighbour block.
|
|
|
|
*/
|
|
|
|
public void neighborChanged(BlockPos neighbour) {
|
2017-05-01 13:32:39 +00:00
|
|
|
var computer = getServerComputer();
|
Update CC: Tweaked to 1.13
Look, I originally had this split into several commits, but lots of
other cleanups got mixed in. I then backported some of the cleanups to
1.12, did other tidy ups there, and eventually the web of merges was
unreadable.
Yes, this is a horrible mess, but it's still nicer than it was. Anyway,
changes:
- Flatten everything. For instance, there are now three instances of
BlockComputer, two BlockTurtle, ItemPocketComputer. There's also no
more BlockPeripheral (thank heavens) - there's separate block classes
for each peripheral type.
- Remove pretty much all legacy code. As we're breaking world
compatibility anyway, we can remove all the code to load worlds from
1.4 days.
- The command system is largely rewriten to take advantage of 1.13's
new system. It's very fancy!
- WidgetTerminal now uses Minecraft's "GUI listener" system.
- BREAKING CHANGE: All the codes in keys.lua are different, due to the
move to LWJGL 3. Hopefully this won't have too much of an impact.
I don't want to map to the old key codes on the Java side, as there
always ends up being small but slight inconsistencies. IMO it's
better to make a clean break - people should be using keys rather
than hard coding the constants anyway.
- commands.list now allows fetching sub-commands. The ROM has already
been updated to allow fancy usage such as commands.time.set("noon").
- Turtles, modems and cables can be waterlogged.
2019-04-02 12:27:27 +00:00
|
|
|
if (computer == null) return;
|
|
|
|
|
2019-06-08 12:36:31 +00:00
|
|
|
for (var dir : DirectionUtil.FACINGS) {
|
2021-11-28 20:03:27 +00:00
|
|
|
var offset = getBlockPos().relative(dir);
|
Update CC: Tweaked to 1.13
Look, I originally had this split into several commits, but lots of
other cleanups got mixed in. I then backported some of the cleanups to
1.12, did other tidy ups there, and eventually the web of merges was
unreadable.
Yes, this is a horrible mess, but it's still nicer than it was. Anyway,
changes:
- Flatten everything. For instance, there are now three instances of
BlockComputer, two BlockTurtle, ItemPocketComputer. There's also no
more BlockPeripheral (thank heavens) - there's separate block classes
for each peripheral type.
- Remove pretty much all legacy code. As we're breaking world
compatibility anyway, we can remove all the code to load worlds from
1.4 days.
- The command system is largely rewriten to take advantage of 1.13's
new system. It's very fancy!
- WidgetTerminal now uses Minecraft's "GUI listener" system.
- BREAKING CHANGE: All the codes in keys.lua are different, due to the
move to LWJGL 3. Hopefully this won't have too much of an impact.
I don't want to map to the old key codes on the Java side, as there
always ends up being small but slight inconsistencies. IMO it's
better to make a clean break - people should be using keys rather
than hard coding the constants anyway.
- commands.list now allows fetching sub-commands. The ROM has already
been updated to allow fancy usage such as commands.time.set("noon").
- Turtles, modems and cables can be waterlogged.
2019-04-02 12:27:27 +00:00
|
|
|
if (offset.equals(neighbour)) {
|
2021-11-28 20:03:27 +00:00
|
|
|
updateRedstoneInput(computer, dir, offset);
|
|
|
|
invalidSides |= 1 << dir.ordinal();
|
2020-04-29 16:37:02 +00:00
|
|
|
return;
|
2017-05-01 13:32:39 +00:00
|
|
|
}
|
|
|
|
}
|
2019-04-08 13:52:24 +00:00
|
|
|
|
2021-11-28 20:03:27 +00:00
|
|
|
// If the position is not any adjacent one, update all inputs. This is pretty terrible, but some redstone mods
|
|
|
|
// handle this incorrectly.
|
2024-03-06 18:56:40 +00:00
|
|
|
for (var dir : DirectionUtil.FACINGS) updateRedstoneInput(computer, dir, getBlockPos().relative(dir));
|
2024-03-17 00:18:27 +00:00
|
|
|
invalidSides = DirectionUtil.ALL_SIDES; // Mark all peripherals as dirty.
|
2020-05-15 16:09:12 +00:00
|
|
|
}
|
|
|
|
|
2024-03-20 10:07:29 +00:00
|
|
|
/**
|
|
|
|
* Called when a neighbour block's shape changes.
|
|
|
|
* <p>
|
|
|
|
* Unlike {@link #neighborChanged(BlockPos)}, we don't update redstone, only peripherals.
|
|
|
|
*
|
|
|
|
* @param direction The side that changed.
|
|
|
|
*/
|
|
|
|
public void neighbourShapeChanged(Direction direction) {
|
|
|
|
invalidSides |= 1 << direction.ordinal();
|
|
|
|
}
|
|
|
|
|
2021-11-28 20:03:27 +00:00
|
|
|
/**
|
2024-03-06 18:56:40 +00:00
|
|
|
* Update outputs in a specific direction.
|
|
|
|
*
|
|
|
|
* @param direction The direction to propagate outputs in.
|
2021-11-28 20:03:27 +00:00
|
|
|
*/
|
2024-03-06 18:56:40 +00:00
|
|
|
protected void updateRedstoneTo(Direction direction) {
|
|
|
|
RedstoneUtil.propagateRedstoneOutput(getLevel(), getBlockPos(), direction);
|
2023-07-22 12:49:26 +00:00
|
|
|
|
|
|
|
var computer = getServerComputer();
|
2024-03-06 18:56:40 +00:00
|
|
|
if (computer != null) updateRedstoneInput(computer, direction, getBlockPos().relative(direction));
|
2017-05-01 13:32:39 +00:00
|
|
|
}
|
|
|
|
|
2024-03-06 18:56:40 +00:00
|
|
|
/**
|
|
|
|
* Update all redstone outputs.
|
|
|
|
*/
|
|
|
|
public void updateRedstone() {
|
|
|
|
for (var dir : DirectionUtil.FACINGS) updateRedstoneTo(dir);
|
|
|
|
}
|
2017-05-01 13:32:39 +00:00
|
|
|
|
|
|
|
@Override
|
2019-04-02 10:50:13 +00:00
|
|
|
public final int getComputerID() {
|
2021-01-15 16:35:49 +00:00
|
|
|
return computerID;
|
2017-05-01 13:32:39 +00:00
|
|
|
}
|
|
|
|
|
2018-12-29 12:38:19 +00:00
|
|
|
@Override
|
2022-11-09 18:58:31 +00:00
|
|
|
public final @Nullable String getLabel() {
|
2019-06-14 19:55:32 +00:00
|
|
|
return label;
|
2018-12-29 12:38:19 +00:00
|
|
|
}
|
2017-05-01 13:32:39 +00:00
|
|
|
|
|
|
|
@Override
|
2019-04-02 10:50:13 +00:00
|
|
|
public final void setComputerID(int id) {
|
2021-01-15 16:35:49 +00:00
|
|
|
if (getLevel().isClientSide || computerID == id) return;
|
2018-12-30 16:14:07 +00:00
|
|
|
|
2021-01-15 16:35:49 +00:00
|
|
|
computerID = id;
|
2024-04-17 14:00:43 +00:00
|
|
|
BlockEntityHelpers.updateBlock(this);
|
2017-05-01 13:32:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2022-11-09 18:58:31 +00:00
|
|
|
public final void setLabel(@Nullable String label) {
|
2021-01-09 19:22:58 +00:00
|
|
|
if (getLevel().isClientSide || Objects.equals(this.label, label)) return;
|
2018-12-30 16:14:07 +00:00
|
|
|
|
2019-06-14 19:55:32 +00:00
|
|
|
this.label = label;
|
2018-12-30 16:14:07 +00:00
|
|
|
var computer = getServerComputer();
|
|
|
|
if (computer != null) computer.setLabel(label);
|
2024-04-17 14:00:43 +00:00
|
|
|
BlockEntityHelpers.updateBlock(this);
|
2017-05-01 13:32:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public ComputerFamily getFamily() {
|
Update CC: Tweaked to 1.13
Look, I originally had this split into several commits, but lots of
other cleanups got mixed in. I then backported some of the cleanups to
1.12, did other tidy ups there, and eventually the web of merges was
unreadable.
Yes, this is a horrible mess, but it's still nicer than it was. Anyway,
changes:
- Flatten everything. For instance, there are now three instances of
BlockComputer, two BlockTurtle, ItemPocketComputer. There's also no
more BlockPeripheral (thank heavens) - there's separate block classes
for each peripheral type.
- Remove pretty much all legacy code. As we're breaking world
compatibility anyway, we can remove all the code to load worlds from
1.4 days.
- The command system is largely rewriten to take advantage of 1.13's
new system. It's very fancy!
- WidgetTerminal now uses Minecraft's "GUI listener" system.
- BREAKING CHANGE: All the codes in keys.lua are different, due to the
move to LWJGL 3. Hopefully this won't have too much of an impact.
I don't want to map to the old key codes on the Java side, as there
always ends up being small but slight inconsistencies. IMO it's
better to make a clean break - people should be using keys rather
than hard coding the constants anyway.
- commands.list now allows fetching sub-commands. The ROM has already
been updated to allow fancy usage such as commands.time.set("noon").
- Turtles, modems and cables can be waterlogged.
2019-04-02 12:27:27 +00:00
|
|
|
return family;
|
2019-01-05 20:57:32 +00:00
|
|
|
}
|
|
|
|
|
2022-10-21 18:51:23 +00:00
|
|
|
public final ServerComputer createServerComputer() {
|
2022-11-09 18:58:31 +00:00
|
|
|
var server = getLevel().getServer();
|
|
|
|
if (server == null) throw new IllegalStateException("Cannot access server computer on the client.");
|
2022-11-03 23:43:14 +00:00
|
|
|
|
2018-12-30 16:14:07 +00:00
|
|
|
var changed = false;
|
2022-11-03 23:43:14 +00:00
|
|
|
|
2022-11-09 18:58:31 +00:00
|
|
|
var computer = ServerContext.get(server).registry().get(instanceID);
|
2021-11-28 20:03:27 +00:00
|
|
|
if (computer == null) {
|
2022-10-21 18:51:23 +00:00
|
|
|
if (computerID < 0) {
|
2022-12-03 15:02:00 +00:00
|
|
|
computerID = ComputerCraftAPI.createUniqueNumberedSaveDir(server, IDAssigner.COMPUTER);
|
2022-11-10 15:48:26 +00:00
|
|
|
BlockEntityHelpers.updateBlock(this);
|
2022-10-21 18:51:23 +00:00
|
|
|
}
|
|
|
|
|
Remove ClientComputer
Historically CC has maintained two computer registries; one on the
server (which runs the actual computer) and one on the client (which
stores the terminal and some small bits of additional data).
This means when a user opens the computer UI, we send the terminal
contents and store it in the client computer registry. We then send the
instance id alongside the "open container" packet, which is used to look
up the client computer (and thus terminal) in our client-side registry.
This patch makes the computer menu syncing behaviour more consistent
with vanilla. The initial terminal contents is sent alongside the "open
container" packet, and subsequent terminal changes apply /just/ to the
open container. Computer on/off state is synced via a vanilla
ContainerData/IIntArray.
Likewise, sending user input to the server now targets the open
container, rather than an arbitrary instance id.
The one remaining usage of ClientComputer is for pocket computers. For
these, we still need to sync the current on/off/blinking state and the
pocket computer light.
We don't need the full ClientComputer interface for this case (after
all, you can't send input to a pocket computer someone else is
holding!). This means we can tear out ClientComputer and
ClientComputerRegistry, replacing it with a much simpler
ClientPocketComputers store.
This in turn allows the following changes:
- Remove IComputer, as we no longer need to abstract over client and
server computers.
- Likewise, we can merge ComputerRegistry into the server
registry. This commit also cleans up the handling of instance IDs a
little bit: ServerComputers are now responsible for generating their
ID and adding/removing themselves from the registry.
- As the client-side terminal will never be null, we can remove a whole
bunch of null checks throughout the codebase.
- As the terminal is available immediately, we don't need to explicitly
pass in terminal sizes to the computer GUIs. This means we're no
longer reliant on those config values on the client side!
- Remove the "request computer state" packet. Pocket computers now
store which players need to know the computer state, automatically
sending data when a new player starts tracking the computer.
2022-10-21 17:17:42 +00:00
|
|
|
computer = createComputer(computerID);
|
|
|
|
instanceID = computer.register();
|
2021-01-15 16:35:49 +00:00
|
|
|
fresh = true;
|
2018-12-30 16:14:07 +00:00
|
|
|
changed = true;
|
|
|
|
}
|
2021-06-01 17:55:12 +00:00
|
|
|
|
2021-11-28 20:03:27 +00:00
|
|
|
if (changed) updateInputsImmediately(computer);
|
|
|
|
return computer;
|
2017-05-01 13:32:39 +00:00
|
|
|
}
|
|
|
|
|
2024-03-06 18:56:40 +00:00
|
|
|
protected abstract ServerComputer createComputer(int id);
|
|
|
|
|
2021-11-28 20:03:27 +00:00
|
|
|
@Nullable
|
2017-05-01 13:32:39 +00:00
|
|
|
public ServerComputer getServerComputer() {
|
2022-11-09 18:58:31 +00:00
|
|
|
return getLevel().isClientSide || getLevel().getServer() == null ? null : ServerContext.get(getLevel().getServer()).registry().get(instanceID);
|
2017-05-01 13:32:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Networking stuff
|
|
|
|
|
2021-11-30 22:01:09 +00:00
|
|
|
@Override
|
2021-11-30 22:37:07 +00:00
|
|
|
public final ClientboundBlockEntityDataPacket getUpdatePacket() {
|
2021-11-30 22:48:37 +00:00
|
|
|
return ClientboundBlockEntityDataPacket.create(this);
|
2021-11-30 22:01:09 +00:00
|
|
|
}
|
|
|
|
|
2017-05-01 13:32:39 +00:00
|
|
|
@Override
|
2024-04-25 19:17:43 +00:00
|
|
|
public CompoundTag getUpdateTag(HolderLookup.Provider registries) {
|
2021-11-30 22:01:09 +00:00
|
|
|
// We need this for pick block on the client side.
|
2024-04-25 19:17:43 +00:00
|
|
|
var nbt = super.getUpdateTag(registries);
|
2019-06-15 07:00:20 +00:00
|
|
|
if (label != null) nbt.putString(NBT_LABEL, label);
|
2021-01-15 16:35:49 +00:00
|
|
|
if (computerID >= 0) nbt.putInt(NBT_ID, computerID);
|
2021-11-30 22:01:09 +00:00
|
|
|
return nbt;
|
2017-05-01 13:32:39 +00:00
|
|
|
}
|
|
|
|
|
2024-04-25 19:17:43 +00:00
|
|
|
protected void loadClient(CompoundTag nbt, HolderLookup.Provider registries) {
|
2019-06-15 07:00:20 +00:00
|
|
|
label = nbt.contains(NBT_LABEL) ? nbt.getString(NBT_LABEL) : null;
|
2021-01-15 16:35:49 +00:00
|
|
|
computerID = nbt.contains(NBT_ID) ? nbt.getInt(NBT_ID) : -1;
|
2017-05-01 13:32:39 +00:00
|
|
|
}
|
|
|
|
|
2022-11-09 23:58:56 +00:00
|
|
|
protected void transferStateFrom(AbstractComputerBlockEntity copy) {
|
Replace integer instance IDs with UUIDs
Here's a fun bug you can try at home:
- Create a new world
- Spawn in a pocket computer, turn it on, and place it in a chest.
- Reload the world - the pocket computer in the chest should now be
off.
- Spawn in a new pocket computer, and turn it on. The computer in chest
will also appear to be on!
This bug has been present since pocket computers were added (27th March,
2024).
When a pocket computer is added to a player's inventory, it is assigned
a unique *per-session* "instance id" , which is used to find the
associated computer. Note the "per-session" there - these ids will be
reused if you reload the world (or restart the server).
In the above bug, we see the following:
- The first pocket computer is assigned an instance id of 0.
- After reloading, the second pocket computer is assigned an instance
id of 0.
- If the first pocket computer was in our inventory, it'd be ticked and
assigned a new instance id. However, because it's in an inventory, it
keeps its old one.
- Both computers look up their client-side computer state and get the
same value, meaning the first pocket computer mirrors the second!
To fix this, we now ensure instance ids are entirely unique (not just
per-session). Rather than sequentially assigning an int, we now use a
random UUID (we probably could get away with a random long, but this
feels more idiomatic).
This has a couple of user-visible changes:
- /computercraft no longer lists instance ids outside of dumping an
individual computer.
- The @c[instance=...] selector uses UUIDs. We still use int instance
ids for the legacy selector, but that'll be removed in a later MC
version.
- Pocket computers now store a UUID rather than an int.
Related to this change (I made this change first, but then they got
kinda mixed up together), we now only create PocketComputerData when
receiving server data. This makes the code a little uglier in some
places (the data may now be null), but means we don't populate the
client-side pocket computer map with computers the server doesn't know
about.
2024-03-17 12:21:21 +00:00
|
|
|
if (copy.computerID != computerID || !Objects.equals(copy.instanceID, instanceID)) {
|
2017-05-01 13:32:39 +00:00
|
|
|
unload();
|
2021-01-15 16:35:49 +00:00
|
|
|
instanceID = copy.instanceID;
|
|
|
|
computerID = copy.computerID;
|
2019-06-14 19:55:32 +00:00
|
|
|
label = copy.label;
|
2021-01-15 16:35:49 +00:00
|
|
|
on = copy.on;
|
|
|
|
startOn = copy.startOn;
|
2022-06-04 14:30:42 +00:00
|
|
|
lockCode = copy.lockCode;
|
2022-11-10 15:48:26 +00:00
|
|
|
BlockEntityHelpers.updateBlock(this);
|
2017-05-01 13:32:39 +00:00
|
|
|
}
|
Replace integer instance IDs with UUIDs
Here's a fun bug you can try at home:
- Create a new world
- Spawn in a pocket computer, turn it on, and place it in a chest.
- Reload the world - the pocket computer in the chest should now be
off.
- Spawn in a new pocket computer, and turn it on. The computer in chest
will also appear to be on!
This bug has been present since pocket computers were added (27th March,
2024).
When a pocket computer is added to a player's inventory, it is assigned
a unique *per-session* "instance id" , which is used to find the
associated computer. Note the "per-session" there - these ids will be
reused if you reload the world (or restart the server).
In the above bug, we see the following:
- The first pocket computer is assigned an instance id of 0.
- After reloading, the second pocket computer is assigned an instance
id of 0.
- If the first pocket computer was in our inventory, it'd be ticked and
assigned a new instance id. However, because it's in an inventory, it
keeps its old one.
- Both computers look up their client-side computer state and get the
same value, meaning the first pocket computer mirrors the second!
To fix this, we now ensure instance ids are entirely unique (not just
per-session). Rather than sequentially assigning an int, we now use a
random UUID (we probably could get away with a random long, but this
feels more idiomatic).
This has a couple of user-visible changes:
- /computercraft no longer lists instance ids outside of dumping an
individual computer.
- The @c[instance=...] selector uses UUIDs. We still use int instance
ids for the legacy selector, but that'll be removed in a later MC
version.
- Pocket computers now store a UUID rather than an int.
Related to this change (I made this change first, but then they got
kinda mixed up together), we now only create PocketComputerData when
receiving server data. This makes the code a little uglier in some
places (the data may now be null), but means we don't populate the
client-side pocket computer map with computers the server doesn't know
about.
2024-03-17 12:21:21 +00:00
|
|
|
copy.instanceID = null;
|
2017-05-01 13:32:39 +00:00
|
|
|
}
|
2019-03-27 18:59:02 +00:00
|
|
|
|
2019-03-29 21:21:39 +00:00
|
|
|
@Override
|
2021-08-03 20:46:53 +00:00
|
|
|
public Component getName() {
|
2019-06-21 20:01:40 +00:00
|
|
|
return hasCustomName()
|
2022-06-07 23:08:24 +00:00
|
|
|
? Component.literal(label)
|
|
|
|
: Component.translatable(getBlockState().getBlock().getDescriptionId());
|
2019-03-29 21:21:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean hasCustomName() {
|
2019-06-14 19:55:32 +00:00
|
|
|
return !Strings.isNullOrEmpty(label);
|
2019-03-29 21:21:39 +00:00
|
|
|
}
|
|
|
|
|
Update CC: Tweaked to 1.13
Look, I originally had this split into several commits, but lots of
other cleanups got mixed in. I then backported some of the cleanups to
1.12, did other tidy ups there, and eventually the web of merges was
unreadable.
Yes, this is a horrible mess, but it's still nicer than it was. Anyway,
changes:
- Flatten everything. For instance, there are now three instances of
BlockComputer, two BlockTurtle, ItemPocketComputer. There's also no
more BlockPeripheral (thank heavens) - there's separate block classes
for each peripheral type.
- Remove pretty much all legacy code. As we're breaking world
compatibility anyway, we can remove all the code to load worlds from
1.4 days.
- The command system is largely rewriten to take advantage of 1.13's
new system. It's very fancy!
- WidgetTerminal now uses Minecraft's "GUI listener" system.
- BREAKING CHANGE: All the codes in keys.lua are different, due to the
move to LWJGL 3. Hopefully this won't have too much of an impact.
I don't want to map to the old key codes on the Java side, as there
always ends up being small but slight inconsistencies. IMO it's
better to make a clean break - people should be using keys rather
than hard coding the constants anyway.
- commands.list now allows fetching sub-commands. The ROM has already
been updated to allow fancy usage such as commands.time.set("noon").
- Turtles, modems and cables can be waterlogged.
2019-04-02 12:27:27 +00:00
|
|
|
@Nullable
|
2019-03-29 21:21:39 +00:00
|
|
|
@Override
|
2021-08-03 20:46:53 +00:00
|
|
|
public Component getCustomName() {
|
2022-06-07 23:08:24 +00:00
|
|
|
return hasCustomName() ? Component.literal(label) : null;
|
2019-03-29 21:21:39 +00:00
|
|
|
}
|
2019-06-11 20:03:40 +00:00
|
|
|
|
|
|
|
@Override
|
2021-08-03 20:46:53 +00:00
|
|
|
public Component getDisplayName() {
|
|
|
|
return Nameable.super.getDisplayName();
|
2019-06-11 20:03:40 +00:00
|
|
|
}
|
2017-05-01 13:32:39 +00:00
|
|
|
}
|