diff --git a/src/main/java/de/srendi/advancedperipherals/common/blocks/base/PeripheralBlockEntity.java b/src/main/java/de/srendi/advancedperipherals/common/blocks/base/PeripheralBlockEntity.java index 2b6d3ca8f..5449207fb 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/blocks/base/PeripheralBlockEntity.java +++ b/src/main/java/de/srendi/advancedperipherals/common/blocks/base/PeripheralBlockEntity.java @@ -3,7 +3,7 @@ import dan200.computercraft.api.peripheral.IComputerAccess; import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.shared.Capabilities; -import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.lib.peripherals.DisabledPeripheral; import de.srendi.advancedperipherals.lib.peripherals.BasePeripheral; import de.srendi.advancedperipherals.lib.peripherals.IPeripheralTileEntity; import net.minecraft.core.BlockPos; @@ -32,63 +32,45 @@ import org.jetbrains.annotations.Nullable; import java.util.Collections; +import java.util.Optional; public abstract class PeripheralBlockEntity> extends BaseContainerBlockEntity implements WorldlyContainer, MenuProvider, IPeripheralTileEntity { - // TODO: move inventory logic to another tile entity! + private static final String PERIPHERAL_SETTINGS_KEY = "peripheralSettings"; - protected CompoundTag peripheralSettings; + protected CompoundTag peripheralSettings = new CompoundTag(); protected NonNullList items; - @Nullable - protected T peripheral = null; - private LazyOptional handler; - private LazyOptional fluidHandler; - private LazyOptional peripheralCap; + private LazyOptional handler = LazyOptional.empty(); + private LazyOptional fluidHandler = LazyOptional.empty(); + private LazyOptional peripheralCap = LazyOptional.empty(); - public PeripheralBlockEntity(BlockEntityType tileEntityTypeIn, BlockPos pos, BlockState state) { + protected PeripheralBlockEntity(BlockEntityType tileEntityTypeIn, BlockPos pos, BlockState state) { super(tileEntityTypeIn, pos, state); - if (this instanceof IInventoryBlock inventoryBlock) { + if (this instanceof IInventoryBlock inventoryBlock) { items = NonNullList.withSize(inventoryBlock.getInvSize(), ItemStack.EMPTY); } else { items = NonNullList.withSize(0, ItemStack.EMPTY); } - peripheralSettings = new CompoundTag(); } @NotNull @Override - public LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction direction) { + public LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction direction) { if (cap == Capabilities.CAPABILITY_PERIPHERAL) { - if (peripheral == null) - // Perform later peripheral creation, because creating peripheral - // on init of tile entity cause some infinity loop, if peripheral - // are depend on tile entity data - this.peripheral = createPeripheral(); - if (peripheral.isEnabled()) { - if (peripheralCap == null) { - peripheralCap = LazyOptional.of(() -> peripheral); - } else if (!peripheralCap.isPresent()) { - // Recreate peripheral to allow CC: Tweaked correctly handle - // peripheral update logic, so new peripheral and old one will be - // different - peripheral = createPeripheral(); - peripheralCap = LazyOptional.of(() -> peripheral); + return this.getLazyPeripheral().cast(); + } else if (cap == ForgeCapabilities.ITEM_HANDLER) { + if (!remove && direction != null && this instanceof IInventoryBlock) { + if (!handler.isPresent()) { + handler = LazyOptional.of(() -> new SidedInvWrapper(this, Direction.NORTH)); } - return peripheralCap.cast(); - } else { - AdvancedPeripherals.debug(peripheral.getType() + " is disabled, you can enable it in the Configuration."); + return handler.cast(); + } + } else if (cap == ForgeCapabilities.FLUID_HANDLER) { + if (!remove && direction != null) { + if (!fluidHandler.isPresent()) { + fluidHandler = LazyOptional.of(() -> new FluidTank(0)); + } + return fluidHandler.cast(); } - } - - if (cap == ForgeCapabilities.ITEM_HANDLER && !remove && direction != null && this instanceof IInventoryBlock) { - if (handler == null || !handler.isPresent()) - handler = LazyOptional.of(() -> new SidedInvWrapper(this, Direction.NORTH)); - return handler.cast(); - } - - if (cap == ForgeCapabilities.FLUID_HANDLER && !remove && direction != null) { - if (fluidHandler == null || !fluidHandler.isPresent()) - fluidHandler = LazyOptional.of(() -> new FluidTank(0)); - return fluidHandler.cast(); } return super.getCapability(cap, direction); } @@ -96,21 +78,50 @@ public LazyOptional getCapability(@NotNull Capability cap, @Nullabl @Override public void invalidateCaps() { super.invalidateCaps(); - if (peripheralCap != null) - peripheralCap.invalidate(); - if (handler != null) - handler.invalidate(); - if (fluidHandler != null) - fluidHandler.invalidate(); + peripheralCap.invalidate(); + handler.invalidate(); + fluidHandler.invalidate(); } @NotNull protected abstract T createPeripheral(); + protected IPeripheral createPeripheralDisable() { + T peripheral = this.createPeripheral(); + if (peripheral.isEnabled()) { + return peripheral; + } + return new DisabledPeripheral(peripheral); + } + public Iterable getConnectedComputers() { - if (peripheral == null) // just avoid some NPE in strange cases - return Collections.emptyList(); - return peripheral.getConnectedComputers(); + return this.getPeripheralOptional().map(BasePeripheral::getConnectedComputers).orElse(Collections.emptyList()); + } + + public LazyOptional getLazyPeripheral() { + // Perform later peripheral creation, because creating peripheral + // on init of tile entity cause some infinity loop, if peripheral + // are depend on tile entity data + if (!this.peripheralCap.isPresent()) { + // Recreate peripheral to allow CC: Tweaked correctly handle + // peripheral update logic, so new peripheral and old one will be + // different + this.peripheralCap = LazyOptional.of(this::createPeripheralDisable); + } + return this.peripheralCap; + } + + @Nullable + public T getPeripheral() { + IPeripheral peripheral = this.getLazyPeripheral().orElse(null); + if (peripheral == null || peripheral instanceof DisabledPeripheral) { + return null; + } + return (T) peripheral; + } + + public Optional getPeripheralOptional() { + return Optional.ofNullable(this.getPeripheral()); } /*@Override @@ -122,7 +133,9 @@ public ITextComponent getDisplayName() { public void saveAdditional(@NotNull CompoundTag compound) { super.saveAdditional(compound); ContainerHelper.saveAllItems(compound, items); - if (!peripheralSettings.isEmpty()) compound.put(PERIPHERAL_SETTINGS_KEY, peripheralSettings); + if (!peripheralSettings.isEmpty()) { + compound.put(PERIPHERAL_SETTINGS_KEY, peripheralSettings); + } } @Override @@ -132,6 +145,7 @@ public void load(@NotNull CompoundTag compound) { super.load(compound); } + @NotNull @Override protected Component getDefaultName() { return this instanceof IInventoryBlock inventoryBlock ? inventoryBlock.getDisplayName() : null; @@ -143,13 +157,14 @@ public AbstractContainerMenu createMenu(int id, @NotNull Inventory inventory, @N return createMenu(id, inventory); } + @NotNull @Override protected AbstractContainerMenu createMenu(int id, @NotNull Inventory player) { return this instanceof IInventoryBlock inventoryBlock ? inventoryBlock.createContainer(id, player, worldPosition, level) : null; } @Override - public int[] getSlotsForFace(@NotNull Direction side) { + public int @NotNull [] getSlotsForFace(@NotNull Direction side) { return new int[]{0}; } @@ -222,7 +237,6 @@ public CompoundTag getPeripheralSettings() { @Override public void markSettingsChanged() { - setChanged(); + this.setChanged(); } } - diff --git a/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/ChatBoxEntity.java b/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/ChatBoxEntity.java index 118611259..716075581 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/ChatBoxEntity.java +++ b/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/ChatBoxEntity.java @@ -23,8 +23,6 @@ protected ChatBoxPeripheral createPeripheral() { @Override public void handleTick(Level level, BlockState state, BlockEntityType type) { - if (peripheral != null) { - peripheral.update(); - } + this.getPeripheralOptional().ifPresent(ChatBoxPeripheral::update); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/MeBridgeEntity.java b/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/MeBridgeEntity.java index d9eb38a98..ecc940044 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/MeBridgeEntity.java +++ b/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/MeBridgeEntity.java @@ -54,10 +54,7 @@ public void handleTick(Level level, BlockState state, Bl mainNode.setInWorldNode(true); mainNode.create(level, getBlockPos()); - //peripheral can be null if `getCapability` was not called before - if (peripheral == null) - peripheral = createPeripheral(); - peripheral.setNode(mainNode); + this.getPeripheralOptional().ifPresent(peripheral -> peripheral.setNode(mainNode)); initialized = true; } diff --git a/src/main/java/de/srendi/advancedperipherals/lib/peripherals/DisabledPeripheral.java b/src/main/java/de/srendi/advancedperipherals/lib/peripherals/DisabledPeripheral.java index 8fd524d0c..5855f8c09 100644 --- a/src/main/java/de/srendi/advancedperipherals/lib/peripherals/DisabledPeripheral.java +++ b/src/main/java/de/srendi/advancedperipherals/lib/peripherals/DisabledPeripheral.java @@ -1,17 +1,73 @@ package de.srendi.advancedperipherals.lib.peripherals; -import dan200.computercraft.api.pocket.IPocketAccess; -import de.srendi.advancedperipherals.common.addons.computercraft.owner.PocketPeripheralOwner; +import dan200.computercraft.api.lua.IArguments; +import dan200.computercraft.api.lua.ILuaContext; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.LuaFunction; +import dan200.computercraft.api.lua.MethodResult; +import dan200.computercraft.api.peripheral.IComputerAccess; +import dan200.computercraft.api.peripheral.IDynamicPeripheral; +import dan200.computercraft.api.peripheral.IPeripheral; -public class DisabledPeripheral extends BasePeripheral { - public static final DisabledPeripheral INSTANCE = new DisabledPeripheral("disabledPeripheral", null); +import java.lang.reflect.Method; +import java.util.stream.Stream; - private DisabledPeripheral(String type, IPocketAccess access) { - super(type, new PocketPeripheralOwner(access)); +public class DisabledPeripheral implements IDynamicPeripheral { + private static final MethodResult TRUE_RESULT = MethodResult.of(true); + + private final IPeripheral basePeripheral; + private final String[] methods; + + public DisabledPeripheral(IPeripheral basePeripheral) { + this.basePeripheral = basePeripheral; + Stream.Builder builder = Stream.builder(); + builder.add("peripheralDisabled"); + for (Method method : basePeripheral.getClass().getMethods()) { + LuaFunction annotation = method.getAnnotation(LuaFunction.class); + if (annotation == null) { + continue; + } + String[] names = annotation.value(); + if (names.length == 0) { + builder.add(method.getName()); + } else { + for (String name : names) { + builder.add(name); + } + } + } + Stream methodStream = builder.build(); + if (basePeripheral instanceof IDynamicPeripheral dynPeripheral) { + methodStream = Stream.concat(methodStream, Stream.of(dynPeripheral.getMethodNames())); + } + this.methods = methodStream.toArray(String[]::new); + } + + @Override + public String getType() { + return this.basePeripheral.getType(); + } + + @Override + public Object getTarget() { + return this.basePeripheral.getTarget(); + } + + @Override + public boolean equals(IPeripheral other) { + return other instanceof DisabledPeripheral disabled && this.basePeripheral.equals(disabled.basePeripheral); + } + + @Override + public String[] getMethodNames() { + return this.methods; } @Override - public boolean isEnabled() { - return true; + public MethodResult callMethod(IComputerAccess computer, ILuaContext context, int method, IArguments arguments) throws LuaException { + if (method == 0) { + return TRUE_RESULT; + } + throw new LuaException("This peripheral is disabled, please contact server administrator if you want to use it"); } } diff --git a/src/main/java/de/srendi/advancedperipherals/lib/pocket/BasePocketUpgrade.java b/src/main/java/de/srendi/advancedperipherals/lib/pocket/BasePocketUpgrade.java index 291a333de..50d7f39c1 100644 --- a/src/main/java/de/srendi/advancedperipherals/lib/pocket/BasePocketUpgrade.java +++ b/src/main/java/de/srendi/advancedperipherals/lib/pocket/BasePocketUpgrade.java @@ -25,7 +25,9 @@ protected BasePocketUpgrade(ResourceLocation id, ItemStack stack) { @Override public IPeripheral createPeripheral(@NotNull IPocketAccess access) { peripheral = getPeripheral(access); - if (!peripheral.isEnabled()) return DisabledPeripheral.INSTANCE; + if (!peripheral.isEnabled()) { + return new DisabledPeripheral(peripheral); + } return peripheral; } } diff --git a/src/main/java/de/srendi/advancedperipherals/lib/turtle/PeripheralTurtleUpgrade.java b/src/main/java/de/srendi/advancedperipherals/lib/turtle/PeripheralTurtleUpgrade.java index 2f06c5944..c1f23646d 100644 --- a/src/main/java/de/srendi/advancedperipherals/lib/turtle/PeripheralTurtleUpgrade.java +++ b/src/main/java/de/srendi/advancedperipherals/lib/turtle/PeripheralTurtleUpgrade.java @@ -34,7 +34,7 @@ protected PeripheralTurtleUpgrade(ResourceLocation id, ItemStack item) { public IPeripheral createPeripheral(@NotNull ITurtleAccess turtle, @NotNull TurtleSide side) { T peripheral = buildPeripheral(turtle, side); if (!peripheral.isEnabled()) { - return DisabledPeripheral.INSTANCE; + return new DisabledPeripheral(peripheral); } return peripheral; }