diff --git a/build.gradle b/build.gradle index 83b806a23..aefcb89a5 100644 --- a/build.gradle +++ b/build.gradle @@ -50,7 +50,7 @@ dependencies { compile 'javax.vecmath:vecmath:1.5.2' - shade 'org.squiddev:Cobalt:0.5.0-SNAPSHOT' + shade 'org.squiddev:Cobalt:0.5.1-SNAPSHOT' testImplementation 'org.junit.jupiter:junit-jupiter-api:5.1.0' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.1.0' diff --git a/src/main/java/dan200/computercraft/ComputerCraft.java b/src/main/java/dan200/computercraft/ComputerCraft.java index f9ebbd4bb..0205aa184 100644 --- a/src/main/java/dan200/computercraft/ComputerCraft.java +++ b/src/main/java/dan200/computercraft/ComputerCraft.java @@ -6,8 +6,9 @@ package dan200.computercraft; -import static dan200.computercraft.shared.Registry.*; +import static dan200.computercraft.shared.ComputerCraftRegistry.*; +import java.nio.file.Paths; import java.util.Collections; import java.util.EnumSet; import java.util.List; @@ -17,15 +18,17 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import dan200.computercraft.api.turtle.event.TurtleAction; +import dan200.computercraft.core.apis.AddressPredicate; import dan200.computercraft.core.apis.http.options.Action; import dan200.computercraft.core.apis.http.options.AddressRule; -import dan200.computercraft.core.asm.GenericSource; -import dan200.computercraft.shared.Config; +import dan200.computercraft.core.apis.http.websocket.Websocket; +import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.computer.core.ClientComputerRegistry; import dan200.computercraft.shared.computer.core.ServerComputerRegistry; import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer; import dan200.computercraft.shared.pocket.peripherals.PocketModem; import dan200.computercraft.shared.pocket.peripherals.PocketSpeaker; +import dan200.computercraft.shared.proxy.ComputerCraftProxyCommon; import dan200.computercraft.shared.turtle.upgrades.TurtleAxe; import dan200.computercraft.shared.turtle.upgrades.TurtleCraftingTable; import dan200.computercraft.shared.turtle.upgrades.TurtleHoe; @@ -34,7 +37,12 @@ import dan200.computercraft.shared.turtle.upgrades.TurtleShovel; import dan200.computercraft.shared.turtle.upgrades.TurtleSpeaker; import dan200.computercraft.shared.turtle.upgrades.TurtleSword; import dan200.computercraft.shared.turtle.upgrades.TurtleTool; -import dan200.computercraft.shared.util.ServiceUtil; +import dan200.computercraft.shared.util.Config; +import net.fabricmc.fabric.api.client.itemgroup.FabricItemGroupBuilder; +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.item.ItemGroup; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Identifier; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -43,52 +51,59 @@ import net.fabricmc.api.ModInitializer; public final class ComputerCraft implements ModInitializer { public static final String MOD_ID = "computercraft"; + public static ItemGroup MAIN_GROUP = FabricItemGroupBuilder.build(new Identifier(MOD_ID, "main"), () -> new ItemStack(ModBlocks.COMPUTER_NORMAL)); + // Configuration options - public static final String[] DEFAULT_HTTP_ALLOW = new String[] {"*"}; - public static final String[] DEFAULT_HTTP_DENY = new String[] { + public static final String[] DEFAULT_HTTP_WHITELIST = new String[] {"*"}; + public static final String[] DEFAULT_HTTP_BLACKLIST = new String[] { "127.0.0.0/8", "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16", "fd00::/8", - }; - + }; + public static List httpRules = Collections.unmodifiableList( Stream.concat( + Stream.of( DEFAULT_HTTP_BLACKLIST ) + .map( x -> AddressRule.parse( x, Action.DENY.toPartial() ) ) + .filter( Objects::nonNull ), + Stream.of( DEFAULT_HTTP_WHITELIST ) + .map( x -> AddressRule.parse( x, Action.ALLOW.toPartial() ) ) + .filter( Objects::nonNull ) + ).collect( Collectors.toList() ) ); + public static boolean commandRequireCreative = false; + public static MonitorRenderer monitorRenderer = MonitorRenderer.BEST; + public static final int terminalWidth_computer = 51; + public static final int terminalHeight_computer = 19; + public static final int terminalWidth_turtle = 39; + public static final int terminalHeight_turtle = 13; + public static final int terminalWidth_pocketComputer = 26; + public static final int terminalHeight_pocketComputer = 20; public static int computerSpaceLimit = 1000 * 1000; public static int floppySpaceLimit = 125 * 1000; public static int maximumFilesOpen = 128; - public static boolean disableLua51Features = false; - public static String defaultComputerSettings = ""; - public static boolean debugEnable = true; - public static boolean logComputerErrors = true; - public static boolean commandRequireCreative = true; - - public static int computerThreads = 1; + public static boolean disable_lua51_features = false; + public static String default_computer_settings = ""; + public static boolean debug_enable = true; + public static boolean logPeripheralErrors = false; + public static int computer_threads = 1; public static long maxMainGlobalTime = TimeUnit.MILLISECONDS.toNanos(10); public static long maxMainComputerTime = TimeUnit.MILLISECONDS.toNanos(5); - - public static boolean httpEnabled = true; - public static boolean httpWebsocketEnabled = true; - public static List httpRules = Collections.unmodifiableList(Stream.concat(Stream.of(DEFAULT_HTTP_DENY) - .map(x -> AddressRule.parse(x, Action.DENY.toPartial())) - .filter(Objects::nonNull), - Stream.of(DEFAULT_HTTP_ALLOW) - .map(x -> AddressRule.parse(x, Action.ALLOW.toPartial())) - .filter(Objects::nonNull)) - .collect(Collectors.toList())); - + public static boolean http_enable = true; + public static boolean http_websocket_enable = true; + public static AddressPredicate http_whitelist = new AddressPredicate(DEFAULT_HTTP_WHITELIST); + public static AddressPredicate http_blacklist = new AddressPredicate(DEFAULT_HTTP_BLACKLIST); + public static int httpTimeout = 30000; public static int httpMaxRequests = 16; + public static long httpMaxDownload = 16 * 1024 * 1024; + public static long httpMaxUpload = 4 * 1024 * 1024; public static int httpMaxWebsockets = 4; - + public static int httpMaxWebsocketMessage = Websocket.MAX_MESSAGE_SIZE; public static boolean enableCommandBlock = false; - public static int modemRange = 64; - public static int modemHighAltitudeRange = 384; - public static int modemRangeDuringStorm = 64; - public static int modemHighAltitudeRangeDuringStorm = 384; + public static int modem_range = 64; + public static int modem_highAltitudeRange = 384; + public static int modem_rangeDuringStorm = 64; + public static int modem_highAltitudeRangeDuringStorm = 384; public static int maxNotesPerTick = 8; - public static MonitorRenderer monitorRenderer = MonitorRenderer.BEST; - public static double monitorDistanceSq = 4096; - public static long monitorBandwidth = 1_000_000; - public static boolean turtlesNeedFuel = true; public static int turtleFuelLimit = 20000; public static int advancedTurtleFuelLimit = 100000; @@ -96,19 +111,9 @@ public final class ComputerCraft implements ModInitializer { public static boolean turtlesCanPush = true; public static EnumSet turtleDisabledActions = EnumSet.noneOf(TurtleAction.class); - public static boolean genericPeripheral = false; - - public static int computerTermWidth = 51; - public static int computerTermHeight = 19; - - public static final int turtleTermWidth = 39; - public static final int turtleTermHeight = 13; - - public static int pocketTermWidth = 26; - public static int pocketTermHeight = 20; - public static int monitorWidth = 8; public static int monitorHeight = 6; + public static double monitorDistanceSq = 4096; public static final class TurtleUpgrades { public static TurtleModem wirelessModemNormal; @@ -139,10 +144,8 @@ public final class ComputerCraft implements ModInitializer { @Override public void onInitialize() { - Config.setup(); - GenericSource.setup(() -> ServiceUtil.loadServicesForge(GenericSource.class)); + Config.load(Paths.get(FabricLoader.getInstance().getConfigDir().toFile().getPath(), MOD_ID + ".json5")); + ComputerCraftProxyCommon.init(); init(); } - - } diff --git a/src/main/java/dan200/computercraft/ComputerCraftAPIImpl.java b/src/main/java/dan200/computercraft/ComputerCraftAPIImpl.java index cd4d2f6b4..4f2f8c890 100644 --- a/src/main/java/dan200/computercraft/ComputerCraftAPIImpl.java +++ b/src/main/java/dan200/computercraft/ComputerCraftAPIImpl.java @@ -21,10 +21,13 @@ import dan200.computercraft.core.apis.ApiFactories; import dan200.computercraft.core.filesystem.FileMount; import dan200.computercraft.core.filesystem.ResourceMount; import dan200.computercraft.shared.*; +import dan200.computercraft.shared.peripheral.modem.wired.TileCable; +import dan200.computercraft.shared.peripheral.modem.wired.TileWiredModemFull; import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork; import dan200.computercraft.shared.util.IDAssigner; import dan200.computercraft.shared.wired.WiredNode; import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.block.entity.BlockEntity; import net.minecraft.resource.ReloadableResourceManager; import net.minecraft.server.MinecraftServer; import net.minecraft.util.Identifier; @@ -34,14 +37,11 @@ import net.minecraft.world.BlockView; import net.minecraft.world.World; import javax.annotation.Nonnull; -import javax.swing.text.html.Option; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.Optional; -import static dan200.computercraft.shared.Capabilities.CAPABILITY_WIRED_ELEMENT; - public final class ComputerCraftAPIImpl implements IComputerCraftAPI { public static final ComputerCraftAPIImpl INSTANCE = new ComputerCraftAPIImpl(); @@ -163,11 +163,14 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI @Nonnull @Override - public Optional getWiredElementAt( @Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull Direction side ) + public IWiredElement getWiredElementAt( @Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull Direction side ) { - // TODO Fix this thing -// BlockEntity tile = world.getBlockEntity( pos ); -// return tile == null ? Optional.empty() : tile.getCapability( CAPABILITY_WIRED_ELEMENT, side ); - return Optional.empty(); + BlockEntity tile = world.getBlockEntity(pos); + if (tile instanceof TileCable) { + return ((TileCable) tile).getElement(side); + } else if (tile instanceof TileWiredModemFull) { + return ((TileWiredModemFull) tile).getElement(); + } + return null; } } diff --git a/src/main/java/dan200/computercraft/api/ComputerCraftAPI.java b/src/main/java/dan200/computercraft/api/ComputerCraftAPI.java index 99176747f..4423bf168 100644 --- a/src/main/java/dan200/computercraft/api/ComputerCraftAPI.java +++ b/src/main/java/dan200/computercraft/api/ComputerCraftAPI.java @@ -218,7 +218,7 @@ public final class ComputerCraftAPI * @see IWiredElement#getNode() */ @Nonnull - public static Optional getWiredElementAt(@Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull Direction side ) + public static IWiredElement getWiredElementAt(@Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull Direction side ) { return getInstance().getWiredElementAt( world, pos, side ); } @@ -275,6 +275,6 @@ public final class ComputerCraftAPI IWiredNode createWiredNodeForElement( @Nonnull IWiredElement element ); @Nonnull - Optional getWiredElementAt( @Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull Direction side ); + IWiredElement getWiredElementAt( @Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull Direction side ); } } diff --git a/src/main/java/dan200/computercraft/api/client/TransformedModel.java b/src/main/java/dan200/computercraft/api/client/TransformedModel.java index b585d0f6e..e485f31ce 100644 --- a/src/main/java/dan200/computercraft/api/client/TransformedModel.java +++ b/src/main/java/dan200/computercraft/api/client/TransformedModel.java @@ -5,6 +5,8 @@ */ package dan200.computercraft.api.client; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.BakedModelManager; @@ -17,6 +19,7 @@ import java.util.Objects; /** * A model to render, combined with a transformation matrix to apply. */ +@Environment(EnvType.CLIENT) public final class TransformedModel { private final BakedModel model; diff --git a/src/main/java/dan200/computercraft/api/lua/ILuaObject.java b/src/main/java/dan200/computercraft/api/lua/ILuaObject.java new file mode 100644 index 000000000..32ec9b863 --- /dev/null +++ b/src/main/java/dan200/computercraft/api/lua/ILuaObject.java @@ -0,0 +1,21 @@ +/* + * This file is part of the public ComputerCraft API - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only. + * For help using the API, and posting your mods, visit the forums at computercraft.info. + */ + +package dan200.computercraft.api.lua; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import dan200.computercraft.api.peripheral.IComputerAccess; +import dan200.computercraft.api.peripheral.IPeripheral; + +public interface ILuaObject { + @Nonnull + String[] getMethodNames(); + + @Nullable + Object[] callMethod(@Nonnull ILuaContext context, int method, @Nonnull Object[] arguments) throws LuaException, InterruptedException; +} diff --git a/src/main/java/dan200/computercraft/api/peripheral/IPeripheral.java b/src/main/java/dan200/computercraft/api/peripheral/IPeripheral.java index fb7cd20ed..17ea8090e 100644 --- a/src/main/java/dan200/computercraft/api/peripheral/IPeripheral.java +++ b/src/main/java/dan200/computercraft/api/peripheral/IPeripheral.java @@ -28,7 +28,7 @@ public interface IPeripheral * @return A string identifying the type of peripheral. */ @Nonnull - String getType0(); + String getType(); /** * Is called when when a computer is attaching to the peripheral. diff --git a/src/main/java/dan200/computercraft/api/peripheral/IPeripheralProvider.java b/src/main/java/dan200/computercraft/api/peripheral/IPeripheralProvider.java index 4d1a5f05d..b57d05ac5 100644 --- a/src/main/java/dan200/computercraft/api/peripheral/IPeripheralProvider.java +++ b/src/main/java/dan200/computercraft/api/peripheral/IPeripheralProvider.java @@ -34,5 +34,5 @@ public interface IPeripheralProvider * @see dan200.computercraft.api.ComputerCraftAPI#registerPeripheralProvider(IPeripheralProvider) */ @Nonnull - Optional getPeripheral( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side ); + IPeripheral getPeripheral( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side ); } diff --git a/src/main/java/dan200/computercraft/client/ClientRegistry.java b/src/main/java/dan200/computercraft/client/ClientRegistry.java index 8a9c694c7..392b7fe31 100644 --- a/src/main/java/dan200/computercraft/client/ClientRegistry.java +++ b/src/main/java/dan200/computercraft/client/ClientRegistry.java @@ -8,10 +8,9 @@ package dan200.computercraft.client; import java.util.HashSet; import java.util.function.Consumer; -import java.util.function.Function; import dan200.computercraft.ComputerCraft; -import dan200.computercraft.shared.Registry; +import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.common.IColouredItem; import dan200.computercraft.shared.media.items.ItemDisk; import dan200.computercraft.shared.media.items.ItemTreasureDisk; @@ -23,7 +22,6 @@ import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.ModelLoader; import net.minecraft.client.render.model.ModelRotation; import net.minecraft.client.render.model.UnbakedModel; -import net.minecraft.client.texture.Sprite; import net.minecraft.client.texture.SpriteAtlasTexture; import net.minecraft.client.util.ModelIdentifier; import net.minecraft.resource.ResourceManager; @@ -87,9 +85,9 @@ public final class ClientRegistry { public static void onItemColours() { ColorProviderRegistry.ITEM.register((stack, layer) -> { return layer == 1 ? ((ItemDisk) stack.getItem()).getColour(stack) : 0xFFFFFF; - }, Registry.ModItems.DISK); + }, ComputerCraftRegistry.ModItems.DISK); - ColorProviderRegistry.ITEM.register((stack, layer) -> layer == 1 ? ItemTreasureDisk.getColour(stack) : 0xFFFFFF, Registry.ModItems.TREASURE_DISK); + ColorProviderRegistry.ITEM.register((stack, layer) -> layer == 1 ? ItemTreasureDisk.getColour(stack) : 0xFFFFFF, ComputerCraftRegistry.ModItems.TREASURE_DISK); ColorProviderRegistry.ITEM.register((stack, layer) -> { switch (layer) { @@ -104,12 +102,12 @@ public final class ClientRegistry { return light == -1 ? Colour.BLACK.getHex() : light; } } - }, Registry.ModItems.POCKET_COMPUTER_NORMAL, Registry.ModItems.POCKET_COMPUTER_ADVANCED); + }, ComputerCraftRegistry.ModItems.POCKET_COMPUTER_NORMAL, ComputerCraftRegistry.ModItems.POCKET_COMPUTER_ADVANCED); // Setup turtle colours ColorProviderRegistry.ITEM.register((stack, tintIndex) -> tintIndex == 0 ? ((IColouredItem) stack.getItem()).getColour(stack) : 0xFFFFFF, - Registry.ModBlocks.TURTLE_NORMAL, - Registry.ModBlocks.TURTLE_ADVANCED); + ComputerCraftRegistry.ModBlocks.TURTLE_NORMAL, + ComputerCraftRegistry.ModBlocks.TURTLE_ADVANCED); } private static BakedModel bake(ModelLoader loader, UnbakedModel model, Identifier identifier) { diff --git a/src/main/java/dan200/computercraft/client/gui/GuiComputer.java b/src/main/java/dan200/computercraft/client/gui/GuiComputer.java index 261bf5332..dadaa4bc7 100644 --- a/src/main/java/dan200/computercraft/client/gui/GuiComputer.java +++ b/src/main/java/dan200/computercraft/client/gui/GuiComputer.java @@ -3,38 +3,32 @@ * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.client.gui; -import static dan200.computercraft.client.render.ComputerBorderRenderer.BORDER; -import static dan200.computercraft.client.render.ComputerBorderRenderer.MARGIN; - -import javax.annotation.Nonnull; - import com.mojang.blaze3d.systems.RenderSystem; import dan200.computercraft.ComputerCraft; import dan200.computercraft.client.gui.widgets.WidgetTerminal; import dan200.computercraft.client.gui.widgets.WidgetWrapper; import dan200.computercraft.client.render.ComputerBorderRenderer; -import dan200.computercraft.shared.computer.blocks.TileComputer; import dan200.computercraft.shared.computer.core.ClientComputer; import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.computer.core.IContainerComputer; import dan200.computercraft.shared.computer.inventory.ContainerComputer; import dan200.computercraft.shared.computer.inventory.ContainerComputerBase; import dan200.computercraft.shared.computer.inventory.ContainerViewComputer; import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer; -import org.lwjgl.glfw.GLFW; - import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.screen.ScreenHandler; -import net.minecraft.text.LiteralText; import net.minecraft.text.Text; +import org.lwjgl.glfw.GLFW; -public final class GuiComputer extends HandledScreen { +import javax.annotation.Nonnull; +import static dan200.computercraft.client.render.ComputerBorderRenderer.BORDER; +import static dan200.computercraft.client.render.ComputerBorderRenderer.MARGIN; + +public final class GuiComputer extends HandledScreen +{ private final ComputerFamily family; private final ClientComputer computer; private final int termWidth; @@ -43,102 +37,123 @@ public final class GuiComputer ext private WidgetTerminal terminal; private WidgetWrapper terminalWrapper; - public GuiComputer(T container, PlayerInventory player, ComputerFamily family, ClientComputer computer, int termWidth, int termHeight) { - super(container, player, new LiteralText("")); - this.family = family; - this.computer = computer; + private GuiComputer( + T container, PlayerInventory player, Text title, int termWidth, int termHeight + ) + { + super( container, player, title ); + family = container.getFamily(); + computer = (ClientComputer) container.getComputer(); this.termWidth = termWidth; this.termHeight = termHeight; - this.terminal = null; + terminal = null; } - private GuiComputer(T container, PlayerInventory player, ComputerFamily family, Text title, int termWidth, int termHeight) { - super(container, player, title); - this.family = family; - this.computer = (ClientComputer) container.getComputer(); - this.termWidth = termWidth; - this.termHeight = termHeight; - this.terminal = null; + public static GuiComputer create( ContainerComputer container, PlayerInventory inventory, Text component ) + { + return new GuiComputer<>( + container, inventory, component, + ComputerCraft.terminalWidth_computer, ComputerCraft.terminalHeight_computer + ); } - - public static GuiComputer create(int id, TileComputer computer, PlayerInventory player) { - return create(new ContainerComputer(id, computer), player, computer.getDisplayName()); + public static GuiComputer createPocket( ContainerPocketComputer container, PlayerInventory inventory, Text component ) + { + return new GuiComputer<>( + container, inventory, component, + ComputerCraft.terminalWidth_pocketComputer, ComputerCraft.terminalHeight_pocketComputer + ); } - public static GuiComputer create(ContainerComputer container, PlayerInventory inventory, Text component) { - return new GuiComputer<>(container, inventory, container.getFamily(), component, ComputerCraft.computerTermWidth, ComputerCraft.computerTermHeight); + public static GuiComputer createView( ContainerViewComputer container, PlayerInventory inventory, Text component ) + { + return new GuiComputer<>( + container, inventory, component, + container.getWidth(), container.getHeight() + ); } + @Override - protected void init() { - this.client.keyboard.setRepeatEvents(true); + protected void init() + { + client.keyboard.setRepeatEvents( true ); - int termPxWidth = this.termWidth * FixedWidthFontRenderer.FONT_WIDTH; - int termPxHeight = this.termHeight * FixedWidthFontRenderer.FONT_HEIGHT; + int termPxWidth = termWidth * FixedWidthFontRenderer.FONT_WIDTH; + int termPxHeight = termHeight * FixedWidthFontRenderer.FONT_HEIGHT; - this.backgroundWidth = termPxWidth + MARGIN * 2 + BORDER * 2; - this.backgroundHeight = termPxHeight + MARGIN * 2 + BORDER * 2; + backgroundWidth = termPxWidth + MARGIN * 2 + BORDER * 2; + backgroundHeight = termPxHeight + MARGIN * 2 + BORDER * 2; super.init(); - this.terminal = new WidgetTerminal(this.client, () -> this.computer, this.termWidth, this.termHeight, MARGIN, MARGIN, MARGIN, MARGIN); - this.terminalWrapper = new WidgetWrapper(this.terminal, MARGIN + BORDER + this.x, MARGIN + BORDER + this.y, termPxWidth, termPxHeight); + terminal = new WidgetTerminal( client, () -> computer, termWidth, termHeight, MARGIN, MARGIN, MARGIN, MARGIN ); + terminalWrapper = new WidgetWrapper( terminal, MARGIN + BORDER + x, MARGIN + BORDER + y, termPxWidth, termPxHeight ); - this.children.add(this.terminalWrapper); - this.setFocused(this.terminalWrapper); + children.add( terminalWrapper ); + setFocused( terminalWrapper ); } @Override - public void removed() { + public void removed() + { super.removed(); - this.children.remove(this.terminal); - this.terminal = null; - this.client.keyboard.setRepeatEvents(false); + children.remove( terminal ); + terminal = null; + client.keyboard.setRepeatEvents( false ); } @Override - public void tick() { + public void tick() + { super.tick(); - this.terminal.update(); + terminal.update(); } @Override - public boolean keyPressed(int key, int scancode, int modifiers) { + public boolean keyPressed( int key, int scancode, int modifiers ) + { // Forward the tab key to the terminal, rather than moving between controls. - if (key == GLFW.GLFW_KEY_TAB && this.getFocused() != null && this.getFocused() == this.terminalWrapper) { - return this.getFocused().keyPressed(key, scancode, modifiers); + if( key == GLFW.GLFW_KEY_TAB && getFocused() != null && getFocused() == terminalWrapper ) + { + return getFocused().keyPressed( key, scancode, modifiers ); } - return super.keyPressed(key, scancode, modifiers); + return super.keyPressed( key, scancode, modifiers ); } @Override - public void drawBackground(@Nonnull MatrixStack stack, float partialTicks, int mouseX, int mouseY) { + public void drawBackground( @Nonnull MatrixStack stack, float partialTicks, int mouseX, int mouseY ) + { // Draw terminal - this.terminal.draw(this.terminalWrapper.getX(), this.terminalWrapper.getY()); + terminal.draw( terminalWrapper.getX(), terminalWrapper.getY() ); // Draw a border around the terminal - RenderSystem.color4f(1, 1, 1, 1); - this.client.getTextureManager() - .bindTexture(ComputerBorderRenderer.getTexture(this.family)); - ComputerBorderRenderer.render(this.terminalWrapper.getX() - MARGIN, this.terminalWrapper.getY() - MARGIN, - this.getZOffset(), this.terminalWrapper.getWidth() + MARGIN * 2, this.terminalWrapper.getHeight() + MARGIN * 2); + RenderSystem.color4f( 1, 1, 1, 1 ); + client.getTextureManager().bindTexture( ComputerBorderRenderer.getTexture( family ) ); + ComputerBorderRenderer.render( + terminalWrapper.getX() - MARGIN, terminalWrapper.getY() - MARGIN, getZOffset(), + terminalWrapper.getWidth() + MARGIN * 2, terminalWrapper.getHeight() + MARGIN * 2 + ); } @Override - public void render(@Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks) { - super.render(stack, mouseX, mouseY, partialTicks); - this.drawMouseoverTooltip(stack, mouseX, mouseY); + public void render( @Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks ) + { + super.render( stack, mouseX, mouseY, partialTicks ); + drawMouseoverTooltip( stack, mouseX, mouseY ); } @Override - public boolean mouseDragged(double x, double y, int button, double deltaX, double deltaY) { - return (this.getFocused() != null && this.getFocused().mouseDragged(x, y, button, deltaX, deltaY)) || super.mouseDragged(x, y, button, deltaX, deltaY); + public boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY ) + { + return (getFocused() != null && getFocused().mouseDragged( x, y, button, deltaX, deltaY )) + || super.mouseDragged( x, y, button, deltaX, deltaY ); } @Override - protected void drawForeground(@Nonnull MatrixStack transform, int mouseX, int mouseY) { + protected void drawForeground( @Nonnull MatrixStack transform, int mouseX, int mouseY ) + { // Skip rendering labels. } } diff --git a/src/main/java/dan200/computercraft/client/gui/GuiDiskDrive.java b/src/main/java/dan200/computercraft/client/gui/GuiDiskDrive.java index 93e3494e8..7f27d1b54 100644 --- a/src/main/java/dan200/computercraft/client/gui/GuiDiskDrive.java +++ b/src/main/java/dan200/computercraft/client/gui/GuiDiskDrive.java @@ -6,7 +6,6 @@ package dan200.computercraft.client.gui; import com.mojang.blaze3d.systems.RenderSystem; -import dan200.computercraft.shared.Registry; import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive; import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.util.math.MatrixStack; @@ -19,9 +18,9 @@ public class GuiDiskDrive extends HandledScreen { private static final Identifier BACKGROUND = new Identifier( "computercraft", "textures/gui/disk_drive.png" ); - public GuiDiskDrive( ContainerDiskDrive container, PlayerInventory player) + public GuiDiskDrive( ContainerDiskDrive container, PlayerInventory player, Text title ) { - super(container, player, Registry.ModBlocks.DISK_DRIVE.getName() ); + super( container, player, title ); } @Override diff --git a/src/main/java/dan200/computercraft/client/gui/GuiPocketComputer.java b/src/main/java/dan200/computercraft/client/gui/GuiPocketComputer.java deleted file mode 100644 index 5855c30c7..000000000 --- a/src/main/java/dan200/computercraft/client/gui/GuiPocketComputer.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.client.gui; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer; -import dan200.computercraft.shared.pocket.items.ItemPocketComputer; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; - -public class GuiPocketComputer extends GuiComputer -{ - public GuiPocketComputer( ContainerPocketComputer container, PlayerInventory player ) - { - super( - container, player, - getFamily( container.getStack() ), - ItemPocketComputer.createClientComputer( container.getStack() ), - ComputerCraft.terminalWidth_pocketComputer, - ComputerCraft.terminalHeight_pocketComputer - ); - } - - private static ComputerFamily getFamily( ItemStack stack ) - { - Item item = stack.getItem(); - return item instanceof ItemPocketComputer ? ((ItemPocketComputer) item).getFamily() : ComputerFamily.NORMAL; - } -} diff --git a/src/main/java/dan200/computercraft/client/gui/GuiPrinter.java b/src/main/java/dan200/computercraft/client/gui/GuiPrinter.java index 9e4349994..e81d847a6 100644 --- a/src/main/java/dan200/computercraft/client/gui/GuiPrinter.java +++ b/src/main/java/dan200/computercraft/client/gui/GuiPrinter.java @@ -6,7 +6,6 @@ package dan200.computercraft.client.gui; import com.mojang.blaze3d.systems.RenderSystem; -import dan200.computercraft.shared.Registry; import dan200.computercraft.shared.peripheral.printer.ContainerPrinter; import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.util.math.MatrixStack; @@ -19,9 +18,9 @@ public class GuiPrinter extends HandledScreen { private static final Identifier BACKGROUND = new Identifier( "computercraft", "textures/gui/printer.png" ); - public GuiPrinter( ContainerPrinter container, PlayerInventory player) + public GuiPrinter( ContainerPrinter container, PlayerInventory player, Text title ) { - super(container, player, Registry.ModBlocks.PRINTER.getName()); + super( container, player, title ); } /*@Override diff --git a/src/main/java/dan200/computercraft/client/gui/GuiPrintout.java b/src/main/java/dan200/computercraft/client/gui/GuiPrintout.java index 5ab83e349..c60f12d36 100644 --- a/src/main/java/dan200/computercraft/client/gui/GuiPrintout.java +++ b/src/main/java/dan200/computercraft/client/gui/GuiPrintout.java @@ -30,9 +30,9 @@ public class GuiPrintout extends HandledScreen private final TextBuffer[] m_colours; private int m_page; - public GuiPrintout( ContainerHeldItem container, PlayerInventory player ) + public GuiPrintout( ContainerHeldItem container, PlayerInventory player, Text title ) { - super( container, player, container.getStack().getName() ); + super( container, player, title ); backgroundHeight = Y_SIZE; diff --git a/src/main/java/dan200/computercraft/client/gui/GuiTurtle.java b/src/main/java/dan200/computercraft/client/gui/GuiTurtle.java index 112da56fd..3e7abec44 100644 --- a/src/main/java/dan200/computercraft/client/gui/GuiTurtle.java +++ b/src/main/java/dan200/computercraft/client/gui/GuiTurtle.java @@ -11,7 +11,6 @@ import dan200.computercraft.client.gui.widgets.WidgetTerminal; import dan200.computercraft.client.gui.widgets.WidgetWrapper; import dan200.computercraft.shared.computer.core.ClientComputer; import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.turtle.blocks.TileTurtle; import dan200.computercraft.shared.turtle.inventory.ContainerTurtle; import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.util.math.MatrixStack; @@ -35,12 +34,12 @@ public class GuiTurtle extends HandledScreen private WidgetTerminal terminal; private WidgetWrapper terminalWrapper; - public GuiTurtle(TileTurtle turtle, ContainerTurtle container, PlayerInventory player ) + public GuiTurtle( ContainerTurtle container, PlayerInventory player, Text title ) { - super( container, player, turtle.getDisplayName() ); + super( container, player, title ); m_container = container; - m_family = turtle.getFamily(); + m_family = container.getFamily(); m_computer = (ClientComputer) container.getComputer(); backgroundWidth = 254; @@ -53,13 +52,13 @@ public class GuiTurtle extends HandledScreen super.init(); client.keyboard.setRepeatEvents( true ); - int termPxWidth = ComputerCraft.turtleTermWidth * FixedWidthFontRenderer.FONT_WIDTH; - int termPxHeight = ComputerCraft.turtleTermHeight * FixedWidthFontRenderer.FONT_HEIGHT; + int termPxWidth = ComputerCraft.terminalWidth_turtle * FixedWidthFontRenderer.FONT_WIDTH; + int termPxHeight = ComputerCraft.terminalHeight_turtle * FixedWidthFontRenderer.FONT_HEIGHT; terminal = new WidgetTerminal( client, () -> m_computer, - ComputerCraft.turtleTermWidth, - ComputerCraft.turtleTermHeight, + ComputerCraft.terminalWidth_turtle, + ComputerCraft.terminalHeight_turtle, 2, 2, 2, 2 ); terminalWrapper = new WidgetWrapper( terminal, 2 + 8 + x, 2 + 8 + y, termPxWidth, termPxHeight ); @@ -115,8 +114,8 @@ public class GuiTurtle extends HandledScreen int slotX = slot % 4; int slotY = slot / 4; drawTexture( transform, - x + m_container.m_turtleInvStartX - 2 + slotX * 18, - y + m_container.m_playerInvStartY - 2 + slotY * 18, + x + ContainerTurtle.TURTLE_START_X - 2 + slotX * 18, + y + ContainerTurtle.PLAYER_START_Y - 2 + slotY * 18, 0, 217, 24, 24 ); } diff --git a/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java b/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java index 20064aa3c..7741566f4 100644 --- a/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java +++ b/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java @@ -6,83 +6,118 @@ package dan200.computercraft.client.proxy; +import java.util.function.Supplier; + import dan200.computercraft.ComputerCraft; import dan200.computercraft.client.ClientRegistry; import dan200.computercraft.client.FrameInfo; import dan200.computercraft.client.gui.GuiComputer; import dan200.computercraft.client.gui.GuiDiskDrive; -import dan200.computercraft.client.gui.GuiPocketComputer; import dan200.computercraft.client.gui.GuiPrinter; import dan200.computercraft.client.gui.GuiPrintout; import dan200.computercraft.client.gui.GuiTurtle; import dan200.computercraft.client.render.TileEntityMonitorRenderer; import dan200.computercraft.client.render.TileEntityTurtleRenderer; -import dan200.computercraft.client.render.TurtleModelLoader; -import dan200.computercraft.shared.Registry; -import dan200.computercraft.shared.computer.blocks.TileComputer; -import dan200.computercraft.shared.computer.core.ClientComputer; +import dan200.computercraft.client.render.TurtlePlayerRenderer; +import dan200.computercraft.shared.ComputerCraftRegistry; +import dan200.computercraft.shared.common.IColouredItem; +import dan200.computercraft.shared.computer.inventory.ContainerComputer; import dan200.computercraft.shared.computer.inventory.ContainerViewComputer; -import dan200.computercraft.shared.network.container.ContainerType; -import dan200.computercraft.shared.network.container.PocketComputerContainerType; -import dan200.computercraft.shared.network.container.PrintoutContainerType; -import dan200.computercraft.shared.network.container.TileEntityContainerType; -import dan200.computercraft.shared.network.container.ViewComputerContainerType; -import dan200.computercraft.shared.turtle.blocks.TileTurtle; -import dan200.computercraft.shared.turtle.inventory.ContainerTurtle; - -import net.minecraft.client.texture.SpriteAtlasTexture; -import net.minecraft.inventory.SimpleInventory; -import net.minecraft.screen.ArrayPropertyDelegate; - -import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry; +import dan200.computercraft.shared.peripheral.monitor.ClientMonitor; +import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer; +import dan200.computercraft.shared.pocket.items.ItemPocketComputer; +import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap; import net.fabricmc.fabric.api.client.rendereregistry.v1.BlockEntityRendererRegistry; -import net.fabricmc.fabric.api.event.client.ClientSpriteRegistryCallback; -import net.fabricmc.fabric.api.event.client.ClientTickCallback; +import net.fabricmc.fabric.api.client.rendereregistry.v1.EntityRendererRegistry; +import net.fabricmc.fabric.api.client.screenhandler.v1.ScreenRegistry; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents; +import net.fabricmc.fabric.mixin.object.builder.ModelPredicateProviderRegistrySpecificAccessor; -@SuppressWarnings ({ - "MethodCallSideOnly", - "NewExpressionSideOnly" -}) -public final class ComputerCraftProxyClient { - public static void setup() { - registerContainers(); - BlockEntityRendererRegistry.INSTANCE.register(Registry.ModTiles.MONITOR_NORMAL, TileEntityMonitorRenderer::new); - BlockEntityRendererRegistry.INSTANCE.register(Registry.ModTiles.MONITOR_ADVANCED, TileEntityMonitorRenderer::new); - BlockEntityRendererRegistry.INSTANCE.register(Registry.ModTiles.TURTLE_NORMAL, TileEntityTurtleRenderer::new); - BlockEntityRendererRegistry.INSTANCE.register(Registry.ModTiles.TURTLE_ADVANCED, TileEntityTurtleRenderer::new); +import net.minecraft.client.item.ModelPredicateProvider; +import net.minecraft.client.render.RenderLayer; +import net.minecraft.item.Item; +import net.minecraft.util.Identifier; - ClientSpriteRegistryCallback.event(SpriteAtlasTexture.BLOCK_ATLAS_TEX) - .register(ClientRegistry::onTextureStitchEvent); - ModelLoadingRegistry.INSTANCE.registerAppender(ClientRegistry::onModelBakeEvent); - ModelLoadingRegistry.INSTANCE.registerResourceProvider(loader -> (name, context) -> TurtleModelLoader.INSTANCE.accepts(name) ? - TurtleModelLoader.INSTANCE.loadModel( - name) : null); +import net.fabricmc.api.ClientModInitializer; - ClientTickCallback.EVENT.register(client -> FrameInfo.onTick()); +@SuppressWarnings ("MethodCallSideOnly") +public final class ComputerCraftProxyClient implements ClientModInitializer { + + @SafeVarargs + private static void registerItemProperty(String name, ModelPredicateProvider getter, Supplier... items) { + Identifier id = new Identifier(ComputerCraft.MOD_ID, name); + for (Supplier item : items) { + ModelPredicateProviderRegistrySpecificAccessor.callRegister(item.get(), id, getter); + } } private static void registerContainers() { // My IDE doesn't think so, but we do actually need these generics. - ContainerType.registerGui(TileEntityContainerType::computer, - (id, packet, player) -> GuiComputer.create(id, (TileComputer) packet.getTileEntity(player), player.inventory)); - ContainerType.registerGui(TileEntityContainerType::diskDrive, GuiDiskDrive::new); - ContainerType.registerGui(TileEntityContainerType::printer, GuiPrinter::new); - ContainerType.registerGui(TileEntityContainerType::turtle, (id, packet, player) -> { - TileTurtle turtle = (TileTurtle) packet.getTileEntity(player); - return new GuiTurtle(turtle, - new ContainerTurtle(id, player.inventory, new SimpleInventory(TileTurtle.INVENTORY_SIZE), new ArrayPropertyDelegate(1)), - player.inventory); - }); - ContainerType.registerGui(PocketComputerContainerType::new, GuiPocketComputer::new); - ContainerType.registerGui(PrintoutContainerType::new, GuiPrintout::new); - ContainerType.registerGui(ViewComputerContainerType::new, (id, packet, player) -> { - ClientComputer computer = ComputerCraft.clientComputerRegistry.get(packet.instanceId); - if (computer == null) { - ComputerCraft.clientComputerRegistry.add(packet.instanceId, computer = new ClientComputer(packet.instanceId)); - } - ContainerViewComputer container = new ContainerViewComputer(id, computer); - return new GuiComputer<>(container, player.inventory, packet.family, computer, packet.width, packet.height); - }); + ScreenRegistry.>register(ComputerCraftRegistry.ModContainers.COMPUTER, GuiComputer::create); + ScreenRegistry.>register(ComputerCraftRegistry.ModContainers.POCKET_COMPUTER, + GuiComputer::createPocket); + ScreenRegistry.register(ComputerCraftRegistry.ModContainers.TURTLE, GuiTurtle::new); + + ScreenRegistry.register(ComputerCraftRegistry.ModContainers.PRINTER, GuiPrinter::new); + ScreenRegistry.register(ComputerCraftRegistry.ModContainers.DISK_DRIVE, GuiDiskDrive::new); + ScreenRegistry.register(ComputerCraftRegistry.ModContainers.PRINTOUT, GuiPrintout::new); + + ScreenRegistry.>register(ComputerCraftRegistry.ModContainers.VIEW_COMPUTER, + GuiComputer::createView); } + + @Override + public void onInitializeClient() { + FrameInfo.init(); + registerContainers(); + + // While turtles themselves are not transparent, their upgrades may be. + BlockRenderLayerMap.INSTANCE.putBlock(ComputerCraftRegistry.ModBlocks.TURTLE_NORMAL, RenderLayer.getTranslucent()); + BlockRenderLayerMap.INSTANCE.putBlock(ComputerCraftRegistry.ModBlocks.TURTLE_ADVANCED, RenderLayer.getTranslucent()); + + // Monitors' textures have transparent fronts and so count as cutouts. + BlockRenderLayerMap.INSTANCE.putBlock(ComputerCraftRegistry.ModBlocks.MONITOR_NORMAL, RenderLayer.getCutout()); + BlockRenderLayerMap.INSTANCE.putBlock(ComputerCraftRegistry.ModBlocks.MONITOR_ADVANCED, RenderLayer.getCutout()); + + // Setup TESRs + BlockEntityRendererRegistry.INSTANCE.register(ComputerCraftRegistry.ModTiles.MONITOR_NORMAL, TileEntityMonitorRenderer::new); + BlockEntityRendererRegistry.INSTANCE.register(ComputerCraftRegistry.ModTiles.MONITOR_ADVANCED, TileEntityMonitorRenderer::new); + BlockEntityRendererRegistry.INSTANCE.register(ComputerCraftRegistry.ModTiles.TURTLE_NORMAL, TileEntityTurtleRenderer::new); + BlockEntityRendererRegistry.INSTANCE.register(ComputerCraftRegistry.ModTiles.TURTLE_ADVANCED, TileEntityTurtleRenderer::new); + // TODO: ClientRegistry.bindTileEntityRenderer( TileCable.FACTORY, x -> new TileEntityCableRenderer() ); + + EntityRendererRegistry.INSTANCE.register(ComputerCraftRegistry.ModEntities.TURTLE_PLAYER, TurtlePlayerRenderer::new); + + registerItemProperty("state", + (stack, world, player) -> ItemPocketComputer.getState(stack) + .ordinal(), + () -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_NORMAL, + () -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_ADVANCED); + registerItemProperty("state", + (stack, world, player) -> IColouredItem.getColourBasic(stack) != -1 ? 1 : 0, + () -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_NORMAL, + () -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_ADVANCED); + ClientRegistry.onItemColours(); + + // TODO Verify this does things properly + ServerWorldEvents.UNLOAD.register(((minecraftServer, serverWorld) -> { + ClientMonitor.destroyAll(); + })); + } + + public static void initEvents() { + + } + +// @Mod.EventBusSubscriber (modid = ComputerCraft.MOD_ID, value = Dist.CLIENT) +// public static final class ForgeHandlers { +// @SubscribeEvent +// public static void onWorldUnload(WorldEvent.Unload event) { +// if (event.getWorld() +// .isClient()) { +// ClientMonitor.destroyAll(); +// } +// } +// } } diff --git a/src/main/java/dan200/computercraft/client/render/CableHighlightRenderer.java b/src/main/java/dan200/computercraft/client/render/CableHighlightRenderer.java index d80d03ae0..0023981c1 100644 --- a/src/main/java/dan200/computercraft/client/render/CableHighlightRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/CableHighlightRenderer.java @@ -5,28 +5,25 @@ */ package dan200.computercraft.client.render; -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.shared.Registry; +import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.peripheral.modem.wired.BlockCable; import dan200.computercraft.shared.peripheral.modem.wired.CableShapes; import dan200.computercraft.shared.util.WorldUtil; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.minecraft.block.BlockState; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.Camera; -import net.minecraft.client.render.RenderLayer; import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.Entity; -import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Matrix4f; import net.minecraft.util.math.Vec3d; import net.minecraft.util.shape.VoxelShape; import net.minecraft.world.World; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.client.event.DrawHighlightEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; -@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT ) +@Environment(EnvType.CLIENT) public final class CableHighlightRenderer { private CableHighlightRenderer() @@ -35,29 +32,19 @@ public final class CableHighlightRenderer /** * Draw an outline for a specific part of a cable "Multipart". - * - * @param event The event to observe - * @see WorldRenderer#drawSelectionBox(MatrixStack, IVertexBuilder, Entity, double, double, double, BlockPos, BlockState) */ - @SubscribeEvent - public static void drawHighlight( DrawHighlightEvent.HighlightBlock event ) + public static boolean drawHighlight(MatrixStack stack, VertexConsumer consumer, Entity entity, double d, double e, double f, BlockPos pos, BlockState state) { - BlockHitResult hit = event.getTarget(); - BlockPos pos = hit.getBlockPos(); - World world = event.getInfo().getFocusedEntity().getEntityWorld(); - Camera info = event.getInfo(); - - BlockState state = world.getBlockState( pos ); + World world = entity.getEntityWorld(); + Camera info = MinecraftClient.getInstance().gameRenderer.getCamera(); // We only care about instances with both cable and modem. - if( state.getBlock() != Registry.ModBlocks.CABLE.get() || state.get( BlockCable.MODEM ).getFacing() == null || !state.get( BlockCable.CABLE ) ) + if( state.getBlock() != ComputerCraftRegistry.ModBlocks.CABLE || state.get( BlockCable.MODEM ).getFacing() == null || !state.get( BlockCable.CABLE ) ) { - return; + return false; } - event.setCanceled( true ); - - VoxelShape shape = WorldUtil.isVecInside( CableShapes.getModemShape( state ), hit.getPos().subtract( pos.getX(), pos.getY(), pos.getZ() ) ) + VoxelShape shape = WorldUtil.isVecInside( CableShapes.getModemShape( state ), new Vec3d(d, e, f).subtract( pos.getX(), pos.getY(), pos.getZ() ) ) ? CableShapes.getModemShape( state ) : CableShapes.getCableShape( state ); @@ -65,14 +52,14 @@ public final class CableHighlightRenderer double xOffset = pos.getX() - cameraPos.getX(); double yOffset = pos.getY() - cameraPos.getY(); double zOffset = pos.getZ() - cameraPos.getZ(); - - VertexConsumer buffer = event.getBuffers().getBuffer( RenderLayer.getLines() ); - Matrix4f matrix4f = event.getMatrix().peek().getModel(); + Matrix4f matrix4f = stack.peek().getModel(); shape.forEachEdge( ( x1, y1, z1, x2, y2, z2 ) -> { - buffer.vertex( matrix4f, (float) (x1 + xOffset), (float) (y1 + yOffset), (float) (z1 + zOffset) ) + consumer.vertex( matrix4f, (float) (x1 + xOffset), (float) (y1 + yOffset), (float) (z1 + zOffset) ) .color( 0, 0, 0, 0.4f ).next(); - buffer.vertex( matrix4f, (float) (x2 + xOffset), (float) (y2 + yOffset), (float) (z2 + zOffset) ) + consumer.vertex( matrix4f, (float) (x2 + xOffset), (float) (y2 + yOffset), (float) (z2 + zOffset) ) .color( 0, 0, 0, 0.4f ).next(); } ); + + return true; } } diff --git a/src/main/java/dan200/computercraft/client/render/ItemMapLikeRenderer.java b/src/main/java/dan200/computercraft/client/render/ItemMapLikeRenderer.java index fc6a8b07d..bd4c57399 100644 --- a/src/main/java/dan200/computercraft/client/render/ItemMapLikeRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/ItemMapLikeRenderer.java @@ -5,6 +5,8 @@ */ package dan200.computercraft.client.render; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.item.HeldItemRenderer; @@ -16,6 +18,7 @@ import net.minecraft.util.Arm; import net.minecraft.util.Hand; import net.minecraft.util.math.MathHelper; +@Environment(EnvType.CLIENT) public abstract class ItemMapLikeRenderer { /** @@ -24,11 +27,10 @@ public abstract class ItemMapLikeRenderer * @param transform The matrix transformation stack * @param render The buffer to render to * @param stack The stack to render - * @see FirstPersonRenderer#renderItemInFirstPerson(AbstractClientPlayerEntity, float, float, Hand, float, ItemStack, float, MatrixStack, IRenderTypeBuffer, int) */ protected abstract void renderItem( MatrixStack transform, VertexConsumerProvider render, ItemStack stack ); - protected void renderItemFirstPerson( MatrixStack transform, VertexConsumerProvider render, int lightTexture, Hand hand, float pitch, float equipProgress, float swingProgress, ItemStack stack ) + public void renderItemFirstPerson(MatrixStack transform, VertexConsumerProvider render, int lightTexture, Hand hand, float pitch, float equipProgress, float swingProgress, ItemStack stack) { PlayerEntity player = MinecraftClient.getInstance().player; @@ -58,7 +60,6 @@ public abstract class ItemMapLikeRenderer * @param equipProgress The equip progress of this item * @param swingProgress The swing progress of this item * @param stack The stack to render - * @see FirstPersonRenderer#renderMapFirstPersonSide(MatrixStack, IRenderTypeBuffer, int, float, HandSide, float, ItemStack) */ private void renderItemFirstPersonSide( MatrixStack transform, VertexConsumerProvider render, int combinedLight, Arm side, float equipProgress, float swingProgress, ItemStack stack ) { @@ -103,7 +104,6 @@ public abstract class ItemMapLikeRenderer * @param equipProgress The equip progress of this item * @param swingProgress The swing progress of this item * @param stack The stack to render - * @see FirstPersonRenderer#renderMapFirstPerson(MatrixStack, IRenderTypeBuffer, int, float, float, float) */ private void renderItemFirstPersonCenter( MatrixStack transform, VertexConsumerProvider render, int combinedLight, float pitch, float equipProgress, float swingProgress, ItemStack stack ) { diff --git a/src/main/java/dan200/computercraft/client/render/ItemPocketRenderer.java b/src/main/java/dan200/computercraft/client/render/ItemPocketRenderer.java index 7da6ceec1..d0efee93c 100644 --- a/src/main/java/dan200/computercraft/client/render/ItemPocketRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/ItemPocketRenderer.java @@ -22,10 +22,6 @@ import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.Vector3f; import net.minecraft.item.ItemStack; import net.minecraft.util.math.Matrix4f; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.client.event.RenderHandEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; import org.lwjgl.opengl.GL11; import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT; @@ -36,30 +32,16 @@ import static dan200.computercraft.client.render.ComputerBorderRenderer.MARGIN; /** * Emulates map rendering for pocket computers. */ -@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT ) public final class ItemPocketRenderer extends ItemMapLikeRenderer { private static final int LIGHT_HEIGHT = 8; - private static final ItemPocketRenderer INSTANCE = new ItemPocketRenderer(); + public static final ItemPocketRenderer INSTANCE = new ItemPocketRenderer(); private ItemPocketRenderer() { } - @SubscribeEvent - public static void onRenderInHand( RenderHandEvent event ) - { - ItemStack stack = event.getItemStack(); - if( !(stack.getItem() instanceof ItemPocketComputer) ) return; - - event.setCanceled( true ); - INSTANCE.renderItemFirstPerson( - event.getMatrixStack(), event.getBuffers(), event.getLight(), - event.getHand(), event.getInterpolatedPitch(), event.getEquipProgress(), event.getSwingProgress(), event.getItemStack() - ); - } - @Override protected void renderItem( MatrixStack transform, VertexConsumerProvider render, ItemStack stack ) { @@ -69,8 +51,8 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer int termWidth, termHeight; if( terminal == null ) { - termWidth = ComputerCraft.pocketTermWidth; - termHeight = ComputerCraft.pocketTermHeight; + termWidth = ComputerCraft.terminalWidth_pocketComputer; + termHeight = ComputerCraft.terminalHeight_pocketComputer; } else { diff --git a/src/main/java/dan200/computercraft/client/render/ItemPrintoutRenderer.java b/src/main/java/dan200/computercraft/client/render/ItemPrintoutRenderer.java index 42bea5a46..f83102559 100644 --- a/src/main/java/dan200/computercraft/client/render/ItemPrintoutRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/ItemPrintoutRenderer.java @@ -7,16 +7,12 @@ package dan200.computercraft.client.render; import dan200.computercraft.ComputerCraft; import dan200.computercraft.shared.media.items.ItemPrintout; +import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.Vector3f; import net.minecraft.item.ItemStack; import net.minecraft.util.math.Matrix4f; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.client.event.RenderHandEvent; -import net.minecraftforge.client.event.RenderItemInFrameEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT; import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_WIDTH; @@ -27,28 +23,14 @@ import static dan200.computercraft.shared.media.items.ItemPrintout.LINE_MAX_LENG /** * Emulates map and item-frame rendering for printouts. */ -@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT ) public final class ItemPrintoutRenderer extends ItemMapLikeRenderer { - private static final ItemPrintoutRenderer INSTANCE = new ItemPrintoutRenderer(); + public static final ItemPrintoutRenderer INSTANCE = new ItemPrintoutRenderer(); private ItemPrintoutRenderer() { } - @SubscribeEvent - public static void onRenderInHand( RenderHandEvent event ) - { - ItemStack stack = event.getItemStack(); - if( !(stack.getItem() instanceof ItemPrintout) ) return; - - event.setCanceled( true ); - INSTANCE.renderItemFirstPerson( - event.getMatrixStack(), event.getBuffers(), event.getLight(), - event.getHand(), event.getInterpolatedPitch(), event.getEquipProgress(), event.getSwingProgress(), event.getItemStack() - ); - } - @Override protected void renderItem( MatrixStack transform, VertexConsumerProvider render, ItemStack stack ) { @@ -59,22 +41,19 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer drawPrintout( transform, render, stack ); } - @SubscribeEvent - public static void onRenderInFrame( RenderItemInFrameEvent event ) + public boolean renderInFrame(MatrixStack matrixStack, VertexConsumerProvider consumerProvider, ItemStack stack ) { - ItemStack stack = event.getItem(); - if( !(stack.getItem() instanceof ItemPrintout) ) return; - event.setCanceled( true ); - - MatrixStack transform = event.getMatrix(); + if( !(stack.getItem() instanceof ItemPrintout) ) return false; // Move a little bit forward to ensure we're not clipping with the frame - transform.translate( 0.0f, 0.0f, -0.001f ); - transform.multiply( Vector3f.POSITIVE_Z.getDegreesQuaternion( 180f ) ); - transform.scale( 0.95f, 0.95f, -0.95f ); - transform.translate( -0.5f, -0.5f, 0.0f ); + matrixStack.translate( 0.0f, 0.0f, -0.001f ); + matrixStack.multiply( Vector3f.POSITIVE_Z.getDegreesQuaternion( 180f ) ); + matrixStack.scale( 0.95f, 0.95f, -0.95f ); + matrixStack.translate( -0.5f, -0.5f, 0.0f ); - drawPrintout( transform, event.getBuffers(), stack ); + drawPrintout( matrixStack, consumerProvider, stack ); + + return true; } private static void drawPrintout( MatrixStack transform, VertexConsumerProvider render, ItemStack stack ) diff --git a/src/main/java/dan200/computercraft/client/render/MonitorHighlightRenderer.java b/src/main/java/dan200/computercraft/client/render/MonitorHighlightRenderer.java index 019cc70a3..fc2b015fc 100644 --- a/src/main/java/dan200/computercraft/client/render/MonitorHighlightRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/MonitorHighlightRenderer.java @@ -5,21 +5,20 @@ */ package dan200.computercraft.client.render; -import dan200.computercraft.ComputerCraft; import dan200.computercraft.shared.peripheral.monitor.TileMonitor; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; -import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.Entity; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Matrix4f; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.client.event.DrawHighlightEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; import java.util.EnumSet; @@ -29,27 +28,24 @@ import static net.minecraft.util.math.Direction.*; * Overrides monitor highlighting to only render the outline of the whole monitor, rather than the current * block. This means you do not get an intrusive outline on top of the screen. */ -@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT ) +@Environment(EnvType.CLIENT) public final class MonitorHighlightRenderer { private MonitorHighlightRenderer() { } - @SubscribeEvent - public static void drawHighlight( DrawHighlightEvent.HighlightBlock event ) + public static boolean drawHighlight(MatrixStack matrixStack, VertexConsumer vertexConsumer, Entity entity, double d, double e, double f, BlockPos pos, BlockState blockState) { // Preserve normal behaviour when crouching. - if( event.getInfo().getFocusedEntity().isInSneakingPose() ) return; + if( entity.isInSneakingPose() ) return false; - World world = event.getInfo().getFocusedEntity().getEntityWorld(); - BlockPos pos = event.getTarget().getBlockPos(); + World world = entity.getEntityWorld(); BlockEntity tile = world.getBlockEntity( pos ); - if( !(tile instanceof TileMonitor) ) return; + if( !(tile instanceof TileMonitor) ) return false; TileMonitor monitor = (TileMonitor) tile; - event.setCanceled( true ); // Determine which sides are part of the external faces of the monitor, and so which need to be rendered. EnumSet faces = EnumSet.allOf( Direction.class ); @@ -60,28 +56,28 @@ public final class MonitorHighlightRenderer if( monitor.getYIndex() != 0 ) faces.remove( monitor.getDown().getOpposite() ); if( monitor.getYIndex() != monitor.getHeight() - 1 ) faces.remove( monitor.getDown() ); - MatrixStack transformStack = event.getMatrix(); - Vec3d cameraPos = event.getInfo().getPos(); - transformStack.push(); - transformStack.translate( pos.getX() - cameraPos.getX(), pos.getY() - cameraPos.getY(), pos.getZ() - cameraPos.getZ() ); + Vec3d cameraPos = MinecraftClient.getInstance().gameRenderer.getCamera().getPos(); + matrixStack.push(); + matrixStack.translate( pos.getX() - cameraPos.getX(), pos.getY() - cameraPos.getY(), pos.getZ() - cameraPos.getZ() ); // I wish I could think of a better way to do this - VertexConsumer buffer = event.getBuffers().getBuffer( RenderLayer.getLines() ); - Matrix4f transform = transformStack.peek().getModel(); - if( faces.contains( NORTH ) || faces.contains( WEST ) ) line( buffer, transform, 0, 0, 0, UP ); - if( faces.contains( SOUTH ) || faces.contains( WEST ) ) line( buffer, transform, 0, 0, 1, UP ); - if( faces.contains( NORTH ) || faces.contains( EAST ) ) line( buffer, transform, 1, 0, 0, UP ); - if( faces.contains( SOUTH ) || faces.contains( EAST ) ) line( buffer, transform, 1, 0, 1, UP ); - if( faces.contains( NORTH ) || faces.contains( DOWN ) ) line( buffer, transform, 0, 0, 0, EAST ); - if( faces.contains( SOUTH ) || faces.contains( DOWN ) ) line( buffer, transform, 0, 0, 1, EAST ); - if( faces.contains( NORTH ) || faces.contains( UP ) ) line( buffer, transform, 0, 1, 0, EAST ); - if( faces.contains( SOUTH ) || faces.contains( UP ) ) line( buffer, transform, 0, 1, 1, EAST ); - if( faces.contains( WEST ) || faces.contains( DOWN ) ) line( buffer, transform, 0, 0, 0, SOUTH ); - if( faces.contains( EAST ) || faces.contains( DOWN ) ) line( buffer, transform, 1, 0, 0, SOUTH ); - if( faces.contains( WEST ) || faces.contains( UP ) ) line( buffer, transform, 0, 1, 0, SOUTH ); - if( faces.contains( EAST ) || faces.contains( UP ) ) line( buffer, transform, 1, 1, 0, SOUTH ); + Matrix4f transform = matrixStack.peek().getModel(); + if( faces.contains( NORTH ) || faces.contains( WEST ) ) line( vertexConsumer, transform, 0, 0, 0, UP ); + if( faces.contains( SOUTH ) || faces.contains( WEST ) ) line( vertexConsumer, transform, 0, 0, 1, UP ); + if( faces.contains( NORTH ) || faces.contains( EAST ) ) line( vertexConsumer, transform, 1, 0, 0, UP ); + if( faces.contains( SOUTH ) || faces.contains( EAST ) ) line( vertexConsumer, transform, 1, 0, 1, UP ); + if( faces.contains( NORTH ) || faces.contains( DOWN ) ) line( vertexConsumer, transform, 0, 0, 0, EAST ); + if( faces.contains( SOUTH ) || faces.contains( DOWN ) ) line( vertexConsumer, transform, 0, 0, 1, EAST ); + if( faces.contains( NORTH ) || faces.contains( UP ) ) line( vertexConsumer, transform, 0, 1, 0, EAST ); + if( faces.contains( SOUTH ) || faces.contains( UP ) ) line( vertexConsumer, transform, 0, 1, 1, EAST ); + if( faces.contains( WEST ) || faces.contains( DOWN ) ) line( vertexConsumer, transform, 0, 0, 0, SOUTH ); + if( faces.contains( EAST ) || faces.contains( DOWN ) ) line( vertexConsumer, transform, 1, 0, 0, SOUTH ); + if( faces.contains( WEST ) || faces.contains( UP ) ) line( vertexConsumer, transform, 0, 1, 0, SOUTH ); + if( faces.contains( EAST ) || faces.contains( UP ) ) line( vertexConsumer, transform, 1, 1, 0, SOUTH ); - transformStack.pop(); + matrixStack.pop(); + + return true; } private static void line( VertexConsumer buffer, Matrix4f transform, float x, float y, float z, Direction direction ) diff --git a/src/main/java/dan200/computercraft/client/render/TileEntityTurtleRenderer.java b/src/main/java/dan200/computercraft/client/render/TileEntityTurtleRenderer.java index db8f03147..f22b40e2d 100644 --- a/src/main/java/dan200/computercraft/client/render/TileEntityTurtleRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/TileEntityTurtleRenderer.java @@ -32,7 +32,6 @@ import net.minecraft.util.hit.HitResult; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Matrix4f; import net.minecraft.util.math.Vec3d; -import net.minecraftforge.client.model.data.EmptyModelData; import javax.annotation.Nonnull; import java.util.List; @@ -80,7 +79,7 @@ public class TileEntityTurtleRenderer extends BlockEntityRenderer if( label != null && hit.getType() == HitResult.Type.BLOCK && turtle.getPos().equals( ((BlockHitResult) hit).getBlockPos() ) ) { MinecraftClient mc = MinecraftClient.getInstance(); - TextRenderer font = dispatcher.textRenderer; + TextRenderer font = mc.textRenderer; transform.push(); transform.translate( 0.5, 1.2, 0.5 ); @@ -146,7 +145,7 @@ public class TileEntityTurtleRenderer extends BlockEntityRenderer transform.translate( 0.0f, -0.5f, -0.5f ); TransformedModel model = upgrade.getModel( turtle.getAccess(), side ); - model.getMatrix().push( transform ); + // model.getMatrix().multiply(transform); renderModel( transform, renderer, lightmapCoord, overlayLight, model.getModel(), null ); transform.pop(); @@ -162,10 +161,10 @@ public class TileEntityTurtleRenderer extends BlockEntityRenderer private void renderModel( @Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, BakedModel model, int[] tints ) { random.setSeed( 0 ); - renderQuads( transform, renderer, lightmapCoord, overlayLight, model.getQuads( null, null, random, EmptyModelData.INSTANCE ), tints ); + renderQuads( transform, renderer, lightmapCoord, overlayLight, model.getQuads( null, null, random ), tints ); for( Direction facing : DirectionUtil.FACINGS ) { - renderQuads( transform, renderer, lightmapCoord, overlayLight, model.getQuads( null, facing, random, EmptyModelData.INSTANCE ), tints ); + renderQuads( transform, renderer, lightmapCoord, overlayLight, model.getQuads( null, facing, random ), tints ); } } @@ -185,7 +184,7 @@ public class TileEntityTurtleRenderer extends BlockEntityRenderer float f = (float) (tint >> 16 & 255) / 255.0F; float f1 = (float) (tint >> 8 & 255) / 255.0F; float f2 = (float) (tint & 255) / 255.0F; - buffer.addVertexData( matrix, bakedquad, f, f1, f2, lightmapCoord, overlayLight, true ); + buffer.quad( matrix, bakedquad, new float[]{1.0F, 1.0F, 1.0F, 1.0F}, f, f1, f2, new int[] {lightmapCoord, lightmapCoord, lightmapCoord, lightmapCoord}, overlayLight, true ); } } } diff --git a/src/main/java/dan200/computercraft/client/render/TurtleModelLoader.java b/src/main/java/dan200/computercraft/client/render/TurtleModelLoader.java deleted file mode 100644 index cbceab909..000000000 --- a/src/main/java/dan200/computercraft/client/render/TurtleModelLoader.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.client.render; - -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonObject; -import com.mojang.datafixers.util.Pair; -import dan200.computercraft.ComputerCraft; -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.render.model.ModelBakeSettings; -import net.minecraft.client.render.model.ModelLoader; -import net.minecraft.client.render.model.UnbakedModel; -import net.minecraft.client.render.model.json.ModelOverrideList; -import net.minecraft.client.renderer.model.*; -import net.minecraft.client.texture.Sprite; -import net.minecraft.client.util.SpriteIdentifier; -import net.minecraft.resource.ResourceManager; -import net.minecraft.util.Identifier; -import net.minecraft.util.JsonHelper; -import net.minecraftforge.client.model.IModelConfiguration; -import net.minecraftforge.client.model.IModelLoader; -import net.minecraftforge.client.model.geometry.IModelGeometry; - -import javax.annotation.Nonnull; -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; -import java.util.function.Function; - -public final class TurtleModelLoader implements IModelLoader -{ - private static final Identifier COLOUR_TURTLE_MODEL = new Identifier( ComputerCraft.MOD_ID, "block/turtle_colour" ); - - public static final TurtleModelLoader INSTANCE = new TurtleModelLoader(); - - private TurtleModelLoader() { - } - - @Override - public void apply( @Nonnull ResourceManager manager ) - { - } - - @Nonnull - @Override - public TurtleModel read( @Nonnull JsonDeserializationContext deserializationContext, @Nonnull JsonObject modelContents ) - { - Identifier model = new Identifier( JsonHelper.getString( modelContents, "model" ) ); - return new TurtleModel( model ); - } - - public static final class TurtleModel implements IModelGeometry - { - private final Identifier family; - - private TurtleModel( Identifier family ) - { - this.family = family; - } - - @Override - public Collection getTextures( IModelConfiguration owner, Function modelGetter, Set> missingTextureErrors ) - { - Set materials = new HashSet<>(); - materials.addAll( modelGetter.apply( family ).getTextureDependencies( modelGetter, missingTextureErrors ) ); - materials.addAll( modelGetter.apply( COLOUR_TURTLE_MODEL ).getTextureDependencies( modelGetter, missingTextureErrors ) ); - return materials; - } - - @Override - public BakedModel bake( IModelConfiguration owner, ModelLoader bakery, Function spriteGetter, ModelBakeSettings transform, ModelOverrideList overrides, Identifier modelLocation ) - { - return new TurtleSmartItemModel( - bakery.getBakedModel( family, transform, spriteGetter ), - bakery.getBakedModel( COLOUR_TURTLE_MODEL, transform, spriteGetter ) - ); - } - } -} diff --git a/src/main/java/dan200/computercraft/client/render/TurtleMultiModel.java b/src/main/java/dan200/computercraft/client/render/TurtleMultiModel.java index c0e351541..d889fb15e 100644 --- a/src/main/java/dan200/computercraft/client/render/TurtleMultiModel.java +++ b/src/main/java/dan200/computercraft/client/render/TurtleMultiModel.java @@ -6,6 +6,8 @@ package dan200.computercraft.client.render; import dan200.computercraft.api.client.TransformedModel; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.minecraft.block.BlockState; import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.BakedQuad; @@ -13,14 +15,11 @@ import net.minecraft.client.render.model.json.ModelOverrideList; import net.minecraft.client.texture.Sprite; import net.minecraft.client.util.math.AffineTransformation; import net.minecraft.util.math.Direction; -import net.minecraftforge.client.model.data.EmptyModelData; -import net.minecraftforge.client.model.data.IModelData; -import net.minecraftforge.client.model.pipeline.BakedQuadBuilder; -import net.minecraftforge.client.model.pipeline.TRSRTransformer; import javax.annotation.Nonnull; import java.util.*; +@Environment(EnvType.CLIENT) public class TurtleMultiModel implements BakedModel { private final BakedModel m_baseModel; @@ -43,15 +42,7 @@ public class TurtleMultiModel implements BakedModel @Nonnull @Override - @Deprecated public List getQuads( BlockState state, Direction side, @Nonnull Random rand ) - { - return getQuads( state, side, rand, EmptyModelData.INSTANCE ); - } - - @Nonnull - @Override - public List getQuads( BlockState state, Direction side, @Nonnull Random rand, @Nonnull IModelData data ) { if( side != null ) { @@ -70,20 +61,20 @@ public class TurtleMultiModel implements BakedModel ArrayList quads = new ArrayList<>(); - transformQuadsTo( quads, m_baseModel.getQuads( state, side, rand, EmptyModelData.INSTANCE ), m_generalTransform ); + transformQuadsTo( quads, m_baseModel.getQuads( state, side, rand ), m_generalTransform ); if( m_overlayModel != null ) { - transformQuadsTo( quads, m_overlayModel.getQuads( state, side, rand, EmptyModelData.INSTANCE ), m_generalTransform ); + transformQuadsTo( quads, m_overlayModel.getQuads( state, side, rand ), m_generalTransform ); } if( m_leftUpgradeModel != null ) { - AffineTransformation upgradeTransform = m_generalTransform.compose( m_leftUpgradeModel.getMatrix() ); - transformQuadsTo( quads, m_leftUpgradeModel.getModel().getQuads( state, side, rand, EmptyModelData.INSTANCE ), upgradeTransform ); + AffineTransformation upgradeTransform = m_generalTransform.multiply( m_leftUpgradeModel.getMatrix() ); + transformQuadsTo( quads, m_leftUpgradeModel.getModel().getQuads( state, side, rand ), upgradeTransform ); } if( m_rightUpgradeModel != null ) { - AffineTransformation upgradeTransform = m_generalTransform.compose( m_rightUpgradeModel.getMatrix() ); - transformQuadsTo( quads, m_rightUpgradeModel.getModel().getQuads( state, side, rand, EmptyModelData.INSTANCE ), upgradeTransform ); + AffineTransformation upgradeTransform = m_generalTransform.multiply( m_rightUpgradeModel.getMatrix() ); + transformQuadsTo( quads, m_rightUpgradeModel.getModel().getQuads( state, side, rand ), upgradeTransform ); } quads.trimToSize(); return quads; @@ -140,10 +131,11 @@ public class TurtleMultiModel implements BakedModel { for( BakedQuad quad : quads ) { - BakedQuadBuilder builder = new BakedQuadBuilder(); - TRSRTransformer transformer = new TRSRTransformer( builder, transform ); - quad.pipe( transformer ); - output.add( builder.build() ); + // TODO Figure out what the fuck to do here +// BakedQuadBuilder builder = new BakedQuadBuilder(); +// TRSRTransformer transformer = new TRSRTransformer( builder, transform ); +// quad.pipe( transformer ); +// output.add( builder.build() ); } } } diff --git a/src/main/java/dan200/computercraft/client/render/TurtlePlayerRenderer.java b/src/main/java/dan200/computercraft/client/render/TurtlePlayerRenderer.java index 9031d111e..9da8c90af 100644 --- a/src/main/java/dan200/computercraft/client/render/TurtlePlayerRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/TurtlePlayerRenderer.java @@ -8,6 +8,8 @@ package dan200.computercraft.client.render; import dan200.computercraft.shared.turtle.core.TurtlePlayer; import javax.annotation.Nonnull; + +import net.fabricmc.fabric.api.client.rendereregistry.v1.EntityRendererRegistry; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.entity.EntityRenderDispatcher; import net.minecraft.client.render.entity.EntityRenderer; @@ -21,9 +23,13 @@ public class TurtlePlayerRenderer extends EntityRenderer super( renderManager ); } + public TurtlePlayerRenderer(EntityRenderDispatcher entityRenderDispatcher, EntityRendererRegistry.Context context) { + super(entityRenderDispatcher); + } + @Nonnull @Override - public Identifier getEntityTexture( @Nonnull TurtlePlayer entity ) + public Identifier getTexture( @Nonnull TurtlePlayer entity ) { return ComputerBorderRenderer.BACKGROUND_NORMAL; } diff --git a/src/main/java/dan200/computercraft/client/render/TurtleSmartItemModel.java b/src/main/java/dan200/computercraft/client/render/TurtleSmartItemModel.java index 7128d1a95..3d8fb8a80 100644 --- a/src/main/java/dan200/computercraft/client/render/TurtleSmartItemModel.java +++ b/src/main/java/dan200/computercraft/client/render/TurtleSmartItemModel.java @@ -5,13 +5,6 @@ */ package dan200.computercraft.client.render; -import java.util.HashMap; -import java.util.List; -import java.util.Random; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import com.google.common.base.Objects; import dan200.computercraft.api.client.TransformedModel; import dan200.computercraft.api.turtle.ITurtleUpgrade; @@ -19,8 +12,8 @@ import dan200.computercraft.api.turtle.TurtleSide; import dan200.computercraft.shared.turtle.items.ItemTurtle; import dan200.computercraft.shared.util.Holiday; import dan200.computercraft.shared.util.HolidayUtil; -import net.minecraftforge.client.model.data.IModelData; - +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.minecraft.block.BlockState; import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.model.BakedModel; @@ -28,7 +21,6 @@ import net.minecraft.client.render.model.BakedModelManager; import net.minecraft.client.render.model.BakedQuad; import net.minecraft.client.render.model.json.ModelOverrideList; import net.minecraft.client.render.model.json.ModelTransformation; -import net.minecraft.client.renderer.model.*; import net.minecraft.client.texture.Sprite; import net.minecraft.client.util.ModelIdentifier; import net.minecraft.client.util.math.AffineTransformation; @@ -39,11 +31,13 @@ import net.minecraft.item.ItemStack; import net.minecraft.util.Identifier; import net.minecraft.util.math.Direction; -@SuppressWarnings ({ - "MethodCallSideOnly", - "LocalVariableDeclarationSideOnly", - "NewExpressionSideOnly" -}) +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.HashMap; +import java.util.List; +import java.util.Random; + +@Environment(EnvType.CLIENT) public class TurtleSmartItemModel implements BakedModel { private static final AffineTransformation identity, flip; @@ -170,14 +164,6 @@ public class TurtleSmartItemModel implements BakedModel return familyModel.getQuads( state, facing, rand ); } - @Nonnull - @Override - @Deprecated - public List getQuads( BlockState state, Direction facing, @Nonnull Random rand, @Nonnull IModelData data ) - { - return familyModel.getQuads( state, facing, rand, data ); - } - @Override public boolean useAmbientOcclusion() { diff --git a/src/main/java/dan200/computercraft/core/apis/AddressPredicate.java b/src/main/java/dan200/computercraft/core/apis/AddressPredicate.java new file mode 100644 index 000000000..ad11bc83b --- /dev/null +++ b/src/main/java/dan200/computercraft/core/apis/AddressPredicate.java @@ -0,0 +1,165 @@ +/* + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.core.apis; + +import java.net.Inet6Address; +import java.net.InetAddress; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.regex.Pattern; + +import com.google.common.net.InetAddresses; +import dan200.computercraft.ComputerCraft; + +/** + * Used to determine whether a domain or IP address matches a series of patterns. + */ +public class AddressPredicate { + private final List wildcards; + private final List ranges; + public AddressPredicate(String... filters) { + this(Arrays.asList(filters)); + } + + public AddressPredicate(Iterable filters) { + List wildcards = this.wildcards = new ArrayList<>(); + List ranges = this.ranges = new ArrayList<>(); + + for (String filter : filters) { + int cidr = filter.indexOf('/'); + if (cidr >= 0) { + String addressStr = filter.substring(0, cidr); + String prefixSizeStr = filter.substring(cidr + 1); + + int prefixSize; + try { + prefixSize = Integer.parseInt(prefixSizeStr); + } catch (NumberFormatException e) { + ComputerCraft.log.error("Malformed http whitelist/blacklist entry '{}': Cannot extract size of CIDR mask from '{}'.", + filter, + prefixSizeStr); + continue; + } + + InetAddress address; + try { + address = InetAddresses.forString(addressStr); + } catch (IllegalArgumentException e) { + ComputerCraft.log.error("Malformed http whitelist/blacklist entry '{}': Cannot extract IP address from '{}'.", filter, prefixSizeStr); + continue; + } + + // Mask the bytes of the IP address. + byte[] minBytes = address.getAddress(), maxBytes = address.getAddress(); + int size = prefixSize; + for (int i = 0; i < minBytes.length; i++) { + if (size <= 0) { + minBytes[i] &= 0; + maxBytes[i] |= 0xFF; + } else if (size < 8) { + minBytes[i] &= 0xFF << (8 - size); + maxBytes[i] |= ~(0xFF << (8 - size)); + } + + size -= 8; + } + + ranges.add(new HostRange(minBytes, maxBytes)); + } else { + wildcards.add(Pattern.compile("^\\Q" + filter.replaceAll("\\*", "\\\\E.*\\\\Q") + "\\E$")); + } + } + } + + /** + * Determine whether the given address matches a series of patterns + * + * @param address The address to check. + * @return Whether it matches any of these patterns. + */ + public boolean matches(InetAddress address) { + // Match the host name + String host = address.getHostName(); + if (host != null && this.matches(host)) { + return true; + } + + // Match the normal address + if (this.matchesAddress(address)) { + return true; + } + + // If we're an IPv4 address in disguise then let's check that. + return address instanceof Inet6Address && InetAddresses.is6to4Address((Inet6Address) address) && this.matchesAddress(InetAddresses.get6to4IPv4Address((Inet6Address) address)); + + } + + /** + * Determine whether a host name matches a series of patterns. + * + * This is intended to allow early exiting, before one has to look up the IP address. You should use {@link #matches(InetAddress)} instead of/in + * addition to this one. + * + * @param domain The domain to match. + * @return Whether the patterns were matched. + */ + public boolean matches(String domain) { + for (Pattern domainPattern : this.wildcards) { + if (domainPattern.matcher(domain) + .matches()) { + return true; + } + } + + return false; + } + + private boolean matchesAddress(InetAddress address) { + String addressString = address.getHostAddress(); + for (Pattern domainPattern : this.wildcards) { + if (domainPattern.matcher(addressString) + .matches()) { + return true; + } + } + + for (HostRange range : this.ranges) { + if (range.contains(address)) { + return true; + } + } + + return false; + } + + private static final class HostRange { + private final byte[] min; + private final byte[] max; + + private HostRange(byte[] min, byte[] max) { + this.min = min; + this.max = max; + } + + public boolean contains(InetAddress address) { + byte[] entry = address.getAddress(); + if (entry.length != this.min.length) { + return false; + } + + for (int i = 0; i < entry.length; i++) { + int value = 0xFF & entry[i]; + if (value < (0xFF & this.min[i]) || value > (0xFF & this.max[i])) { + return false; + } + } + + return true; + } + } +} diff --git a/src/main/java/dan200/computercraft/core/apis/HTTPAPI.java b/src/main/java/dan200/computercraft/core/apis/HTTPAPI.java index 71163f064..502d1d7e8 100644 --- a/src/main/java/dan200/computercraft/core/apis/HTTPAPI.java +++ b/src/main/java/dan200/computercraft/core/apis/HTTPAPI.java @@ -155,7 +155,7 @@ public class HTTPAPI implements ILuaAPI @LuaFunction public final Object[] websocket( String address, Optional> headerTbl ) throws LuaException { - if( !ComputerCraft.httpWebsocketEnabled ) + if( !ComputerCraft.http_websocket_enable ) { throw new LuaException( "Websocket connections are disabled" ); } diff --git a/src/main/java/dan200/computercraft/core/apis/PeripheralAPI.java b/src/main/java/dan200/computercraft/core/apis/PeripheralAPI.java index 60c5267fb..b132ad48c 100644 --- a/src/main/java/dan200/computercraft/core/apis/PeripheralAPI.java +++ b/src/main/java/dan200/computercraft/core/apis/PeripheralAPI.java @@ -46,7 +46,7 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange this.peripheral = peripheral; attached = false; - type = Objects.requireNonNull(peripheral.getType0(), "Peripheral type cannot be null" ); + type = Objects.requireNonNull( peripheral.getType(), "Peripheral type cannot be null" ); methodMap = PeripheralAPI.getMethods( peripheral ); } diff --git a/src/main/java/dan200/computercraft/core/apis/http/options/AddressRuleConfig.java b/src/main/java/dan200/computercraft/core/apis/http/options/AddressRuleConfig.java index 4f0bc5647..46e3f69a9 100644 --- a/src/main/java/dan200/computercraft/core/apis/http/options/AddressRuleConfig.java +++ b/src/main/java/dan200/computercraft/core/apis/http/options/AddressRuleConfig.java @@ -6,127 +6,115 @@ package dan200.computercraft.core.apis.http.options; -import com.electronwill.nightconfig.core.CommentedConfig; -import com.electronwill.nightconfig.core.Config; -import com.electronwill.nightconfig.core.InMemoryCommentedFormat; -import com.electronwill.nightconfig.core.UnmodifiableConfig; -import dan200.computercraft.ComputerCraft; - -import javax.annotation.Nullable; -import java.util.Locale; -import java.util.Optional; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Parses, checks and generates {@link Config}s for {@link AddressRule}. - */ public class AddressRuleConfig { - public static UnmodifiableConfig makeRule( String host, Action action ) - { - CommentedConfig config = InMemoryCommentedFormat.defaultInstance().createConfig( ConcurrentHashMap::new ); - config.add( "host", host ); - config.add( "action", action.name().toLowerCase( Locale.ROOT ) ); + // TODO haha config is gone, do fix - if( host.equals( "*" ) && action == Action.ALLOW ) - { - config.setComment( "timeout", "The period of time (in milliseconds) to wait before a HTTP request times out. Set to 0 for unlimited." ); - config.add( "timeout", AddressRule.TIMEOUT ); - - config.setComment( "max_download", "The maximum size (in bytes) that a computer can download in a single request. Note that responses may receive more data than allowed, but this data will not be returned to the client." ); - config.set( "max_download", AddressRule.MAX_DOWNLOAD ); - - config.setComment( "max_upload", "The maximum size (in bytes) that a computer can upload in a single request. This includes headers and POST text." ); - config.set( "max_upload", AddressRule.MAX_UPLOAD ); - - config.setComment( "max_websocket_message", "The maximum size (in bytes) that a computer can send or receive in one websocket packet." ); - config.set( "max_websocket_message", AddressRule.WEBSOCKET_MESSAGE ); - } - - return config; - } - - public static boolean checkRule( UnmodifiableConfig builder ) - { - String hostObj = get( builder, "host", String.class ).orElse( null ); - return hostObj != null && checkEnum( builder, "action", Action.class ) - && check( builder, "timeout", Number.class ) - && check( builder, "max_upload", Number.class ) - && check( builder, "max_download", Number.class ) - && check( builder, "websocket_message", Number.class ) - && AddressRule.parse( hostObj, PartialOptions.DEFAULT ) != null; - } - - @Nullable - public static AddressRule parseRule( UnmodifiableConfig builder ) - { - String hostObj = get( builder, "host", String.class ).orElse( null ); - if( hostObj == null ) return null; - - Action action = getEnum( builder, "action", Action.class ).orElse( null ); - Integer timeout = get( builder, "timeout", Number.class ).map( Number::intValue ).orElse( null ); - Long maxUpload = get( builder, "max_upload", Number.class ).map( Number::longValue ).orElse( null ); - Long maxDownload = get( builder, "max_download", Number.class ).map( Number::longValue ).orElse( null ); - Integer websocketMessage = get( builder, "websocket_message", Number.class ).map( Number::intValue ).orElse( null ); - - PartialOptions options = new PartialOptions( - action, - maxUpload, - maxDownload, - timeout, - websocketMessage - ); - - return AddressRule.parse( hostObj, options ); - } - - private static boolean check( UnmodifiableConfig config, String field, Class klass ) - { - Object value = config.get( field ); - if( value == null || klass.isInstance( value ) ) return true; - - ComputerCraft.log.warn( "HTTP rule's {} is not a {}.", field, klass.getSimpleName() ); - return false; - } - - private static > boolean checkEnum( UnmodifiableConfig config, String field, Class klass ) - { - Object value = config.get( field ); - if( value == null ) return true; - - if( !(value instanceof String) ) - { - ComputerCraft.log.warn( "HTTP rule's {} is not a string", field ); - return false; - } - - if( parseEnum( klass, (String) value ) == null ) - { - ComputerCraft.log.warn( "HTTP rule's {} is not a known option", field ); - return false; - } - - return true; - } - - private static Optional get( UnmodifiableConfig config, String field, Class klass ) - { - Object value = config.get( field ); - return klass.isInstance( value ) ? Optional.of( klass.cast( value ) ) : Optional.empty(); - } - - private static > Optional getEnum( UnmodifiableConfig config, String field, Class klass ) - { - return get( config, field, String.class ).map( x -> parseEnum( klass, x ) ); - } - - @Nullable - private static > T parseEnum( Class klass, String x ) - { - for( T value : klass.getEnumConstants() ) - { - if( value.name().equalsIgnoreCase( x ) ) return value; - } - return null; - } +// public static UnmodifiableConfig makeRule( String host, Action action ) +// { +// CommentedConfig config = InMemoryCommentedFormat.defaultInstance().createConfig( ConcurrentHashMap::new ); +// config.add( "host", host ); +// config.add( "action", action.name().toLowerCase( Locale.ROOT ) ); +// +// if( host.equals( "*" ) && action == Action.ALLOW ) +// { +// config.setComment( "timeout", "The period of time (in milliseconds) to wait before a HTTP request times out. Set to 0 for unlimited." ); +// config.add( "timeout", AddressRule.TIMEOUT ); +// +// config.setComment( "max_download", "The maximum size (in bytes) that a computer can download in a single request. Note that responses may receive more data than allowed, but this data will not be returned to the client." ); +// config.set( "max_download", AddressRule.MAX_DOWNLOAD ); +// +// config.setComment( "max_upload", "The maximum size (in bytes) that a computer can upload in a single request. This includes headers and POST text." ); +// config.set( "max_upload", AddressRule.MAX_UPLOAD ); +// +// config.setComment( "max_websocket_message", "The maximum size (in bytes) that a computer can send or receive in one websocket packet." ); +// config.set( "max_websocket_message", AddressRule.WEBSOCKET_MESSAGE ); +// } +// +// return config; +// } +// +// public static boolean checkRule( UnmodifiableConfig builder ) +// { +// String hostObj = get( builder, "host", String.class ).orElse( null ); +// return hostObj != null && checkEnum( builder, "action", Action.class ) +// && check( builder, "timeout", Number.class ) +// && check( builder, "max_upload", Number.class ) +// && check( builder, "max_download", Number.class ) +// && check( builder, "websocket_message", Number.class ) +// && AddressRule.parse( hostObj, PartialOptions.DEFAULT ) != null; +// } +// +// @Nullable +// public static AddressRule parseRule( UnmodifiableConfig builder ) +// { +// String hostObj = get( builder, "host", String.class ).orElse( null ); +// if( hostObj == null ) return null; +// +// Action action = getEnum( builder, "action", Action.class ).orElse( null ); +// Integer timeout = get( builder, "timeout", Number.class ).map( Number::intValue ).orElse( null ); +// Long maxUpload = get( builder, "max_upload", Number.class ).map( Number::longValue ).orElse( null ); +// Long maxDownload = get( builder, "max_download", Number.class ).map( Number::longValue ).orElse( null ); +// Integer websocketMessage = get( builder, "websocket_message", Number.class ).map( Number::intValue ).orElse( null ); +// +// PartialOptions options = new PartialOptions( +// action, +// maxUpload, +// maxDownload, +// timeout, +// websocketMessage +// ); +// +// return AddressRule.parse( hostObj, options ); +// } +// +// private static boolean check( UnmodifiableConfig config, String field, Class klass ) +// { +// Object value = config.get( field ); +// if( value == null || klass.isInstance( value ) ) return true; +// +// ComputerCraft.log.warn( "HTTP rule's {} is not a {}.", field, klass.getSimpleName() ); +// return false; +// } +// +// private static > boolean checkEnum( UnmodifiableConfig config, String field, Class klass ) +// { +// Object value = config.get( field ); +// if( value == null ) return true; +// +// if( !(value instanceof String) ) +// { +// ComputerCraft.log.warn( "HTTP rule's {} is not a string", field ); +// return false; +// } +// +// if( parseEnum( klass, (String) value ) == null ) +// { +// ComputerCraft.log.warn( "HTTP rule's {} is not a known option", field ); +// return false; +// } +// +// return true; +// } +// +// private static Optional get( UnmodifiableConfig config, String field, Class klass ) +// { +// Object value = config.get( field ); +// return klass.isInstance( value ) ? Optional.of( klass.cast( value ) ) : Optional.empty(); +// } +// +// private static > Optional getEnum( UnmodifiableConfig config, String field, Class klass ) +// { +// return get( config, field, String.class ).map( x -> parseEnum( klass, x ) ); +// } +// +// @Nullable +// private static > T parseEnum( Class klass, String x ) +// { +// for( T value : klass.getEnumConstants() ) +// { +// if( value.name().equalsIgnoreCase( x ) ) return value; +// } +// return null; +// } } diff --git a/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequest.java b/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequest.java index ebd21a655..84a0ba264 100644 --- a/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequest.java +++ b/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequest.java @@ -203,7 +203,7 @@ public class HttpRequest extends Resource catch( Exception e ) { failure( "Could not connect" ); - if( ComputerCraft.logComputerErrors ) ComputerCraft.log.error( "Error in HTTP request", e ); + if( ComputerCraft.logPeripheralErrors ) ComputerCraft.log.error( "Error in HTTP request", e ); } } diff --git a/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequestHandler.java b/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequestHandler.java index fbd102be6..91a1d7d99 100644 --- a/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequestHandler.java +++ b/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequestHandler.java @@ -188,7 +188,7 @@ public final class HttpRequestHandler extends SimpleChannelInboundHandler catch( Exception e ) { failure( "Could not connect" ); - if( ComputerCraft.logComputerErrors ) ComputerCraft.log.error( "Error in websocket", e ); + if( ComputerCraft.logPeripheralErrors ) ComputerCraft.log.error( "Error in websocket", e ); } } diff --git a/src/main/java/dan200/computercraft/core/asm/GenericSource.java b/src/main/java/dan200/computercraft/core/asm/GenericSource.java index e84fc2ab4..acae12e63 100644 --- a/src/main/java/dan200/computercraft/core/asm/GenericSource.java +++ b/src/main/java/dan200/computercraft/core/asm/GenericSource.java @@ -8,8 +8,6 @@ package dan200.computercraft.core.asm; import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.shared.peripheral.generic.GenericPeripheralProvider; -import dan200.computercraft.shared.util.ServiceUtil; import javax.annotation.Nonnull; import net.minecraft.util.Identifier; import java.lang.reflect.Method; @@ -28,10 +26,6 @@ import java.util.stream.Stream; * * Unlike conventional Lua objects, the annotated methods should be {@code static}, with their target as the first * parameter. - * - * This is used by the generic peripheral system ({@link GenericPeripheralProvider}) to provide methods for arbitrary - * tile entities. Eventually this'll be be exposed in the public API. Until it is stabilised, it will remain in this - * package - do not use it in external mods! */ public interface GenericSource { @@ -47,8 +41,6 @@ public interface GenericSource * Register a stream of generic sources. * * @param sources The source of generic methods. - * @see ServiceUtil For ways to load this. Sadly {@link java.util.ServiceLoader} is broken under Forge, but we don't - * want to add a hard-dep on Forge within core either. */ static void setup( Supplier> sources ) { diff --git a/src/main/java/dan200/computercraft/core/computer/ComputerExecutor.java b/src/main/java/dan200/computercraft/core/computer/ComputerExecutor.java index 021c4b473..46b9f6289 100644 --- a/src/main/java/dan200/computercraft/core/computer/ComputerExecutor.java +++ b/src/main/java/dan200/computercraft/core/computer/ComputerExecutor.java @@ -171,7 +171,7 @@ final class ComputerExecutor apis.add( new FSAPI( environment ) ); apis.add( new PeripheralAPI( environment ) ); apis.add( new OSAPI( environment ) ); - if( ComputerCraft.httpEnabled ) apis.add( new HTTPAPI( environment ) ); + if( ComputerCraft.http_enable ) apis.add( new HTTPAPI( environment ) ); // Load in the externally registered APIs. for( ILuaAPIFactory factory : ApiFactories.getAll() ) diff --git a/src/main/java/dan200/computercraft/core/computer/ComputerThread.java b/src/main/java/dan200/computercraft/core/computer/ComputerThread.java index 66ea9e644..43a5ddfc5 100644 --- a/src/main/java/dan200/computercraft/core/computer/ComputerThread.java +++ b/src/main/java/dan200/computercraft/core/computer/ComputerThread.java @@ -136,7 +136,7 @@ public final class ComputerThread if( runners == null ) { // TODO: Change the runners length on config reloads - runners = new TaskRunner[ComputerCraft.computerThreads]; + runners = new TaskRunner[ComputerCraft.computer_threads]; // latency and minPeriod are scaled by 1 + floor(log2(threads)). We can afford to execute tasks for // longer when executing on more than one thread. @@ -518,7 +518,7 @@ public final class ComputerThread private static void timeoutTask( ComputerExecutor executor, Thread thread, long time ) { - if( !ComputerCraft.logComputerErrors ) return; + if( !ComputerCraft.logPeripheralErrors ) return; StringBuilder builder = new StringBuilder() .append( "Terminating computer #" ).append( executor.getComputer().getID() ) diff --git a/src/main/java/dan200/computercraft/core/filesystem/ResourceMount.java b/src/main/java/dan200/computercraft/core/filesystem/ResourceMount.java index 18c012f98..7c96ab5de 100644 --- a/src/main/java/dan200/computercraft/core/filesystem/ResourceMount.java +++ b/src/main/java/dan200/computercraft/core/filesystem/ResourceMount.java @@ -12,14 +12,13 @@ import com.google.common.io.ByteStreams; import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.filesystem.IMount; import dan200.computercraft.core.apis.handles.ArrayByteChannel; -import dan200.computercraft.core.filesystem.ResourceMount.Listener; import net.minecraft.resource.ReloadableResourceManager; import net.minecraft.resource.Resource; import net.minecraft.resource.ResourceManager; +import net.minecraft.resource.ResourceReloadListener; import net.minecraft.util.Identifier; import net.minecraft.util.InvalidIdentifierException; -import net.minecraftforge.resource.IResourceType; -import net.minecraftforge.resource.ISelectiveResourceReloadListener; +import net.minecraft.util.profiler.Profiler; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -29,6 +28,8 @@ import java.io.InputStream; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import java.util.function.Predicate; @@ -271,12 +272,10 @@ public final class ResourceMount implements IMount } /** - * A {@link ISelectiveResourceReloadListener} which reloads any associated mounts. - * * While people should really be keeping a permanent reference to this, some people construct it every * method call, so let's make this as small as possible. */ - static class Listener implements ISelectiveResourceReloadListener + static class Listener implements ResourceReloadListener { private static final Listener INSTANCE = new Listener(); @@ -284,22 +283,25 @@ public final class ResourceMount implements IMount private final Set managers = Collections.newSetFromMap( new WeakHashMap<>() ); @Override - public void apply( @Nonnull ResourceManager manager ) - { - // FIXME: Remove this. We need this patch in order to prevent trying to load ReloadRequirements. - onResourceManagerReload( manager, x -> true ); + public CompletableFuture reload(Synchronizer synchronizer, ResourceManager resourceManager, Profiler profiler, Profiler profiler1, + Executor executor, Executor executor1) { + return CompletableFuture.runAsync(() -> { + profiler.push("Mount reloading"); + try { + for (ResourceMount mount : this.mounts) { + mount.load(); + } + } finally { + profiler.pop(); + } + }, executor); } - @Override - public synchronized void onResourceManagerReload( @Nonnull ResourceManager manager, @Nonnull Predicate predicate ) - { - for( ResourceMount mount : mounts ) mount.load(); - } - - synchronized void add( ReloadableResourceManager manager, ResourceMount mount ) - { - if( managers.add( manager ) ) manager.registerListener( this ); - mounts.add( mount ); + synchronized void add(ReloadableResourceManager manager, ResourceMount mount) { + if (this.managers.add(manager)) { + manager.registerListener(this); + } + this.mounts.add(mount); } } } diff --git a/src/main/java/dan200/computercraft/core/lua/BasicFunction.java b/src/main/java/dan200/computercraft/core/lua/BasicFunction.java index 6f4b25652..3c988f025 100644 --- a/src/main/java/dan200/computercraft/core/lua/BasicFunction.java +++ b/src/main/java/dan200/computercraft/core/lua/BasicFunction.java @@ -54,7 +54,7 @@ class BasicFunction extends VarArgFunction } catch( Throwable t ) { - if( ComputerCraft.logComputerErrors ) + if( ComputerCraft.logPeripheralErrors ) { ComputerCraft.log.error( "Error calling " + name + " on " + instance, t ); } diff --git a/src/main/java/dan200/computercraft/core/lua/CobaltLuaMachine.java b/src/main/java/dan200/computercraft/core/lua/CobaltLuaMachine.java index e678667e1..99861433c 100644 --- a/src/main/java/dan200/computercraft/core/lua/CobaltLuaMachine.java +++ b/src/main/java/dan200/computercraft/core/lua/CobaltLuaMachine.java @@ -97,7 +97,7 @@ public class CobaltLuaMachine implements ILuaMachine m_globals.load( state, new CoroutineLib() ); m_globals.load( state, new Bit32Lib() ); m_globals.load( state, new Utf8Lib() ); - if( ComputerCraft.debugEnable ) m_globals.load( state, new DebugLib() ); + if( ComputerCraft.debug_enable ) m_globals.load( state, new DebugLib() ); // Remove globals we don't want to expose m_globals.rawset( "collectgarbage", Constants.NIL ); @@ -108,8 +108,8 @@ public class CobaltLuaMachine implements ILuaMachine // Add version globals m_globals.rawset( "_VERSION", valueOf( "Lua 5.1" ) ); m_globals.rawset( "_HOST", valueOf( computer.getAPIEnvironment().getComputerEnvironment().getHostString() ) ); - m_globals.rawset( "_CC_DEFAULT_SETTINGS", valueOf( ComputerCraft.defaultComputerSettings ) ); - if( ComputerCraft.disableLua51Features ) + m_globals.rawset( "_CC_DEFAULT_SETTINGS", valueOf( ComputerCraft.default_computer_settings ) ); + if( ComputerCraft.disable_lua51_features ) { m_globals.rawset( "_CC_DISABLE_LUA51_FEATURES", Constants.TRUE ); } @@ -237,10 +237,10 @@ public class CobaltLuaMachine implements ILuaMachine table.rawset( method, new ResultInterpreterFunction( this, LuaMethod.DYNAMIC.get( i ), object, context, method ) ); } - ObjectSource.allMethods( LuaMethod.GENERATOR, object, ( instance, method ) -> + ObjectSource.allMethods( LuaMethod.GENERATOR, object, (instance, method ) -> table.rawset( method.getName(), method.nonYielding() - ? new BasicFunction( this, method.getMethod(), instance, context, method.getName() ) - : new ResultInterpreterFunction( this, method.getMethod(), instance, context, method.getName() ) ) ); + ? new BasicFunction( this, (LuaMethod) method.getMethod(), instance, context, method.getName() ) + : new ResultInterpreterFunction( this, (LuaMethod) method.getMethod(), instance, context, method.getName() ) ) ); try { @@ -330,7 +330,7 @@ public class CobaltLuaMachine implements ILuaMachine return wrapped; } - if( ComputerCraft.logComputerErrors ) + if( ComputerCraft.logPeripheralErrors ) { ComputerCraft.log.warn( "Received unknown type '{}', returning nil.", object.getClass().getName() ); } @@ -539,7 +539,7 @@ public class CobaltLuaMachine implements ILuaMachine } catch( Throwable t ) { - if( ComputerCraft.logComputerErrors ) ComputerCraft.log.error( "Error running task", t ); + if( ComputerCraft.logPeripheralErrors ) ComputerCraft.log.error( "Error running task", t ); m_computer.queueEvent( "task_complete", new Object[] { taskID, false, "Java Exception Thrown: " + t, } ); diff --git a/src/main/java/dan200/computercraft/core/lua/ResultInterpreterFunction.java b/src/main/java/dan200/computercraft/core/lua/ResultInterpreterFunction.java index 7d02cae7d..38be5bddc 100644 --- a/src/main/java/dan200/computercraft/core/lua/ResultInterpreterFunction.java +++ b/src/main/java/dan200/computercraft/core/lua/ResultInterpreterFunction.java @@ -65,7 +65,7 @@ class ResultInterpreterFunction extends ResumableVarArgFunction tables = new HashMap<>(); - LootTableReporter validation = new LootTableReporter( LootContextTypes.GENERIC, x -> null, tables::get ); - - registerLoot( ( id, table ) -> { - if( tables.containsKey( id ) ) validation.report( "Duplicate loot tables for " + id ); - tables.put( id, table ); - } ); - - tables.forEach( ( key, value ) -> LootManager.validate( validation, key, value ) ); - - Multimap problems = validation.getMessages(); - if( !problems.isEmpty() ) - { - problems.forEach( ( child, problem ) -> - ComputerCraft.log.warn( "Found validation problem in " + child + ": " + problem ) ); - throw new IllegalStateException( "Failed to validate loot tables, see logs" ); - } - - tables.forEach( ( key, value ) -> { - Path path = getPath( key ); - try - { - DataProvider.writeToPath( GSON, cache, LootManager.toJson( value ), path ); - } - catch( IOException e ) - { - ComputerCraft.log.error( "Couldn't save loot table {}", path, e ); - } - } ); - } - - protected abstract void registerLoot( BiConsumer add ); - - @Nonnull - @Override - public String getName() - { - return "LootTables"; - } - - private Path getPath( Identifier id ) - { - return generator.getOutput() - .resolve( "data" ).resolve( id.getNamespace() ).resolve( "loot_tables" ) - .resolve( id.getPath() + ".json" ); - } -} diff --git a/src/main/java/dan200/computercraft/data/LootTables.java b/src/main/java/dan200/computercraft/data/LootTables.java deleted file mode 100644 index e698b97f8..000000000 --- a/src/main/java/dan200/computercraft/data/LootTables.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.data; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.shared.Registry; -import dan200.computercraft.shared.data.BlockNamedEntityLootCondition; -import dan200.computercraft.shared.data.HasComputerIdLootCondition; -import dan200.computercraft.shared.data.PlayerCreativeLootCondition; -import dan200.computercraft.shared.proxy.ComputerCraftProxyCommon; -import net.minecraft.block.Block; -import net.minecraft.data.DataGenerator; -import net.minecraft.loot.*; -import net.minecraft.loot.condition.AlternativeLootCondition; -import net.minecraft.loot.condition.SurvivesExplosionLootCondition; -import net.minecraft.loot.context.LootContextTypes; -import net.minecraft.loot.entry.DynamicEntry; -import net.minecraft.loot.entry.ItemEntry; -import net.minecraft.util.Identifier; -import net.minecraftforge.fml.RegistryObject; - -import java.util.function.BiConsumer; - -public class LootTables extends LootTableProvider -{ - public LootTables( DataGenerator generator ) - { - super( generator ); - } - - @Override - protected void registerLoot( BiConsumer add ) - { - basicDrop( add, Registry.ModBlocks.DISK_DRIVE ); - basicDrop( add, Registry.ModBlocks.MONITOR_NORMAL ); - basicDrop( add, Registry.ModBlocks.MONITOR_ADVANCED ); - basicDrop( add, Registry.ModBlocks.PRINTER ); - basicDrop( add, Registry.ModBlocks.SPEAKER ); - basicDrop( add, Registry.ModBlocks.WIRED_MODEM_FULL ); - basicDrop( add, Registry.ModBlocks.WIRELESS_MODEM_NORMAL ); - basicDrop( add, Registry.ModBlocks.WIRELESS_MODEM_ADVANCED ); - - computerDrop( add, Registry.ModBlocks.COMPUTER_NORMAL ); - computerDrop( add, Registry.ModBlocks.COMPUTER_ADVANCED ); - computerDrop( add, Registry.ModBlocks.TURTLE_NORMAL ); - computerDrop( add, Registry.ModBlocks.TURTLE_ADVANCED ); - - add.accept( ComputerCraftProxyCommon.ForgeHandlers.LOOT_TREASURE_DISK, LootTable - .builder() - .type( LootContextTypes.GENERIC ) - .build() ); - } - - private static void basicDrop( BiConsumer add, RegistryObject wrapper ) - { - Block block = wrapper.get(); - add.accept( block.getLootTableId(), LootTable - .builder() - .type( LootContextTypes.BLOCK ) - .pool( LootPool.builder() - .name( "main" ) - .rolls( ConstantLootTableRange.create( 1 ) ) - .with( ItemEntry.builder( block ) ) - .conditionally( SurvivesExplosionLootCondition.builder() ) - ).build() ); - } - - private static void computerDrop( BiConsumer add, RegistryObject wrapper ) - { - Block block = wrapper.get(); - add.accept( block.getLootTableId(), LootTable - .builder() - .type( LootContextTypes.BLOCK ) - .pool( LootPool.builder() - .name( "main" ) - .rolls( ConstantLootTableRange.create( 1 ) ) - .with( DynamicEntry.builder( new Identifier( ComputerCraft.MOD_ID, "computer" ) ) ) - .conditionally( AlternativeLootCondition.builder( - BlockNamedEntityLootCondition.BUILDER, - HasComputerIdLootCondition.BUILDER, - PlayerCreativeLootCondition.BUILDER.invert() - ) ) - ).build() ); - } -} diff --git a/src/main/java/dan200/computercraft/data/RecipeWrapper.java b/src/main/java/dan200/computercraft/data/RecipeWrapper.java deleted file mode 100644 index 52d597cdb..000000000 --- a/src/main/java/dan200/computercraft/data/RecipeWrapper.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.data; - -import com.google.gson.JsonObject; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import net.minecraft.data.server.recipe.RecipeJsonProvider; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.recipe.RecipeSerializer; -import net.minecraft.util.Identifier; -import net.minecraft.util.JsonHelper; -import java.util.function.Consumer; - -/** - * Adapter for recipes which overrides the serializer and adds custom item NBT. - */ -public final class RecipeWrapper implements RecipeJsonProvider -{ - private final RecipeJsonProvider recipe; - private final CompoundTag resultData; - private final RecipeSerializer serializer; - - private RecipeWrapper( RecipeJsonProvider recipe, CompoundTag resultData, RecipeSerializer serializer ) - { - this.resultData = resultData; - this.recipe = recipe; - this.serializer = serializer; - } - - public static Consumer wrap( RecipeSerializer serializer, Consumer original ) - { - return x -> original.accept( new RecipeWrapper( x, null, serializer ) ); - } - - public static Consumer wrap( RecipeSerializer serializer, Consumer original, CompoundTag resultData ) - { - return x -> original.accept( new RecipeWrapper( x, resultData, serializer ) ); - } - - public static Consumer wrap( RecipeSerializer serializer, Consumer original, Consumer resultData ) - { - CompoundTag tag = new CompoundTag(); - resultData.accept( tag ); - return x -> original.accept( new RecipeWrapper( x, tag, serializer ) ); - } - - @Override - public void serialize( @Nonnull JsonObject jsonObject ) - { - recipe.serialize( jsonObject ); - - if( resultData != null ) - { - JsonObject object = JsonHelper.getObject( jsonObject, "result" ); - object.addProperty( "nbt", resultData.toString() ); - } - } - - @Nonnull - @Override - public Identifier getRecipeId() - { - return recipe.getRecipeId(); - } - - @Nonnull - @Override - public RecipeSerializer getSerializer() - { - return serializer; - } - - @Nullable - @Override - public JsonObject toAdvancementJson() - { - return recipe.toAdvancementJson(); - } - - @Nullable - @Override - public Identifier getAdvancementId() - { - return recipe.getAdvancementId(); - } -} diff --git a/src/main/java/dan200/computercraft/data/Recipes.java b/src/main/java/dan200/computercraft/data/Recipes.java deleted file mode 100644 index b2daa1c7f..000000000 --- a/src/main/java/dan200/computercraft/data/Recipes.java +++ /dev/null @@ -1,325 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.data; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.data.Tags.CCTags; -import dan200.computercraft.shared.Registry; -import dan200.computercraft.shared.TurtleUpgrades; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.pocket.items.PocketComputerItemFactory; -import dan200.computercraft.shared.turtle.items.TurtleItemFactory; -import dan200.computercraft.shared.util.Colour; -import dan200.computercraft.shared.util.ImpostorRecipe; -import dan200.computercraft.shared.util.ImpostorShapelessRecipe; -import net.minecraft.advancement.criterion.InventoryChangedCriterion; -import net.minecraft.block.Blocks; -import net.minecraft.data.*; -import net.minecraft.data.server.RecipesProvider; -import net.minecraft.data.server.recipe.RecipeJsonProvider; -import net.minecraft.data.server.recipe.ShapedRecipeJsonFactory; -import net.minecraft.data.server.recipe.ShapelessRecipeJsonFactory; -import net.minecraft.item.*; -import net.minecraft.predicate.item.ItemPredicate; -import net.minecraft.tag.Tag; -import net.minecraft.util.DyeColor; -import net.minecraft.util.Identifier; -import net.minecraftforge.common.Tags; - -import javax.annotation.Nonnull; -import java.util.Locale; -import java.util.function.Consumer; - -public class Recipes extends RecipesProvider -{ - public Recipes( DataGenerator generator ) - { - super( generator ); - } - - @Override - protected void generate( @Nonnull Consumer add ) - { - basicRecipes( add ); - diskColours( add ); - pocketUpgrades( add ); - turtleUpgrades( add ); - } - - /** - * Register a crafting recipe for a disk of every dye colour. - * - * @param add The callback to add recipes. - */ - private void diskColours( @Nonnull Consumer add ) - { - for( Colour colour : Colour.VALUES ) - { - ShapelessRecipeJsonFactory - .create( Registry.ModItems.DISK.get() ) - .input( Tags.Items.DUSTS_REDSTONE ) - .input( Items.PAPER ) - .input( DyeItem.byColor( ofColour( colour ) ) ) - .group( "computercraft:disk" ) - .criterion( "has_drive", inventoryChange( Registry.ModBlocks.DISK_DRIVE.get() ) ) - .offerTo( RecipeWrapper.wrap( - ImpostorShapelessRecipe.SERIALIZER, add, - x -> x.putInt( "color", colour.getHex() ) - ), new Identifier( ComputerCraft.MOD_ID, "disk_" + (colour.ordinal() + 1) ) ); - } - } - - /** - * Register a crafting recipe for each turtle upgrade. - * - * @param add The callback to add recipes. - */ - private void turtleUpgrades( @Nonnull Consumer add ) - { - for( ComputerFamily family : ComputerFamily.values() ) - { - ItemStack base = TurtleItemFactory.create( -1, null, -1, family, null, null, 0, null ); - if( base.isEmpty() ) continue; - - String nameId = family.name().toLowerCase( Locale.ROOT ); - - TurtleUpgrades.getVanillaUpgrades().forEach( upgrade -> { - ItemStack result = TurtleItemFactory.create( -1, null, -1, family, null, upgrade, -1, null ); - ShapedRecipeJsonFactory - .create( result.getItem() ) - .group( String.format( "%s:turtle_%s", ComputerCraft.MOD_ID, nameId ) ) - .pattern( "#T" ) - .input( '#', base.getItem() ) - .input( 'T', upgrade.getCraftingItem().getItem() ) - .criterion( "has_items", - inventoryChange( base.getItem(), upgrade.getCraftingItem().getItem() ) ) - .offerTo( - RecipeWrapper.wrap( ImpostorRecipe.SERIALIZER, add, result.getTag() ), - new Identifier( ComputerCraft.MOD_ID, String.format( "turtle_%s/%s/%s", - nameId, upgrade.getUpgradeID().getNamespace(), upgrade.getUpgradeID().getPath() - ) ) - ); - } ); - } - } - - /** - * Register a crafting recipe for each pocket upgrade. - * - * @param add The callback to add recipes. - */ - private void pocketUpgrades( @Nonnull Consumer add ) - { - for( ComputerFamily family : ComputerFamily.values() ) - { - ItemStack base = PocketComputerItemFactory.create( -1, null, -1, family, null ); - if( base.isEmpty() ) continue; - - String nameId = family.name().toLowerCase( Locale.ROOT ); - - TurtleUpgrades.getVanillaUpgrades().forEach( upgrade -> { - ItemStack result = PocketComputerItemFactory.create( -1, null, -1, family, null ); - ShapedRecipeJsonFactory - .create( result.getItem() ) - .group( String.format( "%s:pocket_%s", ComputerCraft.MOD_ID, nameId ) ) - .pattern( "#" ) - .pattern( "P" ) - .input( '#', base.getItem() ) - .input( 'P', upgrade.getCraftingItem().getItem() ) - .criterion( "has_items", - inventoryChange( base.getItem(), upgrade.getCraftingItem().getItem() ) ) - .offerTo( - RecipeWrapper.wrap( ImpostorRecipe.SERIALIZER, add, result.getTag() ), - new Identifier( ComputerCraft.MOD_ID, String.format( "pocket_%s/%s/%s", - nameId, upgrade.getUpgradeID().getNamespace(), upgrade.getUpgradeID().getPath() - ) ) - ); - } ); - } - } - - private void basicRecipes( @Nonnull Consumer add ) - { - ShapedRecipeJsonFactory - .create( Registry.ModItems.CABLE.get(), 6 ) - .pattern( " # " ) - .pattern( "#R#" ) - .pattern( " # " ) - .input( '#', Tags.Items.STONE ) - .input( 'R', Tags.Items.DUSTS_REDSTONE ) - .criterion( "has_computer", inventoryChange( CCTags.COMPUTER ) ) - .criterion( "has_modem", inventoryChange( CCTags.COMPUTER ) ) - .offerTo( add ); - - ShapedRecipeJsonFactory - .create( Registry.ModBlocks.COMPUTER_NORMAL.get() ) - .pattern( "###" ) - .pattern( "#R#" ) - .pattern( "#G#" ) - .input( '#', Tags.Items.STONE ) - .input( 'R', Tags.Items.DUSTS_REDSTONE ) - .input( 'G', Tags.Items.GLASS_PANES ) - .criterion( "has_redstone", inventoryChange( Tags.Items.DUSTS_REDSTONE ) ) - .offerTo( add ); - - ShapedRecipeJsonFactory - .create( Registry.ModBlocks.COMPUTER_ADVANCED.get() ) - .pattern( "###" ) - .pattern( "#R#" ) - .pattern( "#G#" ) - .input( '#', Tags.Items.INGOTS_GOLD ) - .input( 'R', Tags.Items.DUSTS_REDSTONE ) - .input( 'G', Tags.Items.GLASS_PANES ) - .criterion( "has_components", inventoryChange( Items.REDSTONE, Items.GOLD_INGOT ) ) - .offerTo( add ); - - ShapedRecipeJsonFactory - .create( Registry.ModBlocks.COMPUTER_COMMAND.get() ) - .pattern( "###" ) - .pattern( "#R#" ) - .pattern( "#G#" ) - .input( '#', Tags.Items.INGOTS_GOLD ) - .input( 'R', Blocks.COMMAND_BLOCK ) - .input( 'G', Tags.Items.GLASS_PANES ) - .criterion( "has_components", inventoryChange( Blocks.COMMAND_BLOCK ) ) - .offerTo( add ); - - ShapedRecipeJsonFactory - .create( Registry.ModBlocks.DISK_DRIVE.get() ) - .pattern( "###" ) - .pattern( "#R#" ) - .pattern( "#R#" ) - .input( '#', Tags.Items.STONE ) - .input( 'R', Tags.Items.DUSTS_REDSTONE ) - .criterion( "has_computer", inventoryChange( CCTags.COMPUTER ) ) - .offerTo( add ); - - ShapedRecipeJsonFactory - .create( Registry.ModBlocks.MONITOR_NORMAL.get() ) - .pattern( "###" ) - .pattern( "#G#" ) - .pattern( "###" ) - .input( '#', Tags.Items.STONE ) - .input( 'G', Tags.Items.GLASS_PANES ) - .criterion( "has_computer", inventoryChange( CCTags.COMPUTER ) ) - .offerTo( add ); - - ShapedRecipeJsonFactory - .create( Registry.ModBlocks.MONITOR_ADVANCED.get(), 4 ) - .pattern( "###" ) - .pattern( "#G#" ) - .pattern( "###" ) - .input( '#', Tags.Items.INGOTS_GOLD ) - .input( 'G', Tags.Items.GLASS_PANES ) - .criterion( "has_computer", inventoryChange( CCTags.COMPUTER ) ) - .offerTo( add ); - - ShapedRecipeJsonFactory - .create( Registry.ModItems.POCKET_COMPUTER_NORMAL.get() ) - .pattern( "###" ) - .pattern( "#A#" ) - .pattern( "#G#" ) - .input( '#', Tags.Items.STONE ) - .input( 'A', Items.GOLDEN_APPLE ) - .input( 'G', Tags.Items.GLASS_PANES ) - .criterion( "has_computer", inventoryChange( CCTags.COMPUTER ) ) - .criterion( "has_apple", inventoryChange( Items.GOLDEN_APPLE ) ) - .offerTo( add ); - - ShapedRecipeJsonFactory - .create( Registry.ModItems.POCKET_COMPUTER_ADVANCED.get() ) - .pattern( "###" ) - .pattern( "#A#" ) - .pattern( "#G#" ) - .input( '#', Tags.Items.INGOTS_GOLD ) - .input( 'A', Items.GOLDEN_APPLE ) - .input( 'G', Tags.Items.GLASS_PANES ) - .criterion( "has_computer", inventoryChange( CCTags.COMPUTER ) ) - .criterion( "has_apple", inventoryChange( Items.GOLDEN_APPLE ) ) - .offerTo( add ); - - ShapedRecipeJsonFactory - .create( Registry.ModBlocks.PRINTER.get() ) - .pattern( "###" ) - .pattern( "#R#" ) - .pattern( "#D#" ) - .input( '#', Tags.Items.STONE ) - .input( 'R', Tags.Items.DUSTS_REDSTONE ) - .input( 'D', Tags.Items.DYES ) - .criterion( "has_computer", inventoryChange( CCTags.COMPUTER ) ) - .offerTo( add ); - - ShapedRecipeJsonFactory - .create( Registry.ModBlocks.SPEAKER.get() ) - .pattern( "###" ) - .pattern( "#N#" ) - .pattern( "#R#" ) - .input( '#', Tags.Items.STONE ) - .input( 'N', Blocks.NOTE_BLOCK ) - .input( 'R', Tags.Items.DUSTS_REDSTONE ) - .criterion( "has_computer", inventoryChange( CCTags.COMPUTER ) ) - .offerTo( add ); - - ShapedRecipeJsonFactory - .create( Registry.ModItems.WIRED_MODEM.get() ) - .pattern( "###" ) - .pattern( "#R#" ) - .pattern( "###" ) - .input( '#', Tags.Items.STONE ) - .input( 'R', Tags.Items.DUSTS_REDSTONE ) - .criterion( "has_computer", inventoryChange( CCTags.COMPUTER ) ) - .criterion( "has_cable", inventoryChange( Registry.ModItems.CABLE.get() ) ) - .offerTo( add ); - - ShapelessRecipeJsonFactory - .create( Registry.ModBlocks.WIRED_MODEM_FULL.get() ) - .input( Registry.ModItems.WIRED_MODEM.get() ) - .criterion( "has_modem", inventoryChange( CCTags.WIRED_MODEM ) ) - .offerTo( add, new Identifier( ComputerCraft.MOD_ID, "wired_modem_full_from" ) ); - ShapelessRecipeJsonFactory - .create( Registry.ModItems.WIRED_MODEM.get() ) - .input( Registry.ModBlocks.WIRED_MODEM_FULL.get() ) - .criterion( "has_modem", inventoryChange( CCTags.WIRED_MODEM ) ) - .offerTo( add, new Identifier( ComputerCraft.MOD_ID, "wired_modem_full_to" ) ); - - ShapedRecipeJsonFactory - .create( Registry.ModBlocks.WIRELESS_MODEM_NORMAL.get() ) - .pattern( "###" ) - .pattern( "#E#" ) - .pattern( "###" ) - .input( '#', Tags.Items.STONE ) - .input( 'E', Tags.Items.ENDER_PEARLS ) - .criterion( "has_computer", inventoryChange( CCTags.COMPUTER ) ) - .offerTo( add ); - - ShapedRecipeJsonFactory - .create( Registry.ModBlocks.WIRELESS_MODEM_ADVANCED.get() ) - .pattern( "###" ) - .pattern( "#E#" ) - .pattern( "###" ) - .input( '#', Tags.Items.INGOTS_GOLD ) - .input( 'E', Items.ENDER_EYE ) - .criterion( "has_computer", inventoryChange( CCTags.COMPUTER ) ) - .criterion( "has_wireless", inventoryChange( Registry.ModBlocks.WIRELESS_MODEM_NORMAL.get() ) ) - .offerTo( add ); - } - - private static DyeColor ofColour( Colour colour ) - { - return DyeColor.byId( 15 - colour.ordinal() ); - } - - private static InventoryChangedCriterion.Conditions inventoryChange( Tag stack ) - { - return InventoryChangedCriterion.Conditions.items( ItemPredicate.Builder.create().tag( stack ).build() ); - } - - private static InventoryChangedCriterion.Conditions inventoryChange( ItemConvertible... stack ) - { - return InventoryChangedCriterion.Conditions.items( stack ); - } -} diff --git a/src/main/java/dan200/computercraft/data/Tags.java b/src/main/java/dan200/computercraft/data/Tags.java deleted file mode 100644 index 6c2eb03f7..000000000 --- a/src/main/java/dan200/computercraft/data/Tags.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.data; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.shared.Registry; -import net.minecraft.data.DataGenerator; -import net.minecraft.data.server.BlockTagsProvider; -import net.minecraft.data.server.ItemTagsProvider; -import net.minecraft.item.Item; -import net.minecraft.tag.ItemTags; -import net.minecraft.tag.Tag; -import net.minecraft.util.Identifier; - -import static dan200.computercraft.data.Tags.CCTags.*; - -public class Tags extends ItemTagsProvider -{ - private static final Tag.Identified PIGLIN_LOVED = ItemTags.PIGLIN_LOVED; - - public static class CCTags - { - public static final Tag.Identified COMPUTER = item( "computer" ); - public static final Tag.Identified TURTLE = item( "turtle" ); - public static final Tag.Identified WIRED_MODEM = item( "wired_modem" ); - public static final Tag.Identified MONITOR = item( "monitor" ); - } - - public Tags( DataGenerator generator, BlockTagsProvider tags ) - { - super( generator, tags ); - } - - @Override - protected void configure() - { - getOrCreateTagBuilder( COMPUTER ).add( - Registry.ModItems.COMPUTER_NORMAL.get(), - Registry.ModItems.COMPUTER_ADVANCED.get(), - Registry.ModItems.COMPUTER_COMMAND.get() - ); - getOrCreateTagBuilder( TURTLE ).add( Registry.ModItems.TURTLE_NORMAL.get(), Registry.ModItems.TURTLE_ADVANCED.get() ); - getOrCreateTagBuilder( WIRED_MODEM ).add( Registry.ModItems.WIRED_MODEM.get(), Registry.ModItems.WIRED_MODEM_FULL.get() ); - getOrCreateTagBuilder( MONITOR ).add( Registry.ModItems.MONITOR_NORMAL.get(), Registry.ModItems.MONITOR_ADVANCED.get() ); - - getOrCreateTagBuilder( PIGLIN_LOVED ).add( - Registry.ModItems.COMPUTER_ADVANCED.get(), Registry.ModItems.TURTLE_ADVANCED.get(), - Registry.ModItems.WIRELESS_MODEM_ADVANCED.get(), Registry.ModItems.POCKET_COMPUTER_ADVANCED.get(), - Registry.ModItems.MONITOR_ADVANCED.get() - ); - } - - private static Tag.Identified item( String name ) - { - return ItemTags.register( new Identifier( ComputerCraft.MOD_ID, name ).toString() ); - } -} diff --git a/src/main/java/dan200/computercraft/mixin/BlockEntityTypeAccessor.java b/src/main/java/dan200/computercraft/mixin/BlockEntityTypeAccessor.java deleted file mode 100644 index fe870ad3f..000000000 --- a/src/main/java/dan200/computercraft/mixin/BlockEntityTypeAccessor.java +++ /dev/null @@ -1,13 +0,0 @@ -package dan200.computercraft.mixin; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; - -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.block.entity.BlockEntityType; - -@Mixin (BlockEntityType.class) -public interface BlockEntityTypeAccessor { - @Invoker - static BlockEntityType callCreate(String string, BlockEntityType.Builder builder) { throw new UnsupportedOperationException(); } -} diff --git a/src/main/java/dan200/computercraft/mixin/ScreenHandlerTypeAccessor.java b/src/main/java/dan200/computercraft/mixin/ScreenHandlerTypeAccessor.java deleted file mode 100644 index 2fca8d012..000000000 --- a/src/main/java/dan200/computercraft/mixin/ScreenHandlerTypeAccessor.java +++ /dev/null @@ -1,13 +0,0 @@ -package dan200.computercraft.mixin; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; - -import net.minecraft.screen.ScreenHandler; -import net.minecraft.screen.ScreenHandlerType; - -@Mixin (ScreenHandlerType.class) -public interface ScreenHandlerTypeAccessor { - @Invoker - static ScreenHandlerType callRegister(String id, ScreenHandlerType.Factory factory) { throw new UnsupportedOperationException(); } -} diff --git a/src/main/java/dan200/computercraft/shared/Registry.java b/src/main/java/dan200/computercraft/shared/ComputerCraftRegistry.java similarity index 83% rename from src/main/java/dan200/computercraft/shared/Registry.java rename to src/main/java/dan200/computercraft/shared/ComputerCraftRegistry.java index 3427fb2a0..9696b03c7 100644 --- a/src/main/java/dan200/computercraft/shared/Registry.java +++ b/src/main/java/dan200/computercraft/shared/ComputerCraftRegistry.java @@ -22,10 +22,6 @@ import dan200.computercraft.shared.computer.items.ItemComputer; import dan200.computercraft.shared.media.items.ItemDisk; import dan200.computercraft.shared.media.items.ItemPrintout; import dan200.computercraft.shared.media.items.ItemTreasureDisk; -import dan200.computercraft.shared.network.container.ComputerContainerData; -import dan200.computercraft.shared.network.container.ContainerData; -import dan200.computercraft.shared.network.container.HeldItemContainerData; -import dan200.computercraft.shared.network.container.ViewComputerContainerData; import dan200.computercraft.shared.peripheral.diskdrive.BlockDiskDrive; import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive; import dan200.computercraft.shared.peripheral.diskdrive.TileDiskDrive; @@ -50,9 +46,9 @@ import dan200.computercraft.shared.turtle.blocks.TileTurtle; import dan200.computercraft.shared.turtle.core.TurtlePlayer; import dan200.computercraft.shared.turtle.inventory.ContainerTurtle; import dan200.computercraft.shared.turtle.items.ItemTurtle; -import dan200.computercraft.shared.util.CreativeTabMain; import dan200.computercraft.shared.util.FixedPointTileEntityType; +import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry; import net.minecraft.block.Block; import net.minecraft.block.Material; import net.minecraft.block.entity.BlockEntity; @@ -66,7 +62,7 @@ import net.minecraft.screen.ScreenHandler; import net.minecraft.screen.ScreenHandlerType; import net.minecraft.util.Identifier; -public final class Registry { +public final class ComputerCraftRegistry { public static final String MOD_ID = ComputerCraft.MOD_ID; public static void init() { @@ -125,10 +121,10 @@ public final class Registry { "monitor_advanced", new BlockMonitor(properties(), ModTiles.MONITOR_ADVANCED)); - public static final BlockWirelessModem WIRELESS_EM_NORMAL = net.minecraft.util.registry.Registry.register(net.minecraft.util.registry.Registry.BLOCK, + public static final BlockWirelessModem WIRELESS_MODEM_NORMAL = net.minecraft.util.registry.Registry.register(net.minecraft.util.registry.Registry.BLOCK, "wireless_em_normal", new BlockWirelessModem(properties(), ModTiles.WIRELESS_MODEM_NORMAL)); - public static final BlockWirelessModem WIRELESS_EM_ADVANCED = net.minecraft.util.registry.Registry.register(net.minecraft.util.registry.Registry.BLOCK, + public static final BlockWirelessModem WIRELESS_MODEM_ADVANCED = net.minecraft.util.registry.Registry.register(net.minecraft.util.registry.Registry.BLOCK, "wireless_em_advanced", new BlockWirelessModem(properties(), ModTiles.WIRELESS_MODEM_ADVANCED)); @@ -164,13 +160,13 @@ public final class Registry { public static final BlockEntityType WIRED_MODEM_FULL = ofBlock(ModBlocks.WIRED_MODEM_FULL, TileWiredModemFull::new); public static final BlockEntityType CABLE = ofBlock(ModBlocks.CABLE, TileCable::new); - public static final BlockEntityType WIRELESS_MODEM_NORMAL = ofBlock(ModBlocks.WIRELESS_EM_NORMAL, f -> new TileWirelessModem(f, + public static final BlockEntityType WIRELESS_MODEM_NORMAL = ofBlock(ModBlocks.WIRELESS_MODEM_NORMAL, f -> new TileWirelessModem(f, false)); - public static final BlockEntityType WIRELESS_MODEM_ADVANCED = ofBlock(ModBlocks.WIRELESS_EM_ADVANCED, f -> new TileWirelessModem(f, true)); + public static final BlockEntityType WIRELESS_MODEM_ADVANCED = ofBlock(ModBlocks.WIRELESS_MODEM_ADVANCED, f -> new TileWirelessModem(f, true)); } public static final class ModItems { - private static final ItemGroup mainItemGroup = new CreativeTabMain(); + private static final ItemGroup mainItemGroup = ComputerCraft.MAIN_GROUP; private static Item.Settings properties() { return new Item.Settings().group(mainItemGroup); @@ -210,12 +206,12 @@ public final class Registry { public static final BlockItem PRINTER = ofBlock(ModBlocks.PRINTER, BlockItem::new); public static final BlockItem MONITOR_NORMAL = ofBlock(ModBlocks.MONITOR_NORMAL, BlockItem::new); public static final BlockItem MONITOR_ADVANCED = ofBlock(ModBlocks.MONITOR_ADVANCED, BlockItem::new); - public static final BlockItem WIRELESS_EM_NORMAL = ofBlock(ModBlocks.WIRELESS_EM_NORMAL, BlockItem::new); - public static final BlockItem WIRELESS_EM_ADVANCED = ofBlock(ModBlocks.WIRELESS_EM_ADVANCED, BlockItem::new); - public static final BlockItem WIRED_EM_FULL = ofBlock(ModBlocks.WIRED_MODEM_FULL, BlockItem::new); + public static final BlockItem WIRELESS_MODEM_NORMAL = ofBlock(ModBlocks.WIRELESS_MODEM_NORMAL, BlockItem::new); + public static final BlockItem WIRELESS_MODEM_ADVANCED = ofBlock(ModBlocks.WIRELESS_MODEM_ADVANCED, BlockItem::new); + public static final BlockItem WIRED_MODEM_FULL = ofBlock(ModBlocks.WIRED_MODEM_FULL, BlockItem::new); public static final ItemBlockCable.Cable CABLE = register("cable", new ItemBlockCable.Cable(ModBlocks.CABLE, properties())); - public static final ItemBlockCable.WiredModem WIRED_EM = register("wired_em", new ItemBlockCable.WiredModem(ModBlocks.CABLE, properties())); + public static final ItemBlockCable.WiredModem WIRED_MODEM = register("wired_em", new ItemBlockCable.WiredModem(ModBlocks.CABLE, properties())); } public static class ModEntities { @@ -230,34 +226,27 @@ public final class Registry { } public static class ModContainers { - private static > T register(String id, T item) { - return net.minecraft.util.registry.Registry.register(net.minecraft.util.registry.Registry.SCREEN_HANDLER, new Identifier(MOD_ID, id), item); + private static ScreenHandlerType registerSimple(String id, ScreenHandlerRegistry.SimpleClientHandlerFactory function) { + return ScreenHandlerRegistry.registerSimple(new Identifier(MOD_ID, id), function); } - public static final ScreenHandlerType COMPUTER = register("computer", - ContainerData.toType(ComputerContainerData::new, - ContainerComputer::new)); + private static ScreenHandlerType registerExtended(String id, ScreenHandlerRegistry.ExtendedClientHandlerFactory function) { + return ScreenHandlerRegistry.registerExtended(new Identifier(MOD_ID, id), function); + } - public static final ScreenHandlerType POCKET_COMPUTER = register("pocket_computer", - ContainerData.toType(ComputerContainerData::new, - ContainerPocketComputer::new)); + public static final ScreenHandlerType COMPUTER = registerExtended("computer", ContainerComputer::new); - public static final ScreenHandlerType TURTLE = register("turtle", - ContainerData.toType(ComputerContainerData::new, - ContainerTurtle::new)); + public static final ScreenHandlerType POCKET_COMPUTER = registerExtended("pocket_computer", ContainerPocketComputer::new); + + public static final ScreenHandlerType TURTLE = registerExtended("turtle", ContainerTurtle::new); - public static final ScreenHandlerType DISK_DRIVE = register("disk_drive", - new ScreenHandlerType<>(ContainerDiskDrive::new)); + public static final ScreenHandlerType DISK_DRIVE = registerSimple("disk_drive", ContainerDiskDrive::new); - public static final ScreenHandlerType PRINTER = register("printer", new ScreenHandlerType<>(ContainerPrinter::new)); + public static final ScreenHandlerType PRINTER = registerSimple("printer", ContainerPrinter::new); - public static final ScreenHandlerType PRINTOUT = register("printout", - ContainerData.toType(HeldItemContainerData::new, - ContainerHeldItem::createPrintout)); + public static final ScreenHandlerType PRINTOUT = registerExtended("printout", ContainerHeldItem::createPrintout); - public static final ScreenHandlerType VIEW_COMPUTER = register("view_computer", - ContainerData.toType(ViewComputerContainerData::new, - ContainerViewComputer::new)); + public static final ScreenHandlerType VIEW_COMPUTER = registerExtended("view_computer", ContainerViewComputer::new); } } diff --git a/src/main/java/dan200/computercraft/shared/Config.java b/src/main/java/dan200/computercraft/shared/Config.java deleted file mode 100644 index 193e60521..000000000 --- a/src/main/java/dan200/computercraft/shared/Config.java +++ /dev/null @@ -1,421 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.shared; - -import com.electronwill.nightconfig.core.CommentedConfig; -import com.electronwill.nightconfig.core.UnmodifiableConfig; -import com.electronwill.nightconfig.core.file.CommentedFileConfig; -import com.google.common.base.CaseFormat; -import com.google.common.base.Converter; -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.turtle.event.TurtleAction; -import dan200.computercraft.core.apis.http.options.Action; -import dan200.computercraft.core.apis.http.options.AddressRuleConfig; -import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer; -import net.minecraftforge.common.ForgeConfigSpec; -import net.minecraftforge.common.ForgeConfigSpec.Builder; -import net.minecraftforge.common.ForgeConfigSpec.ConfigValue; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.ModLoadingContext; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.config.ModConfig; - -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static net.minecraftforge.common.ForgeConfigSpec.Builder; -import static net.minecraftforge.common.ForgeConfigSpec.ConfigValue; - -@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD ) -public final class Config -{ - private static final int MODEM_MAX_RANGE = 100000; - - private static final String TRANSLATION_PREFIX = "gui.computercraft.config."; - - private static final ConfigValue computerSpaceLimit; - private static final ConfigValue floppySpaceLimit; - private static final ConfigValue maximumFilesOpen; - private static final ConfigValue disableLua51Features; - private static final ConfigValue defaultComputerSettings; - private static final ConfigValue debugEnabled; - private static final ConfigValue logComputerErrors; - private static final ConfigValue commandRequireCreative; - - private static final ConfigValue computerThreads; - private static final ConfigValue maxMainGlobalTime; - private static final ConfigValue maxMainComputerTime; - - private static final ConfigValue httpEnabled; - private static final ConfigValue httpWebsocketEnabled; - private static final ConfigValue> httpRules; - - private static final ConfigValue httpMaxRequests; - private static final ConfigValue httpMaxWebsockets; - - private static final ConfigValue commandBlockEnabled; - private static final ConfigValue modemRange; - private static final ConfigValue modemHighAltitudeRange; - private static final ConfigValue modemRangeDuringStorm; - private static final ConfigValue modemHighAltitudeRangeDuringStorm; - private static final ConfigValue maxNotesPerTick; - private static final ConfigValue monitorBandwidth; - - private static final ConfigValue turtlesNeedFuel; - private static final ConfigValue turtleFuelLimit; - private static final ConfigValue advancedTurtleFuelLimit; - private static final ConfigValue turtlesObeyBlockProtection; - private static final ConfigValue turtlesCanPush; - private static final ConfigValue> turtleDisabledActions; - - private static final ConfigValue computerTermWidth; - private static final ConfigValue computerTermHeight; - - private static final ConfigValue pocketTermWidth; - private static final ConfigValue pocketTermHeight; - - private static final ConfigValue monitorWidth; - private static final ConfigValue monitorHeight; - - private static final ConfigValue genericPeripheral; - - private static final ConfigValue monitorRenderer; - private static final ConfigValue monitorDistance; - - private static final ForgeConfigSpec serverSpec; - private static final ForgeConfigSpec clientSpec; - - private Config() {} - - static - { - Builder builder = new Builder(); - - { // General computers - computerSpaceLimit = builder - .comment( "The disk space limit for computers and turtles, in bytes" ) - .translation( TRANSLATION_PREFIX + "computer_space_limit" ) - .define( "computer_space_limit", ComputerCraft.computerSpaceLimit ); - - floppySpaceLimit = builder - .comment( "The disk space limit for floppy disks, in bytes" ) - .translation( TRANSLATION_PREFIX + "floppy_space_limit" ) - .define( "floppy_space_limit", ComputerCraft.floppySpaceLimit ); - - maximumFilesOpen = builder - .comment( "Set how many files a computer can have open at the same time. Set to 0 for unlimited." ) - .translation( TRANSLATION_PREFIX + "maximum_open_files" ) - .defineInRange( "maximum_open_files", ComputerCraft.maximumFilesOpen, 0, Integer.MAX_VALUE ); - - disableLua51Features = builder - .comment( "Set this to true to disable Lua 5.1 functions that will be removed in a future update. " + - "Useful for ensuring forward compatibility of your programs now." ) - .define( "disable_lua51_features", ComputerCraft.disableLua51Features ); - - defaultComputerSettings = builder - .comment( "A comma separated list of default system settings to set on new computers. Example: " + - "\"shell.autocomplete=false,lua.autocomplete=false,edit.autocomplete=false\" will disable all " + - "autocompletion" ) - .define( "default_computer_settings", ComputerCraft.defaultComputerSettings ); - - debugEnabled = builder - .comment( "Enable Lua's debug library. This is sandboxed to each computer, so is generally safe to be used by players." ) - .define( "debug_enabled", ComputerCraft.debugEnable ); - - logComputerErrors = builder - .comment( "Log exceptions thrown by peripherals and other Lua objects.\n" + - "This makes it easier for mod authors to debug problems, but may result in log spam should people use buggy methods." ) - .define( "log_computer_errors", ComputerCraft.logComputerErrors ); - - commandRequireCreative = builder - .comment( "Require players to be in creative mode and be opped in order to interact with command computers." + - "This is the default behaviour for vanilla's Command blocks." ) - .define( "command_require_creative", ComputerCraft.commandRequireCreative ); - } - - { - builder.comment( "Controls execution behaviour of computers. This is largely intended for fine-tuning " + - "servers, and generally shouldn't need to be touched" ); - builder.push( "execution" ); - - computerThreads = builder - .comment( "Set the number of threads computers can run on. A higher number means more computers can run " + - "at once, but may induce lag.\n" + - "Please note that some mods may not work with a thread count higher than 1. Use with caution." ) - .worldRestart() - .defineInRange( "computer_threads", ComputerCraft.computerThreads, 1, Integer.MAX_VALUE ); - - maxMainGlobalTime = builder - .comment( "The maximum time that can be spent executing tasks in a single tick, in milliseconds.\n" + - "Note, we will quite possibly go over this limit, as there's no way to tell how long a will take " + - "- this aims to be the upper bound of the average time." ) - .defineInRange( "max_main_global_time", (int) TimeUnit.NANOSECONDS.toMillis( ComputerCraft.maxMainGlobalTime ), 1, Integer.MAX_VALUE ); - - maxMainComputerTime = builder - .comment( "The ideal maximum time a computer can execute for in a tick, in milliseconds.\n" + - "Note, we will quite possibly go over this limit, as there's no way to tell how long a will take " + - "- this aims to be the upper bound of the average time." ) - .defineInRange( "max_main_computer_time", (int) TimeUnit.NANOSECONDS.toMillis( ComputerCraft.maxMainComputerTime ), 1, Integer.MAX_VALUE ); - - builder.pop(); - } - - { // HTTP - builder.comment( "Controls the HTTP API" ); - builder.push( "http" ); - - httpEnabled = builder - .comment( "Enable the \"http\" API on Computers (see \"rules\" for more fine grained control than this)." ) - .define( "enabled", ComputerCraft.httpEnabled ); - - httpWebsocketEnabled = builder - .comment( "Enable use of http websockets. This requires the \"http_enable\" option to also be true." ) - .define( "websocket_enabled", ComputerCraft.httpWebsocketEnabled ); - - httpRules = builder - .comment( "A list of rules which control behaviour of the \"http\" API for specific domains or IPs.\n" + - "Each rule is an item with a 'host' to match against, and a series of properties. " + - "The host may be a domain name (\"pastebin.com\"),\n" + - "wildcard (\"*.pastebin.com\") or CIDR notation (\"127.0.0.0/8\"). If no rules, the domain is blocked." ) - .defineList( "rules", - Stream.concat( - Stream.of( ComputerCraft.DEFAULT_HTTP_DENY ).map( x -> AddressRuleConfig.makeRule( x, Action.DENY ) ), - Stream.of( ComputerCraft.DEFAULT_HTTP_ALLOW ).map( x -> AddressRuleConfig.makeRule( x, Action.ALLOW ) ) - ).collect( Collectors.toList() ), - x -> x instanceof UnmodifiableConfig && AddressRuleConfig.checkRule( (UnmodifiableConfig) x ) ); - - httpMaxRequests = builder - .comment( "The number of http requests a computer can make at one time. Additional requests will be queued, and sent when the running requests have finished. Set to 0 for unlimited." ) - .defineInRange( "max_requests", ComputerCraft.httpMaxRequests, 0, Integer.MAX_VALUE ); - - httpMaxWebsockets = builder - .comment( "The number of websockets a computer can have open at one time. Set to 0 for unlimited." ) - .defineInRange( "max_websockets", ComputerCraft.httpMaxWebsockets, 1, Integer.MAX_VALUE ); - - builder.pop(); - } - - { // Peripherals - builder.comment( "Various options relating to peripherals." ); - builder.push( "peripheral" ); - - commandBlockEnabled = builder - .comment( "Enable Command Block peripheral support" ) - .define( "command_block_enabled", ComputerCraft.enableCommandBlock ); - - modemRange = builder - .comment( "The range of Wireless Modems at low altitude in clear weather, in meters" ) - .defineInRange( "modem_range", ComputerCraft.modemRange, 0, MODEM_MAX_RANGE ); - - modemHighAltitudeRange = builder - .comment( "The range of Wireless Modems at maximum altitude in clear weather, in meters" ) - .defineInRange( "modem_high_altitude_range", ComputerCraft.modemHighAltitudeRange, 0, MODEM_MAX_RANGE ); - - modemRangeDuringStorm = builder - .comment( "The range of Wireless Modems at low altitude in stormy weather, in meters" ) - .defineInRange( "modem_range_during_storm", ComputerCraft.modemRangeDuringStorm, 0, MODEM_MAX_RANGE ); - - modemHighAltitudeRangeDuringStorm = builder - .comment( "The range of Wireless Modems at maximum altitude in stormy weather, in meters" ) - .defineInRange( "modem_high_altitude_range_during_storm", ComputerCraft.modemHighAltitudeRangeDuringStorm, 0, MODEM_MAX_RANGE ); - - maxNotesPerTick = builder - .comment( "Maximum amount of notes a speaker can play at once" ) - .defineInRange( "max_notes_per_tick", ComputerCraft.maxNotesPerTick, 1, Integer.MAX_VALUE ); - - monitorBandwidth = builder - .comment( "The limit to how much monitor data can be sent *per tick*. Note:\n" + - " - Bandwidth is measured before compression, so the data sent to the client is smaller.\n" + - " - This ignores the number of players a packet is sent to. Updating a monitor for one player consumes " + - "the same bandwidth limit as sending to 20.\n" + - " - A full sized monitor sends ~25kb of data. So the default (1MB) allows for ~40 monitors to be updated " + - "in a single tick. \n" + - "Set to 0 to disable." ) - .defineInRange( "monitor_bandwidth", (int) ComputerCraft.monitorBandwidth, 0, Integer.MAX_VALUE ); - - builder.pop(); - } - - { // Turtles - builder.comment( "Various options relating to turtles." ); - builder.push( "turtle" ); - - turtlesNeedFuel = builder - .comment( "Set whether Turtles require fuel to move" ) - .define( "need_fuel", ComputerCraft.turtlesNeedFuel ); - - turtleFuelLimit = builder - .comment( "The fuel limit for Turtles" ) - .defineInRange( "normal_fuel_limit", ComputerCraft.turtleFuelLimit, 0, Integer.MAX_VALUE ); - - advancedTurtleFuelLimit = builder - .comment( "The fuel limit for Advanced Turtles" ) - .defineInRange( "advanced_fuel_limit", ComputerCraft.advancedTurtleFuelLimit, 0, Integer.MAX_VALUE ); - - turtlesObeyBlockProtection = builder - .comment( "If set to true, Turtles will be unable to build, dig, or enter protected areas (such as near the server spawn point)" ) - .define( "obey_block_protection", ComputerCraft.turtlesObeyBlockProtection ); - - turtlesCanPush = builder - .comment( "If set to true, Turtles will push entities out of the way instead of stopping if there is space to do so" ) - .define( "can_push", ComputerCraft.turtlesCanPush ); - - turtleDisabledActions = builder - .comment( "A list of turtle actions which are disabled." ) - .defineList( "disabled_actions", Collections.emptyList(), x -> x instanceof String && getAction( (String) x ) != null ); - - builder.pop(); - } - - { - builder.comment( "Configure the size of various computer's terminals.\n" + - "Larger terminals require more bandwidth, so use with care." ).push( "term_sizes" ); - - builder.comment( "Terminal size of computers" ).push( "computer" ); - computerTermWidth = builder.defineInRange( "width", ComputerCraft.computerTermWidth, 1, 255 ); - computerTermHeight = builder.defineInRange( "height", ComputerCraft.computerTermHeight, 1, 255 ); - builder.pop(); - - builder.comment( "Terminal size of pocket computers" ).push( "pocket_computer" ); - pocketTermWidth = builder.defineInRange( "width", ComputerCraft.pocketTermWidth, 1, 255 ); - pocketTermHeight = builder.defineInRange( "height", ComputerCraft.pocketTermHeight, 1, 255 ); - builder.pop(); - - builder.comment( "Maximum size of monitors (in blocks)" ).push( "monitor" ); - monitorWidth = builder.defineInRange( "width", ComputerCraft.monitorWidth, 1, 32 ); - monitorHeight = builder.defineInRange( "height", ComputerCraft.monitorHeight, 1, 32 ); - builder.pop(); - - builder.pop(); - } - - { - builder.comment( "Options for various experimental features. These are not guaranteed to be stable, and may change or be removed across versions." ); - builder.push( "experimental" ); - - genericPeripheral = builder - .comment( "Attempt to make any existing block (or tile entity) a peripheral.\n" + - "This provides peripheral methods for any inventory, fluid tank or energy storage block. It will" + - "_not_ provide methods which have an existing peripheral provider." ) - .define( "generic_peripherals", false ); - } - - serverSpec = builder.build(); - - Builder clientBuilder = new Builder(); - monitorRenderer = clientBuilder - .comment( "The renderer to use for monitors. Generally this should be kept at \"best\" - if " + - "monitors have performance issues, you may wish to experiment with alternative renderers." ) - .defineEnum( "monitor_renderer", MonitorRenderer.BEST ); - monitorDistance = clientBuilder - .comment( "The maximum distance monitors will render at. This defaults to the standard tile entity limit, " + - "but may be extended if you wish to build larger monitors." ) - .defineInRange( "monitor_distance", 64, 16, 1024 ); - clientSpec = clientBuilder.build(); - } - - public static void setup() - { - ModLoadingContext.get().registerConfig( ModConfig.Type.SERVER, serverSpec ); - ModLoadingContext.get().registerConfig( ModConfig.Type.CLIENT, clientSpec ); - } - - public static void sync() - { - // General - ComputerCraft.computerSpaceLimit = computerSpaceLimit.get(); - ComputerCraft.floppySpaceLimit = floppySpaceLimit.get(); - ComputerCraft.maximumFilesOpen = maximumFilesOpen.get(); - ComputerCraft.disableLua51Features = disableLua51Features.get(); - ComputerCraft.defaultComputerSettings = defaultComputerSettings.get(); - ComputerCraft.debugEnable = debugEnabled.get(); - ComputerCraft.computerThreads = computerThreads.get(); - ComputerCraft.logComputerErrors = logComputerErrors.get(); - ComputerCraft.commandRequireCreative = commandRequireCreative.get(); - - // Execution - ComputerCraft.computerThreads = computerThreads.get(); - ComputerCraft.maxMainGlobalTime = TimeUnit.MILLISECONDS.toNanos( maxMainGlobalTime.get() ); - ComputerCraft.maxMainComputerTime = TimeUnit.MILLISECONDS.toNanos( maxMainComputerTime.get() ); - - // HTTP - ComputerCraft.httpEnabled = httpEnabled.get(); - ComputerCraft.httpWebsocketEnabled = httpWebsocketEnabled.get(); - ComputerCraft.httpRules = Collections.unmodifiableList( httpRules.get().stream() - .map( AddressRuleConfig::parseRule ).filter( Objects::nonNull ).collect( Collectors.toList() ) ); - - ComputerCraft.httpMaxRequests = httpMaxRequests.get(); - ComputerCraft.httpMaxWebsockets = httpMaxWebsockets.get(); - - // Peripheral - ComputerCraft.enableCommandBlock = commandBlockEnabled.get(); - ComputerCraft.maxNotesPerTick = maxNotesPerTick.get(); - ComputerCraft.modemRange = modemRange.get(); - ComputerCraft.modemHighAltitudeRange = modemHighAltitudeRange.get(); - ComputerCraft.modemRangeDuringStorm = modemRangeDuringStorm.get(); - ComputerCraft.modemHighAltitudeRangeDuringStorm = modemHighAltitudeRangeDuringStorm.get(); - ComputerCraft.monitorBandwidth = monitorBandwidth.get(); - - // Turtles - ComputerCraft.turtlesNeedFuel = turtlesNeedFuel.get(); - ComputerCraft.turtleFuelLimit = turtleFuelLimit.get(); - ComputerCraft.advancedTurtleFuelLimit = advancedTurtleFuelLimit.get(); - ComputerCraft.turtlesObeyBlockProtection = turtlesObeyBlockProtection.get(); - ComputerCraft.turtlesCanPush = turtlesCanPush.get(); - - ComputerCraft.turtleDisabledActions.clear(); - for( String value : turtleDisabledActions.get() ) ComputerCraft.turtleDisabledActions.add( getAction( value ) ); - - // Terminal size - ComputerCraft.computerTermWidth = computerTermWidth.get(); - ComputerCraft.computerTermHeight = computerTermHeight.get(); - ComputerCraft.pocketTermWidth = pocketTermWidth.get(); - ComputerCraft.pocketTermHeight = pocketTermHeight.get(); - ComputerCraft.monitorWidth = monitorWidth.get(); - ComputerCraft.monitorHeight = monitorHeight.get(); - - // Experimental - ComputerCraft.genericPeripheral = genericPeripheral.get(); - - // Client - ComputerCraft.monitorRenderer = monitorRenderer.get(); - ComputerCraft.monitorDistanceSq = monitorDistance.get() * monitorDistance.get(); - } - - @SubscribeEvent - public static void sync( ModConfig.Loading event ) - { - sync(); - } - - @SubscribeEvent - public static void sync( ModConfig.Reloading event ) - { - // Ensure file configs are reloaded. Forge should probably do this, so worth checking in the future. - CommentedConfig config = event.getConfig().getConfigData(); - if( config instanceof CommentedFileConfig ) ((CommentedFileConfig) config).load(); - - sync(); - } - - private static final Converter converter = CaseFormat.LOWER_CAMEL.converterTo( CaseFormat.UPPER_UNDERSCORE ); - - private static TurtleAction getAction( String value ) - { - try - { - return TurtleAction.valueOf( converter.convert( value ) ); - } - catch( IllegalArgumentException e ) - { - return null; - } - } -} diff --git a/src/main/java/dan200/computercraft/shared/Peripherals.java b/src/main/java/dan200/computercraft/shared/Peripherals.java index 6e361aa26..f97a3ee66 100644 --- a/src/main/java/dan200/computercraft/shared/Peripherals.java +++ b/src/main/java/dan200/computercraft/shared/Peripherals.java @@ -3,53 +3,56 @@ * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.shared; -import java.util.Collection; -import java.util.LinkedHashSet; -import java.util.Objects; -import java.util.Optional; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.peripheral.IPeripheralProvider; -import dan200.computercraft.shared.peripheral.generic.GenericPeripheralProvider; -import dan200.computercraft.shared.util.CapabilityUtil; - +import net.minecraft.block.entity.BlockEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; -public final class Peripherals { +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.Objects; + +public final class Peripherals +{ private static final Collection providers = new LinkedHashSet<>(); private Peripherals() {} - public static synchronized void register(@Nonnull IPeripheralProvider provider) { - Objects.requireNonNull(provider, "provider cannot be null"); - providers.add(provider); + public static synchronized void register( @Nonnull IPeripheralProvider provider ) + { + Objects.requireNonNull( provider, "provider cannot be null" ); + providers.add( provider ); } @Nullable - public static IPeripheral getPeripheral(World world, BlockPos pos, Direction side) { - return World.method_24794(pos) && !world.isClient ? getPeripheralAt(world, pos, side) : null; + public static IPeripheral getPeripheral( World world, BlockPos pos, Direction side ) + { + return World.method_24794( pos ) && !world.isClient ? getPeripheralAt( world, pos, side ) : null; } @Nullable - private static IPeripheral getPeripheralAt(World world, BlockPos pos, Direction side) { + private static IPeripheral getPeripheralAt( World world, BlockPos pos, Direction side ) + { + BlockEntity block = world.getBlockEntity( pos ); + // Try the handlers in order: - for (IPeripheralProvider peripheralProvider : providers) { - try { - Optional peripheral = peripheralProvider.getPeripheral(world, pos, side); - if (peripheral.isPresent()) { - return peripheral.get(); - } - } catch (Exception e) { - ComputerCraft.log.error("Peripheral provider " + peripheralProvider + " errored.", e); + for( IPeripheralProvider peripheralProvider : providers ) + { + try + { + IPeripheral peripheral = peripheralProvider.getPeripheral( world, pos, side ); + if( peripheral != null ) return peripheral; + } + catch( Exception e ) + { + ComputerCraft.log.error( "Peripheral provider " + peripheralProvider + " errored.", e ); } } diff --git a/src/main/java/dan200/computercraft/shared/PocketUpgrades.java b/src/main/java/dan200/computercraft/shared/PocketUpgrades.java index f46a87820..d08daba31 100644 --- a/src/main/java/dan200/computercraft/shared/PocketUpgrades.java +++ b/src/main/java/dan200/computercraft/shared/PocketUpgrades.java @@ -9,8 +9,6 @@ import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.pocket.IPocketUpgrade; import dan200.computercraft.shared.util.InventoryUtil; import net.minecraft.item.ItemStack; -import net.minecraftforge.fml.ModContainer; -import net.minecraftforge.fml.ModLoadingContext; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -35,9 +33,6 @@ public final class PocketUpgrades } upgrades.put( id, upgrade ); - - ModContainer mc = ModLoadingContext.get().getActiveContainer(); - if( mc != null && mc.getModId() != null ) upgradeOwners.put( upgrade, mc.getModId() ); } public static IPocketUpgrade get( String id ) diff --git a/src/main/java/dan200/computercraft/shared/TurtlePermissions.java b/src/main/java/dan200/computercraft/shared/TurtlePermissions.java index f7d448048..adcee9260 100644 --- a/src/main/java/dan200/computercraft/shared/TurtlePermissions.java +++ b/src/main/java/dan200/computercraft/shared/TurtlePermissions.java @@ -5,6 +5,7 @@ */ package dan200.computercraft.shared; +import com.google.common.eventbus.Subscribe; import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.turtle.event.TurtleActionEvent; import net.minecraft.entity.player.PlayerEntity; @@ -12,10 +13,7 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; -@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID ) public final class TurtlePermissions { public static boolean isBlockEnterable( World world, BlockPos pos, PlayerEntity player ) @@ -29,12 +27,10 @@ public final class TurtlePermissions return isBlockEnterable( world, pos, player ); } - @SubscribeEvent - public static void onTurtleAction( TurtleActionEvent event ) - { - if( ComputerCraft.turtleDisabledActions.contains( event.getAction() ) ) - { - event.setCanceled( true, "Action has been disabled" ); + @Subscribe + public void onTurtleAction(TurtleActionEvent event) { + if (ComputerCraft.turtleDisabledActions.contains(event.getAction())) { + event.setCanceled(true, "Action has been disabled"); } } } diff --git a/src/main/java/dan200/computercraft/shared/TurtleUpgrades.java b/src/main/java/dan200/computercraft/shared/TurtleUpgrades.java index d9e4bc30f..12b5b5f6f 100644 --- a/src/main/java/dan200/computercraft/shared/TurtleUpgrades.java +++ b/src/main/java/dan200/computercraft/shared/TurtleUpgrades.java @@ -9,8 +9,8 @@ import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.turtle.ITurtleUpgrade; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.util.InventoryUtil; +import net.fabricmc.loader.api.FabricLoader; import net.minecraft.item.ItemStack; -import net.minecraftforge.fml.ModLoadingContext; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -30,7 +30,8 @@ public final class TurtleUpgrades { this.upgrade = upgrade; this.id = upgrade.getUpgradeID().toString(); - this.modId = ModLoadingContext.get().getActiveNamespace(); + // TODO This should be the mod id of the mod the peripheral comes from + this.modId = ComputerCraft.MOD_ID; this.enabled = true; } } diff --git a/src/main/java/dan200/computercraft/shared/command/CommandComputerCraft.java b/src/main/java/dan200/computercraft/shared/command/CommandComputerCraft.java index 6082e2be2..251a1ea86 100644 --- a/src/main/java/dan200/computercraft/shared/command/CommandComputerCraft.java +++ b/src/main/java/dan200/computercraft/shared/command/CommandComputerCraft.java @@ -59,11 +59,11 @@ public final class CommandComputerCraft private static final int DUMP_SINGLE_ID = 1844510720; private static final int TRACK_ID = 373882880; - private CommandComputerCraft() + public CommandComputerCraft() { } - public static void register( CommandDispatcher dispatcher ) + public static void register( CommandDispatcher dispatcher, boolean bool ) { dispatcher.register( choice( "computercraft" ) .then( literal( "dump" ) @@ -127,7 +127,7 @@ public final class CommandComputerCraft IPeripheral peripheral = computer.getPeripheral( side ); if( peripheral != null ) { - table.row( header( "Peripheral " + side.getName() ), text( peripheral.getType0() ) ); + table.row( header( "Peripheral " + side.getName() ), text( peripheral.getType() ) ); } } diff --git a/src/main/java/dan200/computercraft/shared/command/CommandCopy.java b/src/main/java/dan200/computercraft/shared/command/CommandCopy.java index 2d3ba40f6..f43af691c 100644 --- a/src/main/java/dan200/computercraft/shared/command/CommandCopy.java +++ b/src/main/java/dan200/computercraft/shared/command/CommandCopy.java @@ -7,7 +7,8 @@ package dan200.computercraft.shared.command; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.StringArgumentType; -import dan200.computercraft.ComputerCraft; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.minecraft.client.MinecraftClient; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.text.ClickEvent; @@ -16,15 +17,11 @@ import net.minecraft.text.LiteralText; import net.minecraft.text.Style; import net.minecraft.text.Text; import net.minecraft.text.TranslatableText; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.client.event.ClientChatEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; import static net.minecraft.server.command.CommandManager.argument; import static net.minecraft.server.command.CommandManager.literal; -@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT ) +@Environment(EnvType.CLIENT) public final class CommandCopy { private static final String PREFIX = "/computercraft copy "; @@ -45,15 +42,15 @@ public final class CommandCopy ); } - @SubscribeEvent - public static void onClientSendMessage( ClientChatEvent event ) + public static boolean onClientSendMessage( String message ) { // Emulate the command on the client side - if( event.getMessage().startsWith( PREFIX ) ) + if( message.startsWith( PREFIX ) ) { - MinecraftClient.getInstance().keyboard.setClipboard( event.getMessage().substring( PREFIX.length() ) ); - event.setCanceled( true ); + MinecraftClient.getInstance().keyboard.setClipboard( message.substring( PREFIX.length() ) ); + return true; } + return false; } public static Text createCopyText( String text ) diff --git a/src/main/java/dan200/computercraft/shared/command/CommandUtils.java b/src/main/java/dan200/computercraft/shared/command/CommandUtils.java index 7d8937591..094f79723 100644 --- a/src/main/java/dan200/computercraft/shared/command/CommandUtils.java +++ b/src/main/java/dan200/computercraft/shared/command/CommandUtils.java @@ -8,11 +8,11 @@ package dan200.computercraft.shared.command; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import dan200.computercraft.api.turtle.FakePlayer; import net.minecraft.entity.Entity; import net.minecraft.server.command.CommandSource; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraftforge.common.util.FakePlayer; import java.util.Arrays; import java.util.Locale; diff --git a/src/main/java/dan200/computercraft/shared/command/arguments/ComputersArgumentType.java b/src/main/java/dan200/computercraft/shared/command/arguments/ComputersArgumentType.java index 9faa9405a..843a6c84c 100644 --- a/src/main/java/dan200/computercraft/shared/command/arguments/ComputersArgumentType.java +++ b/src/main/java/dan200/computercraft/shared/command/arguments/ComputersArgumentType.java @@ -174,7 +174,7 @@ public final class ComputersArgumentType implements ArgumentType implements ArgumentType> public static class Serializer implements ArgumentSerializer> { @Override - public void write( @Nonnull RepeatArgumentType arg, @Nonnull PacketByteBuf buf ) + public void toPacket( @Nonnull RepeatArgumentType arg, @Nonnull PacketByteBuf buf ) { buf.writeBoolean( arg.flatten ); ArgumentTypes.toPacket( buf, arg.child ); @@ -147,7 +147,7 @@ public final class RepeatArgumentType implements ArgumentType> } @Override - public void write( @Nonnull RepeatArgumentType arg, @Nonnull JsonObject json ) + public void toJson( @Nonnull RepeatArgumentType arg, @Nonnull JsonObject json ) { json.addProperty( "flatten", arg.flatten ); json.addProperty( "child", "<>" ); // TODO: Potentially serialize this using reflection. diff --git a/src/main/java/dan200/computercraft/shared/common/BlockGeneric.java b/src/main/java/dan200/computercraft/shared/common/BlockGeneric.java index fb1044e97..92801d356 100644 --- a/src/main/java/dan200/computercraft/shared/common/BlockGeneric.java +++ b/src/main/java/dan200/computercraft/shared/common/BlockGeneric.java @@ -6,7 +6,9 @@ package dan200.computercraft.shared.common; import net.minecraft.block.Block; +import net.minecraft.block.BlockEntityProvider; import net.minecraft.block.BlockState; +import net.minecraft.block.BlockWithEntity; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.entity.player.PlayerEntity; @@ -15,16 +17,17 @@ import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; import net.minecraft.world.BlockView; import net.minecraft.world.World; +import net.minecraft.world.WorldAccess; import net.minecraft.world.WorldView; -import net.minecraftforge.fml.RegistryObject; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Random; -public abstract class BlockGeneric extends Block +public abstract class BlockGeneric extends BlockWithEntity { private final BlockEntityType type; @@ -63,13 +66,6 @@ public abstract class BlockGeneric extends Block if( tile instanceof TileGeneric ) ((TileGeneric) tile).onNeighbourChange( neighbourPos ); } - @Override - public final void onNeighborChange( BlockState state, WorldView world, BlockPos pos, BlockPos neighbour ) - { - BlockEntity tile = world.getBlockEntity( pos ); - if( tile instanceof TileGeneric ) ((TileGeneric) tile).onNeighbourTileEntityChange( neighbour ); - } - @Override @Deprecated public void scheduledTick( @Nonnull BlockState state, ServerWorld world, @Nonnull BlockPos pos, @Nonnull Random rand ) @@ -78,22 +74,10 @@ public abstract class BlockGeneric extends Block if( te instanceof TileGeneric ) ((TileGeneric) te).blockTick(); } - @Override - public boolean hasTileEntity( BlockState state ) - { - return true; - } - @Nullable @Override - public BlockEntity createTileEntity( @Nonnull BlockState state, @Nonnull BlockView world ) + public BlockEntity createBlockEntity(@Nonnull BlockView world ) { - return type.get().instantiate(); - } - - @Override - public boolean canBeReplacedByLeaves( BlockState state, WorldView world, BlockPos pos ) - { - return false; + return type.instantiate(); } } diff --git a/src/main/java/dan200/computercraft/shared/common/ColourableRecipe.java b/src/main/java/dan200/computercraft/shared/common/ColourableRecipe.java index 2b3f4bb5f..fb531820b 100644 --- a/src/main/java/dan200/computercraft/shared/common/ColourableRecipe.java +++ b/src/main/java/dan200/computercraft/shared/common/ColourableRecipe.java @@ -56,7 +56,7 @@ public final class ColourableRecipe extends SpecialCraftingRecipe @Nonnull @Override - public ItemStack getCraftingResult( @Nonnull CraftingInventory inv ) + public ItemStack craft( @Nonnull CraftingInventory inv ) { ItemStack colourable = ItemStack.EMPTY; diff --git a/src/main/java/dan200/computercraft/shared/common/ContainerHeldItem.java b/src/main/java/dan200/computercraft/shared/common/ContainerHeldItem.java index 3819a17ba..a1a2bb206 100644 --- a/src/main/java/dan200/computercraft/shared/common/ContainerHeldItem.java +++ b/src/main/java/dan200/computercraft/shared/common/ContainerHeldItem.java @@ -5,14 +5,17 @@ */ package dan200.computercraft.shared.common; -import dan200.computercraft.shared.Registry; +import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.network.container.HeldItemContainerData; +import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketByteBuf; import net.minecraft.screen.NamedScreenHandlerFactory; import net.minecraft.screen.ScreenHandler; import net.minecraft.screen.ScreenHandlerType; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; import net.minecraft.util.Hand; import javax.annotation.Nonnull; @@ -31,9 +34,14 @@ public class ContainerHeldItem extends ScreenHandler stack = player.getStackInHand( hand ).copy(); } + public static ContainerHeldItem createPrintout( int id, PlayerInventory inventory, PacketByteBuf data ) + { + return createPrintout(id, inventory, new HeldItemContainerData(data)); + } + public static ContainerHeldItem createPrintout( int id, PlayerInventory inventory, HeldItemContainerData data ) { - return new ContainerHeldItem( Registry.ModContainers.PRINTOUT.get(), id, inventory.player, data.getHand() ); + return new ContainerHeldItem( ComputerCraftRegistry.ModContainers.PRINTOUT, id, inventory.player, data.getHand() ); } @Nonnull @@ -51,7 +59,7 @@ public class ContainerHeldItem extends ScreenHandler return stack == this.stack || !stack.isEmpty() && !this.stack.isEmpty() && stack.getItem() == this.stack.getItem(); } - public static class Factory implements NamedScreenHandlerFactory + public static class Factory implements NamedScreenHandlerFactory, ExtendedScreenHandlerFactory { private final ScreenHandlerType type; private final Text name; @@ -77,5 +85,10 @@ public class ContainerHeldItem extends ScreenHandler { return new ContainerHeldItem( type, id, player, hand ); } + + @Override + public void writeScreenOpeningData(ServerPlayerEntity serverPlayerEntity, PacketByteBuf packetByteBuf) { + packetByteBuf.writeEnumConstant(hand); + } } } diff --git a/src/main/java/dan200/computercraft/shared/common/TileGeneric.java b/src/main/java/dan200/computercraft/shared/common/TileGeneric.java index 7c721be3f..25f45a6c6 100644 --- a/src/main/java/dan200/computercraft/shared/common/TileGeneric.java +++ b/src/main/java/dan200/computercraft/shared/common/TileGeneric.java @@ -5,6 +5,7 @@ */ package dan200.computercraft.shared.common; +import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; @@ -18,7 +19,7 @@ import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import javax.annotation.Nonnull; -public abstract class TileGeneric extends BlockEntity +public abstract class TileGeneric extends BlockEntity implements BlockEntityClientSerializable { public TileGeneric( BlockEntityType type ) { @@ -89,9 +90,14 @@ public abstract class TileGeneric extends BlockEntity } @Override - public final void onDataPacket( ClientConnection net, BlockEntityUpdateS2CPacket packet ) - { - if( packet.getBlockEntityType() == 0 ) readDescription( packet.getCompoundTag() ); + public CompoundTag toClientTag(CompoundTag compoundTag) { + writeDescription(compoundTag); + return compoundTag; + } + + @Override + public void fromClientTag(CompoundTag compoundTag) { + readDescription(compoundTag); } @Nonnull @@ -102,11 +108,4 @@ public abstract class TileGeneric extends BlockEntity writeDescription( tag ); return tag; } - - @Override - public void handleUpdateTag( @Nonnull BlockState state, @Nonnull CompoundTag tag ) - { - super.handleUpdateTag( state, tag ); - readDescription( tag ); - } } diff --git a/src/main/java/dan200/computercraft/shared/computer/apis/CommandAPI.java b/src/main/java/dan200/computercraft/shared/computer/apis/CommandAPI.java index f4636e3bf..a56708410 100644 --- a/src/main/java/dan200/computercraft/shared/computer/apis/CommandAPI.java +++ b/src/main/java/dan200/computercraft/shared/computer/apis/CommandAPI.java @@ -5,20 +5,23 @@ */ package dan200.computercraft.shared.computer.apis; +import com.google.common.collect.ImmutableMap; import com.mojang.brigadier.tree.CommandNode; import com.mojang.brigadier.tree.LiteralCommandNode; import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.lua.*; import dan200.computercraft.shared.computer.blocks.TileCommandComputer; -import dan200.computercraft.shared.peripheral.generic.data.BlockData; import dan200.computercraft.shared.util.NBTUtil; +import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.MinecraftServer; import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.state.property.Property; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.registry.Registry; import net.minecraft.world.World; import java.util.*; @@ -64,7 +67,7 @@ public class CommandAPI implements ILuaAPI } catch( Throwable t ) { - if( ComputerCraft.logComputerErrors ) ComputerCraft.log.error( "Error running command.", t ); + if( ComputerCraft.logPeripheralErrors ) ComputerCraft.log.error( "Error running command.", t ); return new Object[] { false, createOutput( "Java Exception Thrown: " + t ) }; } } @@ -72,15 +75,42 @@ public class CommandAPI implements ILuaAPI private static Map getBlockInfo( World world, BlockPos pos ) { // Get the details of the block - BlockState state = world.getBlockState( pos ); - Map table = BlockData.fill( new HashMap<>(), state ); + BlockState state = world.getBlockState(pos); + Block block = state.getBlock(); - BlockEntity tile = world.getBlockEntity( pos ); - if( tile != null ) table.put( "nbt", NBTUtil.toLua( tile.toTag( new CompoundTag() ) ) ); + Map table = new HashMap<>(); + table.put("name", + Registry.BLOCK.getId(block) + .toString()); + table.put("world", world.getRegistryKey()); + + Map stateTable = new HashMap<>(); + for (ImmutableMap.Entry, Comparable> entry : state.getEntries() + .entrySet()) { + Property property = entry.getKey(); + stateTable.put(property.getName(), getPropertyValue(property, entry.getValue())); + } + table.put("state", stateTable); + + BlockEntity tile = world.getBlockEntity(pos); + if (tile != null) { + table.put("nbt", NBTUtil.toLua(tile.toTag(new CompoundTag()))); + } return table; } + @SuppressWarnings ({ + "unchecked", + "rawtypes" + }) + private static Object getPropertyValue(Property property, Comparable value) { + if (value instanceof String || value instanceof Number || value instanceof Boolean) { + return value; + } + return property.name(value); + } + /** * Execute a specific command. * diff --git a/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputer.java b/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputer.java index 48c2d97de..2f43ce8ab 100644 --- a/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputer.java +++ b/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputer.java @@ -18,7 +18,6 @@ import net.minecraft.state.property.DirectionProperty; import net.minecraft.state.property.EnumProperty; import net.minecraft.state.property.Properties; import net.minecraft.util.math.Direction; -import net.minecraftforge.fml.RegistryObject; import javax.annotation.Nonnull; import javax.annotation.Nullable; diff --git a/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputerBase.java b/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputerBase.java index 658eee05f..670f0a036 100644 --- a/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputerBase.java +++ b/src/main/java/dan200/computercraft/shared/computer/blocks/BlockComputerBase.java @@ -29,7 +29,6 @@ import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; import net.minecraft.world.BlockView; import net.minecraft.world.World; -import net.minecraftforge.fml.RegistryObject; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -115,7 +114,7 @@ public abstract class BlockComputerBase extends Bloc @Nonnull @Override - public ItemStack getPickBlock( BlockState state, HitResult target, BlockView world, BlockPos pos, PlayerEntity player ) + public ItemStack getPickStack( BlockView world, BlockPos pos, BlockState state ) { BlockEntity tile = world.getBlockEntity( pos ); if( tile instanceof TileComputerBase ) @@ -124,7 +123,7 @@ public abstract class BlockComputerBase extends Bloc if( !result.isEmpty() ) return result; } - return super.getPickBlock( state, target, world, pos, player ); + return super.getPickStack(world, pos, state); } @Override diff --git a/src/main/java/dan200/computercraft/shared/computer/blocks/ComputerPeripheral.java b/src/main/java/dan200/computercraft/shared/computer/blocks/ComputerPeripheral.java index 0fb5411f0..8e527be7d 100644 --- a/src/main/java/dan200/computercraft/shared/computer/blocks/ComputerPeripheral.java +++ b/src/main/java/dan200/computercraft/shared/computer/blocks/ComputerPeripheral.java @@ -33,7 +33,7 @@ public class ComputerPeripheral implements IPeripheral @Nonnull @Override - public String getType0() + public String getType() { return type; } diff --git a/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputer.java b/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputer.java index 2aecaf544..2c156d113 100644 --- a/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputer.java +++ b/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputer.java @@ -22,12 +22,9 @@ import net.minecraft.util.math.Direction; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.util.Optional; - public class TileComputer extends TileComputerBase { private ComputerProxy proxy; - private Optional peripheral; public TileComputer( ComputerFamily family, BlockEntityType type ) { @@ -40,8 +37,8 @@ public class TileComputer extends TileComputerBase ComputerFamily family = getFamily(); ServerComputer computer = new ServerComputer( getWorld(), id, label, instanceID, family, - ComputerCraft.computerTermWidth, - ComputerCraft.computerTermHeight + ComputerCraft.terminalWidth_computer, + ComputerCraft.terminalHeight_computer ); computer.setPosition( getPos() ); return computer; diff --git a/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputerBase.java b/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputerBase.java index 3a4cf4031..9110f0388 100644 --- a/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputerBase.java +++ b/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputerBase.java @@ -3,28 +3,22 @@ * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.shared.computer.blocks; -import java.util.Objects; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.core.computer.ComputerSide; import dan200.computercraft.shared.BundledRedstone; import dan200.computercraft.shared.Peripherals; import dan200.computercraft.shared.common.TileGeneric; -import dan200.computercraft.shared.computer.core.ClientComputer; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.core.ComputerState; import dan200.computercraft.shared.computer.core.ServerComputer; +import dan200.computercraft.shared.network.container.ComputerContainerData; import dan200.computercraft.shared.util.DirectionUtil; import dan200.computercraft.shared.util.RedstoneUtil; import joptsimple.internal.Strings; - +import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.RedstoneWireBlock; @@ -33,7 +27,9 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.PacketByteBuf; import net.minecraft.screen.NamedScreenHandlerFactory; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.LiteralText; import net.minecraft.text.Text; import net.minecraft.text.TranslatableText; @@ -46,10 +42,14 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; -public abstract class TileComputerBase extends TileGeneric implements IComputerTile, Tickable, Nameable, NamedScreenHandlerFactory, IPeripheral { +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Objects; + +public abstract class TileComputerBase extends TileGeneric implements IComputerTile, Tickable, Nameable, NamedScreenHandlerFactory, ExtendedScreenHandlerFactory +{ private static final String NBT_ID = "ComputerId"; private static final String NBT_LABEL = "Label"; - private static final String NBT_INSTANCE = "InstanceId"; private static final String NBT_ON = "On"; private int m_instanceID = -1; @@ -61,64 +61,65 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT private final ComputerFamily family; - public TileComputerBase(BlockEntityType type, ComputerFamily family) { - super(type); + public TileComputerBase( BlockEntityType type, ComputerFamily family ) + { + super( type ); this.family = family; } - protected void unload() { - if (m_instanceID >= 0) { - if (!getWorld().isClient) { - ComputerCraft.serverComputerRegistry.remove(m_instanceID); - } + protected void unload() + { + if( m_instanceID >= 0 ) + { + if( !getWorld().isClient ) ComputerCraft.serverComputerRegistry.remove( m_instanceID ); m_instanceID = -1; } } - public abstract void openGui(PlayerEntity entity); - @Override - public void destroy() { + public void destroy() + { unload(); - for (Direction dir : DirectionUtil.FACINGS) { - RedstoneUtil.propagateRedstoneOutput(getWorld(), getPos(), dir); + for( Direction dir : DirectionUtil.FACINGS ) + { + RedstoneUtil.propagateRedstoneOutput( getWorld(), getPos(), dir ); } } - /*@Override - public void onChunkUnloaded() - { - unload(); - }*/ - - @Override - public void markRemoved() { + public void markRemoved() + { unload(); super.markRemoved(); } - protected boolean canNameWithTag(PlayerEntity player) { + protected boolean canNameWithTag( PlayerEntity player ) + { return false; } @Nonnull @Override - public ActionResult onActivate(PlayerEntity player, Hand hand, BlockHitResult hit) { - ItemStack currentItem = player.getStackInHand(hand); - if (!currentItem.isEmpty() && currentItem.getItem() == Items.NAME_TAG && canNameWithTag(player) && currentItem.hasCustomName()) { + public ActionResult onActivate( PlayerEntity player, Hand hand, BlockHitResult hit ) + { + ItemStack currentItem = player.getStackInHand( hand ); + if( !currentItem.isEmpty() && currentItem.getItem() == Items.NAME_TAG && canNameWithTag( player ) && currentItem.hasCustomName() ) + { // Label to rename computer - if (!getWorld().isClient) { - setLabel(currentItem.getName() - .getString()); - currentItem.decrement(1); + if( !getWorld().isClient ) + { + setLabel( currentItem.getName().getString() ); + currentItem.decrement( 1 ); } return ActionResult.SUCCESS; - } else if (!player.isInSneakingPose()) { + } + else if( !player.isInSneakingPose() ) + { // Regular right click to activate computer - if (!getWorld().isClient && isUsable(player, false)) { + if( !getWorld().isClient && isUsable( player, false ) ) + { createServerComputer().turnOn(); - openGui(player); + new ComputerContainerData( createServerComputer() ).open( player, this ); } return ActionResult.SUCCESS; } @@ -126,25 +127,28 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT } @Override - public void onNeighbourChange(@Nonnull BlockPos neighbour) { - updateInput(neighbour); + public void onNeighbourChange( @Nonnull BlockPos neighbour ) + { + updateInput( neighbour ); } @Override - public void onNeighbourTileEntityChange(@Nonnull BlockPos neighbour) { - updateInput(neighbour); + public void onNeighbourTileEntityChange( @Nonnull BlockPos neighbour ) + { + updateInput( neighbour ); } @Override - public void tick() { - if (!getWorld().isClient) { + public void tick() + { + if( !getWorld().isClient ) + { ServerComputer computer = createServerComputer(); - if (computer == null) { - return; - } + if( computer == null ) return; // If the computer isn't on and should be, then turn it on - if (m_startOn || (m_fresh && m_on)) { + if( m_startOn || (m_fresh && m_on) ) + { computer.turnOn(); m_startOn = false; } @@ -156,74 +160,69 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT label = computer.getLabel(); m_on = computer.isOn(); - if (computer.hasOutputChanged()) { - updateOutput(); - } + if( computer.hasOutputChanged() ) updateOutput(); // Update the block state if needed. We don't fire a block update intentionally, // as this only really is needed on the client side. - updateBlockState(computer.getState()); + updateBlockState( computer.getState() ); - if (computer.hasOutputChanged()) { - updateOutput(); - } + if( computer.hasOutputChanged() ) updateOutput(); } - /* else todo is needed? - { - ClientComputer computer = createClientComputer(); - if( computer != null && computer.hasOutputChanged() ) updateBlock(); - }*/ } - protected abstract void updateBlockState(ComputerState newState); + protected abstract void updateBlockState( ComputerState newState ); @Nonnull @Override - public CompoundTag toTag(@Nonnull CompoundTag nbt) { + public CompoundTag toTag( @Nonnull CompoundTag nbt ) + { // Save ID, label and power state - if (m_computerID >= 0) { - nbt.putInt(NBT_ID, m_computerID); - } - if (label != null) { - nbt.putString(NBT_LABEL, label); - } - nbt.putBoolean(NBT_ON, m_on); + if( m_computerID >= 0 ) nbt.putInt( NBT_ID, m_computerID ); + if( label != null ) nbt.putString( NBT_LABEL, label ); + nbt.putBoolean( NBT_ON, m_on ); - return super.toTag(nbt); + return super.toTag( nbt ); } @Override - public void fromTag(@Nonnull BlockState state, @Nonnull CompoundTag nbt) { - super.fromTag(state, nbt); + public void fromTag( @Nonnull BlockState state, @Nonnull CompoundTag nbt ) + { + super.fromTag( state, nbt ); // Load ID, label and power state - m_computerID = nbt.contains(NBT_ID) ? nbt.getInt(NBT_ID) : -1; - label = nbt.contains(NBT_LABEL) ? nbt.getString(NBT_LABEL) : null; - m_on = m_startOn = nbt.getBoolean(NBT_ON); + m_computerID = nbt.contains( NBT_ID ) ? nbt.getInt( NBT_ID ) : -1; + label = nbt.contains( NBT_LABEL ) ? nbt.getString( NBT_LABEL ) : null; + m_on = m_startOn = nbt.getBoolean( NBT_ON ); } - protected boolean isPeripheralBlockedOnSide(ComputerSide localSide) { + protected boolean isPeripheralBlockedOnSide( ComputerSide localSide ) + { return false; } protected abstract Direction getDirection(); - protected ComputerSide remapToLocalSide(Direction globalSide) { - return remapLocalSide(DirectionUtil.toLocal(getDirection(), globalSide)); + protected ComputerSide remapToLocalSide( Direction globalSide ) + { + return remapLocalSide( DirectionUtil.toLocal( getDirection(), globalSide ) ); } - protected ComputerSide remapLocalSide(ComputerSide localSide) { + protected ComputerSide remapLocalSide( ComputerSide localSide ) + { return localSide; } - private void updateSideInput(ServerComputer computer, Direction dir, BlockPos offset) { + private void updateSideInput( ServerComputer computer, Direction dir, BlockPos offset ) + { Direction offsetSide = dir.getOpposite(); - ComputerSide localDir = remapToLocalSide(dir); + ComputerSide localDir = remapToLocalSide( dir ); - computer.setRedstoneInput(localDir, getRedstoneInput(world, offset, dir)); - computer.setBundledRedstoneInput(localDir, BundledRedstone.getOutput(getWorld(), offset, offsetSide)); - if (!isPeripheralBlockedOnSide(localDir)) { - computer.setPeripheral(localDir, Peripherals.getPeripheral(getWorld(), offset, offsetSide)); + computer.setRedstoneInput( localDir, getRedstoneInput( world, offset, dir ) ); + computer.setBundledRedstoneInput( localDir, BundledRedstone.getOutput( getWorld(), offset, offsetSide ) ); + if( !isPeripheralBlockedOnSide( localDir ) ) + { + IPeripheral peripheral = Peripherals.getPeripheral( getWorld(), offset, offsetSide); + computer.setPeripheral( localDir, peripheral ); } } @@ -231,52 +230,50 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT * Gets the redstone input for an adjacent block. * * @param world The world we exist in - * @param pos The position of the neighbour - * @param side The side we are reading from + * @param pos The position of the neighbour + * @param side The side we are reading from * @return The effective redstone power */ - protected static int getRedstoneInput(World world, BlockPos pos, Direction side) { - int power = world.getEmittedRedstonePower(pos, side); - if (power >= 15) { - return power; - } + protected static int getRedstoneInput( World world, BlockPos pos, Direction side ) + { + int power = world.getEmittedRedstonePower( pos, side ); + if( power >= 15 ) return power; - BlockState neighbour = world.getBlockState(pos); - return neighbour.getBlock() == Blocks.REDSTONE_WIRE ? Math.max(power, neighbour.get(RedstoneWireBlock.POWER)) : power; + BlockState neighbour = world.getBlockState( pos ); + return neighbour.getBlock() == Blocks.REDSTONE_WIRE + ? Math.max( power, neighbour.get( RedstoneWireBlock.POWER ) ) + : power; } - public void updateInput() { - if (getWorld() == null || getWorld().isClient) { - return; - } + public void updateInput() + { + if( getWorld() == null || getWorld().isClient ) return; // Update all sides ServerComputer computer = getServerComputer(); - if (computer == null) { - return; - } + if( computer == null ) return; BlockPos pos = computer.getPosition(); - for (Direction dir : DirectionUtil.FACINGS) { - updateSideInput(computer, dir, pos.offset(dir)); + for( Direction dir : DirectionUtil.FACINGS ) + { + updateSideInput( computer, dir, pos.offset( dir ) ); } } - private void updateInput(BlockPos neighbour) { - if (getWorld() == null || getWorld().isClient) { - return; - } + private void updateInput( BlockPos neighbour ) + { + if( getWorld() == null || getWorld().isClient ) return; ServerComputer computer = getServerComputer(); - if (computer == null) { - return; - } + if( computer == null ) return; - for (Direction dir : DirectionUtil.FACINGS) { - BlockPos offset = pos.offset(dir); - if (offset.equals(neighbour)) { - updateSideInput(computer, dir, offset); - return; // todo break;? + for( Direction dir : DirectionUtil.FACINGS ) + { + BlockPos offset = pos.offset( dir ); + if( offset.equals( neighbour ) ) + { + updateSideInput( computer, dir, offset ); + return; } } @@ -284,110 +281,120 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT updateInput(); } - public void updateOutput() { + private void updateInput( Direction dir ) + { + if( getWorld() == null || getWorld().isClient ) return; + + ServerComputer computer = getServerComputer(); + if( computer == null ) return; + + updateSideInput( computer, dir, pos.offset( dir ) ); + } + + public void updateOutput() + { // Update redstone updateBlock(); - for (Direction dir : DirectionUtil.FACINGS) { - RedstoneUtil.propagateRedstoneOutput(getWorld(), getPos(), dir); + for( Direction dir : DirectionUtil.FACINGS ) + { + RedstoneUtil.propagateRedstoneOutput( getWorld(), getPos(), dir ); } } - public abstract ComputerProxy createProxy(); - - protected abstract ServerComputer createComputer(int instanceID, int id); + protected abstract ServerComputer createComputer( int instanceID, int id ); @Override - public final int getComputerID() { + public final int getComputerID() + { return m_computerID; } @Override - public final String getLabel() { + public final String getLabel() + { return label; } @Override - public final void setComputerID(int id) { - if (getWorld().isClient || m_computerID == id) { - return; - } + public final void setComputerID( int id ) + { + if( getWorld().isClient || m_computerID == id ) return; m_computerID = id; ServerComputer computer = getServerComputer(); - if (computer != null) { - computer.setID(m_computerID); - } + if( computer != null ) computer.setID( m_computerID ); markDirty(); } @Override - public final void setLabel(String label) { - if (getWorld().isClient || Objects.equals(this.label, label)) { - return; - } + public final void setLabel( String label ) + { + if( getWorld().isClient || Objects.equals( this.label, label ) ) return; this.label = label; ServerComputer computer = getServerComputer(); - if (computer != null) { - computer.setLabel(label); - } + if( computer != null ) computer.setLabel( label ); markDirty(); } @Override - public ComputerFamily getFamily() { + public ComputerFamily getFamily() + { return family; } - public ServerComputer createServerComputer() { - if (getWorld().isClient) { - return null; - } + public ServerComputer createServerComputer() + { + if( getWorld().isClient ) return null; boolean changed = false; - if (m_instanceID < 0) { + if( m_instanceID < 0 ) + { m_instanceID = ComputerCraft.serverComputerRegistry.getUnusedInstanceID(); changed = true; } - if (!ComputerCraft.serverComputerRegistry.contains(m_instanceID)) { - ServerComputer computer = createComputer(m_instanceID, m_computerID); - ComputerCraft.serverComputerRegistry.add(m_instanceID, computer); + if( !ComputerCraft.serverComputerRegistry.contains( m_instanceID ) ) + { + ServerComputer computer = createComputer( m_instanceID, m_computerID ); + ComputerCraft.serverComputerRegistry.add( m_instanceID, computer ); m_fresh = true; changed = true; } - if (changed) { + if( changed ) + { updateBlock(); updateInput(); } - return ComputerCraft.serverComputerRegistry.get(m_instanceID); + return ComputerCraft.serverComputerRegistry.get( m_instanceID ); } - public ServerComputer getServerComputer() { - return getWorld().isClient ? null : ComputerCraft.serverComputerRegistry.get(m_instanceID); + public ServerComputer getServerComputer() + { + return getWorld().isClient ? null : ComputerCraft.serverComputerRegistry.get( m_instanceID ); } // Networking stuff @Override - protected void writeDescription(@Nonnull CompoundTag nbt) { - super.writeDescription(nbt); - if (label != null) { - nbt.putString(NBT_LABEL, label); - } - if (m_computerID >= 0) { - nbt.putInt(NBT_ID, m_computerID); - } + protected void writeDescription( @Nonnull CompoundTag nbt ) + { + super.writeDescription( nbt ); + if( label != null ) nbt.putString( NBT_LABEL, label ); + if( m_computerID >= 0 ) nbt.putInt( NBT_ID, m_computerID ); } @Override - protected void readDescription(@Nonnull CompoundTag nbt) { - super.readDescription(nbt); - label = nbt.contains(NBT_LABEL) ? nbt.getString(NBT_LABEL) : null; - m_computerID = nbt.contains(NBT_ID) ? nbt.getInt(NBT_ID) : -1; + protected void readDescription( @Nonnull CompoundTag nbt ) + { + super.readDescription( nbt ); + label = nbt.contains( NBT_LABEL ) ? nbt.getString( NBT_LABEL ) : null; + m_computerID = nbt.contains( NBT_ID ) ? nbt.getInt( NBT_ID ) : -1; } - protected void transferStateFrom(TileComputerBase copy) { - if (copy.m_computerID != m_computerID || copy.m_instanceID != m_instanceID) { + protected void transferStateFrom( TileComputerBase copy ) + { + if( copy.m_computerID != m_computerID || copy.m_instanceID != m_instanceID ) + { unload(); m_instanceID = copy.m_instanceID; m_computerID = copy.m_computerID; @@ -401,25 +408,36 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT @Nonnull @Override - public Text getName() { - return hasCustomName() ? new LiteralText(label) : new TranslatableText(getCachedState().getBlock() - .getTranslationKey()); + public Text getName() + { + return hasCustomName() + ? new LiteralText( label ) + : new TranslatableText( getCachedState().getBlock().getTranslationKey() ); } @Override - public boolean hasCustomName() { - return !Strings.isNullOrEmpty(label); + public boolean hasCustomName() + { + return !Strings.isNullOrEmpty( label ); } @Nullable @Override - public Text getCustomName() { - return hasCustomName() ? new LiteralText(label) : null; + public Text getCustomName() + { + return hasCustomName() ? new LiteralText( label ) : null; } @Nonnull @Override - public Text getDisplayName() { + public Text getDisplayName() + { return Nameable.super.getDisplayName(); } + + @Override + public void writeScreenOpeningData(ServerPlayerEntity serverPlayerEntity, PacketByteBuf packetByteBuf) { + packetByteBuf.writeInt(getServerComputer().getInstanceID()); + packetByteBuf.writeEnumConstant(getServerComputer().getFamily()); + } } diff --git a/src/main/java/dan200/computercraft/shared/computer/core/ServerComputer.java b/src/main/java/dan200/computercraft/shared/computer/core/ServerComputer.java index 1affdb1dc..fb2db0823 100644 --- a/src/main/java/dan200/computercraft/shared/computer/core/ServerComputer.java +++ b/src/main/java/dan200/computercraft/shared/computer/core/ServerComputer.java @@ -163,7 +163,8 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput if( hasOutputChanged() || force ) { // Send computer state to all clients - NetworkHandler.sendToAllPlayers( createComputerPacket() ); + if (FabricLoader.getInstance().getGameInstance() instanceof MinecraftServer) + NetworkHandler.sendToAllPlayers((MinecraftServer) FabricLoader.getInstance().getGameInstance(), createComputerPacket() ); } if( hasTerminalChanged() || force ) @@ -198,7 +199,8 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput public void broadcastDelete() { // Send deletion to client - NetworkHandler.sendToAllPlayers( new ComputerDeletedClientMessage( getInstanceID() ) ); + if (FabricLoader.getInstance().getGameInstance() instanceof MinecraftServer) + NetworkHandler.sendToAllPlayers((MinecraftServer) FabricLoader.getInstance().getGameInstance(), new ComputerDeletedClientMessage( getInstanceID() ) ); } public void setID( int id ) diff --git a/src/main/java/dan200/computercraft/shared/computer/inventory/ContainerComputer.java b/src/main/java/dan200/computercraft/shared/computer/inventory/ContainerComputer.java index 9ce948931..cff96f0ea 100644 --- a/src/main/java/dan200/computercraft/shared/computer/inventory/ContainerComputer.java +++ b/src/main/java/dan200/computercraft/shared/computer/inventory/ContainerComputer.java @@ -5,20 +5,20 @@ */ package dan200.computercraft.shared.computer.inventory; -import dan200.computercraft.shared.Registry; +import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.computer.blocks.TileComputer; import dan200.computercraft.shared.network.container.ComputerContainerData; import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.network.PacketByteBuf; public class ContainerComputer extends ContainerComputerBase { public ContainerComputer( int id, TileComputer tile ) { - super( Registry.ModContainers.COMPUTER.get(), id, tile::isUsableByPlayer, tile.createServerComputer(), tile.getFamily() ); + super( ComputerCraftRegistry.ModContainers.COMPUTER, id, tile::isUsableByPlayer, tile.createServerComputer(), tile.getFamily() ); } - public ContainerComputer( int id, PlayerInventory player, ComputerContainerData data ) - { - super( Registry.ModContainers.COMPUTER.get(), id, player, data ); + public ContainerComputer(int i, PlayerInventory playerInventory, PacketByteBuf packetByteBuf) { + super(ComputerCraftRegistry.ModContainers.COMPUTER, i, playerInventory, packetByteBuf); } } diff --git a/src/main/java/dan200/computercraft/shared/computer/inventory/ContainerComputerBase.java b/src/main/java/dan200/computercraft/shared/computer/inventory/ContainerComputerBase.java index 82f2cc760..9f439c9a9 100644 --- a/src/main/java/dan200/computercraft/shared/computer/inventory/ContainerComputerBase.java +++ b/src/main/java/dan200/computercraft/shared/computer/inventory/ContainerComputerBase.java @@ -10,6 +10,7 @@ import dan200.computercraft.shared.computer.core.*; import dan200.computercraft.shared.network.container.ComputerContainerData; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.network.PacketByteBuf; import net.minecraft.screen.ScreenHandler; import net.minecraft.screen.ScreenHandlerType; import javax.annotation.Nonnull; @@ -31,9 +32,9 @@ public class ContainerComputerBase extends ScreenHandler implements IContainerCo this.family = family; } - protected ContainerComputerBase( ScreenHandlerType type, int id, PlayerInventory player, ComputerContainerData data ) + protected ContainerComputerBase(ScreenHandlerType type, int id, PlayerInventory player, PacketByteBuf packetByteBuf) { - this( type, id, x -> true, getComputer( player, data ), data.getFamily() ); + this( type, id, x -> true, getComputer( player, new ComputerContainerData((PacketByteBuf) packetByteBuf.copy()) ), new ComputerContainerData(packetByteBuf).getFamily() ); } protected static IComputer getComputer( PlayerInventory player, ComputerContainerData data ) diff --git a/src/main/java/dan200/computercraft/shared/computer/inventory/ContainerViewComputer.java b/src/main/java/dan200/computercraft/shared/computer/inventory/ContainerViewComputer.java index 9d63d4c95..dd424080c 100644 --- a/src/main/java/dan200/computercraft/shared/computer/inventory/ContainerViewComputer.java +++ b/src/main/java/dan200/computercraft/shared/computer/inventory/ContainerViewComputer.java @@ -3,85 +3,63 @@ * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.shared.computer.inventory; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import dan200.computercraft.ComputerCraft; +import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.computer.blocks.TileCommandComputer; import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.computer.core.IComputer; import dan200.computercraft.shared.computer.core.IContainerComputer; -import dan200.computercraft.shared.computer.core.InputState; import dan200.computercraft.shared.computer.core.ServerComputer; - +import dan200.computercraft.shared.network.container.ViewComputerContainerData; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.screen.ScreenHandler; -import net.minecraft.server.MinecraftServer; -import net.minecraft.text.TranslatableText; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.network.PacketByteBuf; -public class ContainerViewComputer extends ScreenHandler implements IContainerComputer { - private final IComputer computer; - private final InputState input = new InputState(this); +import javax.annotation.Nonnull; - public ContainerViewComputer(int id, IComputer computer) { - super(null, id); - this.computer = computer; +public class ContainerViewComputer extends ContainerComputerBase implements IContainerComputer +{ + private final int width; + private final int height; + + public ContainerViewComputer( int id, ServerComputer computer ) + { + super( ComputerCraftRegistry.ModContainers.VIEW_COMPUTER, id, player -> canInteractWith( computer, player ), computer, computer.getFamily() ); + this.width = this.height = 0; + } + public ContainerViewComputer(int id, PlayerInventory player, PacketByteBuf packetByteBuf) + { + super( ComputerCraftRegistry.ModContainers.VIEW_COMPUTER, id, player, packetByteBuf ); + ViewComputerContainerData data = new ViewComputerContainerData((PacketByteBuf) packetByteBuf.copy()); + this.width = data.getWidth(); + this.height = data.getHeight(); } - private static boolean canInteractWith(@Nonnull ServerComputer computer, @Nonnull PlayerEntity player) { + private static boolean canInteractWith( @Nonnull ServerComputer computer, @Nonnull PlayerEntity player ) + { // If this computer no longer exists then discard it. - if (ComputerCraft.serverComputerRegistry.get(computer.getInstanceID()) != computer) { + if( ComputerCraft.serverComputerRegistry.get( computer.getInstanceID() ) != computer ) + { return false; } // If we're a command computer then ensure we're in creative - return computer.getFamily() != ComputerFamily.COMMAND || TileCommandComputer.isUsable(player); - } - - @Nullable - @Override - public IComputer getComputer() { - return this.computer; - } - - @Override - public boolean canUse(PlayerEntity player) { - if (this.computer instanceof ServerComputer) { - ServerComputer serverComputer = (ServerComputer) this.computer; - - // If this computer no longer exists then discard it. - if (ComputerCraft.serverComputerRegistry.get(serverComputer.getInstanceID()) != serverComputer) { - return false; - } - - // If we're a command computer then ensure we're in creative - if (serverComputer.getFamily() == ComputerFamily.COMMAND) { - MinecraftServer server = player.getServer(); - if (server == null || !server.areCommandBlocksEnabled()) { - player.sendMessage(new TranslatableText("advMode.notEnabled"), false); - return false; - } else if (!player.isCreativeLevelTwoOp()) { - player.sendMessage(new TranslatableText("advMode.notAllowed"), false); - return false; - } - } + if( computer.getFamily() == ComputerFamily.COMMAND && !TileCommandComputer.isUsable( player ) ) + { + return false; } return true; } - @Nonnull - @Override - public InputState getInput() { - return this.input; + public int getWidth() + { + return width; } - @Override - public void close(PlayerEntity player) { - super.close(player); - this.input.close(); + public int getHeight() + { + return height; } } diff --git a/src/main/java/dan200/computercraft/shared/computer/items/ComputerItemFactory.java b/src/main/java/dan200/computercraft/shared/computer/items/ComputerItemFactory.java index 3be415994..6f5e96e2b 100644 --- a/src/main/java/dan200/computercraft/shared/computer/items/ComputerItemFactory.java +++ b/src/main/java/dan200/computercraft/shared/computer/items/ComputerItemFactory.java @@ -5,7 +5,7 @@ */ package dan200.computercraft.shared.computer.items; -import dan200.computercraft.shared.Registry; +import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.computer.blocks.TileComputer; import dan200.computercraft.shared.computer.core.ComputerFamily; import net.minecraft.item.ItemStack; @@ -28,11 +28,11 @@ public final class ComputerItemFactory switch( family ) { case NORMAL: - return Registry.ModItems.COMPUTER_NORMAL.get().create( id, label ); + return ComputerCraftRegistry.ModItems.COMPUTER_NORMAL.create( id, label ); case ADVANCED: - return Registry.ModItems.COMPUTER_ADVANCED.get().create( id, label ); + return ComputerCraftRegistry.ModItems.COMPUTER_ADVANCED.create( id, label ); case COMMAND: - return Registry.ModItems.COMPUTER_COMMAND.get().create( id, label ); + return ComputerCraftRegistry.ModItems.COMPUTER_COMMAND.create( id, label ); default: return ItemStack.EMPTY; } diff --git a/src/main/java/dan200/computercraft/shared/computer/recipe/ComputerFamilyRecipe.java b/src/main/java/dan200/computercraft/shared/computer/recipe/ComputerFamilyRecipe.java index 4d37488dd..f0a1bcc44 100644 --- a/src/main/java/dan200/computercraft/shared/computer/recipe/ComputerFamilyRecipe.java +++ b/src/main/java/dan200/computercraft/shared/computer/recipe/ComputerFamilyRecipe.java @@ -7,11 +7,11 @@ package dan200.computercraft.shared.computer.recipe; import com.google.gson.JsonObject; import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.util.BasicRecipeSerializer; import dan200.computercraft.shared.util.RecipeUtil; import net.minecraft.item.ItemStack; import net.minecraft.network.PacketByteBuf; import net.minecraft.recipe.Ingredient; +import net.minecraft.recipe.RecipeSerializer; import net.minecraft.util.Identifier; import net.minecraft.util.JsonHelper; import net.minecraft.util.collection.DefaultedList; @@ -32,8 +32,7 @@ public abstract class ComputerFamilyRecipe extends ComputerConvertRecipe return family; } - public abstract static class Serializer extends BasicRecipeSerializer - { + public abstract static class Serializer implements RecipeSerializer { protected abstract T create( Identifier identifier, String group, int width, int height, DefaultedList ingredients, ItemStack result, ComputerFamily family ); @Nonnull diff --git a/src/main/java/dan200/computercraft/shared/data/ConstantLootConditionSerializer.java b/src/main/java/dan200/computercraft/shared/data/ConstantLootConditionSerializer.java index 664628406..4085e6b8d 100644 --- a/src/main/java/dan200/computercraft/shared/data/ConstantLootConditionSerializer.java +++ b/src/main/java/dan200/computercraft/shared/data/ConstantLootConditionSerializer.java @@ -28,7 +28,7 @@ public final class ConstantLootConditionSerializer impl } @Override - public void func_230424_a_( @Nonnull JsonObject json, @Nonnull T object, @Nonnull JsonSerializationContext context ) + public void toJson( @Nonnull JsonObject json, @Nonnull T object, @Nonnull JsonSerializationContext context ) { } diff --git a/src/main/java/dan200/computercraft/shared/integration/jei/JEIComputerCraft.java b/src/main/java/dan200/computercraft/shared/integration/jei/JEIComputerCraft.java index 5457f2b2a..82425a802 100644 --- a/src/main/java/dan200/computercraft/shared/integration/jei/JEIComputerCraft.java +++ b/src/main/java/dan200/computercraft/shared/integration/jei/JEIComputerCraft.java @@ -10,7 +10,7 @@ import dan200.computercraft.api.pocket.IPocketUpgrade; import dan200.computercraft.api.turtle.ITurtleUpgrade; import dan200.computercraft.api.turtle.TurtleSide; import dan200.computercraft.shared.PocketUpgrades; -import dan200.computercraft.shared.Registry; +import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.TurtleUpgrades; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.media.items.ItemDisk; @@ -51,13 +51,13 @@ public class JEIComputerCraft implements IModPlugin @Override public void registerItemSubtypes( ISubtypeRegistration subtypeRegistry ) { - subtypeRegistry.registerSubtypeInterpreter( Registry.ModItems.TURTLE_NORMAL.get(), turtleSubtype ); - subtypeRegistry.registerSubtypeInterpreter( Registry.ModItems.TURTLE_ADVANCED.get(), turtleSubtype ); + subtypeRegistry.registerSubtypeInterpreter( ComputerCraftRegistry.ModItems.TURTLE_NORMAL.get(), turtleSubtype ); + subtypeRegistry.registerSubtypeInterpreter( ComputerCraftRegistry.ModItems.TURTLE_ADVANCED.get(), turtleSubtype ); - subtypeRegistry.registerSubtypeInterpreter( Registry.ModItems.POCKET_COMPUTER_NORMAL.get(), pocketSubtype ); - subtypeRegistry.registerSubtypeInterpreter( Registry.ModItems.POCKET_COMPUTER_ADVANCED.get(), pocketSubtype ); + subtypeRegistry.registerSubtypeInterpreter( ComputerCraftRegistry.ModItems.POCKET_COMPUTER_NORMAL.get(), pocketSubtype ); + subtypeRegistry.registerSubtypeInterpreter( ComputerCraftRegistry.ModItems.POCKET_COMPUTER_ADVANCED.get(), pocketSubtype ); - subtypeRegistry.registerSubtypeInterpreter( Registry.ModItems.DISK.get(), diskSubtype ); + subtypeRegistry.registerSubtypeInterpreter( ComputerCraftRegistry.ModItems.DISK.get(), diskSubtype ); } @Override diff --git a/src/main/java/dan200/computercraft/shared/media/items/ItemDisk.java b/src/main/java/dan200/computercraft/shared/media/items/ItemDisk.java index 84ab0e941..dce22792a 100644 --- a/src/main/java/dan200/computercraft/shared/media/items/ItemDisk.java +++ b/src/main/java/dan200/computercraft/shared/media/items/ItemDisk.java @@ -9,7 +9,7 @@ import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.api.filesystem.IMount; import dan200.computercraft.api.media.IMedia; -import dan200.computercraft.shared.Registry; +import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.common.IColouredItem; import dan200.computercraft.shared.util.Colour; import net.minecraft.client.item.TooltipContext; @@ -42,9 +42,9 @@ public class ItemDisk extends Item implements IMedia, IColouredItem @Nonnull public static ItemStack createFromIDAndColour( int id, String label, int colour ) { - ItemStack stack = new ItemStack( Registry.ModItems.DISK.get() ); + ItemStack stack = new ItemStack( ComputerCraftRegistry.ModItems.DISK ); setDiskID( stack, id ); - Registry.ModItems.DISK.get().setLabel( stack, label ); + ComputerCraftRegistry.ModItems.DISK.setLabel( stack, label ); IColouredItem.setColourBasic( stack, colour ); return stack; } @@ -73,12 +73,6 @@ public class ItemDisk extends Item implements IMedia, IColouredItem } } - @Override - public boolean doesSneakBypassUse( ItemStack stack, WorldView world, BlockPos pos, PlayerEntity player ) - { - return true; - } - @Override public String getLabel( @Nonnull ItemStack stack ) { diff --git a/src/main/java/dan200/computercraft/shared/media/items/ItemPrintout.java b/src/main/java/dan200/computercraft/shared/media/items/ItemPrintout.java index 597724bb5..c993f89ad 100644 --- a/src/main/java/dan200/computercraft/shared/media/items/ItemPrintout.java +++ b/src/main/java/dan200/computercraft/shared/media/items/ItemPrintout.java @@ -5,7 +5,7 @@ */ package dan200.computercraft.shared.media.items; -import dan200.computercraft.shared.Registry; +import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.common.ContainerHeldItem; import dan200.computercraft.shared.network.container.HeldItemContainerData; import net.minecraft.client.item.TooltipContext; @@ -63,7 +63,7 @@ public class ItemPrintout extends Item if( !world.isClient ) { new HeldItemContainerData( hand ) - .open( player, new ContainerHeldItem.Factory( Registry.ModContainers.PRINTOUT.get(), player.getStackInHand( hand ), hand ) ); + .open( player, new ContainerHeldItem.Factory( ComputerCraftRegistry.ModContainers.PRINTOUT, player.getStackInHand( hand ), hand ) ); } return new TypedActionResult<>( ActionResult.SUCCESS, player.getStackInHand( hand ) ); } @@ -100,19 +100,19 @@ public class ItemPrintout extends Item @Nonnull public static ItemStack createSingleFromTitleAndText( String title, String[] text, String[] colours ) { - return Registry.ModItems.PRINTED_PAGE.get().createFromTitleAndText( title, text, colours ); + return ComputerCraftRegistry.ModItems.PRINTED_PAGE.createFromTitleAndText( title, text, colours ); } @Nonnull public static ItemStack createMultipleFromTitleAndText( String title, String[] text, String[] colours ) { - return Registry.ModItems.PRINTED_PAGES.get().createFromTitleAndText( title, text, colours ); + return ComputerCraftRegistry.ModItems.PRINTED_PAGES.createFromTitleAndText( title, text, colours ); } @Nonnull public static ItemStack createBookFromTitleAndText( String title, String[] text, String[] colours ) { - return Registry.ModItems.PRINTED_BOOK.get().createFromTitleAndText( title, text, colours ); + return ComputerCraftRegistry.ModItems.PRINTED_BOOK.createFromTitleAndText( title, text, colours ); } public Type getType() diff --git a/src/main/java/dan200/computercraft/shared/media/items/ItemTreasureDisk.java b/src/main/java/dan200/computercraft/shared/media/items/ItemTreasureDisk.java index 692f30f5c..48499282f 100644 --- a/src/main/java/dan200/computercraft/shared/media/items/ItemTreasureDisk.java +++ b/src/main/java/dan200/computercraft/shared/media/items/ItemTreasureDisk.java @@ -9,7 +9,7 @@ import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.api.filesystem.IMount; import dan200.computercraft.api.media.IMedia; import dan200.computercraft.core.filesystem.SubMount; -import dan200.computercraft.shared.Registry; +import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.util.Colour; import net.minecraft.client.item.TooltipContext; import net.minecraft.entity.player.PlayerEntity; @@ -51,12 +51,6 @@ public class ItemTreasureDisk extends Item implements IMedia if( !label.isEmpty() ) list.add( new LiteralText( label ) ); } - @Override - public boolean doesSneakBypassUse( @Nonnull ItemStack stack, WorldView world, BlockPos pos, PlayerEntity player ) - { - return true; - } - @Override public String getLabel( @Nonnull ItemStack stack ) { @@ -91,7 +85,7 @@ public class ItemTreasureDisk extends Item implements IMedia public static ItemStack create( String subPath, int colourIndex ) { - ItemStack result = new ItemStack( Registry.ModItems.TREASURE_DISK.get() ); + ItemStack result = new ItemStack( ComputerCraftRegistry.ModItems.TREASURE_DISK ); CompoundTag nbt = result.getOrCreateTag(); nbt.putString( NBT_SUB_PATH, subPath ); diff --git a/src/main/java/dan200/computercraft/shared/media/items/RecordMedia.java b/src/main/java/dan200/computercraft/shared/media/items/RecordMedia.java index f05d487d2..26d1a02a8 100644 --- a/src/main/java/dan200/computercraft/shared/media/items/RecordMedia.java +++ b/src/main/java/dan200/computercraft/shared/media/items/RecordMedia.java @@ -12,9 +12,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.item.MusicDiscItem; import net.minecraft.sound.SoundEvent; import net.minecraft.text.TranslatableText; -import net.minecraftforge.fml.common.ObfuscationReflectionHelper; -import net.minecraftforge.fml.common.ObfuscationReflectionHelper.UnableToAccessFieldException; -import net.minecraftforge.fml.common.ObfuscationReflectionHelper.UnableToFindFieldException; import javax.annotation.Nonnull; @@ -47,17 +44,6 @@ public final class RecordMedia implements IMedia @Override public SoundEvent getAudio( @Nonnull ItemStack stack ) { - Item item = stack.getItem(); - if( !(item instanceof MusicDiscItem) ) return null; - - try - { - return ObfuscationReflectionHelper.getPrivateValue( MusicDiscItem.class, (MusicDiscItem) item, "field_185076_b" ); - } - catch( UnableToAccessFieldException | UnableToFindFieldException e ) - { - ComputerCraft.log.error( "Cannot get disk sound", e ); - return null; - } + return ((MusicDiscItem) stack.getItem()).getSound(); } } diff --git a/src/main/java/dan200/computercraft/shared/media/recipes/DiskRecipe.java b/src/main/java/dan200/computercraft/shared/media/recipes/DiskRecipe.java index e8dcc3787..6b4b4e3e5 100644 --- a/src/main/java/dan200/computercraft/shared/media/recipes/DiskRecipe.java +++ b/src/main/java/dan200/computercraft/shared/media/recipes/DiskRecipe.java @@ -67,7 +67,7 @@ public class DiskRecipe extends SpecialCraftingRecipe @Nonnull @Override - public ItemStack getCraftingResult( @Nonnull CraftingInventory inv ) + public ItemStack craft( @Nonnull CraftingInventory inv ) { ColourTracker tracker = new ColourTracker(); diff --git a/src/main/java/dan200/computercraft/shared/media/recipes/PrintoutRecipe.java b/src/main/java/dan200/computercraft/shared/media/recipes/PrintoutRecipe.java index 3f567b9bc..f71586d51 100644 --- a/src/main/java/dan200/computercraft/shared/media/recipes/PrintoutRecipe.java +++ b/src/main/java/dan200/computercraft/shared/media/recipes/PrintoutRecipe.java @@ -45,12 +45,12 @@ public final class PrintoutRecipe extends SpecialCraftingRecipe @Override public boolean matches( @Nonnull CraftingInventory inventory, @Nonnull World world ) { - return !getCraftingResult( inventory ).isEmpty(); + return !craft( inventory ).isEmpty(); } @Nonnull @Override - public ItemStack getCraftingResult( @Nonnull CraftingInventory inventory ) + public ItemStack craft( @Nonnull CraftingInventory inventory ) { // See if we match the recipe, and extract the input disk ID and dye colour int numPages = 0; diff --git a/src/main/java/dan200/computercraft/shared/mixed/MixedFirstPersonRenderer.java b/src/main/java/dan200/computercraft/shared/mixed/MixedFirstPersonRenderer.java new file mode 100644 index 000000000..c420d8cc4 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/mixed/MixedFirstPersonRenderer.java @@ -0,0 +1,17 @@ +/* + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.mixed; + +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.Arm; + +public interface MixedFirstPersonRenderer { + void renderArmFirstPerson_CC(MatrixStack stack, VertexConsumerProvider consumerProvider, int light, float equip, float swing, Arm hand); + + float getMapAngleFromPitch_CC(float pitch); +} diff --git a/src/main/java/dan200/computercraft/shared/mixin/MixinBlock.java b/src/main/java/dan200/computercraft/shared/mixin/MixinBlock.java new file mode 100644 index 000000000..91a65c66a --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/mixin/MixinBlock.java @@ -0,0 +1,33 @@ +/* + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.mixin; + +import dan200.computercraft.shared.util.DropConsumer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.block.Block; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +/** + * @see Block#dropStack(World, BlockPos, ItemStack) + */ +@Mixin (Block.class) +public class MixinBlock { + @Inject (method = "dropStack", + at = @At (value = "INVOKE", target = "Lnet/minecraft/world/World;spawnEntity(Lnet/minecraft/entity/Entity;)Z"), + cancellable = true) + private static void dropStack(World world, BlockPos pos, ItemStack stack, CallbackInfo callbackInfo) { + if (DropConsumer.onHarvestDrops(world, pos, stack)) { + callbackInfo.cancel(); + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/mixin/MixinEntity.java b/src/main/java/dan200/computercraft/shared/mixin/MixinEntity.java new file mode 100644 index 000000000..18455bc6f --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/mixin/MixinEntity.java @@ -0,0 +1,32 @@ +/* + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.mixin; + +import dan200.computercraft.shared.util.DropConsumer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.ItemEntity; +import net.minecraft.item.ItemStack; + +/** + * @see Entity#dropStack(ItemStack, float) + */ +@Mixin (Entity.class) +public class MixinEntity { + @Inject (method = "dropStack(Lnet/minecraft/item/ItemStack;F)Lnet/minecraft/entity/ItemEntity;", + at = @At (value = "INVOKE", target = "Lnet/minecraft/world/World;spawnEntity(Lnet/minecraft/entity/Entity;)Z"), + cancellable = true) + public void dropStack(ItemStack stack, float height, CallbackInfoReturnable callbackInfo) { + if (DropConsumer.onLivingDrops((Entity) (Object) this, stack)) { + callbackInfo.setReturnValue(null); + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/mixin/MixinHeldItemRenderer.java b/src/main/java/dan200/computercraft/shared/mixin/MixinHeldItemRenderer.java new file mode 100644 index 000000000..6d67b2a11 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/mixin/MixinHeldItemRenderer.java @@ -0,0 +1,65 @@ +/* + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.mixin; + +import dan200.computercraft.client.render.ItemPocketRenderer; +import dan200.computercraft.client.render.ItemPrintoutRenderer; +import dan200.computercraft.shared.media.items.ItemPrintout; +import dan200.computercraft.shared.mixed.MixedFirstPersonRenderer; +import dan200.computercraft.shared.pocket.items.ItemPocketComputer; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.util.math.MatrixStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.client.network.AbstractClientPlayerEntity; +import net.minecraft.client.render.item.HeldItemRenderer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Arm; +import net.minecraft.util.Hand; + +@Mixin (HeldItemRenderer.class) +@Environment(EnvType.CLIENT) +public class MixinHeldItemRenderer implements MixedFirstPersonRenderer { + @Override + public void renderArmFirstPerson_CC(MatrixStack stack, VertexConsumerProvider consumerProvider, int light, float equip, float swing, Arm hand) { + this.renderArmHoldingItem(stack, consumerProvider, light, equip, swing, hand); + } + + @Shadow + private void renderArmHoldingItem(MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, float equipProgress, float swingProgress, Arm arm) { + } + + @Override + public float getMapAngleFromPitch_CC(float pitch) { + return this.getMapAngle(pitch); + } + + @Shadow + private float getMapAngle(float pitch) { + return 0; + } + + @Inject (method = "Lnet/minecraft/client/render/item/HeldItemRenderer;renderFirstPersonItem(Lnet/minecraft/client/network/AbstractClientPlayerEntity;FFLnet/minecraft/util/Hand;FLnet/minecraft/item/ItemStack;FLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V", + at = @At ("HEAD"), + cancellable = true) + public void renderFirstPersonItem_Injected(AbstractClientPlayerEntity player, float var2, float pitch, Hand hand, float swingProgress, + ItemStack stack, float equipProgress, MatrixStack matrixStack, VertexConsumerProvider provider, int light, CallbackInfo callback) { + if (stack.getItem() instanceof ItemPrintout) { + ItemPrintoutRenderer.INSTANCE.renderItemFirstPerson(matrixStack, provider, light, hand, pitch, equipProgress, swingProgress, stack); + callback.cancel(); + } else if (stack.getItem() instanceof ItemPocketComputer) { + ItemPocketRenderer.INSTANCE.renderItemFirstPerson(matrixStack, provider, light, hand, pitch, equipProgress, swingProgress, stack); + callback.cancel(); + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/mixin/MixinItemFrameEntityRenderer.java b/src/main/java/dan200/computercraft/shared/mixin/MixinItemFrameEntityRenderer.java new file mode 100644 index 000000000..847a98b99 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/mixin/MixinItemFrameEntityRenderer.java @@ -0,0 +1,35 @@ +/* + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.mixin; + +import dan200.computercraft.client.render.ItemPrintoutRenderer; +import dan200.computercraft.shared.media.items.ItemPrintout; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.util.math.MatrixStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.client.render.entity.ItemFrameEntityRenderer; +import net.minecraft.entity.decoration.ItemFrameEntity; +import net.minecraft.item.ItemStack; + +@Mixin (ItemFrameEntityRenderer.class) +@Environment(EnvType.CLIENT) +public class MixinItemFrameEntityRenderer { + @Inject (method = "render", at = @At ("HEAD"), cancellable = true) + private void renderItem_Injected(ItemFrameEntity itemFrameEntity, float f, float g, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int i, CallbackInfo info) { + ItemStack stack = itemFrameEntity.getHeldItemStack(); + if (stack.getItem() instanceof ItemPrintout) { + ItemPrintoutRenderer.INSTANCE.renderInFrame(matrixStack, vertexConsumerProvider, stack); + info.cancel(); + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/mixin/MixinMinecraftGame.java b/src/main/java/dan200/computercraft/shared/mixin/MixinMinecraftGame.java new file mode 100644 index 000000000..7f5b5c4ab --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/mixin/MixinMinecraftGame.java @@ -0,0 +1,23 @@ +/* + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.mixin; + +import dan200.computercraft.client.FrameInfo; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.client.MinecraftClient; + +@Mixin (MinecraftClient.class) +public abstract class MixinMinecraftGame { + @Inject (method = "render", at = @At ("HEAD")) + private void onRender(CallbackInfo info) { + FrameInfo.onRenderFrame(); + } +} diff --git a/src/main/java/dan200/computercraft/shared/mixin/MixinScreen.java b/src/main/java/dan200/computercraft/shared/mixin/MixinScreen.java new file mode 100644 index 000000000..f1e7529de --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/mixin/MixinScreen.java @@ -0,0 +1,28 @@ +/* + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.mixin; + +import dan200.computercraft.shared.command.CommandCopy; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.client.gui.screen.Screen; + +@Mixin (Screen.class) +@Environment(EnvType.CLIENT) +public class MixinScreen { + @Inject (method = "sendMessage(Ljava/lang/String;Z)V", at = @At ("HEAD"), cancellable = true) + public void sendClientCommand(String message, boolean add, CallbackInfo info) { + if (CommandCopy.onClientSendMessage(message)) { + info.cancel(); + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/mixin/MixinServerWorld.java b/src/main/java/dan200/computercraft/shared/mixin/MixinServerWorld.java new file mode 100644 index 000000000..6cb0fbf73 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/mixin/MixinServerWorld.java @@ -0,0 +1,29 @@ +/* + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.mixin; + +import dan200.computercraft.shared.util.DropConsumer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import net.minecraft.entity.Entity; +import net.minecraft.server.world.ServerWorld; + +/** + * @see ServerWorld#spawnEntity(Entity) + */ +@Mixin (ServerWorld.class) +public class MixinServerWorld { + @Inject (method = "spawnEntity", at = @At ("HEAD"), cancellable = true) + public void spawnEntity(Entity entity, CallbackInfoReturnable callbackInfo) { + if (DropConsumer.onEntitySpawn(entity)) { + callbackInfo.setReturnValue(false); + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/mixin/MixinWorld.java b/src/main/java/dan200/computercraft/shared/mixin/MixinWorld.java new file mode 100644 index 000000000..d6465034d --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/mixin/MixinWorld.java @@ -0,0 +1,54 @@ +/* + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.mixin; + +import java.util.Collection; + +import javax.annotation.Nullable; + +import dan200.computercraft.shared.common.TileGeneric; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +/** + * Horrible bodge to ensure a {@link BlockEntity}'s world is always present when setting a TE during another TE's tick. + * + * Forge does this, this is just a bodge to get Fabric in line with that behaviour. + */ +@Mixin (World.class) +public class MixinWorld { + @Shadow protected boolean iteratingTickingBlockEntities; + + @Inject (method = "setBlockEntity", at = @At ("HEAD")) + public void setBlockEntity(BlockPos pos, @Nullable BlockEntity entity, CallbackInfo info) { + if (!World.isHeightInvalid(pos) && entity != null && !entity.isRemoved() && this.iteratingTickingBlockEntities) { + setWorld(entity, this); + } + } + + private static void setWorld(BlockEntity entity, Object world) { + if (entity.getWorld() != world && entity instanceof TileGeneric) { + entity.setLocation((World) world, entity.getPos()); + } + } + + @Inject (method = "addBlockEntities", at = @At ("HEAD")) + public void addBlockEntities(Collection entities, CallbackInfo info) { + if (this.iteratingTickingBlockEntities) { + for (BlockEntity entity : entities) { + setWorld(entity, this); + } + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/mixin/MixinWorldRenderer.java b/src/main/java/dan200/computercraft/shared/mixin/MixinWorldRenderer.java new file mode 100644 index 000000000..53c26a6b2 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/mixin/MixinWorldRenderer.java @@ -0,0 +1,37 @@ +/* + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.shared.mixin; + +import dan200.computercraft.client.render.CableHighlightRenderer; +import dan200.computercraft.client.render.MonitorHighlightRenderer; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.block.BlockState; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.Entity; +import net.minecraft.util.math.BlockPos; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.client.render.Camera; +import net.minecraft.client.render.WorldRenderer; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.hit.HitResult; + +@Mixin (WorldRenderer.class) +@Environment(EnvType.CLIENT) +public class MixinWorldRenderer { + @Inject (method = "drawBlockOutline", cancellable = true, at = @At ("HEAD")) + public void drawBlockOutline(MatrixStack matrixStack, VertexConsumer vertexConsumer, Entity entity, double d, double e, double f, BlockPos blockPos, BlockState blockState, CallbackInfo info) { + if (CableHighlightRenderer.drawHighlight(matrixStack, vertexConsumer, entity, d, e, f, blockPos, blockState) || MonitorHighlightRenderer.drawHighlight(matrixStack, vertexConsumer, entity, d, e, f, blockPos, blockState)) { + info.cancel(); + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/network/Containers.java b/src/main/java/dan200/computercraft/shared/network/Containers.java deleted file mode 100644 index 7d806a023..000000000 --- a/src/main/java/dan200/computercraft/shared/network/Containers.java +++ /dev/null @@ -1,109 +0,0 @@ -package dan200.computercraft.shared.network; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.mixin.ScreenHandlerTypeAccessor; -import dan200.computercraft.shared.common.ContainerHeldItem; -import dan200.computercraft.shared.computer.blocks.TileComputer; -import dan200.computercraft.shared.computer.core.ServerComputer; -import dan200.computercraft.shared.computer.inventory.ContainerComputer; -import dan200.computercraft.shared.computer.inventory.ContainerViewComputer; -import dan200.computercraft.shared.media.items.ItemPrintout; -import dan200.computercraft.shared.network.container.ContainerType; -import dan200.computercraft.shared.network.container.PocketComputerContainerType; -import dan200.computercraft.shared.network.container.PrintoutContainerType; -import dan200.computercraft.shared.network.container.TileEntityContainerType; -import dan200.computercraft.shared.network.container.ViewComputerContainerType; -import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive; -import dan200.computercraft.shared.peripheral.diskdrive.TileDiskDrive; -import dan200.computercraft.shared.peripheral.printer.ContainerPrinter; -import dan200.computercraft.shared.peripheral.printer.TilePrinter; -import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer; -import dan200.computercraft.shared.pocket.items.ItemPocketComputer; -import dan200.computercraft.shared.turtle.blocks.TileTurtle; -import dan200.computercraft.shared.turtle.inventory.ContainerTurtle; - -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.screen.ScreenHandlerType; -import net.minecraft.util.Hand; - -public final class Containers -{ - private Containers() - { - } - - public static void openDiskDriveGUI(PlayerEntity player, TileDiskDrive drive ) - { - TileEntityContainerType.diskDrive( drive.getPos() ).open( player ); - } - - public static void openComputerGUI( PlayerEntity player, TileComputer computer ) - { - computer.createServerComputer().sendTerminalState( player ); - TileEntityContainerType.computer( computer.getPos() ).open( player ); - } - - public static void openPrinterGUI( PlayerEntity player, TilePrinter printer ) - { - TileEntityContainerType.printer( printer.getPos() ).open( player ); - } - - public static void openTurtleGUI( PlayerEntity player, TileTurtle turtle ) - { - turtle.createServerComputer().sendTerminalState( player ); - TileEntityContainerType.turtle( turtle.getPos() ).open( player ); - } - - public static void openPrintoutGUI( PlayerEntity player, Hand hand ) - { - ItemStack stack = player.getStackInHand( hand ); - Item item = stack.getItem(); - if (!(item instanceof ItemPrintout)) { - return; - } - - new PrintoutContainerType( hand ).open( player ); - } - - public static void openPocketComputerGUI( PlayerEntity player, Hand hand ) - { - ItemStack stack = player.getStackInHand(hand ); - Item item = stack.getItem(); - if (!(item instanceof ItemPocketComputer)) { - return; - } - - ServerComputer computer = ItemPocketComputer.getServerComputer(stack ); - if (computer != null) { - computer.sendTerminalState(player); - } - - new PocketComputerContainerType( hand ).open( player ); - } - - public static void openComputerGUI( PlayerEntity player, ServerComputer computer ) - { - computer.sendTerminalState( player ); - new ViewComputerContainerType( computer ).open( player ); - } - - public static void setup() - { - ContainerType.register(TileEntityContainerType::computer, (id, packet, player ) -> - new ContainerComputer(id, (TileComputer) packet.getTileEntity(player ) ) ); - ContainerType.register( TileEntityContainerType::turtle, ( id, packet, player ) -> { - TileTurtle turtle = (TileTurtle) packet.getTileEntity( player ); - return new ContainerTurtle(id, player.inventory, turtle.getAccess(), turtle.getServerComputer() ); - } ); - ContainerType.register(TileEntityContainerType::diskDrive, (id, packet, player ) -> - new ContainerDiskDrive(id, player.inventory, (TileDiskDrive) packet.getTileEntity(player ) ) ); - ContainerType.register( TileEntityContainerType::printer, ( id, packet, player ) -> - new ContainerPrinter(id, player.inventory, (TilePrinter) packet.getTileEntity(player ) ) ); - - ContainerType.register(PocketComputerContainerType::new, (id, packet, player ) -> new ContainerPocketComputer(id, player, packet.hand ) ); - ContainerType.register(PrintoutContainerType::new, (id, packet, player ) -> new ContainerHeldItem(id, player, packet.hand ) ); - ContainerType.register(ViewComputerContainerType::new, (id, packet, player ) -> new ContainerViewComputer(id, ComputerCraft.serverComputerRegistry.get(packet.instanceId ) ) ); - } -} diff --git a/src/main/java/dan200/computercraft/shared/network/NetworkHandler.java b/src/main/java/dan200/computercraft/shared/network/NetworkHandler.java index f741bd517..f40c29d93 100644 --- a/src/main/java/dan200/computercraft/shared/network/NetworkHandler.java +++ b/src/main/java/dan200/computercraft/shared/network/NetworkHandler.java @@ -9,26 +9,43 @@ import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.shared.network.client.*; import dan200.computercraft.shared.network.server.*; +import io.netty.buffer.Unpooled; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.network.ClientSidePacketRegistry; +import net.fabricmc.fabric.api.network.PacketContext; +import net.fabricmc.fabric.api.network.ServerSidePacketRegistry; +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.client.MinecraftClient; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.network.PacketByteBuf; +import net.minecraft.network.packet.c2s.play.CustomPayloadC2SPacket; +import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket; +import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.Identifier; import net.minecraft.util.math.Vec3d; +import net.minecraft.util.registry.BuiltinRegistries; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryKey; import net.minecraft.world.World; import net.minecraft.world.chunk.WorldChunk; -import net.minecraftforge.fml.network.NetworkDirection; -import net.minecraftforge.fml.network.NetworkEvent; -import net.minecraftforge.fml.network.NetworkRegistry; -import net.minecraftforge.fml.network.PacketDistributor; -import net.minecraftforge.fml.network.simple.SimpleChannel; -import net.minecraftforge.fml.server.ServerLifecycleHooks; +import net.minecraft.world.dimension.DimensionType; +import java.util.function.BiConsumer; import java.util.function.Function; import java.util.function.Supplier; public final class NetworkHandler { - public static SimpleChannel network; + private static final Int2ObjectMap> packetReaders = new Int2ObjectOpenHashMap<>(); + private static final Object2IntMap> packetIds = new Object2IntOpenHashMap<>(); + + private static final Identifier ID = new Identifier(ComputerCraft.MOD_ID, "main"); private NetworkHandler() { @@ -36,101 +53,98 @@ public final class NetworkHandler public static void setup() { - String version = ComputerCraftAPI.getInstalledVersion(); - network = NetworkRegistry.ChannelBuilder.named( new Identifier( ComputerCraft.MOD_ID, "network" ) ) - .networkProtocolVersion( () -> version ) - .clientAcceptedVersions( version::equals ).serverAcceptedVersions( version::equals ) - .simpleChannel(); + ServerSidePacketRegistry.INSTANCE.register(ID, NetworkHandler::receive); + if (FabricLoader.getInstance() + .getEnvironmentType() == EnvType.CLIENT) { + ClientSidePacketRegistry.INSTANCE.register(ID, NetworkHandler::receive); + } // Server messages - registerMainThread( 0, NetworkDirection.PLAY_TO_SERVER, ComputerActionServerMessage::new ); - registerMainThread( 1, NetworkDirection.PLAY_TO_SERVER, QueueEventServerMessage::new ); - registerMainThread( 2, NetworkDirection.PLAY_TO_SERVER, RequestComputerMessage::new ); - registerMainThread( 3, NetworkDirection.PLAY_TO_SERVER, KeyEventServerMessage::new ); - registerMainThread( 4, NetworkDirection.PLAY_TO_SERVER, MouseEventServerMessage::new ); + registerMainThread(0, ComputerActionServerMessage::new); + registerMainThread(1, QueueEventServerMessage::new); + registerMainThread(2, RequestComputerMessage::new); + registerMainThread(3, KeyEventServerMessage::new); + registerMainThread(4, MouseEventServerMessage::new); // Client messages - registerMainThread( 10, NetworkDirection.PLAY_TO_CLIENT, ChatTableClientMessage::new ); - registerMainThread( 11, NetworkDirection.PLAY_TO_CLIENT, ComputerDataClientMessage::new ); - registerMainThread( 12, NetworkDirection.PLAY_TO_CLIENT, ComputerDeletedClientMessage::new ); - registerMainThread( 13, NetworkDirection.PLAY_TO_CLIENT, ComputerTerminalClientMessage::new ); - registerMainThread( 14, NetworkDirection.PLAY_TO_CLIENT, PlayRecordClientMessage.class, PlayRecordClientMessage::new ); - registerMainThread( 15, NetworkDirection.PLAY_TO_CLIENT, MonitorClientMessage.class, MonitorClientMessage::new ); + registerMainThread(10, ChatTableClientMessage::new); + registerMainThread(11, ComputerDataClientMessage::new); + registerMainThread(12, ComputerDeletedClientMessage::new); + registerMainThread(13, ComputerTerminalClientMessage::new); + registerMainThread(14, PlayRecordClientMessage.class, PlayRecordClientMessage::new); } - public static void sendToPlayer( PlayerEntity player, NetworkMessage packet ) - { - network.sendTo( packet, ((ServerPlayerEntity) player).networkHandler.connection, NetworkDirection.PLAY_TO_CLIENT ); - } - - public static void sendToAllPlayers( NetworkMessage packet ) - { - for( ServerPlayerEntity player : ServerLifecycleHooks.getCurrentServer().getPlayerManager().getPlayerList() ) - { - sendToPlayer( player, packet ); - } - } - - public static void sendToServer( NetworkMessage packet ) - { - network.sendToServer( packet ); - } - - public static void sendToAllAround( NetworkMessage packet, World world, Vec3d pos, double range ) - { - PacketDistributor.TargetPoint target = new PacketDistributor.TargetPoint( pos.x, pos.y, pos.z, range, world.getRegistryKey() ); - network.send( PacketDistributor.NEAR.with( () -> target ), packet ); - } - - public static void sendToAllTracking( NetworkMessage packet, WorldChunk chunk ) - { - network.send( PacketDistributor.TRACKING_CHUNK.with( () -> chunk ), packet ); + private static void receive(PacketContext context, PacketByteBuf buffer) { + int type = buffer.readByte(); + packetReaders.get(type) + .accept(context, buffer); } /** - * /** - * Register packet, and a thread-unsafe handler for it. + * /** Register packet, and a thread-unsafe handler for it. * - * @param The type of the packet to send. - * @param id The identifier for this packet type. - * @param direction A network direction which will be asserted before any processing of this message occurs. - * @param factory The factory for this type of packet. + * @param id The identifier for this packet type + * @param factory The factory for this type of packet. */ - private static void registerMainThread( int id, NetworkDirection direction, Supplier factory ) - { - registerMainThread( id, direction, getType( factory ), buf -> { + private static void registerMainThread(int id, Supplier factory) { + registerMainThread(id, getType(factory), buf -> { T instance = factory.get(); - instance.fromBytes( buf ); + instance.fromBytes(buf); return instance; - } ); + }); } /** - * /** - * Register packet, and a thread-unsafe handler for it. + * /** Register packet, and a thread-unsafe handler for it. * - * @param The type of the packet to send. - * @param type The class of the type of packet to send. - * @param id The identifier for this packet type. - * @param direction A network direction which will be asserted before any processing of this message occurs - * @param decoder The factory for this type of packet. + * @param id The identifier for this packet type + * @param decoder The factory for this type of packet. */ - private static void registerMainThread( int id, NetworkDirection direction, Class type, Function decoder ) - { - network.messageBuilder( type, id, direction ) - .encoder( NetworkMessage::toBytes ) - .decoder( decoder ) - .consumer( ( packet, contextSup ) -> { - NetworkEvent.Context context = contextSup.get(); - context.enqueueWork( () -> packet.handle( context ) ); - context.setPacketHandled( true ); - } ) - .add(); + private static void registerMainThread(int id, Class type, Function decoder) { + packetIds.put(type, id); + packetReaders.put(id, (context, buf) -> { + T result = decoder.apply(buf); + context.getTaskQueue() + .execute(() -> result.handle(context)); + }); } - @SuppressWarnings( "unchecked" ) - private static Class getType( Supplier supplier ) - { - return (Class) supplier.get().getClass(); + @SuppressWarnings ("unchecked") + private static Class getType(Supplier supplier) { + return (Class) supplier.get() + .getClass(); + } + + public static void sendToPlayer(PlayerEntity player, NetworkMessage packet) { + ((ServerPlayerEntity) player).networkHandler.sendPacket(new CustomPayloadS2CPacket(ID, encode(packet))); + } + + private static PacketByteBuf encode(NetworkMessage message) { + PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer()); + buf.writeByte(packetIds.getInt(message.getClass())); + message.toBytes(buf); + return buf; + } + + public static void sendToAllPlayers(MinecraftServer server, NetworkMessage packet) { + server.getPlayerManager() + .sendToAll(new CustomPayloadS2CPacket(ID, encode(packet))); + } + + @Environment(EnvType.CLIENT) + public static void sendToServer(NetworkMessage packet) { + MinecraftClient.getInstance().player.networkHandler.sendPacket(new CustomPayloadC2SPacket(ID, encode(packet))); + } + + public static void sendToAllAround(NetworkMessage packet, World world, Vec3d pos, double range) { + world.getServer() + .getPlayerManager() + .sendToAround(null, + pos.x, + pos.y, + pos.z, + range, + world.getRegistryKey(), + new CustomPayloadS2CPacket(ID, encode(packet))); } } diff --git a/src/main/java/dan200/computercraft/shared/network/NetworkMessage.java b/src/main/java/dan200/computercraft/shared/network/NetworkMessage.java index a4fb93bcb..8a613d3dd 100644 --- a/src/main/java/dan200/computercraft/shared/network/NetworkMessage.java +++ b/src/main/java/dan200/computercraft/shared/network/NetworkMessage.java @@ -5,11 +5,10 @@ */ package dan200.computercraft.shared.network; -import javax.annotation.Nonnull; - +import net.fabricmc.fabric.api.network.PacketContext; import net.minecraft.network.PacketByteBuf; -import net.fabricmc.fabric.api.network.PacketContext; +import javax.annotation.Nonnull; /** * The base interface for any message which will be sent to the client or server. diff --git a/src/main/java/dan200/computercraft/shared/network/client/ChatTableClientMessage.java b/src/main/java/dan200/computercraft/shared/network/client/ChatTableClientMessage.java index aa88660bc..a9cd136a4 100644 --- a/src/main/java/dan200/computercraft/shared/network/client/ChatTableClientMessage.java +++ b/src/main/java/dan200/computercraft/shared/network/client/ChatTableClientMessage.java @@ -10,11 +10,9 @@ import dan200.computercraft.shared.command.text.TableBuilder; import dan200.computercraft.shared.network.NetworkMessage; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.network.PacketContext; import net.minecraft.network.PacketByteBuf; import net.minecraft.text.Text; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.fml.network.NetworkEvent; import javax.annotation.Nonnull; @@ -83,7 +81,7 @@ public class ChatTableClientMessage implements NetworkMessage @Override @Environment(EnvType.CLIENT) - public void handle( NetworkEvent.Context context ) + public void handle( PacketContext context ) { ClientTableFormatter.INSTANCE.display( table ); } diff --git a/src/main/java/dan200/computercraft/shared/network/client/ComputerDataClientMessage.java b/src/main/java/dan200/computercraft/shared/network/client/ComputerDataClientMessage.java index 1f7db362a..2e58dbc87 100644 --- a/src/main/java/dan200/computercraft/shared/network/client/ComputerDataClientMessage.java +++ b/src/main/java/dan200/computercraft/shared/network/client/ComputerDataClientMessage.java @@ -7,9 +7,9 @@ package dan200.computercraft.shared.network.client; import dan200.computercraft.shared.computer.core.ComputerState; import dan200.computercraft.shared.computer.core.ServerComputer; +import net.fabricmc.fabric.api.network.PacketContext; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.PacketByteBuf; -import net.minecraftforge.fml.network.NetworkEvent; import javax.annotation.Nonnull; @@ -49,7 +49,7 @@ public class ComputerDataClientMessage extends ComputerClientMessage } @Override - public void handle( NetworkEvent.Context context ) + public void handle( PacketContext context ) { getComputer().setState( state, userData ); } diff --git a/src/main/java/dan200/computercraft/shared/network/client/ComputerDeletedClientMessage.java b/src/main/java/dan200/computercraft/shared/network/client/ComputerDeletedClientMessage.java index 5c42aa73e..14a027d9b 100644 --- a/src/main/java/dan200/computercraft/shared/network/client/ComputerDeletedClientMessage.java +++ b/src/main/java/dan200/computercraft/shared/network/client/ComputerDeletedClientMessage.java @@ -6,7 +6,7 @@ package dan200.computercraft.shared.network.client; import dan200.computercraft.ComputerCraft; -import net.minecraftforge.fml.network.NetworkEvent; +import net.fabricmc.fabric.api.network.PacketContext; public class ComputerDeletedClientMessage extends ComputerClientMessage { @@ -20,7 +20,7 @@ public class ComputerDeletedClientMessage extends ComputerClientMessage } @Override - public void handle( NetworkEvent.Context context ) + public void handle( PacketContext context ) { ComputerCraft.clientComputerRegistry.remove( getInstanceId() ); } diff --git a/src/main/java/dan200/computercraft/shared/network/client/ComputerTerminalClientMessage.java b/src/main/java/dan200/computercraft/shared/network/client/ComputerTerminalClientMessage.java index e330e1f48..da59bd293 100644 --- a/src/main/java/dan200/computercraft/shared/network/client/ComputerTerminalClientMessage.java +++ b/src/main/java/dan200/computercraft/shared/network/client/ComputerTerminalClientMessage.java @@ -5,8 +5,8 @@ */ package dan200.computercraft.shared.network.client; +import net.fabricmc.fabric.api.network.PacketContext; import net.minecraft.network.PacketByteBuf; -import net.minecraftforge.fml.network.NetworkEvent; import javax.annotation.Nonnull; @@ -39,7 +39,7 @@ public class ComputerTerminalClientMessage extends ComputerClientMessage } @Override - public void handle( NetworkEvent.Context context ) + public void handle( PacketContext context ) { getComputer().read( state ); } diff --git a/src/main/java/dan200/computercraft/shared/network/client/MonitorClientMessage.java b/src/main/java/dan200/computercraft/shared/network/client/MonitorClientMessage.java index b3849c1b2..d738d3a2e 100644 --- a/src/main/java/dan200/computercraft/shared/network/client/MonitorClientMessage.java +++ b/src/main/java/dan200/computercraft/shared/network/client/MonitorClientMessage.java @@ -8,12 +8,12 @@ package dan200.computercraft.shared.network.client; import dan200.computercraft.shared.network.NetworkMessage; import dan200.computercraft.shared.peripheral.monitor.TileMonitor; +import net.fabricmc.fabric.api.network.PacketContext; import net.minecraft.block.entity.BlockEntity; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.network.PacketByteBuf; import net.minecraft.util.math.BlockPos; -import net.minecraftforge.fml.network.NetworkEvent; import javax.annotation.Nonnull; @@ -42,7 +42,7 @@ public class MonitorClientMessage implements NetworkMessage } @Override - public void handle( NetworkEvent.Context context ) + public void handle( PacketContext context ) { ClientPlayerEntity player = MinecraftClient.getInstance().player; if( player == null || player.world == null ) return; diff --git a/src/main/java/dan200/computercraft/shared/network/client/PlayRecordClientMessage.java b/src/main/java/dan200/computercraft/shared/network/client/PlayRecordClientMessage.java index 932ca9c76..b64c5efdc 100644 --- a/src/main/java/dan200/computercraft/shared/network/client/PlayRecordClientMessage.java +++ b/src/main/java/dan200/computercraft/shared/network/client/PlayRecordClientMessage.java @@ -8,14 +8,13 @@ package dan200.computercraft.shared.network.client; import dan200.computercraft.shared.network.NetworkMessage; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.network.PacketContext; import net.minecraft.client.MinecraftClient; import net.minecraft.network.PacketByteBuf; import net.minecraft.sound.SoundEvent; import net.minecraft.text.LiteralText; import net.minecraft.util.math.BlockPos; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.fml.network.NetworkEvent; +import net.minecraft.util.registry.Registry; import javax.annotation.Nonnull; @@ -52,7 +51,7 @@ public class PlayRecordClientMessage implements NetworkMessage if( buf.readBoolean() ) { name = buf.readString( Short.MAX_VALUE ); - soundEvent = buf.readRegistryIdSafe( SoundEvent.class ); + soundEvent = Registry.SOUND_EVENT.get(buf.readIdentifier()); } else { @@ -73,16 +72,16 @@ public class PlayRecordClientMessage implements NetworkMessage { buf.writeBoolean( true ); buf.writeString( name ); - buf.writeRegistryId( soundEvent ); + buf.writeIdentifier( soundEvent.getId() ); } } @Override @Environment(EnvType.CLIENT) - public void handle( NetworkEvent.Context context ) + public void handle( PacketContext context ) { MinecraftClient mc = MinecraftClient.getInstance(); - mc.worldRenderer.playRecord( soundEvent, pos, null ); + mc.worldRenderer.playSong( soundEvent, pos ); if( name != null ) mc.inGameHud.setRecordPlayingOverlay( new LiteralText( name ) ); } } diff --git a/src/main/java/dan200/computercraft/shared/network/container/ComputerContainerData.java b/src/main/java/dan200/computercraft/shared/network/container/ComputerContainerData.java index bf80c1726..8ed7772ba 100644 --- a/src/main/java/dan200/computercraft/shared/network/container/ComputerContainerData.java +++ b/src/main/java/dan200/computercraft/shared/network/container/ComputerContainerData.java @@ -23,18 +23,19 @@ public class ComputerContainerData implements ContainerData { this.family = computer.getFamily(); } - @Override + public ComputerContainerData(PacketByteBuf byteBuf) { + fromBytes(byteBuf); + } + public Identifier getId() { return IDENTIFIER; } - @Override public void fromBytes(PacketByteBuf buf) { this.id = buf.readInt(); this.family = buf.readEnumConstant(ComputerFamily.class); } - @Override public void toBytes(PacketByteBuf buf) { buf.writeInt(id); buf.writeEnumConstant(family); diff --git a/src/main/java/dan200/computercraft/shared/network/container/ContainerData.java b/src/main/java/dan200/computercraft/shared/network/container/ContainerData.java index 1fca53b95..df6f940f9 100644 --- a/src/main/java/dan200/computercraft/shared/network/container/ContainerData.java +++ b/src/main/java/dan200/computercraft/shared/network/container/ContainerData.java @@ -5,6 +5,7 @@ */ package dan200.computercraft.shared.network.container; +import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.network.PacketByteBuf; @@ -12,6 +13,7 @@ import net.minecraft.screen.NamedScreenHandlerFactory; import net.minecraft.screen.ScreenHandler; import net.minecraft.screen.ScreenHandlerType; import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.Identifier; import javax.annotation.Nonnull; import java.util.function.Consumer; @@ -25,19 +27,18 @@ public interface ContainerData { void toBytes( PacketByteBuf buf ); - //TODO Figure out what the heck to do here -// default void open( PlayerEntity player, NamedScreenHandlerFactory owner ) -// { -// NetworkHooks.openGui( (ServerPlayerEntity) player, owner, this::toBytes ); -// } -// -// static ScreenHandlerType toType( Function reader, Factory factory ) -// { -// return IForgeContainerType.create( ( id, player, data ) -> factory.create( id, player, reader.apply( data ) ) ); -// } -// -// interface Factory -// { -// C create( int id, @Nonnull PlayerInventory inventory, T data ); -// } + default void open( PlayerEntity player, NamedScreenHandlerFactory owner ) + { + player.openHandledScreen(owner); + } + + static ScreenHandlerType toType(Identifier identifier, Function reader, Factory factory ) + { + return ScreenHandlerRegistry.registerExtended(identifier, (id, playerInventory, packetByteBuf) -> factory.create(id, playerInventory, reader.apply(packetByteBuf))); + } + + interface Factory + { + C create( int id, @Nonnull PlayerInventory inventory, T data ); + } } diff --git a/src/main/java/dan200/computercraft/shared/network/container/ViewComputerContainerData.java b/src/main/java/dan200/computercraft/shared/network/container/ViewComputerContainerData.java index f30cdc8ae..05fbb2f12 100644 --- a/src/main/java/dan200/computercraft/shared/network/container/ViewComputerContainerData.java +++ b/src/main/java/dan200/computercraft/shared/network/container/ViewComputerContainerData.java @@ -35,6 +35,11 @@ public class ViewComputerContainerData extends ComputerContainerData { } } + public ViewComputerContainerData(PacketByteBuf packetByteBuf) { + super(packetByteBuf); + toBytes(packetByteBuf); + } + private static final Identifier IDENTIFIER = new Identifier(ComputerCraft.MOD_ID, "viewComputerContainerData"); @Override diff --git a/src/main/java/dan200/computercraft/shared/network/server/ComputerServerMessage.java b/src/main/java/dan200/computercraft/shared/network/server/ComputerServerMessage.java index 1c017193a..c3ec25944 100644 --- a/src/main/java/dan200/computercraft/shared/network/server/ComputerServerMessage.java +++ b/src/main/java/dan200/computercraft/shared/network/server/ComputerServerMessage.java @@ -9,8 +9,8 @@ import dan200.computercraft.ComputerCraft; import dan200.computercraft.shared.computer.core.IContainerComputer; import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.network.NetworkMessage; +import net.fabricmc.fabric.api.network.PacketContext; import net.minecraft.network.PacketByteBuf; -import net.minecraftforge.fml.network.NetworkEvent; import javax.annotation.Nonnull; @@ -46,12 +46,12 @@ public abstract class ComputerServerMessage implements NetworkMessage } @Override - public void handle( NetworkEvent.Context context ) + public void handle( PacketContext context ) { ServerComputer computer = ComputerCraft.serverComputerRegistry.get( instanceId ); if( computer == null ) return; - IContainerComputer container = computer.getContainer( context.getSender() ); + IContainerComputer container = computer.getContainer( context.getPlayer() ); if( container == null ) return; handle( computer, container ); diff --git a/src/main/java/dan200/computercraft/shared/network/server/RequestComputerMessage.java b/src/main/java/dan200/computercraft/shared/network/server/RequestComputerMessage.java index e83c4bcf2..1d8148aab 100644 --- a/src/main/java/dan200/computercraft/shared/network/server/RequestComputerMessage.java +++ b/src/main/java/dan200/computercraft/shared/network/server/RequestComputerMessage.java @@ -8,8 +8,8 @@ package dan200.computercraft.shared.network.server; import dan200.computercraft.ComputerCraft; import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.network.NetworkMessage; +import net.fabricmc.fabric.api.network.PacketContext; import net.minecraft.network.PacketByteBuf; -import net.minecraftforge.fml.network.NetworkEvent; import javax.annotation.Nonnull; @@ -39,9 +39,9 @@ public class RequestComputerMessage implements NetworkMessage } @Override - public void handle( NetworkEvent.Context context ) + public void handle( PacketContext context ) { ServerComputer computer = ComputerCraft.serverComputerRegistry.get( instance ); - if( computer != null ) computer.sendComputerState( context.getSender() ); + if( computer != null ) computer.sendComputerState( context.getPlayer() ); } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/commandblock/CommandBlockPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/commandblock/CommandBlockPeripheral.java index d5e625024..61d1c0e91 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/commandblock/CommandBlockPeripheral.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/commandblock/CommandBlockPeripheral.java @@ -9,23 +9,14 @@ import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.lua.LuaFunction; import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.shared.computer.apis.CommandAPI; -import dan200.computercraft.shared.util.CapabilityUtil; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.CommandBlockBlockEntity; import net.minecraft.util.Identifier; import net.minecraft.util.math.Direction; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.capabilities.ICapabilityProvider; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.event.AttachCapabilitiesEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import static dan200.computercraft.shared.Capabilities.CAPABILITY_PERIPHERAL; - /** * This peripheral allows you to interact with command blocks. * @@ -36,13 +27,11 @@ import static dan200.computercraft.shared.Capabilities.CAPABILITY_PERIPHERAL; * * @cc.module command */ -@Mod.EventBusSubscriber -public class CommandBlockPeripheral implements IPeripheral, ICapabilityProvider +public class CommandBlockPeripheral implements IPeripheral { private static final Identifier CAP_ID = new Identifier( ComputerCraft.MOD_ID, "command_block" ); private final CommandBlockBlockEntity commandBlock; - private LazyOptional self; public CommandBlockPeripheral( CommandBlockBlockEntity commandBlock ) { @@ -51,7 +40,7 @@ public class CommandBlockPeripheral implements IPeripheral, ICapabilityProvider @Nonnull @Override - public String getType0() + public String getType() { return "command"; } @@ -106,33 +95,4 @@ public class CommandBlockPeripheral implements IPeripheral, ICapabilityProvider { return commandBlock; } - - @Nonnull - @Override - public LazyOptional getCapability( @Nonnull Capability cap, @Nullable Direction side ) - { - if( cap == CAPABILITY_PERIPHERAL ) - { - if( self == null ) self = LazyOptional.of( () -> this ); - return self.cast(); - } - return LazyOptional.empty(); - } - - private void invalidate() - { - self = CapabilityUtil.invalidate( self ); - } - - @SubscribeEvent - public static void onCapability( AttachCapabilitiesEvent event ) - { - BlockEntity tile = event.getObject(); - if( tile instanceof CommandBlockBlockEntity ) - { - CommandBlockPeripheral peripheral = new CommandBlockPeripheral( (CommandBlockBlockEntity) tile ); - event.addCapability( CAP_ID, peripheral ); - event.addListener( peripheral::invalidate ); - } - } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/BlockDiskDrive.java b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/BlockDiskDrive.java index 53d1aaf84..992b871c2 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/BlockDiskDrive.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/BlockDiskDrive.java @@ -5,7 +5,7 @@ */ package dan200.computercraft.shared.peripheral.diskdrive; -import dan200.computercraft.shared.Registry; +import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.common.BlockGeneric; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -34,7 +34,7 @@ public class BlockDiskDrive extends BlockGeneric public BlockDiskDrive( Settings settings ) { - super( settings, Registry.ModTiles.DISK_DRIVE ); + super( settings, ComputerCraftRegistry.ModTiles.DISK_DRIVE ); setDefaultState( getStateManager().getDefaultState() .with( FACING, Direction.NORTH ) .with( STATE, DiskDriveState.EMPTY ) ); diff --git a/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/ContainerDiskDrive.java b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/ContainerDiskDrive.java index ba0df2f84..c42bc80aa 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/ContainerDiskDrive.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/ContainerDiskDrive.java @@ -5,7 +5,7 @@ */ package dan200.computercraft.shared.peripheral.diskdrive; -import dan200.computercraft.shared.Registry; +import dan200.computercraft.shared.ComputerCraftRegistry; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.inventory.Inventory; @@ -21,7 +21,7 @@ public class ContainerDiskDrive extends ScreenHandler public ContainerDiskDrive( int id, PlayerInventory player, Inventory inventory ) { - super( Registry.ModContainers.DISK_DRIVE.get(), id ); + super( ComputerCraftRegistry.ModContainers.DISK_DRIVE, id ); this.inventory = inventory; diff --git a/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/DiskDrivePeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/DiskDrivePeripheral.java index b72a934fa..dd15192db 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/DiskDrivePeripheral.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/DiskDrivePeripheral.java @@ -43,7 +43,7 @@ public class DiskDrivePeripheral implements IPeripheral @Nonnull @Override - public String getType0() + public String getType() { return "drive"; } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/TileDiskDrive.java b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/TileDiskDrive.java index 89b6035b8..8f0593491 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/TileDiskDrive.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/TileDiskDrive.java @@ -12,7 +12,6 @@ import dan200.computercraft.api.peripheral.IComputerAccess; import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.shared.MediaProviders; import dan200.computercraft.shared.common.TileGeneric; -import dan200.computercraft.shared.util.CapabilityUtil; import dan200.computercraft.shared.util.DefaultInventory; import dan200.computercraft.shared.util.InventoryUtil; import dan200.computercraft.shared.util.RecordUtil; @@ -33,11 +32,6 @@ import net.minecraft.util.*; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.fml.network.NetworkHooks; -import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.wrapper.InvWrapper; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -45,9 +39,6 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; -import static dan200.computercraft.shared.Capabilities.CAPABILITY_PERIPHERAL; -import static net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY; - public final class TileDiskDrive extends TileGeneric implements DefaultInventory, Tickable, Nameable, NamedScreenHandlerFactory { private static final String NBT_NAME = "CustomName"; @@ -64,8 +55,6 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory @Nonnull private ItemStack m_diskStack = ItemStack.EMPTY; - private LazyOptional itemHandlerCap; - private LazyOptional peripheralCap; private IMount m_diskMount = null; private boolean m_recordQueued = false; @@ -85,14 +74,6 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory if( m_recordPlaying ) stopRecord(); } - @Override - protected void invalidateCaps() - { - super.invalidateCaps(); - itemHandlerCap = CapabilityUtil.invalidate( itemHandlerCap ); - peripheralCap = CapabilityUtil.invalidate( peripheralCap ); - } - @Nonnull @Override public ActionResult onActivate( PlayerEntity player, Hand hand, BlockHitResult hit ) @@ -112,7 +93,7 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory else { // Open the GUI - if( !getWorld().isClient ) NetworkHooks.openGui( (ServerPlayerEntity) player, this ); + if( !getWorld().isClient ) player.openHandledScreen( this ); return ActionResult.SUCCESS; } } @@ -514,25 +495,6 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory RecordUtil.playRecord( null, null, getWorld(), getPos() ); } - @Nonnull - @Override - public LazyOptional getCapability( @Nonnull Capability cap, @Nullable final Direction side ) - { - if( cap == ITEM_HANDLER_CAPABILITY ) - { - if( itemHandlerCap == null ) itemHandlerCap = LazyOptional.of( () -> new InvWrapper( this ) ); - return itemHandlerCap.cast(); - } - - if( cap == CAPABILITY_PERIPHERAL ) - { - if( peripheralCap == null ) peripheralCap = LazyOptional.of( () -> new DiskDrivePeripheral( this ) ); - return peripheralCap.cast(); - } - - return super.getCapability( cap, side ); - } - @Override public boolean hasCustomName() { diff --git a/src/main/java/dan200/computercraft/shared/peripheral/generic/GenericPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/generic/GenericPeripheral.java deleted file mode 100644 index 5f5b8631e..000000000 --- a/src/main/java/dan200/computercraft/shared/peripheral/generic/GenericPeripheral.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.generic; - -import dan200.computercraft.api.lua.IArguments; -import dan200.computercraft.api.lua.ILuaContext; -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.MethodResult; -import dan200.computercraft.api.peripheral.IComputerAccess; -import dan200.computercraft.api.peripheral.IDynamicPeripheral; -import dan200.computercraft.api.peripheral.IPeripheral; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.util.Identifier; -import java.util.List; - -class GenericPeripheral implements IDynamicPeripheral -{ - private final String type; - private final BlockEntity tile; - private final List methods; - - GenericPeripheral( BlockEntity tile, List methods ) - { - Identifier type = tile.getType().getRegistryName(); - this.tile = tile; - this.type = type == null ? "unknown" : type.toString(); - this.methods = methods; - } - - @Nonnull - @Override - public String[] getMethodNames() - { - String[] names = new String[methods.size()]; - for( int i = 0; i < methods.size(); i++ ) names[i] = methods.get( i ).getName(); - return names; - } - - @Nonnull - @Override - public MethodResult callMethod( @Nonnull IComputerAccess computer, @Nonnull ILuaContext context, int method, @Nonnull IArguments arguments ) throws LuaException - { - return methods.get( method ).apply( context, computer, arguments ); - } - - @Nonnull - @Override - public String getType0() - { - return type; - } - - @Nullable - @Override - public Object getTarget() - { - return tile; - } - - @Override - public boolean equals( @Nullable IPeripheral other ) - { - if( other == this ) return true; - if( !(other instanceof GenericPeripheral) ) return false; - - GenericPeripheral generic = (GenericPeripheral) other; - return tile == generic.tile && methods.equals( generic.methods ); - } -} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/generic/GenericPeripheralProvider.java b/src/main/java/dan200/computercraft/shared/peripheral/generic/GenericPeripheralProvider.java deleted file mode 100644 index 0cedb9764..000000000 --- a/src/main/java/dan200/computercraft/shared/peripheral/generic/GenericPeripheralProvider.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.generic; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.core.asm.NamedMethod; -import dan200.computercraft.core.asm.PeripheralMethod; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.world.World; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.energy.CapabilityEnergy; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; -import net.minecraftforge.items.CapabilityItemHandler; - -import javax.annotation.Nonnull; -import java.util.ArrayList; -import java.util.List; - -public class GenericPeripheralProvider -{ - private static final Capability[] CAPABILITIES = new Capability[] { - CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, - CapabilityEnergy.ENERGY, - CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, - }; - - @Nonnull - public static LazyOptional getPeripheral( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side ) - { - if( !ComputerCraft.genericPeripheral ) return LazyOptional.empty(); - - BlockEntity tile = world.getBlockEntity( pos ); - if( tile == null ) return LazyOptional.empty(); - - ArrayList saturated = new ArrayList<>( 0 ); - LazyOptional peripheral = LazyOptional.of( () -> new GenericPeripheral( tile, saturated ) ); - - List> tileMethods = PeripheralMethod.GENERATOR.getMethods( tile.getClass() ); - if( !tileMethods.isEmpty() ) addSaturated( saturated, tile, tileMethods ); - - for( Capability capability : CAPABILITIES ) - { - LazyOptional wrapper = tile.getCapability( capability ); - wrapper.ifPresent( contents -> { - List> capabilityMethods = PeripheralMethod.GENERATOR.getMethods( contents.getClass() ); - if( capabilityMethods.isEmpty() ) return; - - addSaturated( saturated, contents, capabilityMethods ); - wrapper.addListener( x -> peripheral.invalidate() ); - } ); - } - - return saturated.isEmpty() ? LazyOptional.empty() : peripheral; - } - - private static void addSaturated( ArrayList saturated, Object target, List> methods ) - { - saturated.ensureCapacity( saturated.size() + methods.size() ); - for( NamedMethod method : methods ) - { - saturated.add( new SaturatedMethod( target, method ) ); - } - } -} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/generic/SaturatedMethod.java b/src/main/java/dan200/computercraft/shared/peripheral/generic/SaturatedMethod.java deleted file mode 100644 index 6db3f6aa4..000000000 --- a/src/main/java/dan200/computercraft/shared/peripheral/generic/SaturatedMethod.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.generic; - -import dan200.computercraft.api.lua.IArguments; -import dan200.computercraft.api.lua.ILuaContext; -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.MethodResult; -import dan200.computercraft.api.peripheral.IComputerAccess; -import dan200.computercraft.core.asm.NamedMethod; -import dan200.computercraft.core.asm.PeripheralMethod; - -import javax.annotation.Nonnull; - -final class SaturatedMethod -{ - private final Object target; - private final String name; - private final PeripheralMethod method; - - SaturatedMethod( Object target, NamedMethod method ) - { - this.target = target; - this.name = method.getName(); - this.method = method.getMethod(); - } - - @Nonnull - MethodResult apply( @Nonnull ILuaContext context, @Nonnull IComputerAccess computer, @Nonnull IArguments args ) throws LuaException - { - return method.apply( target, context, computer, args ); - } - - @Nonnull - String getName() - { - return name; - } - - @Override - public boolean equals( Object obj ) - { - if( obj == this ) return true; - if( !(obj instanceof SaturatedMethod) ) return false; - - SaturatedMethod other = (SaturatedMethod) obj; - return method == other.method && target.equals( other.target ); - } - - @Override - public int hashCode() - { - return 31 * target.hashCode() + method.hashCode(); - } -} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/generic/data/BlockData.java b/src/main/java/dan200/computercraft/shared/peripheral/generic/data/BlockData.java deleted file mode 100644 index 69b93db05..000000000 --- a/src/main/java/dan200/computercraft/shared/peripheral/generic/data/BlockData.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.generic.data; - -import com.google.common.collect.ImmutableMap; -import net.minecraft.block.BlockState; -import net.minecraft.state.property.Property; -import javax.annotation.Nonnull; -import java.util.HashMap; -import java.util.Map; - -public class BlockData -{ - @Nonnull - public static > T fill( @Nonnull T data, @Nonnull BlockState state ) - { - data.put( "name", DataHelpers.getId( state.getBlock() ) ); - - Map stateTable = new HashMap<>(); - for( ImmutableMap.Entry, ? extends Comparable> entry : state.getEntries().entrySet() ) - { - Property property = entry.getKey(); - stateTable.put( property.getName(), getPropertyValue( property, entry.getValue() ) ); - } - data.put( "state", stateTable ); - data.put( "tags", DataHelpers.getTags( state.getBlock().getTags() ) ); - - return data; - } - - @SuppressWarnings( { "unchecked", "rawtypes" } ) - private static Object getPropertyValue( Property property, Comparable value ) - { - if( value instanceof String || value instanceof Number || value instanceof Boolean ) return value; - return property.name( value ); - } -} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/generic/data/DataHelpers.java b/src/main/java/dan200/computercraft/shared/peripheral/generic/data/DataHelpers.java deleted file mode 100644 index 0f6ced166..000000000 --- a/src/main/java/dan200/computercraft/shared/peripheral/generic/data/DataHelpers.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.generic.data; - -import net.minecraft.util.Identifier; -import net.minecraftforge.registries.IForgeRegistryEntry; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -public final class DataHelpers -{ - private DataHelpers() - { } - - @Nonnull - public static Map getTags( @Nonnull Collection tags ) - { - Map result = new HashMap<>( tags.size() ); - for( Identifier location : tags ) result.put( location.toString(), true ); - return result; - } - - @Nullable - public static String getId( @Nonnull IForgeRegistryEntry entry ) - { - Identifier id = entry.getRegistryName(); - return id == null ? null : id.toString(); - } -} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/generic/data/FluidData.java b/src/main/java/dan200/computercraft/shared/peripheral/generic/data/FluidData.java deleted file mode 100644 index e5b19af7d..000000000 --- a/src/main/java/dan200/computercraft/shared/peripheral/generic/data/FluidData.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.generic.data; - -import net.minecraftforge.fluids.FluidStack; - -import javax.annotation.Nonnull; -import java.util.Map; - -public class FluidData -{ - @Nonnull - public static > T fillBasic( @Nonnull T data, @Nonnull FluidStack stack ) - { - data.put( "name", DataHelpers.getId( stack.getFluid() ) ); - data.put( "amount", stack.getAmount() ); - return data; - } - - @Nonnull - public static > T fill( @Nonnull T data, @Nonnull FluidStack stack ) - { - fillBasic( data, stack ); - data.put( "tags", DataHelpers.getTags( stack.getFluid().getTags() ) ); - return data; - } -} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/generic/data/ItemData.java b/src/main/java/dan200/computercraft/shared/peripheral/generic/data/ItemData.java deleted file mode 100644 index 4e68909ef..000000000 --- a/src/main/java/dan200/computercraft/shared/peripheral/generic/data/ItemData.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.generic.data; - -import com.google.gson.JsonParseException; -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.shared.util.NBTUtil; -import net.minecraft.enchantment.Enchantment; -import net.minecraft.enchantment.EnchantmentHelper; -import net.minecraft.item.EnchantedBookItem; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.Tag; -import net.minecraft.text.Text; -import net.minecraftforge.common.util.Constants; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.*; -import java.util.stream.Collectors; - -/** - * Data providers for items. - * - * We guard using {@link ComputerCraft#genericPeripheral} in several places, as advanced functionality should not be - * exposed for {@code turtle.getItemDetail} when generic peripehrals are disabled. - */ -public class ItemData -{ - @Nonnull - public static > T fillBasicSafe( @Nonnull T data, @Nonnull ItemStack stack ) - { - data.put( "name", DataHelpers.getId( stack.getItem() ) ); - data.put( "count", stack.getCount() ); - - return data; - } - - @Nonnull - public static > T fillBasic( @Nonnull T data, @Nonnull ItemStack stack ) - { - fillBasicSafe( data, stack ); - String hash = NBTUtil.getNBTHash( stack.getTag() ); - if( hash != null ) data.put( "nbt", hash ); - return data; - } - - @Nonnull - public static > T fill( @Nonnull T data, @Nonnull ItemStack stack ) - { - if( stack.isEmpty() ) return data; - - fillBasic( data, stack ); - - data.put( "displayName", stack.getName().getString() ); - data.put( "maxCount", stack.getMaxCount() ); - - if( stack.isDamageable() ) - { - data.put( "damage", stack.getDamage() ); - data.put( "maxDamage", stack.getMaxDamage() ); - } - - if( stack.getItem().showDurabilityBar( stack ) ) - { - data.put( "durability", stack.getItem().getDurabilityForDisplay( stack ) ); - } - - data.put( "tags", DataHelpers.getTags( stack.getItem().getTags() ) ); - - if( !ComputerCraft.genericPeripheral ) return data; - - CompoundTag tag = stack.getTag(); - if( tag != null && tag.contains( "display", NBTUtil.TAG_COMPOUND ) ) - { - CompoundTag displayTag = tag.getCompound( "display" ); - if( displayTag.contains( "Lore", NBTUtil.TAG_LIST ) ) - { - ListTag loreTag = displayTag.getList( "Lore", NBTUtil.TAG_STRING ); - data.put( "lore", loreTag.stream() - .map( ItemData::parseTextComponent ) - .filter( Objects::nonNull ) - .map( Text::getString ) - .collect( Collectors.toList() ) ); - } - } - - /* - * Used to hide some data from ItemStack tooltip. - * @see https://minecraft.gamepedia.com/Tutorials/Command_NBT_tags - * @see ItemStack#getTooltip - */ - int hideFlags = tag != null ? tag.getInt( "HideFlags" ) : 0; - - List> enchants = getAllEnchants( stack, hideFlags ); - if( !enchants.isEmpty() ) data.put( "enchantments", enchants ); - - if( tag != null && tag.getBoolean( "Unbreakable" ) && (hideFlags & 4) == 0 ) - { - data.put( "unbreakable", true ); - } - - return data; - } - - @Nullable - private static Text parseTextComponent( @Nonnull Tag x ) - { - try - { - return Text.Serializer.fromJson( x.asString() ); - } - catch( JsonParseException e ) - { - return null; - } - } - - /** - * Retrieve all visible enchantments from given stack. Try to follow all tooltip rules : order and visibility. - * - * @param stack Stack to analyse - * @param hideFlags An int used as bit field to provide visibility rules. - * @return A filled list that contain all visible enchantments. - */ - @Nonnull - private static List> getAllEnchants( @Nonnull ItemStack stack, int hideFlags ) - { - ArrayList> enchants = new ArrayList<>( 0 ); - - if( stack.getItem() instanceof EnchantedBookItem && (hideFlags & 32) == 0 ) - { - addEnchantments( EnchantedBookItem.getEnchantmentTag( stack ), enchants ); - } - - if( stack.hasEnchantments() && (hideFlags & 1) == 0 ) - { - /* - * Mimic the EnchantmentHelper.getEnchantments(ItemStack stack) behavior without special case for Enchanted book. - * I'll do that to have the same data than ones displayed in tooltip. - * @see EnchantmentHelper.getEnchantments(ItemStack stack) - */ - addEnchantments( stack.getEnchantments(), enchants ); - } - - return enchants; - } - - /** - * Converts a Mojang enchant map to a Lua list. - * - * @param rawEnchants The raw NBT list of enchantments - * @param enchants The enchantment map to add it to. - * @see net.minecraft.enchantment.EnchantmentHelper - */ - private static void addEnchantments( @Nonnull ListTag rawEnchants, @Nonnull ArrayList> enchants ) - { - if( rawEnchants.isEmpty() ) return; - - enchants.ensureCapacity( enchants.size() + rawEnchants.size() ); - - for( Map.Entry entry : EnchantmentHelper.fromTag( rawEnchants ).entrySet() ) - { - Enchantment enchantment = entry.getKey(); - Integer level = entry.getValue(); - HashMap enchant = new HashMap<>( 3 ); - enchant.put( "name", DataHelpers.getId( enchantment ) ); - enchant.put( "level", level ); - enchant.put( "displayName", enchantment.getName( level ).getString() ); - enchants.add( enchant ); - } - } -} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/ArgumentHelpers.java b/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/ArgumentHelpers.java deleted file mode 100644 index 7c95de7a9..000000000 --- a/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/ArgumentHelpers.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.generic.methods; - -import dan200.computercraft.api.lua.LuaException; -import net.minecraft.util.Identifier; -import net.minecraft.util.InvalidIdentifierException; -import net.minecraftforge.registries.IForgeRegistry; -import net.minecraftforge.registries.IForgeRegistryEntry; - -import javax.annotation.Nonnull; - -/** - * A few helpers for working with arguments. - * - * This should really be moved into the public API. However, until I have settled on a suitable format, we'll keep it - * where it is used. - */ -final class ArgumentHelpers -{ - private ArgumentHelpers() - { - } - - public static void assertBetween( double value, double min, double max, String message ) throws LuaException - { - if( value < min || value > max || Double.isNaN( value ) ) - { - throw new LuaException( String.format( message, "between " + min + " and " + max ) ); - } - } - - public static void assertBetween( int value, int min, int max, String message ) throws LuaException - { - if( value < min || value > max ) - { - throw new LuaException( String.format( message, "between " + min + " and " + max ) ); - } - } - - @Nonnull - public static > T getRegistryEntry( String name, String typeName, IForgeRegistry registry ) throws LuaException - { - Identifier id; - try - { - id = new Identifier( name ); - } - catch( InvalidIdentifierException e ) - { - id = null; - } - - T value; - if( id == null || !registry.containsKey( id ) || (value = registry.getValue( id )) == null ) - { - throw new LuaException( String.format( "Unknown %s '%s'", typeName, name ) ); - } - - return value; - } -} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/EnergyMethods.java b/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/EnergyMethods.java deleted file mode 100644 index c2da4dd21..000000000 --- a/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/EnergyMethods.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.generic.methods; - -import com.google.auto.service.AutoService; -import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.core.asm.GenericSource; -import net.minecraft.util.Identifier; -import net.minecraftforge.energy.IEnergyStorage; -import net.minecraftforge.versions.forge.ForgeVersion; - -import javax.annotation.Nonnull; - -@AutoService( GenericSource.class ) -public class EnergyMethods implements GenericSource -{ - @Nonnull - @Override - public Identifier id() - { - return new Identifier( ForgeVersion.MOD_ID, "energy" ); - } - - @LuaFunction( mainThread = true ) - public static int getEnergy( IEnergyStorage energy ) - { - return energy.getEnergyStored(); - } - - @LuaFunction( mainThread = true ) - public static int getEnergyCapacity( IEnergyStorage energy ) - { - return energy.getMaxEnergyStored(); - } -} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/FluidMethods.java b/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/FluidMethods.java deleted file mode 100644 index 45d8dd696..000000000 --- a/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/FluidMethods.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.generic.methods; - -import com.google.auto.service.AutoService; -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.api.peripheral.IComputerAccess; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.core.asm.GenericSource; -import dan200.computercraft.shared.peripheral.generic.data.FluidData; -import net.minecraft.fluid.Fluid; -import net.minecraft.util.Identifier; -import net.minecraftforge.common.capabilities.ICapabilityProvider; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; -import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.registries.ForgeRegistries; -import net.minecraftforge.versions.forge.ForgeVersion; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; - -import static dan200.computercraft.shared.peripheral.generic.methods.ArgumentHelpers.getRegistryEntry; - -@AutoService( GenericSource.class ) -public class FluidMethods implements GenericSource -{ - @Nonnull - @Override - public Identifier id() - { - return new Identifier( ForgeVersion.MOD_ID, "fluid" ); - } - - @LuaFunction( mainThread = true ) - public static Map> tanks( IFluidHandler fluids ) - { - Map> result = new HashMap<>(); - int size = fluids.getTanks(); - for( int i = 0; i < size; i++ ) - { - FluidStack stack = fluids.getFluidInTank( i ); - if( !stack.isEmpty() ) result.put( i + 1, FluidData.fillBasic( new HashMap<>( 4 ), stack ) ); - } - - return result; - } - - @LuaFunction( mainThread = true ) - public static int pushFluid( - IFluidHandler from, IComputerAccess computer, - String toName, Optional limit, Optional fluidName - ) throws LuaException - { - Fluid fluid = fluidName.isPresent() - ? getRegistryEntry( fluidName.get(), "fluid", ForgeRegistries.FLUIDS ) - : null; - - // Find location to transfer to - IPeripheral location = computer.getAvailablePeripheral( toName ); - if( location == null ) throw new LuaException( "Target '" + toName + "' does not exist" ); - - IFluidHandler to = extractHandler( location.getTarget() ); - if( to == null ) throw new LuaException( "Target '" + toName + "' is not an tank" ); - - int actualLimit = limit.orElse( Integer.MAX_VALUE ); - if( actualLimit <= 0 ) throw new LuaException( "Limit must be > 0" ); - - return fluid == null - ? moveFluid( from, actualLimit, to ) - : moveFluid( from, new FluidStack( fluid, actualLimit ), to ); - } - - @LuaFunction( mainThread = true ) - public static int pullFluid( - IFluidHandler to, IComputerAccess computer, - String fromName, Optional limit, Optional fluidName - ) throws LuaException - { - Fluid fluid = fluidName.isPresent() - ? getRegistryEntry( fluidName.get(), "fluid", ForgeRegistries.FLUIDS ) - : null; - - // Find location to transfer to - IPeripheral location = computer.getAvailablePeripheral( fromName ); - if( location == null ) throw new LuaException( "Target '" + fromName + "' does not exist" ); - - IFluidHandler from = extractHandler( location.getTarget() ); - if( from == null ) throw new LuaException( "Target '" + fromName + "' is not an tank" ); - - int actualLimit = limit.orElse( Integer.MAX_VALUE ); - if( actualLimit <= 0 ) throw new LuaException( "Limit must be > 0" ); - - return fluid == null - ? moveFluid( from, actualLimit, to ) - : moveFluid( from, new FluidStack( fluid, actualLimit ), to ); - } - - @Nullable - private static IFluidHandler extractHandler( @Nullable Object object ) - { - if( object instanceof ICapabilityProvider ) - { - LazyOptional cap = ((ICapabilityProvider) object).getCapability( CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY ); - if( cap.isPresent() ) return cap.orElseThrow( NullPointerException::new ); - } - - if( object instanceof IFluidHandler ) return (IFluidHandler) object; - return null; - } - - /** - * Move fluid from one handler to another. - * - * @param from The handler to move from. - * @param limit The maximum amount of fluid to move. - * @param to The handler to move to. - * @return The amount of fluid moved. - */ - private static int moveFluid( IFluidHandler from, int limit, IFluidHandler to ) - { - return moveFluid( from, from.drain( limit, IFluidHandler.FluidAction.SIMULATE ), limit, to ); - } - - /** - * Move fluid from one handler to another. - * - * @param from The handler to move from. - * @param fluid The fluid and limit to move. - * @param to The handler to move to. - * @return The amount of fluid moved. - */ - private static int moveFluid( IFluidHandler from, FluidStack fluid, IFluidHandler to ) - { - return moveFluid( from, from.drain( fluid, IFluidHandler.FluidAction.SIMULATE ), fluid.getAmount(), to ); - } - - /** - * Move fluid from one handler to another. - * - * @param from The handler to move from. - * @param extracted The fluid which is extracted from {@code from}. - * @param limit The maximum amount of fluid to move. - * @param to The handler to move to. - * @return The amount of fluid moved. - */ - private static int moveFluid( IFluidHandler from, FluidStack extracted, int limit, IFluidHandler to ) - { - if( extracted == null || extracted.getAmount() <= 0 ) return 0; - - // Limit the amount to extract. - extracted = extracted.copy(); - extracted.setAmount( Math.min( extracted.getAmount(), limit ) ); - - int inserted = to.fill( extracted.copy(), IFluidHandler.FluidAction.EXECUTE ); - if( inserted <= 0 ) return 0; - - // Remove the item from the original inventory. Technically this could fail, but there's little we can do - // about that. - extracted.setAmount( inserted ); - from.drain( extracted, IFluidHandler.FluidAction.EXECUTE ); - return inserted; - } -} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/InventoryMethods.java b/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/InventoryMethods.java deleted file mode 100644 index 9c7257d6a..000000000 --- a/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/InventoryMethods.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.generic.methods; - -import com.google.auto.service.AutoService; -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.api.peripheral.IComputerAccess; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.core.asm.GenericSource; -import dan200.computercraft.shared.peripheral.generic.data.ItemData; -import net.minecraft.inventory.Inventory; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Identifier; -import net.minecraftforge.common.capabilities.ICapabilityProvider; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.items.CapabilityItemHandler; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.ItemHandlerHelper; -import net.minecraftforge.items.wrapper.InvWrapper; -import net.minecraftforge.versions.forge.ForgeVersion; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; - -import static dan200.computercraft.shared.peripheral.generic.methods.ArgumentHelpers.assertBetween; - -@AutoService( GenericSource.class ) -public class InventoryMethods implements GenericSource -{ - @Nonnull - @Override - public Identifier id() - { - return new Identifier( ForgeVersion.MOD_ID, "inventory" ); - } - - @LuaFunction( mainThread = true ) - public static int size( IItemHandler inventory ) - { - return inventory.getSlots(); - } - - @LuaFunction( mainThread = true ) - public static Map> list( IItemHandler inventory ) - { - Map> result = new HashMap<>(); - int size = inventory.getSlots(); - for( int i = 0; i < size; i++ ) - { - ItemStack stack = inventory.getStackInSlot( i ); - if( !stack.isEmpty() ) result.put( i + 1, ItemData.fillBasic( new HashMap<>( 4 ), stack ) ); - } - - return result; - } - - @LuaFunction( mainThread = true ) - public static Map getItemDetail( IItemHandler inventory, int slot ) throws LuaException - { - assertBetween( slot, 1, inventory.getSlots(), "Slot out of range (%s)" ); - - ItemStack stack = inventory.getStackInSlot( slot - 1 ); - return stack.isEmpty() ? null : ItemData.fill( new HashMap<>(), stack ); - } - - @LuaFunction( mainThread = true ) - public static int pushItems( - IItemHandler from, IComputerAccess computer, - String toName, int fromSlot, Optional limit, Optional toSlot - ) throws LuaException - { - // Find location to transfer to - IPeripheral location = computer.getAvailablePeripheral( toName ); - if( location == null ) throw new LuaException( "Target '" + toName + "' does not exist" ); - - IItemHandler to = extractHandler( location.getTarget() ); - if( to == null ) throw new LuaException( "Target '" + toName + "' is not an inventory" ); - - // Validate slots - int actualLimit = limit.orElse( Integer.MAX_VALUE ); - if( actualLimit <= 0 ) throw new LuaException( "Limit must be > 0" ); - assertBetween( fromSlot, 1, from.getSlots(), "From slot out of range (%s)" ); - if( toSlot.isPresent() ) assertBetween( toSlot.get(), 1, to.getSlots(), "To slot out of range (%s)" ); - - return moveItem( from, fromSlot - 1, to, toSlot.orElse( 0 ) - 1, actualLimit ); - } - - @LuaFunction( mainThread = true ) - public static int pullItems( - IItemHandler to, IComputerAccess computer, - String fromName, int fromSlot, Optional limit, Optional toSlot - ) throws LuaException - { - // Find location to transfer to - IPeripheral location = computer.getAvailablePeripheral( fromName ); - if( location == null ) throw new LuaException( "Source '" + fromName + "' does not exist" ); - - IItemHandler from = extractHandler( location.getTarget() ); - if( from == null ) throw new LuaException( "Source '" + fromName + "' is not an inventory" ); - - // Validate slots - int actualLimit = limit.orElse( Integer.MAX_VALUE ); - if( actualLimit <= 0 ) throw new LuaException( "Limit must be > 0" ); - assertBetween( fromSlot, 1, from.getSlots(), "From slot out of range (%s)" ); - if( toSlot.isPresent() ) assertBetween( toSlot.get(), 1, to.getSlots(), "To slot out of range (%s)" ); - - return moveItem( from, fromSlot - 1, to, toSlot.orElse( 0 ) - 1, actualLimit ); - } - - @Nullable - private static IItemHandler extractHandler( @Nullable Object object ) - { - if( object instanceof ICapabilityProvider ) - { - LazyOptional cap = ((ICapabilityProvider) object).getCapability( CapabilityItemHandler.ITEM_HANDLER_CAPABILITY ); - if( cap.isPresent() ) return cap.orElseThrow( NullPointerException::new ); - } - - if( object instanceof IItemHandler ) return (IItemHandler) object; - if( object instanceof Inventory ) return new InvWrapper( (Inventory) object ); - return null; - } - - /** - * Move an item from one handler to another. - * - * @param from The handler to move from. - * @param fromSlot The slot to move from. - * @param to The handler to move to. - * @param toSlot The slot to move to. Use any number < 0 to represent any slot. - * @param limit The max number to move. {@link Integer#MAX_VALUE} for no limit. - * @return The number of items moved. - */ - private static int moveItem( IItemHandler from, int fromSlot, IItemHandler to, int toSlot, final int limit ) - { - // See how much we can get out of this slot - ItemStack extracted = from.extractItem( fromSlot, limit, true ); - if( extracted.isEmpty() ) return 0; - - // Limit the amount to extract - int extractCount = Math.min( extracted.getCount(), limit ); - extracted.setCount( extractCount ); - - ItemStack remainder = toSlot < 0 ? ItemHandlerHelper.insertItem( to, extracted, false ) : to.insertItem( toSlot, extracted, false ); - int inserted = remainder.isEmpty() ? extractCount : extractCount - remainder.getCount(); - if( inserted <= 0 ) return 0; - - // Remove the item from the original inventory. Technically this could fail, but there's little we can do - // about that. - from.extractItem( fromSlot, inserted, false ); - return inserted; - } -} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/ModemPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/ModemPeripheral.java index f836417f1..0805406a9 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/ModemPeripheral.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/ModemPeripheral.java @@ -94,7 +94,7 @@ public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPa @Nonnull @Override - public String getType0() + public String getType() { return "modem"; } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/BlockCable.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/BlockCable.java index f9a2a10c1..b8085e34f 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/BlockCable.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/BlockCable.java @@ -7,7 +7,7 @@ package dan200.computercraft.shared.peripheral.modem.wired; import com.google.common.collect.ImmutableMap; import dan200.computercraft.api.ComputerCraftAPI; -import dan200.computercraft.shared.Registry; +import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.common.BlockGeneric; import dan200.computercraft.shared.util.WorldUtil; import net.minecraft.block.Block; @@ -60,7 +60,7 @@ public class BlockCable extends BlockGeneric implements Waterloggable public BlockCable( Settings settings ) { - super( settings, Registry.ModTiles.CABLE ); + super( settings, ComputerCraftRegistry.ModTiles.CABLE ); setDefaultState( getStateManager().getDefaultState() .with( MODEM, CableModemVariant.None ) @@ -87,7 +87,7 @@ public class BlockCable extends BlockGeneric implements Waterloggable { if( !state.get( CABLE ) ) return false; if( state.get( MODEM ).getFacing() == direction ) return true; - return ComputerCraftAPI.getWiredElementAt( world, pos.offset( direction ), direction.getOpposite() ).isPresent(); + return ComputerCraftAPI.getWiredElementAt( world, pos.offset( direction ), direction.getOpposite() ) != null; } @Nonnull @@ -98,70 +98,68 @@ public class BlockCable extends BlockGeneric implements Waterloggable return CableShapes.getShape( state ); } - @Override - public boolean removedByPlayer( BlockState state, World world, BlockPos pos, PlayerEntity player, boolean willHarvest, FluidState fluid ) - { - if( state.get( CABLE ) && state.get( MODEM ).getFacing() != null ) - { - BlockHitResult hit = world.raycast( new RaycastContext( - WorldUtil.getRayStart( player ), WorldUtil.getRayEnd( player ), - RaycastContext.ShapeType.COLLIDER, RaycastContext.FluidHandling.NONE, player - ) ); - if( hit.getType() == HitResult.Type.BLOCK ) - { - BlockEntity tile = world.getBlockEntity( pos ); - if( tile instanceof TileCable && tile.hasWorld() ) - { - TileCable cable = (TileCable) tile; +// @Override +// public boolean removedByPlayer( BlockState state, World world, BlockPos pos, PlayerEntity player, boolean willHarvest, FluidState fluid ) +// { +// if( state.get( CABLE ) && state.get( MODEM ).getFacing() != null ) +// { +// BlockHitResult hit = world.raycast( new RaycastContext( +// WorldUtil.getRayStart( player ), WorldUtil.getRayEnd( player ), +// RaycastContext.ShapeType.COLLIDER, RaycastContext.FluidHandling.NONE, player +// ) ); +// if( hit.getType() == HitResult.Type.BLOCK ) +// { +// BlockEntity tile = world.getBlockEntity( pos ); +// if( tile instanceof TileCable && tile.hasWorld() ) +// { +// TileCable cable = (TileCable) tile; +// +// ItemStack item; +// BlockState newState; +// +// if( WorldUtil.isVecInside( CableShapes.getModemShape( state ), hit.getPos().subtract( pos.getX(), pos.getY(), pos.getZ() ) ) ) +// { +// newState = state.with( MODEM, CableModemVariant.None ); +// item = new ItemStack( ComputerCraftRegistry.ModItems.WIRED_MODEM.get() ); +// } +// else +// { +// newState = state.with( CABLE, false ); +// item = new ItemStack( ComputerCraftRegistry.ModItems.CABLE.get() ); +// } +// +// world.setBlockState( pos, correctConnections( world, pos, newState ), 3 ); +// +// cable.modemChanged(); +// cable.connectionsChanged(); +// if( !world.isClient && !player.abilities.creativeMode ) +// { +// Block.dropStack( world, pos, item ); +// } +// +// return false; +// } +// } +// } +// +// return super.removedByPlayer( state, world, pos, player, willHarvest, fluid ); +// } - ItemStack item; - BlockState newState; - - if( WorldUtil.isVecInside( CableShapes.getModemShape( state ), hit.getPos().subtract( pos.getX(), pos.getY(), pos.getZ() ) ) ) - { - newState = state.with( MODEM, CableModemVariant.None ); - item = new ItemStack( Registry.ModItems.WIRED_MODEM.get() ); - } - else - { - newState = state.with( CABLE, false ); - item = new ItemStack( Registry.ModItems.CABLE.get() ); - } - - world.setBlockState( pos, correctConnections( world, pos, newState ), 3 ); - - cable.modemChanged(); - cable.connectionsChanged(); - if( !world.isClient && !player.abilities.creativeMode ) - { - Block.dropStack( world, pos, item ); - } - - return false; - } - } - } - - return super.removedByPlayer( state, world, pos, player, willHarvest, fluid ); - } - - @Nonnull - @Override - public ItemStack getPickBlock( BlockState state, HitResult hit, BlockView world, BlockPos pos, PlayerEntity player ) - { - Direction modem = state.get( MODEM ).getFacing(); - boolean cable = state.get( CABLE ); - - // If we've only got one, just use that. - if( !cable ) return new ItemStack( Registry.ModItems.WIRED_MODEM.get() ); - if( modem == null ) return new ItemStack( Registry.ModItems.CABLE.get() ); - - // We've a modem and cable, so try to work out which one we're interacting with - return hit != null && WorldUtil.isVecInside( CableShapes.getModemShape( state ), hit.getPos().subtract( pos.getX(), pos.getY(), pos.getZ() ) ) - ? new ItemStack( Registry.ModItems.WIRED_MODEM.get() ) - : new ItemStack( Registry.ModItems.CABLE.get() ); - - } + // TODO Re-implement, likely will need mixin +// @Override +// public ItemStack getPickStack(BlockView world, BlockPos pos, BlockState state) { +// Direction modem = state.get( MODEM ).getFacing(); +// boolean cable = state.get( CABLE ); +// +// // If we've only got one, just use that. +// if( !cable ) return new ItemStack( ComputerCraftRegistry.ModItems.WIRED_MODEM.get() ); +// if( modem == null ) return new ItemStack( ComputerCraftRegistry.ModItems.CABLE.get() ); +// +// // We've a modem and cable, so try to work out which one we're interacting with +// return hit != null && WorldUtil.isVecInside( CableShapes.getModemShape( state ), hit.getPos().subtract( pos.getX(), pos.getY(), pos.getZ() ) ) +// ? new ItemStack( ComputerCraftRegistry.ModItems.WIRED_MODEM.get() ) +// : new ItemStack( ComputerCraftRegistry.ModItems.CABLE.get() ); +// } @Override public void onPlaced( World world, @Nonnull BlockPos pos, @Nonnull BlockState state, LivingEntity placer, @Nonnull ItemStack stack ) diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/BlockWiredModemFull.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/BlockWiredModemFull.java index c292de160..0ee271544 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/BlockWiredModemFull.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/BlockWiredModemFull.java @@ -5,9 +5,7 @@ */ package dan200.computercraft.shared.peripheral.modem.wired; -import dan200.computercraft.shared.Registry; import dan200.computercraft.shared.common.BlockGeneric; -import dan200.computercraft.shared.peripheral.monitor.TileMonitor; import net.minecraft.block.Block; import net.minecraft.block.BlockState; diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/ItemBlockCable.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/ItemBlockCable.java index c488178c0..6b34f1b01 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/ItemBlockCable.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/ItemBlockCable.java @@ -5,7 +5,7 @@ */ package dan200.computercraft.shared.peripheral.modem.wired; -import dan200.computercraft.shared.Registry; +import dan200.computercraft.shared.ComputerCraftRegistry; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.entity.player.PlayerEntity; @@ -19,8 +19,8 @@ import net.minecraft.util.*; import net.minecraft.util.collection.DefaultedList; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; +import net.minecraft.util.registry.Registry; import net.minecraft.world.World; -import net.minecraftforge.registries.ForgeRegistries; import javax.annotation.Nonnull; @@ -41,7 +41,7 @@ public abstract class ItemBlockCable extends BlockItem if( !state.canPlaceAt( world, pos ) ) return false; world.setBlockState( pos, state, 3 ); - BlockSoundGroup soundType = state.getBlock().getSoundType( state, world, pos, player ); + BlockSoundGroup soundType = state.getBlock().getSoundGroup( state ); world.playSound( null, pos, soundType.getPlaceSound(), SoundCategory.BLOCKS, (soundType.getVolume() + 1.0F) / 2.0F, soundType.getPitch() * 0.8F ); BlockEntity tile = world.getBlockEntity( pos ); @@ -72,7 +72,7 @@ public abstract class ItemBlockCable extends BlockItem { if( translationKey == null ) { - translationKey = Util.createTranslationKey( "block", ForgeRegistries.ITEMS.getKey( this ) ); + translationKey = Util.createTranslationKey( "block", Registry.ITEM.getId( this ) ); } return translationKey; } @@ -96,7 +96,7 @@ public abstract class ItemBlockCable extends BlockItem BlockState existingState = world.getBlockState( pos ); // Try to add a modem to a cable - if( existingState.getBlock() == Registry.ModBlocks.CABLE.get() && existingState.get( MODEM ) == CableModemVariant.None ) + if( existingState.getBlock() == ComputerCraftRegistry.ModBlocks.CABLE && existingState.get( MODEM ) == CableModemVariant.None ) { Direction side = context.getSide().getOpposite(); BlockState newState = existingState @@ -133,7 +133,7 @@ public abstract class ItemBlockCable extends BlockItem // Try to add a cable to a modem inside the block we're clicking on. BlockPos insidePos = pos.offset( context.getSide().getOpposite() ); BlockState insideState = world.getBlockState( insidePos ); - if( insideState.getBlock() == Registry.ModBlocks.CABLE.get() && !insideState.get( BlockCable.CABLE ) + if( insideState.getBlock() == ComputerCraftRegistry.ModBlocks.CABLE && !insideState.get( BlockCable.CABLE ) && placeAtCorrected( world, insidePos, insideState.with( BlockCable.CABLE, true ) ) ) { stack.decrement( 1 ); @@ -142,7 +142,7 @@ public abstract class ItemBlockCable extends BlockItem // Try to add a cable to a modem adjacent to this block BlockState existingState = world.getBlockState( pos ); - if( existingState.getBlock() == Registry.ModBlocks.CABLE.get() && !existingState.get( BlockCable.CABLE ) + if( existingState.getBlock() == ComputerCraftRegistry.ModBlocks.CABLE && !existingState.get( BlockCable.CABLE ) && placeAtCorrected( world, pos, existingState.with( BlockCable.CABLE, true ) ) ) { stack.decrement( 1 ); diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/TileCable.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/TileCable.java index d1c46fafa..1ef767c84 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/TileCable.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/TileCable.java @@ -10,11 +10,10 @@ import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.api.network.wired.IWiredElement; import dan200.computercraft.api.network.wired.IWiredNode; import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.shared.Registry; +import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.command.CommandCopy; import dan200.computercraft.shared.common.TileGeneric; import dan200.computercraft.shared.peripheral.modem.ModemState; -import dan200.computercraft.shared.util.CapabilityUtil; import dan200.computercraft.shared.util.DirectionUtil; import dan200.computercraft.shared.util.TickScheduler; import net.minecraft.block.Block; @@ -31,18 +30,12 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.common.util.NonNullConsumer; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collections; import java.util.Map; -import static dan200.computercraft.shared.Capabilities.CAPABILITY_PERIPHERAL; -import static dan200.computercraft.shared.Capabilities.CAPABILITY_WIRED_ELEMENT; - public class TileCable extends TileGeneric { private static final String NBT_PERIPHERAL_ENABLED = "PeirpheralAccess"; @@ -78,7 +71,7 @@ public class TileCable extends TileGeneric } private boolean m_peripheralAccessAllowed; - private final WiredModemLocalPeripheral m_peripheral = new WiredModemLocalPeripheral( this::refreshPeripheral ); + private final WiredModemLocalPeripheral m_peripheral = new WiredModemLocalPeripheral(); private boolean m_destroyed = false; @@ -87,7 +80,6 @@ public class TileCable extends TileGeneric private boolean m_connectionsFormed = false; private final WiredModemElement m_cable = new CableElement(); - private LazyOptional elementCap; private final IWiredNode m_node = m_cable.getNode(); private final WiredModemPeripheral m_modem = new WiredModemPeripheral( new ModemState( () -> TickScheduler.schedule( this ) ), @@ -116,9 +108,6 @@ public class TileCable extends TileGeneric return TileCable.this; } }; - private LazyOptional modemCap; - - private final NonNullConsumer> connectedNodeChanged = x -> connectionsChanged(); public TileCable( BlockEntityType type ) { @@ -145,13 +134,6 @@ public class TileCable extends TileGeneric } } - @Override - public void onChunkUnloaded() - { - super.onChunkUnloaded(); - onRemove(); - } - @Override public void markRemoved() { @@ -160,17 +142,9 @@ public class TileCable extends TileGeneric } @Override - protected void invalidateCaps() + public void cancelRemoval() { - super.invalidateCaps(); - elementCap = CapabilityUtil.invalidate( elementCap ); - modemCap = CapabilityUtil.invalidate( modemCap ); - } - - @Override - public void onLoad() - { - super.onLoad(); + super.cancelRemoval(); TickScheduler.schedule( this ); } @@ -213,7 +187,7 @@ public class TileCable extends TileGeneric if( hasCable() ) { // Drop the modem and convert to cable - Block.dropStack( getWorld(), getPos(), new ItemStack( Registry.ModItems.WIRED_MODEM.get() ) ); + Block.dropStack( getWorld(), getPos(), new ItemStack( ComputerCraftRegistry.ModItems.WIRED_MODEM ) ); getWorld().setBlockState( getPos(), getCachedState().with( BlockCable.MODEM, CableModemVariant.None ) ); modemChanged(); connectionsChanged(); @@ -221,7 +195,7 @@ public class TileCable extends TileGeneric else { // Drop everything and remove block - Block.dropStack( getWorld(), getPos(), new ItemStack( Registry.ModItems.WIRED_MODEM.get() ) ); + Block.dropStack( getWorld(), getPos(), new ItemStack( ComputerCraftRegistry.ModItems.WIRED_MODEM ) ); getWorld().removeBlock( getPos(), false ); // This'll call #destroy(), so we don't need to reset the network here. } @@ -315,14 +289,7 @@ public class TileCable extends TileGeneric { if( getWorld().isClient ) return; - Direction oldDirection = modemDirection; refreshDirection(); - if( modemDirection != oldDirection ) - { - // We invalidate both the modem and element if the modem's direction is different. - modemCap = CapabilityUtil.invalidate( modemCap ); - elementCap = CapabilityUtil.invalidate( elementCap ); - } if( m_modem.getModemState().pollChanged() ) updateBlockState(); @@ -349,13 +316,12 @@ public class TileCable extends TileGeneric for( Direction facing : DirectionUtil.FACINGS ) { BlockPos offset = current.offset( facing ); - if( !world.isAreaLoaded( offset, 0 ) ) continue; + if( !world.isChunkLoaded( offset ) ) continue; - LazyOptional element = ComputerCraftAPI.getWiredElementAt( world, offset, facing.getOpposite() ); - if( !element.isPresent() ) continue; + IWiredElement element = ComputerCraftAPI.getWiredElementAt( world, offset, facing.getOpposite() ); + if( element != null ) continue; - element.addListener( connectedNodeChanged ); - IWiredNode node = element.orElseThrow( NullPointerException::new ).getNode(); + IWiredNode node = element.getNode(); if( BlockCable.canConnectIn( state, facing ) ) { // If we can connect to it then do so @@ -372,8 +338,6 @@ public class TileCable extends TileGeneric void modemChanged() { // Tell anyone who cares that the connection state has changed - elementCap = CapabilityUtil.invalidate( elementCap ); - if( getWorld().isClient ) return; // If we can no longer attach peripherals, then detach any @@ -388,6 +352,10 @@ public class TileCable extends TileGeneric } } + public IWiredElement getElement(Direction facing) { + return BlockCable.canConnectIn(this.getCachedState(), facing) ? this.m_cable : null; + } + private void togglePeripheralAccess() { if( !m_peripheralAccessAllowed ) @@ -422,28 +390,6 @@ public class TileCable extends TileGeneric m_node.updatePeripherals( peripherals ); } - @Nonnull - @Override - public LazyOptional getCapability( @Nonnull Capability capability, @Nullable Direction side ) - { - if( capability == CAPABILITY_WIRED_ELEMENT ) - { - if( m_destroyed || !BlockCable.canConnectIn( getCachedState(), side ) ) return LazyOptional.empty(); - if( elementCap == null ) elementCap = LazyOptional.of( () -> m_cable ); - return elementCap.cast(); - } - - if( capability == CAPABILITY_PERIPHERAL ) - { - refreshDirection(); - if( side != null && getMaybeDirection() != side ) return LazyOptional.empty(); - if( modemCap == null ) modemCap = LazyOptional.of( () -> m_modem ); - return modemCap.cast(); - } - - return super.getCapability( capability, side ); - } - boolean hasCable() { return getCachedState().get( BlockCable.CABLE ); diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/TileWiredModemFull.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/TileWiredModemFull.java index 8fbef71f4..aed9da94b 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/TileWiredModemFull.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/TileWiredModemFull.java @@ -6,6 +6,7 @@ package dan200.computercraft.shared.peripheral.modem.wired; import com.google.common.base.Objects; +import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.api.network.wired.IWiredElement; import dan200.computercraft.api.network.wired.IWiredNode; @@ -13,9 +14,7 @@ import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.shared.command.CommandCopy; import dan200.computercraft.shared.common.TileGeneric; import dan200.computercraft.shared.peripheral.modem.ModemState; -import dan200.computercraft.shared.util.CapabilityUtil; import dan200.computercraft.shared.util.DirectionUtil; -import dan200.computercraft.shared.util.SidedCaps; import dan200.computercraft.shared.util.TickScheduler; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntityType; @@ -30,16 +29,11 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.common.util.NonNullConsumer; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.*; -import static dan200.computercraft.shared.Capabilities.CAPABILITY_PERIPHERAL; -import static dan200.computercraft.shared.Capabilities.CAPABILITY_WIRED_ELEMENT; import static dan200.computercraft.shared.peripheral.modem.wired.BlockWiredModemFull.MODEM_ON; import static dan200.computercraft.shared.peripheral.modem.wired.BlockWiredModemFull.PERIPHERAL_ON; @@ -93,7 +87,6 @@ public class TileWiredModemFull extends TileGeneric } private final WiredModemPeripheral[] modems = new WiredModemPeripheral[6]; - private final SidedCaps modemCaps = SidedCaps.ofNonNull( this::getPeripheral ); private boolean m_peripheralAccessAllowed = false; private final WiredModemLocalPeripheral[] m_peripherals = new WiredModemLocalPeripheral[6]; @@ -103,18 +96,15 @@ public class TileWiredModemFull extends TileGeneric private final ModemState m_modemState = new ModemState( () -> TickScheduler.schedule( this ) ); private final WiredModemElement m_element = new FullElement( this ); - private LazyOptional elementCap; private final IWiredNode m_node = m_element.getNode(); - private final NonNullConsumer> connectedNodeChanged = x -> connectionsChanged(); - public TileWiredModemFull( BlockEntityType type ) { super( type ); for( int i = 0; i < m_peripherals.length; i++ ) { Direction facing = Direction.byId( i ); - m_peripherals[i] = new WiredModemLocalPeripheral( () -> refreshPeripheral( facing ) ); + m_peripherals[i] = new WiredModemLocalPeripheral(); } } @@ -138,21 +128,6 @@ public class TileWiredModemFull extends TileGeneric super.destroy(); } - @Override - public void onChunkUnloaded() - { - super.onChunkUnloaded(); - doRemove(); - } - - @Override - protected void invalidateCaps() - { - super.invalidateCaps(); - elementCap = CapabilityUtil.invalidate( elementCap ); - modemCaps.invalidate(); - } - @Override public void markRemoved() { @@ -218,7 +193,7 @@ public class TileWiredModemFull extends TileGeneric for( int i = 0; i < names.size(); i++ ) { if( i > 0 ) base.append( ", " ); - base.append( CommandCopy.createCopyText( names.get( i ) ) ); + base.append(CommandCopy.createCopyText( names.get( i ) ) ); } player.sendMessage( new TranslatableText( kind, base ), false ); @@ -251,9 +226,9 @@ public class TileWiredModemFull extends TileGeneric } @Override - public void onLoad() + public void cancelRemoval() { - super.onLoad(); + super.cancelRemoval(); TickScheduler.schedule( this ); } @@ -289,13 +264,12 @@ public class TileWiredModemFull extends TileGeneric for( Direction facing : DirectionUtil.FACINGS ) { BlockPos offset = current.offset( facing ); - if( !world.isAreaLoaded( offset, 0 ) ) continue; + if( !world.isChunkLoaded(offset) ) continue; - LazyOptional element = ComputerCraftAPI.getWiredElementAt( world, offset, facing.getOpposite() ); - if( !element.isPresent() ) continue; + IWiredElement element = ComputerCraftAPI.getWiredElementAt( world, offset, facing.getOpposite() ); + if( element == null ) continue; - element.addListener( connectedNodeChanged ); - m_node.connectTo( element.orElseThrow( NullPointerException::new ).getNode() ); + m_node.connectTo( element.getNode() ); } } @@ -362,21 +336,6 @@ public class TileWiredModemFull extends TileGeneric m_node.updatePeripherals( peripherals ); } - @Nonnull - @Override - public LazyOptional getCapability( @Nonnull Capability capability, @Nullable Direction side ) - { - if( capability == CAPABILITY_WIRED_ELEMENT ) - { - if( elementCap == null ) elementCap = LazyOptional.of( () -> m_element ); - return elementCap.cast(); - } - - if( capability == CAPABILITY_PERIPHERAL ) return modemCaps.get( side ).cast(); - - return super.getCapability( capability, side ); - } - public IWiredElement getElement() { return m_element; diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemLocalPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemLocalPeripheral.java index 957c4b493..f2ca1c3e5 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemLocalPeripheral.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemLocalPeripheral.java @@ -7,16 +7,14 @@ package dan200.computercraft.shared.peripheral.modem.wired; import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.shared.Peripherals; -import dan200.computercraft.shared.Registry; +import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.util.IDAssigner; +import dan200.computercraft.shared.util.NBTUtil; import net.minecraft.block.Block; import net.minecraft.nbt.CompoundTag; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; -import net.minecraftforge.common.util.Constants; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.common.util.NonNullConsumer; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -38,12 +36,6 @@ public final class WiredModemLocalPeripheral private String type; private IPeripheral peripheral; - private final NonNullConsumer> invalidate; - - public WiredModemLocalPeripheral( @Nonnull Runnable invalidate ) - { - this.invalidate = x -> invalidate.run(); - } /** * Attach a new peripheral from the world. @@ -64,7 +56,7 @@ public final class WiredModemLocalPeripheral } else { - String type = peripheral.getType0(); + String type = peripheral.getType(); int id = this.id; if( id > 0 && this.type == null ) @@ -144,9 +136,9 @@ public final class WiredModemLocalPeripheral BlockPos offset = pos.offset( direction ); Block block = world.getBlockState( offset ).getBlock(); - if( block == Registry.ModBlocks.WIRED_MODEM_FULL.get() || block == Registry.ModBlocks.CABLE.get() ) return null; + if( block == ComputerCraftRegistry.ModBlocks.WIRED_MODEM_FULL || block == ComputerCraftRegistry.ModBlocks.CABLE ) return null; - IPeripheral peripheral = Peripherals.getPeripheral( world, offset, direction.getOpposite(), invalidate ); + IPeripheral peripheral = Peripherals.getPeripheral( world, offset, direction.getOpposite() ); return peripheral instanceof WiredModemPeripheral ? null : peripheral; } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemPeripheral.java index 76bcd6bcb..bdd1187ca 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemPeripheral.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemPeripheral.java @@ -317,7 +317,7 @@ public abstract class WiredModemPeripheral extends ModemPeripheral implements IW this.computer = computer; this.name = name; - type = Objects.requireNonNull(peripheral.getType0(), "Peripheral type cannot be null" ); + type = Objects.requireNonNull( peripheral.getType(), "Peripheral type cannot be null" ); methodMap = PeripheralAPI.getMethods( peripheral ); } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/TileWirelessModem.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/TileWirelessModem.java index aecfbfa73..4db8318de 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/TileWirelessModem.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/TileWirelessModem.java @@ -9,7 +9,6 @@ import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.shared.common.TileGeneric; import dan200.computercraft.shared.peripheral.modem.ModemPeripheral; import dan200.computercraft.shared.peripheral.modem.ModemState; -import dan200.computercraft.shared.util.CapabilityUtil; import dan200.computercraft.shared.util.TickScheduler; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntityType; @@ -17,14 +16,10 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import static dan200.computercraft.shared.Capabilities.CAPABILITY_PERIPHERAL; - public class TileWirelessModem extends TileGeneric { private static class Peripheral extends WirelessModemPeripheral @@ -72,7 +67,6 @@ public class TileWirelessModem extends TileGeneric private Direction modemDirection = Direction.DOWN; private final ModemPeripheral modem; private boolean destroyed = false; - private LazyOptional modemCap; public TileWirelessModem( BlockEntityType type, boolean advanced ) { @@ -82,9 +76,9 @@ public class TileWirelessModem extends TileGeneric } @Override - public void onLoad() + public void cancelRemoval() { - super.onLoad(); + super.cancelRemoval(); TickScheduler.schedule( this ); } @@ -114,8 +108,6 @@ public class TileWirelessModem extends TileGeneric // Invalidate the capability if the direction has changed. I'm not 100% happy with this implementation // - ideally we'd do it within refreshDirection or updateContainingBlockInfo, but this seems the _safest_ // place. - if( currentDirection != modemDirection ) modemCap = CapabilityUtil.invalidate( modemCap ); - if( modem.getModemState().pollChanged() ) updateBlockState(); } @@ -136,19 +128,4 @@ public class TileWirelessModem extends TileGeneric getWorld().setBlockState( getPos(), state.with( BlockWirelessModem.ON, on ) ); } } - - @Nonnull - @Override - public LazyOptional getCapability( @Nonnull Capability cap, @Nullable Direction side ) - { - if( cap == CAPABILITY_PERIPHERAL ) - { - refreshDirection(); - if( side != null && modemDirection != side ) return LazyOptional.empty(); - if( modemCap == null ) modemCap = LazyOptional.of( () -> modem ); - return modemCap.cast(); - } - - return super.getCapability( cap, side ); - } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/WirelessModemPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/WirelessModemPeripheral.java index 68d77d366..1bd677a8c 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/WirelessModemPeripheral.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/WirelessModemPeripheral.java @@ -41,12 +41,12 @@ public abstract class WirelessModemPeripheral extends ModemPeripheral if( world != null ) { Vec3d position = getPosition(); - double minRange = ComputerCraft.modemRange; - double maxRange = ComputerCraft.modemHighAltitudeRange; + double minRange = ComputerCraft.modem_range; + double maxRange = ComputerCraft.modem_highAltitudeRange; if( world.isRaining() && world.isThundering() ) { - minRange = ComputerCraft.modemRangeDuringStorm; - maxRange = ComputerCraft.modemHighAltitudeRangeDuringStorm; + minRange = ComputerCraft.modem_rangeDuringStorm; + maxRange = ComputerCraft.modem_highAltitudeRangeDuringStorm; } if( position.y > 96.0 && maxRange > minRange ) { diff --git a/src/main/java/dan200/computercraft/shared/peripheral/monitor/BlockMonitor.java b/src/main/java/dan200/computercraft/shared/peripheral/monitor/BlockMonitor.java index 3233e8468..516faa24b 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/monitor/BlockMonitor.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/monitor/BlockMonitor.java @@ -20,7 +20,6 @@ import net.minecraft.state.property.Properties; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; -import net.minecraftforge.fml.RegistryObject; import javax.annotation.Nonnull; import javax.annotation.Nullable; diff --git a/src/main/java/dan200/computercraft/shared/peripheral/monitor/ClientMonitor.java b/src/main/java/dan200/computercraft/shared/peripheral/monitor/ClientMonitor.java index 7d89cf426..55d7d01de 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/monitor/ClientMonitor.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/monitor/ClientMonitor.java @@ -13,8 +13,6 @@ import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.gl.VertexBuffer; import net.minecraft.util.math.BlockPos; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL15; import org.lwjgl.opengl.GL30; @@ -24,6 +22,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.Set; +@Environment(EnvType.CLIENT) public final class ClientMonitor extends ClientTerminal { private static final Set allMonitors = new HashSet<>(); diff --git a/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorPeripheral.java index 40b4919ab..c2e8cb050 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorPeripheral.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorPeripheral.java @@ -45,7 +45,7 @@ public class MonitorPeripheral extends TermMethods implements IPeripheral @Nonnull @Override - public String getType0() + public String getType() { return "monitor"; } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorWatcher.java b/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorWatcher.java deleted file mode 100644 index a986a8f74..000000000 --- a/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorWatcher.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.monitor; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.shared.network.NetworkHandler; -import dan200.computercraft.shared.network.client.MonitorClientMessage; -import dan200.computercraft.shared.network.client.TerminalState; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.ChunkPos; -import net.minecraft.world.World; -import net.minecraft.world.chunk.ChunkStatus; -import net.minecraft.world.chunk.WorldChunk; -import net.minecraftforge.event.TickEvent; -import net.minecraftforge.event.world.ChunkWatchEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; - -import java.util.ArrayDeque; -import java.util.Queue; - -@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID ) -public final class MonitorWatcher -{ - private static final Queue watching = new ArrayDeque<>(); - - private MonitorWatcher() - { - } - - static void enqueue( TileMonitor monitor ) - { - if( monitor.enqueued ) return; - - monitor.enqueued = true; - monitor.cached = null; - watching.add( monitor ); - } - - @SubscribeEvent - public static void onWatch( ChunkWatchEvent.Watch event ) - { - ChunkPos chunkPos = event.getPos(); - WorldChunk chunk = (WorldChunk) event.getWorld().getChunk( chunkPos.x, chunkPos.z, ChunkStatus.FULL, false ); - if( chunk == null ) return; - - for( BlockEntity te : chunk.getBlockEntities().values() ) - { - // Find all origin monitors who are not already on the queue. - if( !(te instanceof TileMonitor) ) continue; - - TileMonitor monitor = (TileMonitor) te; - ServerMonitor serverMonitor = getMonitor( monitor ); - if( serverMonitor == null || monitor.enqueued ) continue; - - // We use the cached terminal state if available - this is guaranteed to - TerminalState state = monitor.cached; - if( state == null ) state = monitor.cached = serverMonitor.write(); - NetworkHandler.sendToPlayer( event.getPlayer(), new MonitorClientMessage( monitor.getPos(), state ) ); - } - } - - @SubscribeEvent - public static void onTick( TickEvent.ServerTickEvent event ) - { - if( event.phase != TickEvent.Phase.END ) return; - - long limit = ComputerCraft.monitorBandwidth; - boolean obeyLimit = limit > 0; - - TileMonitor tile; - while( (!obeyLimit || limit > 0) && (tile = watching.poll()) != null ) - { - tile.enqueued = false; - ServerMonitor monitor = getMonitor( tile ); - if( monitor == null ) continue; - - BlockPos pos = tile.getPos(); - World world = tile.getWorld(); - if( !(world instanceof ServerWorld) ) continue; - - WorldChunk chunk = world.getWorldChunk( pos ); - if( !((ServerWorld) world).getChunkManager().threadedAnvilChunkStorage.getPlayersWatchingChunk( chunk.getPos(), false ).findAny().isPresent() ) - { - continue; - } - - TerminalState state = tile.cached = monitor.write(); - NetworkHandler.sendToAllTracking( new MonitorClientMessage( pos, state ), chunk ); - - limit -= state.size(); - } - } - - private static ServerMonitor getMonitor( TileMonitor monitor ) - { - return !monitor.isRemoved() && monitor.getXIndex() == 0 && monitor.getYIndex() == 0 ? monitor.getCachedServerMonitor() : null; - } -} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/monitor/TileMonitor.java b/src/main/java/dan200/computercraft/shared/peripheral/monitor/TileMonitor.java index 8aa20e8a8..4acd1212b 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/monitor/TileMonitor.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/monitor/TileMonitor.java @@ -7,13 +7,13 @@ package dan200.computercraft.shared.peripheral.monitor; import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.peripheral.IComputerAccess; -import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.core.terminal.Terminal; import dan200.computercraft.shared.common.ServerTerminal; import dan200.computercraft.shared.common.TileGeneric; import dan200.computercraft.shared.network.client.TerminalState; -import dan200.computercraft.shared.util.CapabilityUtil; import dan200.computercraft.shared.util.TickScheduler; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; @@ -26,16 +26,12 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Box; import net.minecraft.util.math.Direction; import net.minecraft.world.World; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.HashSet; import java.util.Set; -import static dan200.computercraft.shared.Capabilities.CAPABILITY_PERIPHERAL; - public class TileMonitor extends TileGeneric { public static final double RENDER_BORDER = 2.0 / 16.0; @@ -52,7 +48,6 @@ public class TileMonitor extends TileGeneric private ServerMonitor m_serverMonitor; private ClientMonitor m_clientMonitor; private MonitorPeripheral peripheral; - private LazyOptional peripheralCap; private final Set m_computers = new HashSet<>(); private boolean m_destroyed = false; @@ -74,9 +69,9 @@ public class TileMonitor extends TileGeneric } @Override - public void onLoad() + public void cancelRemoval() { - super.onLoad(); + super.cancelRemoval(); TickScheduler.schedule( this ); } @@ -90,19 +85,13 @@ public class TileMonitor extends TileGeneric } @Override + @Environment(EnvType.CLIENT) public void markRemoved() { super.markRemoved(); if( m_clientMonitor != null && m_xIndex == 0 && m_yIndex == 0 ) m_clientMonitor.destroy(); } - @Override - public void onChunkUnloaded() - { - super.onChunkUnloaded(); - if( m_clientMonitor != null && m_xIndex == 0 && m_yIndex == 0 ) m_clientMonitor.destroy(); - } - @Nonnull @Override public ActionResult onActivate( PlayerEntity player, Hand hand, BlockHitResult hit ) @@ -169,28 +158,7 @@ public class TileMonitor extends TileGeneric } } - if( m_serverMonitor.pollTerminalChanged() ) MonitorWatcher.enqueue( this ); - } - - @Override - protected void invalidateCaps() - { - super.invalidateCaps(); - peripheralCap = CapabilityUtil.invalidate( peripheralCap ); - } - - @Nonnull - @Override - public LazyOptional getCapability( @Nonnull Capability cap, @Nullable Direction side ) - { - if( cap == CAPABILITY_PERIPHERAL ) - { - createServerMonitor(); // Ensure the monitor is created before doing anything else. - if( peripheral == null ) peripheral = new MonitorPeripheral( this ); - if( peripheralCap == null ) peripheralCap = LazyOptional.of( () -> peripheral ); - return peripheralCap.cast(); - } - return super.getCapability( cap, side ); + if( m_serverMonitor.pollTerminalChanged() ) updateBlock(); } public ServerMonitor getCachedServerMonitor() @@ -284,7 +252,7 @@ public class TileMonitor extends TileGeneric { // If our index has changed then it's possible the origin monitor has changed. Thus // we'll clear our cache. If we're the origin then we'll need to remove the glList as well. - if( oldXIndex == 0 && oldYIndex == 0 && m_clientMonitor != null ) m_clientMonitor.destroy(); + if(world.isClient() && oldXIndex == 0 && oldYIndex == 0 && m_clientMonitor != null) m_clientMonitor.destroy(); m_clientMonitor = null; } @@ -379,7 +347,7 @@ public class TileMonitor extends TileGeneric int y = pos.getY(); World world = getWorld(); - if( world == null || !world.isAreaLoaded( pos, 0 ) ) return null; + if( world == null || !world.isChunkLoaded(pos) ) return null; BlockEntity tile = world.getBlockEntity( pos ); if( !(tile instanceof TileMonitor) ) return null; @@ -666,30 +634,30 @@ public class TileMonitor extends TileGeneric m_computers.remove( computer ); } - @Nonnull - @Override - public Box getRenderBoundingBox() - { - TileMonitor start = getNeighbour( 0, 0 ); - TileMonitor end = getNeighbour( m_width - 1, m_height - 1 ); - if( start != null && end != null ) - { - BlockPos startPos = start.getPos(); - BlockPos endPos = end.getPos(); - int minX = Math.min( startPos.getX(), endPos.getX() ); - int minY = Math.min( startPos.getY(), endPos.getY() ); - int minZ = Math.min( startPos.getZ(), endPos.getZ() ); - int maxX = Math.max( startPos.getX(), endPos.getX() ) + 1; - int maxY = Math.max( startPos.getY(), endPos.getY() ) + 1; - int maxZ = Math.max( startPos.getZ(), endPos.getZ() ) + 1; - return new Box( minX, minY, minZ, maxX, maxY, maxZ ); - } - else - { - BlockPos pos = getPos(); - return new Box( pos.getX(), pos.getY(), pos.getZ(), pos.getX() + 1, pos.getY() + 1, pos.getZ() + 1 ); - } - } +// @Nonnull +// @Override +// public Box getRenderBoundingBox() +// { +// TileMonitor start = getNeighbour( 0, 0 ); +// TileMonitor end = getNeighbour( m_width - 1, m_height - 1 ); +// if( start != null && end != null ) +// { +// BlockPos startPos = start.getPos(); +// BlockPos endPos = end.getPos(); +// int minX = Math.min( startPos.getX(), endPos.getX() ); +// int minY = Math.min( startPos.getY(), endPos.getY() ); +// int minZ = Math.min( startPos.getZ(), endPos.getZ() ); +// int maxX = Math.max( startPos.getX(), endPos.getX() ) + 1; +// int maxY = Math.max( startPos.getY(), endPos.getY() ) + 1; +// int maxZ = Math.max( startPos.getZ(), endPos.getZ() ) + 1; +// return new Box( minX, minY, minZ, maxX, maxY, maxZ ); +// } +// else +// { +// BlockPos pos = getPos(); +// return new Box( pos.getX(), pos.getY(), pos.getZ(), pos.getX() + 1, pos.getY() + 1, pos.getZ() + 1 ); +// } +// } @Override public double getSquaredRenderDistance() diff --git a/src/main/java/dan200/computercraft/shared/peripheral/printer/BlockPrinter.java b/src/main/java/dan200/computercraft/shared/peripheral/printer/BlockPrinter.java index 31d011850..8e90626c0 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/printer/BlockPrinter.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/printer/BlockPrinter.java @@ -5,7 +5,7 @@ */ package dan200.computercraft.shared.peripheral.printer; -import dan200.computercraft.shared.Registry; +import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.common.BlockGeneric; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -35,7 +35,7 @@ public class BlockPrinter extends BlockGeneric public BlockPrinter( Settings settings ) { - super( settings, Registry.ModTiles.PRINTER ); + super( settings, ComputerCraftRegistry.ModTiles.PRINTER ); setDefaultState( getStateManager().getDefaultState() .with( FACING, Direction.NORTH ) .with( TOP, false ) diff --git a/src/main/java/dan200/computercraft/shared/peripheral/printer/ContainerPrinter.java b/src/main/java/dan200/computercraft/shared/peripheral/printer/ContainerPrinter.java index 91701de97..4912ae238 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/printer/ContainerPrinter.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/printer/ContainerPrinter.java @@ -5,7 +5,7 @@ */ package dan200.computercraft.shared.peripheral.printer; -import dan200.computercraft.shared.Registry; +import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.util.SingleIntArray; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; @@ -26,7 +26,7 @@ public class ContainerPrinter extends ScreenHandler private ContainerPrinter( int id, PlayerInventory player, Inventory inventory, PropertyDelegate properties ) { - super( Registry.ModContainers.PRINTER, id ); + super( ComputerCraftRegistry.ModContainers.PRINTER, id ); this.properties = properties; this.inventory = inventory; diff --git a/src/main/java/dan200/computercraft/shared/peripheral/printer/PrinterPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/printer/PrinterPeripheral.java index 098f4c573..7c6543b14 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/printer/PrinterPeripheral.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/printer/PrinterPeripheral.java @@ -31,7 +31,7 @@ public class PrinterPeripheral implements IPeripheral @Nonnull @Override - public String getType0() + public String getType() { return "printer"; } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java b/src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java index 4760b3f2f..b825b7e24 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java @@ -3,173 +3,150 @@ * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.shared.peripheral.printer; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import dan200.computercraft.ComputerCraft; +import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.core.terminal.Terminal; import dan200.computercraft.shared.common.TileGeneric; import dan200.computercraft.shared.media.items.ItemPrintout; -import dan200.computercraft.shared.network.Containers; -import dan200.computercraft.shared.util.ColourUtils; -import dan200.computercraft.shared.util.DefaultSidedInventory; -import dan200.computercraft.shared.util.ItemStorage; -import dan200.computercraft.shared.util.NamedBlockEntityType; -import dan200.computercraft.shared.util.WorldUtil; - +import dan200.computercraft.shared.util.*; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.inventory.Inventories; -import net.minecraft.item.DyeItem; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; +import net.minecraft.item.*; import net.minecraft.nbt.CompoundTag; import net.minecraft.screen.NamedScreenHandlerFactory; import net.minecraft.screen.ScreenHandler; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; import net.minecraft.text.TranslatableText; -import net.minecraft.util.ActionResult; -import net.minecraft.util.DyeColor; -import net.minecraft.util.Hand; -import net.minecraft.util.Identifier; -import net.minecraft.util.Nameable; +import net.minecraft.util.*; import net.minecraft.util.collection.DefaultedList; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; -public final class TilePrinter extends TileGeneric implements DefaultSidedInventory, Nameable, NamedScreenHandlerFactory { +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public final class TilePrinter extends TileGeneric implements DefaultSidedInventory, Nameable, NamedScreenHandlerFactory +{ private static final String NBT_NAME = "CustomName"; private static final String NBT_PRINTING = "Printing"; private static final String NBT_PAGE_TITLE = "PageTitle"; - public static final NamedBlockEntityType FACTORY = NamedBlockEntityType.create(new Identifier(ComputerCraft.MOD_ID, "printer"), - TilePrinter::new); static final int SLOTS = 13; - private static final int[] BOTTOM_SLOTS = new int[] { - 7, - 8, - 9, - 10, - 11, - 12 - }; - private static final int[] TOP_SLOTS = new int[] { - 1, - 2, - 3, - 4, - 5, - 6 - }; - private static final int[] SIDE_SLOTS = new int[] {0}; + private static final int[] BOTTOM_SLOTS = new int[] { 7, 8, 9, 10, 11, 12 }; + private static final int[] TOP_SLOTS = new int[] { 1, 2, 3, 4, 5, 6 }; + private static final int[] SIDE_SLOTS = new int[] { 0 }; Text customName; - private final DefaultedList m_inventory = DefaultedList.ofSize(SLOTS, ItemStack.EMPTY); - private final ItemStorage itemHandlerCaps = ItemStorage.wrap(this); + private final DefaultedList m_inventory = DefaultedList.ofSize( SLOTS, ItemStack.EMPTY ); + private final ItemStorage m_itemHandlerAll = ItemStorage.wrap( this ); - private final Terminal m_page = new Terminal(ItemPrintout.LINE_MAX_LENGTH, ItemPrintout.LINES_PER_PAGE); + private final Terminal m_page = new Terminal( ItemPrintout.LINE_MAX_LENGTH, ItemPrintout.LINES_PER_PAGE ); private String m_pageTitle = ""; private boolean m_printing = false; - public TilePrinter(BlockEntityType type) { - super(type); + public TilePrinter( BlockEntityType type ) + { + super( type ); } @Override - public void destroy() { + public void destroy() + { ejectContents(); } @Nonnull @Override - public ActionResult onActivate(PlayerEntity player, Hand hand, BlockHitResult hit) { - if (player.isInSneakingPose()) { - return ActionResult.PASS; - } + public ActionResult onActivate( PlayerEntity player, Hand hand, BlockHitResult hit ) + { + if( player.isInSneakingPose() ) return ActionResult.PASS; - if (!getWorld().isClient) { - Containers.openPrinterGUI(player, this); - } + if( !getWorld().isClient ) player.openHandledScreen( this ); return ActionResult.SUCCESS; } @Override - public void fromTag(@Nonnull BlockState state, @Nonnull CompoundTag nbt) { - super.fromTag(state, nbt); + public void fromTag( @Nonnull BlockState state, @Nonnull CompoundTag nbt ) + { + super.fromTag( state, nbt ); - customName = nbt.contains(NBT_NAME) ? Text.Serializer.fromJson(nbt.getString(NBT_NAME)) : null; + customName = nbt.contains( NBT_NAME ) ? Text.Serializer.fromJson( nbt.getString( NBT_NAME ) ) : null; // Read page - synchronized (m_page) { - m_printing = nbt.getBoolean(NBT_PRINTING); - m_pageTitle = nbt.getString(NBT_PAGE_TITLE); - m_page.readFromNBT(nbt); + synchronized( m_page ) + { + m_printing = nbt.getBoolean( NBT_PRINTING ); + m_pageTitle = nbt.getString( NBT_PAGE_TITLE ); + m_page.readFromNBT( nbt ); } // Read inventory - Inventories.fromTag(nbt, m_inventory); + Inventories.fromTag( nbt, m_inventory ); } @Nonnull @Override - public CompoundTag toTag(@Nonnull CompoundTag nbt) { - if (customName != null) { - nbt.putString(NBT_NAME, Text.Serializer.toJson(customName)); - } + public CompoundTag toTag( @Nonnull CompoundTag nbt ) + { + if( customName != null ) nbt.putString( NBT_NAME, Text.Serializer.toJson( customName ) ); // Write page - synchronized (m_page) { - nbt.putBoolean(NBT_PRINTING, m_printing); - nbt.putString(NBT_PAGE_TITLE, m_pageTitle); - m_page.writeToNBT(nbt); + synchronized( m_page ) + { + nbt.putBoolean( NBT_PRINTING, m_printing ); + nbt.putString( NBT_PAGE_TITLE, m_pageTitle ); + m_page.writeToNBT( nbt ); } // Write inventory - Inventories.toTag(nbt, m_inventory); + Inventories.toTag( nbt, m_inventory ); - return super.toTag(nbt); + return super.toTag( nbt ); } - boolean isPrinting() { + boolean isPrinting() + { return m_printing; } // IInventory implementation @Override - public int size() { + public int size() + { return m_inventory.size(); } @Override - public boolean isEmpty() { - for (ItemStack stack : m_inventory) { - if (!stack.isEmpty()) { - return false; - } + public boolean isEmpty() + { + for( ItemStack stack : m_inventory ) + { + if( !stack.isEmpty() ) return false; } return true; } @Nonnull @Override - public ItemStack getStack(int slot) { - return m_inventory.get(slot); + public ItemStack getStack( int slot ) + { + return m_inventory.get( slot ); } @Nonnull @Override - public ItemStack removeStack(int slot) { - ItemStack result = m_inventory.get(slot); - m_inventory.set(slot, ItemStack.EMPTY); + public ItemStack removeStack( int slot ) + { + ItemStack result = m_inventory.get( slot ); + m_inventory.set( slot, ItemStack.EMPTY ); markDirty(); updateBlockState(); return result; @@ -177,21 +154,21 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent @Nonnull @Override - public ItemStack removeStack(int slot, int count) { - ItemStack stack = m_inventory.get(slot); - if (stack.isEmpty()) { - return ItemStack.EMPTY; - } + public ItemStack removeStack( int slot, int count ) + { + ItemStack stack = m_inventory.get( slot ); + if( stack.isEmpty() ) return ItemStack.EMPTY; - if (stack.getCount() <= count) { - setStack(slot, ItemStack.EMPTY); + if( stack.getCount() <= count ) + { + setStack( slot, ItemStack.EMPTY ); return stack; } - ItemStack part = stack.split(count); - if (m_inventory.get(slot) - .isEmpty()) { - m_inventory.set(slot, ItemStack.EMPTY); + ItemStack part = stack.split( count ); + if( m_inventory.get( slot ).isEmpty() ) + { + m_inventory.set( slot, ItemStack.EMPTY ); updateBlockState(); } markDirty(); @@ -199,154 +176,171 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent } @Override - public void setStack(int slot, @Nonnull ItemStack stack) { - m_inventory.set(slot, stack); + public void setStack( int slot, @Nonnull ItemStack stack ) + { + m_inventory.set( slot, stack ); markDirty(); updateBlockState(); } @Override - public void clear() { - for (int i = 0; i < m_inventory.size(); i++) { - m_inventory.set(i, ItemStack.EMPTY); + public void clear() + { + for( int i = 0; i < m_inventory.size(); i++ ) m_inventory.set( i, ItemStack.EMPTY ); + markDirty(); + updateBlockState(); + } + + @Override + public boolean isValid( int slot, @Nonnull ItemStack stack ) + { + if( slot == 0 ) + { + return isInk( stack ); } - markDirty(); - updateBlockState(); - } - - @Override - public boolean isValid(int slot, @Nonnull ItemStack stack) { - if (slot == 0) { - return isInk(stack); - } else if (slot >= TOP_SLOTS[0] && slot <= TOP_SLOTS[TOP_SLOTS.length - 1]) { - return isPaper(stack); - } else { + else if( slot >= TOP_SLOTS[0] && slot <= TOP_SLOTS[TOP_SLOTS.length - 1] ) + { + return isPaper( stack ); + } + else + { return false; } } @Override - public boolean canPlayerUse(@Nonnull PlayerEntity playerEntity) { - return isUsable(playerEntity, false); + public boolean canPlayerUse( @Nonnull PlayerEntity playerEntity ) + { + return isUsable( playerEntity, false ); } // ISidedInventory implementation @Nonnull @Override - public int[] getAvailableSlots(@Nonnull Direction side) { - switch (side) { - case DOWN: // Bottom (Out tray) - return BOTTOM_SLOTS; - case UP: // Top (In tray) - return TOP_SLOTS; - default: // Sides (Ink) - return SIDE_SLOTS; + public int[] getAvailableSlots( @Nonnull Direction side ) + { + switch( side ) + { + case DOWN: // Bottom (Out tray) + return BOTTOM_SLOTS; + case UP: // Top (In tray) + return TOP_SLOTS; + default: // Sides (Ink) + return SIDE_SLOTS; } } @Nullable - Terminal getCurrentPage() { - synchronized (m_page) { + Terminal getCurrentPage() + { + synchronized( m_page ) + { return m_printing ? m_page : null; } } - boolean startNewPage() { - synchronized (m_page) { - if (!canInputPage()) { - return false; - } - if (m_printing && !outputPage()) { - return false; - } + boolean startNewPage() + { + synchronized( m_page ) + { + if( !canInputPage() ) return false; + if( m_printing && !outputPage() ) return false; return inputPage(); } } - boolean endCurrentPage() { - synchronized (m_page) { + boolean endCurrentPage() + { + synchronized( m_page ) + { return m_printing && outputPage(); } } - int getInkLevel() { - ItemStack inkStack = m_inventory.get(0); - return isInk(inkStack) ? inkStack.getCount() : 0; + int getInkLevel() + { + ItemStack inkStack = m_inventory.get( 0 ); + return isInk( inkStack ) ? inkStack.getCount() : 0; } - int getPaperLevel() { + int getPaperLevel() + { int count = 0; - for (int i = 1; i < 7; i++) { - ItemStack paperStack = m_inventory.get(i); - if (isPaper(paperStack)) { - count += paperStack.getCount(); - } + for( int i = 1; i < 7; i++ ) + { + ItemStack paperStack = m_inventory.get( i ); + if( isPaper( paperStack ) ) count += paperStack.getCount(); } return count; } - void setPageTitle(String title) { - synchronized (m_page) { - if (m_printing) { - m_pageTitle = title; - } + void setPageTitle( String title ) + { + synchronized( m_page ) + { + if( m_printing ) m_pageTitle = title; } } - private static boolean isInk(@Nonnull ItemStack stack) { + private static boolean isInk( @Nonnull ItemStack stack ) + { return stack.getItem() instanceof DyeItem; } - private static boolean isPaper(@Nonnull ItemStack stack) { + private static boolean isPaper( @Nonnull ItemStack stack ) + { Item item = stack.getItem(); - return item == Items.PAPER || (item instanceof ItemPrintout && ((ItemPrintout) item).getType() == ItemPrintout.Type.PAGE); + return item == Items.PAPER + || (item instanceof ItemPrintout && ((ItemPrintout) item).getType() == ItemPrintout.Type.PAGE); } - private boolean canInputPage() { - ItemStack inkStack = m_inventory.get(0); - return !inkStack.isEmpty() && isInk(inkStack) && getPaperLevel() > 0; + private boolean canInputPage() + { + ItemStack inkStack = m_inventory.get( 0 ); + return !inkStack.isEmpty() && isInk( inkStack ) && getPaperLevel() > 0; } - private boolean inputPage() { - ItemStack inkStack = m_inventory.get(0); - if (!isInk(inkStack)) { - return false; - } + private boolean inputPage() + { + ItemStack inkStack = m_inventory.get( 0 ); + if( !isInk( inkStack ) ) return false; - for (int i = 1; i < 7; i++) { - ItemStack paperStack = m_inventory.get(i); - if (paperStack.isEmpty() || !isPaper(paperStack)) { - continue; - } + for( int i = 1; i < 7; i++ ) + { + ItemStack paperStack = m_inventory.get( i ); + if( paperStack.isEmpty() || !isPaper( paperStack ) ) continue; // Setup the new page - DyeColor dye = ColourUtils.getStackColour(inkStack); - m_page.setTextColour(dye != null ? dye.getId() : 15); + DyeColor dye = ColourUtils.getStackColour( inkStack ); + m_page.setTextColour( dye != null ? dye.getId() : 15 ); m_page.clear(); - if (paperStack.getItem() instanceof ItemPrintout) { - m_pageTitle = ItemPrintout.getTitle(paperStack); - String[] text = ItemPrintout.getText(paperStack); - String[] textColour = ItemPrintout.getColours(paperStack); - for (int y = 0; y < m_page.getHeight(); y++) { - m_page.setLine(y, text[y], textColour[y], ""); + if( paperStack.getItem() instanceof ItemPrintout ) + { + m_pageTitle = ItemPrintout.getTitle( paperStack ); + String[] text = ItemPrintout.getText( paperStack ); + String[] textColour = ItemPrintout.getColours( paperStack ); + for( int y = 0; y < m_page.getHeight(); y++ ) + { + m_page.setLine( y, text[y], textColour[y], "" ); } - } else { + } + else + { m_pageTitle = ""; } - m_page.setCursorPos(0, 0); + m_page.setCursorPos( 0, 0 ); // Decrement ink - inkStack.decrement(1); - if (inkStack.isEmpty()) { - m_inventory.set(0, ItemStack.EMPTY); - } + inkStack.decrement( 1 ); + if( inkStack.isEmpty() ) m_inventory.set( 0, ItemStack.EMPTY ); // Decrement paper - paperStack.decrement(1); - if (paperStack.isEmpty()) { - m_inventory.set(i, ItemStack.EMPTY); + paperStack.decrement( 1 ); + if( paperStack.isEmpty() ) + { + m_inventory.set( i, ItemStack.EMPTY ); updateBlockState(); } @@ -357,22 +351,23 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent return false; } - private boolean outputPage() { + private boolean outputPage() + { int height = m_page.getHeight(); String[] lines = new String[height]; String[] colours = new String[height]; - for (int i = 0; i < height; i++) { - lines[i] = m_page.getLine(i) - .toString(); - colours[i] = m_page.getTextColourLine(i) - .toString(); + for( int i = 0; i < height; i++ ) + { + lines[i] = m_page.getLine( i ).toString(); + colours[i] = m_page.getTextColourLine( i ).toString(); } - ItemStack stack = ItemPrintout.createSingleFromTitleAndText(m_pageTitle, lines, colours); - for (int slot : BOTTOM_SLOTS) { - if (m_inventory.get(slot) - .isEmpty()) { - setStack(slot, stack); + ItemStack stack = ItemPrintout.createSingleFromTitleAndText( m_pageTitle, lines, colours ); + for( int slot : BOTTOM_SLOTS ) + { + if( m_inventory.get( slot ).isEmpty() ) + { + setStack( slot, stack ); m_printing = false; return true; } @@ -380,84 +375,87 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent return false; } - private void ejectContents() { - for (int i = 0; i < 13; i++) { - ItemStack stack = m_inventory.get(i); - if (!stack.isEmpty()) { + private void ejectContents() + { + for( int i = 0; i < 13; i++ ) + { + ItemStack stack = m_inventory.get( i ); + if( !stack.isEmpty() ) + { // Remove the stack from the inventory - setStack(i, ItemStack.EMPTY); + setStack( i, ItemStack.EMPTY ); // Spawn the item in the world - WorldUtil.dropItemStack(stack, - getWorld(), - Vec3d.of(getPos()) - .add(0.5, 0.75, 0.5)); + WorldUtil.dropItemStack( stack, getWorld(), Vec3d.of( getPos() ).add( 0.5, 0.75, 0.5 ) ); } } } - private void updateBlockState() { + private void updateBlockState() + { boolean top = false, bottom = false; - for (int i = 1; i < 7; i++) { - ItemStack stack = m_inventory.get(i); - if (!stack.isEmpty() && isPaper(stack)) { + for( int i = 1; i < 7; i++ ) + { + ItemStack stack = m_inventory.get( i ); + if( !stack.isEmpty() && isPaper( stack ) ) + { top = true; break; } } - for (int i = 7; i < 13; i++) { - ItemStack stack = m_inventory.get(i); - if (!stack.isEmpty() && isPaper(stack)) { + for( int i = 7; i < 13; i++ ) + { + ItemStack stack = m_inventory.get( i ); + if( !stack.isEmpty() && isPaper( stack ) ) + { bottom = true; break; } } - updateBlockState(top, bottom); + updateBlockState( top, bottom ); } - private void updateBlockState(boolean top, boolean bottom) { - if (removed) { - return; - } + private void updateBlockState( boolean top, boolean bottom ) + { + if( removed ) return; BlockState state = getCachedState(); - if (state.get(BlockPrinter.TOP) == top & state.get(BlockPrinter.BOTTOM) == bottom) { - return; - } + if( state.get( BlockPrinter.TOP ) == top & state.get( BlockPrinter.BOTTOM ) == bottom ) return; - getWorld().setBlockState(getPos(), - state.with(BlockPrinter.TOP, top) - .with(BlockPrinter.BOTTOM, bottom)); + getWorld().setBlockState( getPos(), state.with( BlockPrinter.TOP, top ).with( BlockPrinter.BOTTOM, bottom ) ); } - @Override - public boolean hasCustomName() { + public boolean hasCustomName() + { return customName != null; } @Nullable @Override - public Text getCustomName() { + public Text getCustomName() + { return customName; } @Nonnull @Override - public Text getName() { - return customName != null ? customName : new TranslatableText(getCachedState().getBlock() - .getTranslationKey()); + public Text getName() + { + return customName != null ? customName : new TranslatableText( getCachedState().getBlock().getTranslationKey() ); } @Override - public Text getDisplayName() { + public Text getDisplayName() + { return Nameable.super.getDisplayName(); } @Nonnull @Override - public ScreenHandler createMenu(int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity player) { - return new ContainerPrinter(id, inventory, this); + public ScreenHandler createMenu( int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity player ) + { + return new ContainerPrinter( id, inventory, this ); } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/speaker/BlockSpeaker.java b/src/main/java/dan200/computercraft/shared/peripheral/speaker/BlockSpeaker.java index 8305c06b6..7a44a6751 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/speaker/BlockSpeaker.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/speaker/BlockSpeaker.java @@ -5,7 +5,7 @@ */ package dan200.computercraft.shared.peripheral.speaker; -import dan200.computercraft.shared.Registry; +import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.common.BlockGeneric; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -22,7 +22,7 @@ public class BlockSpeaker extends BlockGeneric public BlockSpeaker( Settings settings ) { - super( settings, Registry.ModTiles.SPEAKER ); + super( settings, ComputerCraftRegistry.ModTiles.SPEAKER ); setDefaultState( getStateManager().getDefaultState() .with( FACING, Direction.NORTH ) ); } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/speaker/SpeakerPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/speaker/SpeakerPeripheral.java index 4b31d7ce0..7c00ed8cd 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/speaker/SpeakerPeripheral.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/speaker/SpeakerPeripheral.java @@ -53,7 +53,7 @@ public abstract class SpeakerPeripheral implements IPeripheral @Nonnull @Override - public String getType0() + public String getType() { return "speaker"; } @@ -128,7 +128,7 @@ public abstract class SpeakerPeripheral implements IPeripheral if( instrument == null ) throw new LuaException( "Invalid instrument, \"" + name + "\"!" ); // If the resource location for note block notes changes, this method call will need to be updated - boolean success = playSound( context, instrument.getSound().getRegistryName(), volume, (float) Math.pow( 2.0, (pitch - 12.0) / 12.0 ), true ); + boolean success = playSound( context, instrument.getSound().getId(), volume, (float) Math.pow( 2.0, (pitch - 12.0) / 12.0 ), true ); if( success ) m_notesThisTick.incrementAndGet(); return success; } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/speaker/TileSpeaker.java b/src/main/java/dan200/computercraft/shared/peripheral/speaker/TileSpeaker.java index 35550694d..dd9dd1900 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/speaker/TileSpeaker.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/speaker/TileSpeaker.java @@ -7,27 +7,21 @@ package dan200.computercraft.shared.peripheral.speaker; import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.shared.common.TileGeneric; -import dan200.computercraft.shared.util.CapabilityUtil; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.util.Tickable; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import static dan200.computercraft.shared.Capabilities.CAPABILITY_PERIPHERAL; - public class TileSpeaker extends TileGeneric implements Tickable { public static final int MIN_TICKS_BETWEEN_SOUNDS = 1; private final SpeakerPeripheral peripheral; - private LazyOptional peripheralCap; public TileSpeaker( BlockEntityType type ) { @@ -41,26 +35,6 @@ public class TileSpeaker extends TileGeneric implements Tickable peripheral.update(); } - @Nonnull - @Override - public LazyOptional getCapability( @Nonnull Capability cap, @Nullable Direction side ) - { - if( cap == CAPABILITY_PERIPHERAL ) - { - if( peripheralCap == null ) peripheralCap = LazyOptional.of( () -> peripheral ); - return peripheralCap.cast(); - } - - return super.getCapability( cap, side ); - } - - @Override - protected void invalidateCaps() - { - super.invalidateCaps(); - peripheralCap = CapabilityUtil.invalidate( peripheralCap ); - } - private static final class Peripheral extends SpeakerPeripheral { private final TileSpeaker speaker; diff --git a/src/main/java/dan200/computercraft/shared/pocket/apis/PocketAPI.java b/src/main/java/dan200/computercraft/shared/pocket/apis/PocketAPI.java index 12ad5b326..028f0f9bb 100644 --- a/src/main/java/dan200/computercraft/shared/pocket/apis/PocketAPI.java +++ b/src/main/java/dan200/computercraft/shared/pocket/apis/PocketAPI.java @@ -11,13 +11,13 @@ import dan200.computercraft.api.pocket.IPocketUpgrade; import dan200.computercraft.shared.PocketUpgrades; import dan200.computercraft.shared.pocket.core.PocketServerComputer; import dan200.computercraft.shared.util.InventoryUtil; +import dan200.computercraft.shared.util.ItemStorage; import dan200.computercraft.shared.util.WorldUtil; import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.item.ItemStack; import net.minecraft.util.collection.DefaultedList; -import net.minecraftforge.items.wrapper.PlayerMainInvWrapper; /** * Control the current pocket computer, adding or removing upgrades. @@ -83,7 +83,7 @@ public class PocketAPI implements ILuaAPI ItemStack stack = previousUpgrade.getCraftingItem(); if( !stack.isEmpty() ) { - stack = InventoryUtil.storeItems( stack, new PlayerMainInvWrapper( inventory ), inventory.selectedSlot ); + stack = InventoryUtil.storeItems( stack, ItemStorage.wrap( inventory ), inventory.selectedSlot ); if( !stack.isEmpty() ) { WorldUtil.dropItemStack( stack, player.getEntityWorld(), player.getPos() ); @@ -120,7 +120,7 @@ public class PocketAPI implements ILuaAPI ItemStack stack = previousUpgrade.getCraftingItem(); if( !stack.isEmpty() ) { - stack = InventoryUtil.storeItems( stack, new PlayerMainInvWrapper( inventory ), inventory.selectedSlot ); + stack = InventoryUtil.storeItems( stack, ItemStorage.wrap( inventory ), inventory.selectedSlot ); if( stack.isEmpty() ) { WorldUtil.dropItemStack( stack, player.getEntityWorld(), player.getPos() ); diff --git a/src/main/java/dan200/computercraft/shared/pocket/core/PocketServerComputer.java b/src/main/java/dan200/computercraft/shared/pocket/core/PocketServerComputer.java index 40abd8670..a317621cd 100644 --- a/src/main/java/dan200/computercraft/shared/pocket/core/PocketServerComputer.java +++ b/src/main/java/dan200/computercraft/shared/pocket/core/PocketServerComputer.java @@ -16,14 +16,12 @@ import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.network.NetworkHandler; import dan200.computercraft.shared.pocket.items.ItemPocketComputer; import dan200.computercraft.shared.util.NBTUtil; - import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtHelper; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.Identifier; import net.minecraft.world.World; @@ -35,8 +33,6 @@ import java.util.Map; import static dan200.computercraft.shared.pocket.items.ItemPocketComputer.NBT_LIGHT; -import net.fabricmc.fabric.api.util.NbtType; - public class PocketServerComputer extends ServerComputer implements IPocketAccess { private IPocketUpgrade m_upgrade; @@ -45,7 +41,7 @@ public class PocketServerComputer extends ServerComputer implements IPocketAcces public PocketServerComputer( World world, int computerID, String label, int instanceID, ComputerFamily family ) { - super( world, computerID, label, instanceID, family, ComputerCraft.pocketTermWidth, ComputerCraft.pocketTermHeight ); + super( world, computerID, label, instanceID, family, ComputerCraft.terminalWidth_pocketComputer, ComputerCraft.terminalHeight_pocketComputer ); } @Nullable @@ -88,7 +84,7 @@ public class PocketServerComputer extends ServerComputer implements IPocketAcces public int getLight() { CompoundTag tag = getUserData(); - return tag.contains(NBT_LIGHT, NBTUtil.TAG_ANY_NUMERIC) ? tag.getInt(NBT_LIGHT ) : -1; + return tag.contains( NBT_LIGHT, NBTUtil.TAG_ANY_NUMERIC) ? tag.getInt( NBT_LIGHT ) : -1; } @Override diff --git a/src/main/java/dan200/computercraft/shared/pocket/inventory/ContainerPocketComputer.java b/src/main/java/dan200/computercraft/shared/pocket/inventory/ContainerPocketComputer.java index e830343a6..da88dcdc1 100644 --- a/src/main/java/dan200/computercraft/shared/pocket/inventory/ContainerPocketComputer.java +++ b/src/main/java/dan200/computercraft/shared/pocket/inventory/ContainerPocketComputer.java @@ -5,16 +5,19 @@ */ package dan200.computercraft.shared.pocket.inventory; -import dan200.computercraft.shared.Registry; +import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.computer.inventory.ContainerComputerBase; import dan200.computercraft.shared.network.container.ComputerContainerData; import dan200.computercraft.shared.pocket.items.ItemPocketComputer; +import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketByteBuf; import net.minecraft.screen.NamedScreenHandlerFactory; import net.minecraft.screen.ScreenHandler; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; import net.minecraft.util.Hand; import javax.annotation.Nonnull; @@ -24,18 +27,18 @@ public final class ContainerPocketComputer extends ContainerComputerBase { private ContainerPocketComputer( int id, ServerComputer computer, ItemPocketComputer item, Hand hand ) { - super( Registry.ModContainers.POCKET_COMPUTER.get(), id, p -> { + super( ComputerCraftRegistry.ModContainers.POCKET_COMPUTER, id, p -> { ItemStack stack = p.getStackInHand( hand ); return stack.getItem() == item && ItemPocketComputer.getServerComputer( stack ) == computer; }, computer, item.getFamily() ); } - public ContainerPocketComputer( int id, PlayerInventory player, ComputerContainerData data ) + public ContainerPocketComputer( int id, PlayerInventory player, PacketByteBuf packetByteBuf ) { - super( Registry.ModContainers.POCKET_COMPUTER.get(), id, player, data ); + super( ComputerCraftRegistry.ModContainers.POCKET_COMPUTER, id, player, packetByteBuf ); } - public static class Factory implements NamedScreenHandlerFactory + public static class Factory implements NamedScreenHandlerFactory, ExtendedScreenHandlerFactory { private final ServerComputer computer; private final Text name; @@ -64,5 +67,11 @@ public final class ContainerPocketComputer extends ContainerComputerBase { return new ContainerPocketComputer( id, computer, item, hand ); } + + @Override + public void writeScreenOpeningData(ServerPlayerEntity serverPlayerEntity, PacketByteBuf packetByteBuf) { + packetByteBuf.writeInt(computer.getInstanceID()); + packetByteBuf.writeEnumConstant(computer.getFamily()); + } } } diff --git a/src/main/java/dan200/computercraft/shared/pocket/items/ItemPocketComputer.java b/src/main/java/dan200/computercraft/shared/pocket/items/ItemPocketComputer.java index dbfccb9e4..ae1a47a57 100644 --- a/src/main/java/dan200/computercraft/shared/pocket/items/ItemPocketComputer.java +++ b/src/main/java/dan200/computercraft/shared/pocket/items/ItemPocketComputer.java @@ -195,21 +195,21 @@ public class ItemPocketComputer extends Item implements IComputerItem, IMedia, I } } - @Nullable - @Override - public String getCreatorModId( ItemStack stack ) - { - IPocketUpgrade upgrade = getUpgrade( stack ); - if( upgrade != null ) - { - // If we're a non-vanilla, non-CC upgrade then return whichever mod this upgrade - // belongs to. - String mod = PocketUpgrades.getOwner( upgrade ); - if( mod != null && !mod.equals( ComputerCraft.MOD_ID ) ) return mod; - } - - return super.getCreatorModId( stack ); - } +// @Nullable +// @Override +// public String getCreatorModId( ItemStack stack ) +// { +// IPocketUpgrade upgrade = getUpgrade( stack ); +// if( upgrade != null ) +// { +// // If we're a non-vanilla, non-CC upgrade then return whichever mod this upgrade +// // belongs to. +// String mod = PocketUpgrades.getOwner( upgrade ); +// if( mod != null && !mod.equals( ComputerCraft.MOD_ID ) ) return mod; +// } +// +// return super.getCreatorModId( stack ); +// } public PocketServerComputer createServerComputer( final World world, Inventory inventory, Entity entity, @Nonnull ItemStack stack ) { diff --git a/src/main/java/dan200/computercraft/shared/pocket/items/PocketComputerItemFactory.java b/src/main/java/dan200/computercraft/shared/pocket/items/PocketComputerItemFactory.java index 25b2210d1..a8d54b53c 100644 --- a/src/main/java/dan200/computercraft/shared/pocket/items/PocketComputerItemFactory.java +++ b/src/main/java/dan200/computercraft/shared/pocket/items/PocketComputerItemFactory.java @@ -6,7 +6,7 @@ package dan200.computercraft.shared.pocket.items; import dan200.computercraft.api.pocket.IPocketUpgrade; -import dan200.computercraft.shared.Registry; +import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.computer.core.ComputerFamily; import net.minecraft.item.ItemStack; @@ -22,9 +22,9 @@ public final class PocketComputerItemFactory switch( family ) { case NORMAL: - return Registry.ModItems.POCKET_COMPUTER_NORMAL.get().create( id, label, colour, upgrade ); + return ComputerCraftRegistry.ModItems.POCKET_COMPUTER_NORMAL.create( id, label, colour, upgrade ); case ADVANCED: - return Registry.ModItems.POCKET_COMPUTER_ADVANCED.get().create( id, label, colour, upgrade ); + return ComputerCraftRegistry.ModItems.POCKET_COMPUTER_ADVANCED.create( id, label, colour, upgrade ); default: return ItemStack.EMPTY; } diff --git a/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketModem.java b/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketModem.java index eb968493f..cd9960cc2 100644 --- a/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketModem.java +++ b/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketModem.java @@ -8,7 +8,7 @@ package dan200.computercraft.shared.pocket.peripherals; import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.pocket.AbstractPocketUpgrade; import dan200.computercraft.api.pocket.IPocketAccess; -import dan200.computercraft.shared.Registry; +import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.peripheral.modem.ModemState; import net.minecraft.entity.Entity; import net.minecraft.util.Identifier; @@ -24,8 +24,8 @@ public class PocketModem extends AbstractPocketUpgrade super( new Identifier( "computercraft", advanced ? "wireless_modem_advanced" : "wireless_modem_normal" ), advanced - ? Registry.ModBlocks.WIRELESS_MODEM_ADVANCED - : Registry.ModBlocks.WIRELESS_MODEM_NORMAL + ? ComputerCraftRegistry.ModBlocks.WIRELESS_MODEM_ADVANCED + : ComputerCraftRegistry.ModBlocks.WIRELESS_MODEM_NORMAL ); this.advanced = advanced; } diff --git a/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketSpeaker.java b/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketSpeaker.java index 44594858b..20329d446 100644 --- a/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketSpeaker.java +++ b/src/main/java/dan200/computercraft/shared/pocket/peripherals/PocketSpeaker.java @@ -8,7 +8,7 @@ package dan200.computercraft.shared.pocket.peripherals; import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.pocket.AbstractPocketUpgrade; import dan200.computercraft.api.pocket.IPocketAccess; -import dan200.computercraft.shared.Registry; +import dan200.computercraft.shared.ComputerCraftRegistry; import net.minecraft.entity.Entity; import net.minecraft.util.Identifier; import javax.annotation.Nonnull; @@ -18,7 +18,7 @@ public class PocketSpeaker extends AbstractPocketUpgrade { public PocketSpeaker() { - super( new Identifier( "computercraft", "speaker" ), Registry.ModBlocks.SPEAKER ); + super( new Identifier( "computercraft", "speaker" ), ComputerCraftRegistry.ModBlocks.SPEAKER ); } @Nullable diff --git a/src/main/java/dan200/computercraft/shared/pocket/recipes/PocketComputerUpgradeRecipe.java b/src/main/java/dan200/computercraft/shared/pocket/recipes/PocketComputerUpgradeRecipe.java index 9ed34e2b9..301b00684 100644 --- a/src/main/java/dan200/computercraft/shared/pocket/recipes/PocketComputerUpgradeRecipe.java +++ b/src/main/java/dan200/computercraft/shared/pocket/recipes/PocketComputerUpgradeRecipe.java @@ -43,12 +43,12 @@ public final class PocketComputerUpgradeRecipe extends SpecialCraftingRecipe @Override public boolean matches( @Nonnull CraftingInventory inventory, @Nonnull World world ) { - return !getCraftingResult( inventory ).isEmpty(); + return !craft( inventory ).isEmpty(); } @Nonnull @Override - public ItemStack getCraftingResult( @Nonnull CraftingInventory inventory ) + public ItemStack craft( @Nonnull CraftingInventory inventory ) { // Scan the grid for a pocket computer ItemStack computer = ItemStack.EMPTY; diff --git a/src/main/java/dan200/computercraft/shared/proxy/ComputerCraftProxyCommon.java b/src/main/java/dan200/computercraft/shared/proxy/ComputerCraftProxyCommon.java index bc0cb3514..6f5f7d310 100644 --- a/src/main/java/dan200/computercraft/shared/proxy/ComputerCraftProxyCommon.java +++ b/src/main/java/dan200/computercraft/shared/proxy/ComputerCraftProxyCommon.java @@ -8,60 +8,42 @@ package dan200.computercraft.shared.proxy; import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.api.media.IMedia; -import dan200.computercraft.api.network.wired.IWiredElement; -import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.api.turtle.event.TurtleEvent; import dan200.computercraft.core.computer.MainThread; import dan200.computercraft.core.tracking.Tracking; +import dan200.computercraft.shared.TurtlePermissions; import dan200.computercraft.shared.command.CommandComputerCraft; import dan200.computercraft.shared.command.arguments.ArgumentSerializers; import dan200.computercraft.shared.common.DefaultBundledRedstoneProvider; -import dan200.computercraft.shared.computer.core.IComputer; -import dan200.computercraft.shared.computer.core.IContainerComputer; -import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.data.BlockNamedEntityLootCondition; import dan200.computercraft.shared.data.HasComputerIdLootCondition; import dan200.computercraft.shared.data.PlayerCreativeLootCondition; import dan200.computercraft.shared.media.items.RecordMedia; import dan200.computercraft.shared.network.NetworkHandler; import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork; -import dan200.computercraft.shared.util.NullStorage; +import dan200.computercraft.shared.turtle.FurnaceRefuelHandler; +import dan200.computercraft.shared.util.TickScheduler; +import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.minecraft.item.Item; import net.minecraft.item.MusicDiscItem; -import net.minecraft.loot.*; import net.minecraft.loot.condition.LootConditionType; -import net.minecraft.loot.entry.LootTableEntry; -import net.minecraft.screen.ScreenHandler; +import net.minecraft.server.MinecraftServer; import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; -import net.minecraftforge.common.capabilities.CapabilityManager; -import net.minecraftforge.event.LootTableLoadEvent; -import net.minecraftforge.event.RegisterCommandsEvent; -import net.minecraftforge.event.TickEvent; -import net.minecraftforge.event.entity.player.PlayerContainerEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; -import net.minecraftforge.fml.event.server.FMLServerStartedEvent; -import net.minecraftforge.fml.event.server.FMLServerStoppedEvent; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD ) public final class ComputerCraftProxyCommon { - @SubscribeEvent - @SuppressWarnings( "deprecation" ) - public static void init( FMLCommonSetupEvent event ) - { + private static MinecraftServer server; + + public static void init() { NetworkHandler.setup(); - net.minecraftforge.fml.DeferredWorkQueue.runLater( () -> { - registerProviders(); - ArgumentSerializers.register(); - registerLoot(); - } ); + registerProviders(); + registerHandlers(); + + ArgumentSerializers.register(); } public static void registerLoot() @@ -88,106 +70,34 @@ public final class ComputerCraftProxyCommon if( item instanceof MusicDiscItem ) return RecordMedia.INSTANCE; return null; } ); - - // Register capabilities - CapabilityManager.INSTANCE.register( IWiredElement.class, new NullStorage<>(), () -> null ); - CapabilityManager.INSTANCE.register( IPeripheral.class, new NullStorage<>(), () -> null ); } - @Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID ) - public static final class ForgeHandlers - { - private ForgeHandlers() - { - } + private static void registerHandlers() { + CommandRegistrationCallback.EVENT.register(CommandComputerCraft::register); - /* - @SubscribeEvent - public static void onConnectionOpened( FMLNetworkEvent.ClientConnectedToServerEvent event ) - { - ComputerCraft.clientComputerRegistry.reset(); - } + ServerTickEvents.START_SERVER_TICK.register(server -> { + MainThread.executePendingTasks(); + ComputerCraft.serverComputerRegistry.update(); + TickScheduler.tick(); + }); - @SubscribeEvent - public static void onConnectionClosed( FMLNetworkEvent.ClientDisconnectionFromServerEvent event ) - { - ComputerCraft.clientComputerRegistry.reset(); - } - */ - - @SubscribeEvent - public static void onServerTick( TickEvent.ServerTickEvent event ) - { - if( event.phase == TickEvent.Phase.START ) - { - MainThread.executePendingTasks(); - ComputerCraft.serverComputerRegistry.update(); - } - } - - @SubscribeEvent - public static void onContainerOpen( PlayerContainerEvent.Open event ) - { - // If we're opening a computer container then broadcast the terminal state - ScreenHandler container = event.getContainer(); - if( container instanceof IContainerComputer ) - { - IComputer computer = ((IContainerComputer) container).getComputer(); - if( computer instanceof ServerComputer ) - { - ((ServerComputer) computer).sendTerminalState( event.getPlayer() ); - } - } - } - - @SubscribeEvent - public static void onRegisterCommand( RegisterCommandsEvent event ) - { - CommandComputerCraft.register( event.getDispatcher() ); - } - - @SubscribeEvent - public static void onServerStarted( FMLServerStartedEvent event ) - { + ServerLifecycleEvents.SERVER_STARTED.register(server -> { + ComputerCraftProxyCommon.server = server; ComputerCraft.serverComputerRegistry.reset(); WirelessNetwork.resetNetworks(); + MainThread.reset(); Tracking.reset(); - } + }); - @SubscribeEvent - public static void onServerStopped( FMLServerStoppedEvent event ) - { + ServerLifecycleEvents.SERVER_STOPPING.register(server -> { ComputerCraft.serverComputerRegistry.reset(); WirelessNetwork.resetNetworks(); + MainThread.reset(); Tracking.reset(); - } + ComputerCraftProxyCommon.server = null; + }); - public static final Identifier LOOT_TREASURE_DISK = new Identifier( ComputerCraft.MOD_ID, "treasure_disk" ); - - private static final Set TABLES = new HashSet<>( Arrays.asList( - LootTables.SIMPLE_DUNGEON_CHEST, - LootTables.ABANDONED_MINESHAFT_CHEST, - LootTables.STRONGHOLD_CORRIDOR_CHEST, - LootTables.STRONGHOLD_CROSSING_CHEST, - LootTables.STRONGHOLD_LIBRARY_CHEST, - LootTables.DESERT_PYRAMID_CHEST, - LootTables.JUNGLE_TEMPLE_CHEST, - LootTables.IGLOO_CHEST_CHEST, - LootTables.WOODLAND_MANSION_CHEST, - LootTables.VILLAGE_CARTOGRAPHER_CHEST - ) ); - - @SubscribeEvent - public static void lootLoad( LootTableLoadEvent event ) - { - Identifier name = event.getName(); - if( !name.getNamespace().equals( "minecraft" ) || !TABLES.contains( name ) ) return; - - event.getTable().addPool( LootPool.builder() - .with( LootTableEntry.builder( LOOT_TREASURE_DISK ) ) - .rolls( ConstantLootTableRange.create( 1 ) ) - .name( "computercraft_treasure" ) - .build() ); - } + TurtleEvent.EVENT_BUS.register(FurnaceRefuelHandler.INSTANCE); + TurtleEvent.EVENT_BUS.register(new TurtlePermissions()); } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/FurnaceRefuelHandler.java b/src/main/java/dan200/computercraft/shared/turtle/FurnaceRefuelHandler.java index d70cbcf9b..849ccd1da 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/FurnaceRefuelHandler.java +++ b/src/main/java/dan200/computercraft/shared/turtle/FurnaceRefuelHandler.java @@ -5,22 +5,21 @@ */ package dan200.computercraft.shared.turtle; -import dan200.computercraft.ComputerCraft; +import com.google.common.eventbus.Subscribe; import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.event.TurtleRefuelEvent; import dan200.computercraft.shared.util.InventoryUtil; +import dan200.computercraft.shared.util.ItemStorage; import dan200.computercraft.shared.util.WorldUtil; +import net.minecraft.block.entity.FurnaceBlockEntity; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraftforge.common.ForgeHooks; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; import javax.annotation.Nonnull; -@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID ) public final class FurnaceRefuelHandler implements TurtleRefuelEvent.Handler { - private static final FurnaceRefuelHandler INSTANCE = new FurnaceRefuelHandler(); + public static final FurnaceRefuelHandler INSTANCE = new FurnaceRefuelHandler(); private FurnaceRefuelHandler() { @@ -29,21 +28,21 @@ public final class FurnaceRefuelHandler implements TurtleRefuelEvent.Handler @Override public int refuel( @Nonnull ITurtleAccess turtle, @Nonnull ItemStack currentStack, int slot, int limit ) { - int fuelSpaceLeft = turtle.getFuelLimit() - turtle.getFuelLevel(); - int fuelPerItem = getFuelPerItem( turtle.getItemHandler().getStackInSlot( slot ) ); - int fuelItemLimit = (int) Math.ceil( fuelSpaceLeft / (double) fuelPerItem ); - if( limit > fuelItemLimit ) limit = fuelItemLimit; + ItemStorage storage = ItemStorage.wrap(turtle.getInventory()); + ItemStack stack = storage.take(slot, limit, ItemStack.EMPTY, false); + int fuelToGive = getFuelPerItem(stack) * stack.getCount(); - ItemStack stack = turtle.getItemHandler().extractItem( slot, limit, false ); - int fuelToGive = fuelPerItem * stack.getCount(); // Store the replacement item in the inventory - ItemStack replacementStack = stack.getItem().getContainerItem( stack ); - if( !replacementStack.isEmpty() ) - { - ItemStack remainder = InventoryUtil.storeItems( replacementStack, turtle.getItemHandler(), turtle.getSelectedSlot() ); - if( !remainder.isEmpty() ) - { - WorldUtil.dropItemStack( remainder, turtle.getWorld(), turtle.getPosition(), turtle.getDirection().getOpposite() ); + Item replacementStack = stack.getItem() + .getRecipeRemainder(); + if (replacementStack != null) { + ItemStack remainder = InventoryUtil.storeItems(new ItemStack(replacementStack), storage, turtle.getSelectedSlot()); + if (!remainder.isEmpty()) { + WorldUtil.dropItemStack(remainder, + turtle.getWorld(), + turtle.getPosition(), + turtle.getDirection() + .getOpposite()); } } @@ -52,12 +51,16 @@ public final class FurnaceRefuelHandler implements TurtleRefuelEvent.Handler private static int getFuelPerItem( @Nonnull ItemStack stack ) { - return (ForgeHooks.getBurnTime( stack ) * 5) / 100; + int burnTime = FurnaceBlockEntity.createFuelTimeMap() + .getOrDefault(stack.getItem(), 0); + return (burnTime * 5) / 100; } - @SubscribeEvent + @Subscribe public static void onTurtleRefuel( TurtleRefuelEvent event ) { - if( event.getHandler() == null && getFuelPerItem( event.getStack() ) > 0 ) event.setHandler( INSTANCE ); + if (event.getHandler() == null && getFuelPerItem(event.getStack()) > 0) { + event.setHandler(INSTANCE); + } } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/apis/TurtleAPI.java b/src/main/java/dan200/computercraft/shared/turtle/apis/TurtleAPI.java index 41f0f49ff..9eae79611 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/apis/TurtleAPI.java +++ b/src/main/java/dan200/computercraft/shared/turtle/apis/TurtleAPI.java @@ -11,14 +11,15 @@ import dan200.computercraft.api.turtle.ITurtleCommand; import dan200.computercraft.api.turtle.TurtleCommandResult; import dan200.computercraft.api.turtle.TurtleSide; import dan200.computercraft.api.turtle.event.TurtleActionEvent; +import dan200.computercraft.api.turtle.event.TurtleEvent; import dan200.computercraft.api.turtle.event.TurtleInspectItemEvent; import dan200.computercraft.core.apis.IAPIEnvironment; import dan200.computercraft.core.asm.TaskCallback; import dan200.computercraft.core.tracking.TrackingField; -import dan200.computercraft.shared.peripheral.generic.data.ItemData; import dan200.computercraft.shared.turtle.core.*; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraftforge.common.MinecraftForge; +import net.minecraft.util.registry.Registry; import java.util.HashMap; import java.util.Map; @@ -603,12 +604,15 @@ public class TurtleAPI implements ILuaAPI ItemStack stack = turtle.getInventory().getStack( slot ); if( stack.isEmpty() ) return new Object[] { null }; - Map table = detailed - ? ItemData.fill( new HashMap<>(), stack ) - : ItemData.fillBasicSafe( new HashMap<>(), stack ); + Item item = stack.getItem(); + String name = Registry.ITEM.getId(item).toString(); + int count = stack.getCount(); + Map table = new HashMap<>(); + table.put("name", name); + table.put("count", count); TurtleActionEvent event = new TurtleInspectItemEvent( turtle, stack, table, detailed ); - if( MinecraftForge.EVENT_BUS.post( event ) ) return new Object[] { false, event.getFailureMessage() }; + if( TurtleEvent.post( event ) ) return new Object[] { false, event.getFailureMessage() }; return new Object[] { table }; } diff --git a/src/main/java/dan200/computercraft/shared/turtle/blocks/BlockTurtle.java b/src/main/java/dan200/computercraft/shared/turtle/blocks/BlockTurtle.java index 61c273567..adab3d02e 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/blocks/BlockTurtle.java +++ b/src/main/java/dan200/computercraft/shared/turtle/blocks/BlockTurtle.java @@ -39,7 +39,6 @@ import net.minecraft.world.BlockView; import net.minecraft.world.World; import net.minecraft.world.WorldAccess; import net.minecraft.world.explosion.Explosion; -import net.minecraftforge.fml.RegistryObject; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -154,17 +153,23 @@ public class BlockTurtle extends BlockComputerBase implements Waterl } @Override - public float getExplosionResistance( BlockState state, BlockView world, BlockPos pos, Explosion explosion ) - { - Entity exploder = explosion.getExploder(); - if( getFamily() == ComputerFamily.ADVANCED || exploder instanceof LivingEntity || exploder instanceof ExplosiveProjectileEntity ) - { - return 2000; - } - - return super.getExplosionResistance( state, world, pos, explosion ); + public float getBlastResistance() { + // TODO Implement below functionality + return 2000; } +// @Override +// public float getBlastResistance( BlockState state, BlockView world, BlockPos pos, Explosion explosion ) +// { +// Entity exploder = explosion.getExploder(); +// if( getFamily() == ComputerFamily.ADVANCED || exploder instanceof LivingEntity || exploder instanceof ExplosiveProjectileEntity ) +// { +// return 2000; +// } +// +// return super.getExplosionResistance( state, world, pos, explosion ); +// } + @Nonnull @Override protected ItemStack getItem( TileComputerBase tile ) diff --git a/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java b/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java index fa2ea88c4..c3c7f1114 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java +++ b/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java @@ -3,13 +3,8 @@ * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.shared.turtle.blocks; -import java.util.Collections; - -import javax.annotation.Nonnull; - import com.mojang.authlib.GameProfile; import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.peripheral.IPeripheral; @@ -24,148 +19,157 @@ import dan200.computercraft.shared.computer.blocks.TileComputerBase; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.core.ComputerState; import dan200.computercraft.shared.computer.core.ServerComputer; -import dan200.computercraft.shared.network.Containers; import dan200.computercraft.shared.turtle.apis.TurtleAPI; +import dan200.computercraft.shared.turtle.blocks.TileTurtle.MoveState; import dan200.computercraft.shared.turtle.core.TurtleBrain; -import dan200.computercraft.shared.util.DefaultInventory; -import dan200.computercraft.shared.util.DirectionUtil; -import dan200.computercraft.shared.util.InventoryUtil; -import dan200.computercraft.shared.util.NBTUtil; -import dan200.computercraft.shared.util.NamedBlockEntityType; -import dan200.computercraft.shared.util.RedstoneUtil; -import dan200.computercraft.shared.util.WorldUtil; - +import dan200.computercraft.shared.turtle.inventory.ContainerTurtle; +import dan200.computercraft.shared.util.*; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; import net.minecraft.item.DyeItem; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; -import net.minecraft.util.ActionResult; -import net.minecraft.util.DyeColor; -import net.minecraft.util.Hand; -import net.minecraft.util.Identifier; -import net.minecraft.util.Nameable; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.util.*; import net.minecraft.util.collection.DefaultedList; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; -public class TileTurtle extends TileComputerBase implements ITurtleTile, DefaultInventory, Nameable { +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collections; +import java.util.Optional; + +public class TileTurtle extends TileComputerBase implements ITurtleTile, DefaultInventory +{ public static final int INVENTORY_SIZE = 16; public static final int INVENTORY_WIDTH = 4; public static final int INVENTORY_HEIGHT = 4; - public static final NamedBlockEntityType FACTORY_NORMAL = NamedBlockEntityType.create(new Identifier(ComputerCraft.MOD_ID, "turtle_normal"), - type -> new TileTurtle(type, ComputerFamily.NORMAL)); - public static final NamedBlockEntityType FACTORY_ADVANCED = NamedBlockEntityType.create(new Identifier(ComputerCraft.MOD_ID, - "turtle_advanced"), - type -> new TileTurtle(type, - ComputerFamily.ADVANCED)); - - enum MoveState { - NOT_MOVED, IN_PROGRESS, MOVED + enum MoveState + { + NOT_MOVED, + IN_PROGRESS, + MOVED } - private DefaultedList m_inventory; - private DefaultedList m_previousInventory; - private boolean m_inventoryChanged; - private TurtleBrain m_brain; - private MoveState m_moveState; + private final DefaultedList m_inventory = DefaultedList.ofSize( INVENTORY_SIZE, ItemStack.EMPTY ); + private final DefaultedList m_previousInventory = DefaultedList.ofSize( INVENTORY_SIZE, ItemStack.EMPTY ); + private boolean m_inventoryChanged = false; + private TurtleBrain m_brain = new TurtleBrain( this ); + private MoveState m_moveState = MoveState.NOT_MOVED; - public TileTurtle(BlockEntityType type, ComputerFamily family) { - super(type, family); - this.m_inventory = DefaultedList.ofSize(INVENTORY_SIZE, ItemStack.EMPTY); - this.m_previousInventory = DefaultedList.ofSize(INVENTORY_SIZE, ItemStack.EMPTY); - this.m_inventoryChanged = false; - this.m_brain = new TurtleBrain(this); - this.m_moveState = MoveState.NOT_MOVED; + public TileTurtle( BlockEntityType type, ComputerFamily family ) + { + super( type, family ); } - private boolean hasMoved() { - return this.m_moveState == MoveState.MOVED; + private boolean hasMoved() + { + return m_moveState == MoveState.MOVED; } @Override - protected ServerComputer createComputer(int instanceID, int id) { - ServerComputer computer = new ServerComputer(this.getWorld(), - id, - this.label, - instanceID, - this.getFamily(), - ComputerCraft.turtleTermWidth, - ComputerCraft.turtleTermHeight); - computer.setPosition(this.getPos()); - computer.addAPI(new TurtleAPI(computer.getAPIEnvironment(), this.getAccess())); - this.m_brain.setupComputer(computer); + protected ServerComputer createComputer( int instanceID, int id ) + { + ServerComputer computer = new ServerComputer( + getWorld(), id, label, instanceID, getFamily(), + ComputerCraft.terminalWidth_turtle, ComputerCraft.terminalHeight_turtle + ); + computer.setPosition( getPos() ); + computer.addAPI( new TurtleAPI( computer.getAPIEnvironment(), getAccess() ) ); + m_brain.setupComputer( computer ); return computer; } - @Override - public ComputerProxy createProxy() { - return this.m_brain.getProxy(); + public ComputerProxy createProxy() + { + return m_brain.getProxy(); } @Override - public void destroy() { - if (!this.hasMoved()) { + public void destroy() + { + if( !hasMoved() ) + { // Stop computer super.destroy(); // Drop contents - if (!this.getWorld().isClient) { - int size = this.size(); - for (int i = 0; i < size; i++) { - ItemStack stack = this.getStack(i); - if (!stack.isEmpty()) { - WorldUtil.dropItemStack(stack, this.getWorld(), this.getPos()); + if( !getWorld().isClient ) + { + int size = size(); + for( int i = 0; i < size; i++ ) + { + ItemStack stack = getStack( i ); + if( !stack.isEmpty() ) + { + WorldUtil.dropItemStack( stack, getWorld(), getPos() ); } } } - } else { + } + else + { // Just turn off any redstone we had on - for (Direction dir : DirectionUtil.FACINGS) { - RedstoneUtil.propagateRedstoneOutput(this.getWorld(), this.getPos(), dir); + for( Direction dir : DirectionUtil.FACINGS ) + { + RedstoneUtil.propagateRedstoneOutput( getWorld(), getPos(), dir ); } } } @Override - protected void unload() { - if (!this.hasMoved()) { + protected void unload() + { + if( !hasMoved() ) + { super.unload(); } } - @Nonnull @Override - public ActionResult onActivate(PlayerEntity player, Hand hand, BlockHitResult hit) { + public ActionResult onActivate( PlayerEntity player, Hand hand, BlockHitResult hit ) + { // Apply dye - ItemStack currentItem = player.getStackInHand(hand); - if (!currentItem.isEmpty()) { - if (currentItem.getItem() instanceof DyeItem) { + ItemStack currentItem = player.getStackInHand( hand ); + if( !currentItem.isEmpty() ) + { + if( currentItem.getItem() instanceof DyeItem ) + { // Dye to change turtle colour - if (!this.getWorld().isClient) { + if( !getWorld().isClient ) + { DyeColor dye = ((DyeItem) currentItem.getItem()).getColor(); - if (this.m_brain.getDyeColour() != dye) { - this.m_brain.setDyeColour(dye); - if (!player.isCreative()) { - currentItem.decrement(1); + if( m_brain.getDyeColour() != dye ) + { + m_brain.setDyeColour( dye ); + if( !player.isCreative() ) + { + currentItem.decrement( 1 ); } } } return ActionResult.SUCCESS; - } else if (currentItem.getItem() == Items.WATER_BUCKET && this.m_brain.getColour() != -1) { + } + else if( currentItem.getItem() == Items.WATER_BUCKET && m_brain.getColour() != -1 ) + { // Water to remove turtle colour - if (!this.getWorld().isClient) { - if (this.m_brain.getColour() != -1) { - this.m_brain.setColour(-1); - if (!player.isCreative()) { - player.setStackInHand(hand, new ItemStack(Items.BUCKET)); + if( !getWorld().isClient ) + { + if( m_brain.getColour() != -1 ) + { + m_brain.setColour( -1 ); + if( !player.isCreative() ) + { + player.setStackInHand( hand, new ItemStack( Items.BUCKET ) ); player.inventory.markDirty(); } } @@ -175,271 +179,279 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default } // Open GUI or whatever - return super.onActivate(player, hand, hit); + return super.onActivate( player, hand, hit ); } @Override - public void openGui(PlayerEntity entity) { - Containers.openTurtleGUI(entity, this); - } - - @Override - protected boolean canNameWithTag(PlayerEntity player) { + protected boolean canNameWithTag( PlayerEntity player ) + { return true; } @Override - protected double getInteractRange(PlayerEntity player) { + protected double getInteractRange( PlayerEntity player ) + { return 12.0; } @Override - public void tick() { + public void tick() + { super.tick(); - this.m_brain.update(); - if (!this.getWorld().isClient && this.m_inventoryChanged) { - ServerComputer computer = this.getServerComputer(); - if (computer != null) { - computer.queueEvent("turtle_inventory"); - } + m_brain.update(); + if( !getWorld().isClient && m_inventoryChanged ) + { + ServerComputer computer = getServerComputer(); + if( computer != null ) computer.queueEvent( "turtle_inventory" ); - this.m_inventoryChanged = false; - for (int n = 0; n < this.size(); n++) { - this.m_previousInventory.set(n, - this.getStack(n) - .copy()); + m_inventoryChanged = false; + for( int n = 0; n < size(); n++ ) + { + m_previousInventory.set( n, getStack( n ).copy() ); } } } @Override - protected void updateBlockState(ComputerState newState) { + protected void updateBlockState( ComputerState newState ) + { } @Override - public void onNeighbourChange(@Nonnull BlockPos neighbour) { - if (this.m_moveState == MoveState.NOT_MOVED) { - super.onNeighbourChange(neighbour); - } + public void onNeighbourChange( @Nonnull BlockPos neighbour ) + { + if( m_moveState == MoveState.NOT_MOVED ) super.onNeighbourChange( neighbour ); } @Override - public void onNeighbourTileEntityChange(@Nonnull BlockPos neighbour) { - if (this.m_moveState == MoveState.NOT_MOVED) { - super.onNeighbourTileEntityChange(neighbour); - } + public void onNeighbourTileEntityChange( @Nonnull BlockPos neighbour ) + { + if( m_moveState == MoveState.NOT_MOVED ) super.onNeighbourTileEntityChange( neighbour ); } - public void notifyMoveStart() { - if (this.m_moveState == MoveState.NOT_MOVED) { - this.m_moveState = MoveState.IN_PROGRESS; - } + public void notifyMoveStart() + { + if( m_moveState == MoveState.NOT_MOVED ) m_moveState = MoveState.IN_PROGRESS; } - public void notifyMoveEnd() { + public void notifyMoveEnd() + { // MoveState.MOVED is final - if (this.m_moveState == MoveState.IN_PROGRESS) { - this.m_moveState = MoveState.NOT_MOVED; - } + if( m_moveState == MoveState.IN_PROGRESS ) m_moveState = MoveState.NOT_MOVED; } @Override - public void fromTag(@Nonnull BlockState state, @Nonnull CompoundTag nbt) { - super.fromTag(state, nbt); + public void fromTag( @Nonnull BlockState state, @Nonnull CompoundTag nbt ) + { + super.fromTag( state, nbt ); // Read inventory - ListTag nbttaglist = nbt.getList("Items", NBTUtil.TAG_COMPOUND); - this.m_inventory.clear(); - this.m_previousInventory.clear(); - for (int i = 0; i < nbttaglist.size(); i++) { - CompoundTag tag = nbttaglist.getCompound(i); - int slot = tag.getByte("Slot") & 0xff; - if (slot < this.size()) { - this.m_inventory.set(slot, ItemStack.fromTag(tag)); - this.m_previousInventory.set(slot, - this.m_inventory.get(slot) - .copy()); + ListTag nbttaglist = nbt.getList( "Items", NBTUtil.TAG_COMPOUND ); + m_inventory.clear(); + m_previousInventory.clear(); + for( int i = 0; i < nbttaglist.size(); i++ ) + { + CompoundTag tag = nbttaglist.getCompound( i ); + int slot = tag.getByte( "Slot" ) & 0xff; + if( slot < size() ) + { + m_inventory.set( slot, ItemStack.fromTag( tag ) ); + m_previousInventory.set( slot, m_inventory.get( slot ).copy() ); } } // Read state - this.m_brain.readFromNBT(nbt); + m_brain.readFromNBT( nbt ); } @Nonnull @Override - public CompoundTag toTag(@Nonnull CompoundTag nbt) { + public CompoundTag toTag( @Nonnull CompoundTag nbt ) + { // Write inventory ListTag nbttaglist = new ListTag(); - for (int i = 0; i < INVENTORY_SIZE; i++) { - if (!this.m_inventory.get(i) - .isEmpty()) { + for( int i = 0; i < INVENTORY_SIZE; i++ ) + { + if( !m_inventory.get( i ).isEmpty() ) + { CompoundTag tag = new CompoundTag(); - tag.putByte("Slot", (byte) i); - this.m_inventory.get(i) - .toTag(tag); - nbttaglist.add(tag); + tag.putByte( "Slot", (byte) i ); + m_inventory.get( i ).toTag( tag ); + nbttaglist.add( tag ); } } - nbt.put("Items", nbttaglist); + nbt.put( "Items", nbttaglist ); // Write brain - nbt = this.m_brain.writeToNBT(nbt); + nbt = m_brain.writeToNBT( nbt ); - return super.toTag(nbt); + return super.toTag( nbt ); } @Override - protected boolean isPeripheralBlockedOnSide(ComputerSide localSide) { - return this.hasPeripheralUpgradeOnSide(localSide); + protected boolean isPeripheralBlockedOnSide( ComputerSide localSide ) + { + return hasPeripheralUpgradeOnSide( localSide ); } // IDirectionalTile @Override - public Direction getDirection() { - return this.getCachedState() - .get(BlockTurtle.FACING); + public Direction getDirection() + { + return getCachedState().get( BlockTurtle.FACING ); } - public void setDirection(Direction dir) { - if (dir.getAxis() == Direction.Axis.Y) { - dir = Direction.NORTH; - } - this.world.setBlockState(this.pos, - this.getCachedState() - .with(BlockTurtle.FACING, dir)); - this.updateOutput(); - this.updateInput(); - this.onTileEntityChange(); + public void setDirection( Direction dir ) + { + if( dir.getAxis() == Direction.Axis.Y ) dir = Direction.NORTH; + world.setBlockState( pos, getCachedState().with( BlockTurtle.FACING, dir ) ); + updateOutput(); + updateInput(); + onTileEntityChange(); } // ITurtleTile @Override - public ITurtleUpgrade getUpgrade(TurtleSide side) { - return this.m_brain.getUpgrade(side); + public ITurtleUpgrade getUpgrade( TurtleSide side ) + { + return m_brain.getUpgrade( side ); } @Override - public int getColour() { - return this.m_brain.getColour(); + public int getColour() + { + return m_brain.getColour(); } @Override - public Identifier getOverlay() { - return this.m_brain.getOverlay(); + public Identifier getOverlay() + { + return m_brain.getOverlay(); } @Override - public ITurtleAccess getAccess() { - return this.m_brain; + public ITurtleAccess getAccess() + { + return m_brain; } @Override - public Vec3d getRenderOffset(float f) { - return this.m_brain.getRenderOffset(f); + public Vec3d getRenderOffset( float f ) + { + return m_brain.getRenderOffset( f ); } @Override - public float getRenderYaw(float f) { - return this.m_brain.getVisualYaw(f); + public float getRenderYaw( float f ) + { + return m_brain.getVisualYaw( f ); } @Override - public float getToolRenderAngle(TurtleSide side, float f) { - return this.m_brain.getToolRenderAngle(side, f); + public float getToolRenderAngle( TurtleSide side, float f ) + { + return m_brain.getToolRenderAngle( side, f ); } - void setOwningPlayer(GameProfile player) { - this.m_brain.setOwningPlayer(player); - this.markDirty(); + void setOwningPlayer( GameProfile player ) + { + m_brain.setOwningPlayer( player ); + markDirty(); } // IInventory @Override - public int size() { + public int size() + { return INVENTORY_SIZE; } @Override - public boolean isEmpty() { - for (ItemStack stack : this.m_inventory) { - if (!stack.isEmpty()) { - return false; - } + public boolean isEmpty() + { + for( ItemStack stack : m_inventory ) + { + if( !stack.isEmpty() ) return false; } return true; } @Nonnull @Override - public ItemStack getStack(int slot) { - return slot >= 0 && slot < INVENTORY_SIZE ? this.m_inventory.get(slot) : ItemStack.EMPTY; + public ItemStack getStack( int slot ) + { + return slot >= 0 && slot < INVENTORY_SIZE ? m_inventory.get( slot ) : ItemStack.EMPTY; } @Nonnull @Override - public ItemStack removeStack(int slot) { - ItemStack result = this.getStack(slot); - this.setStack(slot, ItemStack.EMPTY); + public ItemStack removeStack( int slot ) + { + ItemStack result = getStack( slot ); + setStack( slot, ItemStack.EMPTY ); return result; } @Nonnull @Override - public ItemStack removeStack(int slot, int count) { - if (count == 0) { - return ItemStack.EMPTY; - } + public ItemStack removeStack( int slot, int count ) + { + if( count == 0 ) return ItemStack.EMPTY; - ItemStack stack = this.getStack(slot); - if (stack.isEmpty()) { - return ItemStack.EMPTY; - } + ItemStack stack = getStack( slot ); + if( stack.isEmpty() ) return ItemStack.EMPTY; - if (stack.getCount() <= count) { - this.setStack(slot, ItemStack.EMPTY); + if( stack.getCount() <= count ) + { + setStack( slot, ItemStack.EMPTY ); return stack; } - ItemStack part = stack.split(count); - this.onInventoryDefinitelyChanged(); + ItemStack part = stack.split( count ); + onInventoryDefinitelyChanged(); return part; } @Override - public void setStack(int i, @Nonnull ItemStack stack) { - if (i >= 0 && i < INVENTORY_SIZE && !InventoryUtil.areItemsEqual(stack, this.m_inventory.get(i))) { - this.m_inventory.set(i, stack); - this.onInventoryDefinitelyChanged(); + public void setStack( int i, @Nonnull ItemStack stack ) + { + if( i >= 0 && i < INVENTORY_SIZE && !InventoryUtil.areItemsEqual( stack, m_inventory.get( i ) ) ) + { + m_inventory.set( i, stack ); + onInventoryDefinitelyChanged(); } } @Override - public void clear() { + public void clear() + { boolean changed = false; - for (int i = 0; i < INVENTORY_SIZE; i++) { - if (!this.m_inventory.get(i) - .isEmpty()) { - this.m_inventory.set(i, ItemStack.EMPTY); + for( int i = 0; i < INVENTORY_SIZE; i++ ) + { + if( !m_inventory.get( i ).isEmpty() ) + { + m_inventory.set( i, ItemStack.EMPTY ); changed = true; } } - if (changed) { - this.onInventoryDefinitelyChanged(); - } + if( changed ) onInventoryDefinitelyChanged(); } @Override - public void markDirty() { + public void markDirty() + { super.markDirty(); - if (!this.m_inventoryChanged) { - for (int n = 0; n < this.size(); n++) { - if (!ItemStack.areEqual(this.getStack(n), this.m_previousInventory.get(n))) { - this.m_inventoryChanged = true; + if( !m_inventoryChanged ) + { + for( int n = 0; n < size(); n++ ) + { + if( !ItemStack.areEqual( getStack( n ), m_previousInventory.get( n ) ) ) + { + m_inventoryChanged = true; break; } } @@ -447,65 +459,74 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default } @Override - public boolean canPlayerUse(@Nonnull PlayerEntity player) { - return this.isUsable(player, false); + public boolean canPlayerUse( @Nonnull PlayerEntity player ) + { + return isUsable( player, false ); } - private void onInventoryDefinitelyChanged() { + private void onInventoryDefinitelyChanged() + { super.markDirty(); - this.m_inventoryChanged = true; + m_inventoryChanged = true; } - public void onTileEntityChange() { + public void onTileEntityChange() + { super.markDirty(); } // Networking stuff @Override - protected void writeDescription(@Nonnull CompoundTag nbt) { - super.writeDescription(nbt); - this.m_brain.writeDescription(nbt); + protected void writeDescription( @Nonnull CompoundTag nbt ) + { + super.writeDescription( nbt ); + m_brain.writeDescription( nbt ); } @Override - protected void readDescription(@Nonnull CompoundTag nbt) { - super.readDescription(nbt); - this.m_brain.readDescription(nbt); + protected void readDescription( @Nonnull CompoundTag nbt ) + { + super.readDescription( nbt ); + m_brain.readDescription( nbt ); } // Privates - private boolean hasPeripheralUpgradeOnSide(ComputerSide side) { + private boolean hasPeripheralUpgradeOnSide( ComputerSide side ) + { ITurtleUpgrade upgrade; - switch (side) { - case RIGHT: - upgrade = this.getUpgrade(TurtleSide.RIGHT); - break; - case LEFT: - upgrade = this.getUpgrade(TurtleSide.LEFT); - break; - default: - return false; + switch( side ) + { + case RIGHT: + upgrade = getUpgrade( TurtleSide.RIGHT ); + break; + case LEFT: + upgrade = getUpgrade( TurtleSide.LEFT ); + break; + default: + return false; } - return upgrade != null && upgrade.getType() - .isPeripheral(); + return upgrade != null && upgrade.getType().isPeripheral(); } - public void transferStateFrom(TileTurtle copy) { - super.transferStateFrom(copy); - Collections.copy(this.m_inventory, copy.m_inventory); - Collections.copy(this.m_previousInventory, copy.m_previousInventory); - this.m_inventoryChanged = copy.m_inventoryChanged; - this.m_brain = copy.m_brain; - this.m_brain.setOwner(this); + public void transferStateFrom( TileTurtle copy ) + { + super.transferStateFrom( copy ); + Collections.copy( m_inventory, copy.m_inventory ); + Collections.copy( m_previousInventory, copy.m_previousInventory ); + m_inventoryChanged = copy.m_inventoryChanged; + m_brain = copy.m_brain; + m_brain.setOwner( this ); // Mark the other turtle as having moved, and so its peripheral is dead. copy.m_moveState = MoveState.MOVED; } - public IPeripheral getPeripheral(@Nonnull Direction side) { - return hasMoved() ? null : new ComputerPeripheral("turtle", createProxy()); + @Nullable + @Override + public ScreenHandler createMenu( int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity player ) + { + return new ContainerTurtle( id, inventory, m_brain ); } - } diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java index 94af4a9fc..d0109437c 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java @@ -18,10 +18,7 @@ import dan200.computercraft.shared.computer.blocks.ComputerProxy; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.turtle.blocks.TileTurtle; -import dan200.computercraft.shared.util.Colour; -import dan200.computercraft.shared.util.Holiday; -import dan200.computercraft.shared.util.HolidayUtil; -import dan200.computercraft.shared.util.InventoryDelegate; +import dan200.computercraft.shared.util.*; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; @@ -40,9 +37,6 @@ import net.minecraft.util.math.Box; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -import net.minecraftforge.common.util.Constants; -import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.wrapper.InvWrapper; import javax.annotation.Nonnull; import java.util.*; @@ -69,7 +63,6 @@ public class TurtleBrain implements ITurtleAccess private GameProfile m_owningPlayer; private final Inventory m_inventory = (InventoryDelegate) () -> m_owner; - private final IItemHandlerModifiable m_inventoryWrapper = new InvWrapper( m_inventory ); private final Queue m_commandQueue = new ArrayDeque<>(); private int m_commandsIssued = 0; @@ -299,7 +292,7 @@ public class TurtleBrain implements ITurtleAccess } // Ensure the chunk is loaded - if( !world.isAreaLoaded( pos, 0 ) ) return false; + if( !world.isChunkLoaded( pos ) ) return false; // Ensure we're inside the world border if( !world.getWorldBorder().contains( pos ) ) return false; @@ -434,13 +427,6 @@ public class TurtleBrain implements ITurtleAccess return m_inventory; } - @Nonnull - @Override - public IItemHandlerModifiable getItemHandler() - { - return m_inventoryWrapper; - } - @Override public boolean isFuelNeeded() { diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCompareCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCompareCommand.java index 965007222..47a8dd61d 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCompareCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCompareCommand.java @@ -15,7 +15,6 @@ import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; -import net.minecraftforge.fml.common.ObfuscationReflectionHelper; import javax.annotation.Nonnull; import java.lang.reflect.Method; @@ -50,21 +49,8 @@ public class TurtleCompareCommand implements ITurtleCommand { BlockState lookAtState = world.getBlockState( newPosition ); Block lookAtBlock = lookAtState.getBlock(); - if( !lookAtBlock.isAir( lookAtState, world, newPosition ) ) + if( !lookAtState.isAir() ) { - // Try getSilkTouchDrop first - if( !lookAtBlock.hasTileEntity( lookAtState ) ) - { - try - { - Method method = ObfuscationReflectionHelper.findMethod( Block.class, "func_180643_i", BlockState.class ); - lookAtStack = (ItemStack) method.invoke( lookAtBlock, lookAtState ); - } - catch( ReflectiveOperationException | RuntimeException ignored ) - { - } - } - // See if the block drops anything with the same ID as itself // (try 5 times to try and beat random number generators) for( int i = 0; i < 5 && lookAtStack.isEmpty(); i++ ) diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDropCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDropCommand.java index b95aa31f7..1c5b3d3a2 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDropCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDropCommand.java @@ -9,15 +9,16 @@ import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.ITurtleCommand; import dan200.computercraft.api.turtle.TurtleAnimation; import dan200.computercraft.api.turtle.TurtleCommandResult; +import dan200.computercraft.api.turtle.event.TurtleEvent; import dan200.computercraft.api.turtle.event.TurtleInventoryEvent; import dan200.computercraft.shared.util.InventoryUtil; +import dan200.computercraft.shared.util.ItemStorage; import dan200.computercraft.shared.util.WorldUtil; +import net.minecraft.inventory.Inventory; import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.items.IItemHandler; import javax.annotation.Nonnull; @@ -59,12 +60,12 @@ public class TurtleDropCommand implements ITurtleCommand BlockPos newPosition = oldPosition.offset( direction ); Direction side = direction.getOpposite(); - IItemHandler inventory = InventoryUtil.getInventory( world, newPosition, side ); + Inventory inventory = InventoryUtil.getInventory( world, newPosition, side ); // Fire the event, restoring the inventory and exiting if it is cancelled. TurtlePlayer player = TurtlePlaceCommand.createPlayer( turtle, oldPosition, direction ); TurtleInventoryEvent.Drop event = new TurtleInventoryEvent.Drop( turtle, player, world, newPosition, inventory, stack ); - if( MinecraftForge.EVENT_BUS.post( event ) ) + if( TurtleEvent.post( event ) ) { InventoryUtil.storeItems( stack, turtle.getItemHandler(), turtle.getSelectedSlot() ); return TurtleCommandResult.failure( event.getFailureMessage() ); @@ -73,7 +74,7 @@ public class TurtleDropCommand implements ITurtleCommand if( inventory != null ) { // Drop the item into the inventory - ItemStack remainder = InventoryUtil.storeItems( stack, inventory ); + ItemStack remainder = InventoryUtil.storeItems( stack, ItemStorage.wrap(inventory, side) ); if( !remainder.isEmpty() ) { // Put the remainder back in the turtle diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleEquipCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleEquipCommand.java index 7c4990f35..2950aeb27 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleEquipCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleEquipCommand.java @@ -8,13 +8,14 @@ package dan200.computercraft.shared.turtle.core; import dan200.computercraft.api.turtle.*; import dan200.computercraft.api.turtle.event.TurtleAction; import dan200.computercraft.api.turtle.event.TurtleActionEvent; +import dan200.computercraft.api.turtle.event.TurtleEvent; import dan200.computercraft.shared.TurtleUpgrades; import dan200.computercraft.shared.util.InventoryUtil; +import dan200.computercraft.shared.util.ItemStorage; import dan200.computercraft.shared.util.WorldUtil; +import net.minecraft.inventory.Inventory; import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.items.IItemHandler; import javax.annotation.Nonnull; @@ -34,8 +35,8 @@ public class TurtleEquipCommand implements ITurtleCommand // Determine the upgrade to equipLeft ITurtleUpgrade newUpgrade; ItemStack newUpgradeStack; - IItemHandler inventory = turtle.getItemHandler(); - ItemStack selectedStack = inventory.getStackInSlot( turtle.getSelectedSlot() ); + Inventory inventory = turtle.getInventory(); + ItemStack selectedStack = inventory.getStack( turtle.getSelectedSlot() ); if( !selectedStack.isEmpty() ) { newUpgradeStack = selectedStack.copy(); @@ -65,7 +66,7 @@ public class TurtleEquipCommand implements ITurtleCommand } TurtleActionEvent event = new TurtleActionEvent( turtle, TurtleAction.EQUIP ); - if( MinecraftForge.EVENT_BUS.post( event ) ) + if( TurtleEvent.post( event ) ) { return TurtleCommandResult.failure( event.getFailureMessage() ); } @@ -74,12 +75,12 @@ public class TurtleEquipCommand implements ITurtleCommand if( newUpgradeStack != null ) { // Consume new upgrades item - InventoryUtil.takeItems( 1, inventory, turtle.getSelectedSlot(), 1, turtle.getSelectedSlot() ); + InventoryUtil.takeItems( 1, ItemStorage.wrap(inventory), turtle.getSelectedSlot(), 1, turtle.getSelectedSlot() ); } if( oldUpgradeStack != null ) { // Store old upgrades item - ItemStack remainder = InventoryUtil.storeItems( oldUpgradeStack, inventory, turtle.getSelectedSlot() ); + ItemStack remainder = InventoryUtil.storeItems( oldUpgradeStack, ItemStorage.wrap(inventory), turtle.getSelectedSlot() ); if( !remainder.isEmpty() ) { // If there's no room for the items, drop them diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleInspectCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleInspectCommand.java index c5e2b50c9..04affe4b3 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleInspectCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleInspectCommand.java @@ -5,16 +5,19 @@ */ package dan200.computercraft.shared.turtle.core; +import com.google.common.collect.ImmutableMap; import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.ITurtleCommand; import dan200.computercraft.api.turtle.TurtleCommandResult; import dan200.computercraft.api.turtle.event.TurtleBlockEvent; -import dan200.computercraft.shared.peripheral.generic.data.BlockData; +import dan200.computercraft.api.turtle.event.TurtleEvent; +import net.minecraft.block.Block; import net.minecraft.block.BlockState; +import net.minecraft.state.property.Property; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; +import net.minecraft.util.registry.Registry; import net.minecraft.world.World; -import net.minecraftforge.common.MinecraftForge; import javax.annotation.Nonnull; import java.util.HashMap; @@ -42,19 +45,45 @@ public class TurtleInspectCommand implements ITurtleCommand BlockPos newPosition = oldPosition.offset( direction ); BlockState state = world.getBlockState( newPosition ); - if( state.getBlock().isAir( state, world, newPosition ) ) + if( state.isAir() ) { return TurtleCommandResult.failure( "No block to inspect" ); } - Map table = BlockData.fill( new HashMap<>(), state ); + Block block = state.getBlock(); + String name = Registry.BLOCK.getId(block) + .toString(); + + Map table = new HashMap<>(); + table.put("name", name); + + Map stateTable = new HashMap<>(); + for (ImmutableMap.Entry, ? extends Comparable> entry : state.getEntries() + .entrySet()) { + Property property = entry.getKey(); + stateTable.put(property.getName(), getPropertyValue(property, entry.getValue())); + } + table.put("state", stateTable); // Fire the event, exiting if it is cancelled - TurtlePlayer turtlePlayer = TurtlePlaceCommand.createPlayer( turtle, oldPosition, direction ); - TurtleBlockEvent.Inspect event = new TurtleBlockEvent.Inspect( turtle, turtlePlayer, world, newPosition, state, table ); - if( MinecraftForge.EVENT_BUS.post( event ) ) return TurtleCommandResult.failure( event.getFailureMessage() ); + TurtlePlayer turtlePlayer = TurtlePlaceCommand.createPlayer(turtle, oldPosition, direction); + TurtleBlockEvent.Inspect event = new TurtleBlockEvent.Inspect(turtle, turtlePlayer, world, newPosition, state, table); + if (TurtleEvent.post(event)) { + return TurtleCommandResult.failure(event.getFailureMessage()); + } - return TurtleCommandResult.success( new Object[] { table } ); + return TurtleCommandResult.success(new Object[] {table}); } + + @SuppressWarnings ({ + "unchecked", + "rawtypes" + }) + private static Object getPropertyValue(Property property, Comparable value) { + if (value instanceof String || value instanceof Number || value instanceof Boolean) { + return value; + } + return property.name(value); + } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleMoveCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleMoveCommand.java index bd6f89301..083a360cb 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleMoveCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleMoveCommand.java @@ -11,6 +11,7 @@ import dan200.computercraft.api.turtle.ITurtleCommand; import dan200.computercraft.api.turtle.TurtleAnimation; import dan200.computercraft.api.turtle.TurtleCommandResult; import dan200.computercraft.api.turtle.event.TurtleBlockEvent; +import dan200.computercraft.api.turtle.event.TurtleEvent; import dan200.computercraft.shared.TurtlePermissions; import dan200.computercraft.shared.util.WorldUtil; import net.minecraft.block.BlockState; @@ -21,7 +22,6 @@ import net.minecraft.util.math.Direction; import net.minecraft.util.shape.VoxelShape; import net.minecraft.util.shape.VoxelShapes; import net.minecraft.world.World; -import net.minecraftforge.common.MinecraftForge; import javax.annotation.Nonnull; import java.util.List; @@ -94,7 +94,7 @@ public class TurtleMoveCommand implements ITurtleCommand } TurtleBlockEvent.Move moveEvent = new TurtleBlockEvent.Move( turtle, turtlePlayer, oldWorld, newPosition ); - if( MinecraftForge.EVENT_BUS.post( moveEvent ) ) + if( TurtleEvent.post( moveEvent ) ) { return TurtleCommandResult.failure( moveEvent.getFailureMessage() ); } @@ -145,7 +145,7 @@ public class TurtleMoveCommand implements ITurtleCommand return TurtleCommandResult.failure( "Cannot enter protected area" ); } - if( !world.isAreaLoaded( position, 0 ) ) return TurtleCommandResult.failure( "Cannot leave loaded world" ); + if( !world.isChunkLoaded( position ) ) return TurtleCommandResult.failure( "Cannot leave loaded world" ); if( !world.getWorldBorder().contains( position ) ) { return TurtleCommandResult.failure( "Cannot pass the world border" ); diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java index 9973c56dd..f4141be86 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java @@ -11,6 +11,7 @@ import dan200.computercraft.api.turtle.ITurtleCommand; import dan200.computercraft.api.turtle.TurtleAnimation; import dan200.computercraft.api.turtle.TurtleCommandResult; import dan200.computercraft.api.turtle.event.TurtleBlockEvent; +import dan200.computercraft.api.turtle.event.TurtleEvent; import dan200.computercraft.shared.TurtlePermissions; import dan200.computercraft.shared.util.DirectionUtil; import dan200.computercraft.shared.util.DropConsumer; @@ -31,10 +32,6 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -import net.minecraftforge.common.ForgeHooks; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.entity.player.PlayerInteractEvent; -import net.minecraftforge.eventbus.api.Event; import org.apache.commons.lang3.tuple.Pair; import javax.annotation.Nonnull; @@ -71,7 +68,7 @@ public class TurtlePlaceCommand implements ITurtleCommand TurtlePlayer turtlePlayer = createPlayer( turtle, playerPosition, direction ); TurtleBlockEvent.Place place = new TurtleBlockEvent.Place( turtle, turtlePlayer, turtle.getWorld(), coordinates, stack ); - if( MinecraftForge.EVENT_BUS.post( place ) ) + if( TurtleEvent.post( place ) ) { return TurtleCommandResult.failure( place.getFailureMessage() ); } @@ -232,7 +229,7 @@ public class TurtlePlaceCommand implements ITurtleCommand // Place on the entity boolean placed = false; - ActionResult cancelResult = ForgeHooks.onInteractEntityAt( turtlePlayer, hitEntity, hitPos, Hand.MAIN_HAND ); + ActionResult cancelResult = hitEntity.interactAt(turtlePlayer, hitPos, Hand.MAIN_HAND);; if( cancelResult == null ) { cancelResult = hitEntity.interactAt( turtlePlayer, hitPos, Hand.MAIN_HAND ); @@ -245,7 +242,7 @@ public class TurtlePlaceCommand implements ITurtleCommand else { // See EntityPlayer.interactOn - cancelResult = ForgeHooks.onInteractEntity( turtlePlayer, hitEntity, Hand.MAIN_HAND ); + cancelResult = stackCopy.useOnEntity(turtlePlayer, (LivingEntity) hitEntity, Hand.MAIN_HAND); if( cancelResult != null && cancelResult.isAccepted() ) { placed = true; @@ -340,6 +337,7 @@ public class TurtlePlaceCommand implements ITurtleCommand // Check if there's something suitable to place onto BlockHitResult hit = new BlockHitResult( new Vec3d( hitX, hitY, hitZ ), side, position, false ); ItemUsageContext context = new ItemUsageContext( turtlePlayer, Hand.MAIN_HAND, hit ); + ItemPlacementContext placementContext = new ItemPlacementContext( context ); if( !canDeployOnBlock( new ItemPlacementContext( context ), turtle, turtlePlayer, position, side, allowReplace, outErrorMessage ) ) { return stack; @@ -352,26 +350,17 @@ public class TurtlePlaceCommand implements ITurtleCommand boolean placed = false; BlockEntity existingTile = turtle.getWorld().getBlockEntity( position ); - // See PlayerInteractionManager.processRightClickBlock - PlayerInteractEvent.RightClickBlock event = ForgeHooks.onRightClickBlock( turtlePlayer, Hand.MAIN_HAND, position, side ); - if( !event.isCanceled() ) - { - if( item.onItemUseFirst( stack, context ).isAccepted() ) - { + if (placementContext.canPlace()) { + if (stackCopy.useOnBlock(context) == ActionResult.SUCCESS) { placed = true; - turtlePlayer.loadInventory( stackCopy ); - } - else if( event.getUseItem() != Event.Result.DENY && stackCopy.useOnBlock( context ).isAccepted() ) - { - placed = true; - turtlePlayer.loadInventory( stackCopy ); + turtlePlayer.loadInventory(stackCopy); } } if( !placed && (item instanceof BucketItem || item instanceof BoatItem || item instanceof LilyPadItem || item instanceof GlassBottleItem) ) { - ActionResult actionResult = ForgeHooks.onItemRightClick( turtlePlayer, Hand.MAIN_HAND ); - if( actionResult != null && actionResult.isAccepted() ) + TypedActionResult actionResult = stackCopy.use(turtle.getWorld(), turtlePlayer, Hand.MAIN_HAND); + if( actionResult != null && actionResult.getResult().isAccepted() ) { placed = true; } diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlayer.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlayer.java index 36f6dceb4..26025832d 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlayer.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlayer.java @@ -15,7 +15,7 @@ import com.mojang.authlib.GameProfile; import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.turtle.FakePlayer; import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.shared.Registry; +import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.util.FakeNetHandler; import dan200.computercraft.shared.util.InventoryUtil; import dan200.computercraft.shared.util.WorldUtil; @@ -130,7 +130,7 @@ public final class TurtlePlayer extends FakePlayer @Override public EntityType getType() { - return Registry.ModEntities.TURTLE_PLAYER; + return ComputerCraftRegistry.ModEntities.TURTLE_PLAYER; } @Override diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleRefuelCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleRefuelCommand.java index 6fef3384f..6def4ffb7 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleRefuelCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleRefuelCommand.java @@ -9,9 +9,9 @@ import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.ITurtleCommand; import dan200.computercraft.api.turtle.TurtleAnimation; import dan200.computercraft.api.turtle.TurtleCommandResult; +import dan200.computercraft.api.turtle.event.TurtleEvent; import dan200.computercraft.api.turtle.event.TurtleRefuelEvent; import net.minecraft.item.ItemStack; -import net.minecraftforge.common.MinecraftForge; import javax.annotation.Nonnull; @@ -33,7 +33,7 @@ public class TurtleRefuelCommand implements ITurtleCommand if( stack.isEmpty() ) return TurtleCommandResult.failure( "No items to combust" ); TurtleRefuelEvent event = new TurtleRefuelEvent( turtle, stack ); - if( MinecraftForge.EVENT_BUS.post( event ) ) return TurtleCommandResult.failure( event.getFailureMessage() ); + if( TurtleEvent.post( event ) ) return TurtleCommandResult.failure( event.getFailureMessage() ); if( event.getHandler() == null ) return TurtleCommandResult.failure( "Items not combustible" ); if( limit != 0 ) diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleSuckCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleSuckCommand.java index a3b064734..6f4978762 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleSuckCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleSuckCommand.java @@ -9,17 +9,18 @@ import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.ITurtleCommand; import dan200.computercraft.api.turtle.TurtleAnimation; import dan200.computercraft.api.turtle.TurtleCommandResult; +import dan200.computercraft.api.turtle.event.TurtleEvent; import dan200.computercraft.api.turtle.event.TurtleInventoryEvent; import dan200.computercraft.shared.util.InventoryUtil; +import dan200.computercraft.shared.util.ItemStorage; import net.minecraft.entity.ItemEntity; +import net.minecraft.inventory.Inventory; import net.minecraft.item.ItemStack; import net.minecraft.predicate.entity.EntityPredicates; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Box; import net.minecraft.util.math.Direction; import net.minecraft.world.World; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.items.IItemHandler; import javax.annotation.Nonnull; import java.util.List; @@ -55,12 +56,12 @@ public class TurtleSuckCommand implements ITurtleCommand BlockPos blockPosition = turtlePosition.offset( direction ); Direction side = direction.getOpposite(); - IItemHandler inventory = InventoryUtil.getInventory( world, blockPosition, side ); + Inventory inventory = InventoryUtil.getInventory( world, blockPosition, side ); // Fire the event, exiting if it is cancelled. TurtlePlayer player = TurtlePlaceCommand.createPlayer( turtle, turtlePosition, direction ); TurtleInventoryEvent.Suck event = new TurtleInventoryEvent.Suck( turtle, player, world, blockPosition, inventory ); - if( MinecraftForge.EVENT_BUS.post( event ) ) + if( TurtleEvent.post( event ) ) { return TurtleCommandResult.failure( event.getFailureMessage() ); } @@ -68,7 +69,7 @@ public class TurtleSuckCommand implements ITurtleCommand if( inventory != null ) { // Take from inventory of thing in front - ItemStack stack = InventoryUtil.takeItems( m_quantity, inventory ); + ItemStack stack = InventoryUtil.takeItems( m_quantity, ItemStorage.wrap(inventory) ); if( stack.isEmpty() ) return TurtleCommandResult.failure( "No items to take" ); // Try to place into the turtle @@ -76,7 +77,7 @@ public class TurtleSuckCommand implements ITurtleCommand if( !remainder.isEmpty() ) { // Put the remainder back in the inventory - InventoryUtil.storeItems( remainder, inventory ); + InventoryUtil.storeItems( remainder, ItemStorage.wrap(inventory) ); } // Return true if we consumed anything diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleTurnCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleTurnCommand.java index 2365451ef..f5910b867 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleTurnCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleTurnCommand.java @@ -11,7 +11,7 @@ import dan200.computercraft.api.turtle.TurtleAnimation; import dan200.computercraft.api.turtle.TurtleCommandResult; import dan200.computercraft.api.turtle.event.TurtleAction; import dan200.computercraft.api.turtle.event.TurtleActionEvent; -import net.minecraftforge.common.MinecraftForge; +import dan200.computercraft.api.turtle.event.TurtleEvent; import javax.annotation.Nonnull; @@ -29,7 +29,7 @@ public class TurtleTurnCommand implements ITurtleCommand public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) { TurtleActionEvent event = new TurtleActionEvent( turtle, TurtleAction.TURN ); - if( MinecraftForge.EVENT_BUS.post( event ) ) + if( TurtleEvent.post( event ) ) { return TurtleCommandResult.failure( event.getFailureMessage() ); } diff --git a/src/main/java/dan200/computercraft/shared/turtle/inventory/ContainerTurtle.java b/src/main/java/dan200/computercraft/shared/turtle/inventory/ContainerTurtle.java index 1aac1abc7..9890feff6 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/inventory/ContainerTurtle.java +++ b/src/main/java/dan200/computercraft/shared/turtle/inventory/ContainerTurtle.java @@ -3,115 +3,125 @@ * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.shared.turtle.inventory; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import dan200.computercraft.api.turtle.ITurtleAccess; +import dan200.computercraft.shared.ComputerCraftRegistry; +import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.core.IComputer; -import dan200.computercraft.shared.computer.core.IContainerComputer; -import dan200.computercraft.shared.computer.core.InputState; +import dan200.computercraft.shared.computer.inventory.ContainerComputerBase; import dan200.computercraft.shared.network.container.ComputerContainerData; import dan200.computercraft.shared.turtle.blocks.TileTurtle; -import dan200.computercraft.shared.util.DefaultPropertyDelegate; - +import dan200.computercraft.shared.turtle.core.TurtleBrain; +import dan200.computercraft.shared.util.SingleIntArray; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.inventory.Inventory; import net.minecraft.inventory.SimpleInventory; import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketByteBuf; import net.minecraft.screen.ArrayPropertyDelegate; import net.minecraft.screen.PropertyDelegate; -import net.minecraft.screen.ScreenHandler; import net.minecraft.screen.slot.Slot; +import javax.annotation.Nonnull; +import java.util.function.Predicate; -public class ContainerTurtle extends ScreenHandler implements IContainerComputer { - private static final int PROPERTY_SLOT = 0; +public class ContainerTurtle extends ContainerComputerBase +{ + public static final int PLAYER_START_Y = 134; + public static final int TURTLE_START_X = 175; - public final int m_playerInvStartY; - public final int m_turtleInvStartX; - - private final Inventory inventory; private final PropertyDelegate properties; - private IComputer computer; - private final InputState input = new InputState(this); - private int m_selectedSlot; - private ContainerTurtle(int id, PlayerInventory playerInventory, Inventory inventory, PropertyDelegate properties, int playerInvStartY, - int turtleInvStartX) { - super(null, id); + private ContainerTurtle( + int id, Predicate canUse, IComputer computer, ComputerFamily family, + PlayerInventory playerInventory, Inventory inventory, PropertyDelegate properties + ) + { + super( ComputerCraftRegistry.ModContainers.TURTLE, id, canUse, computer, family ); this.properties = properties; - m_playerInvStartY = playerInvStartY; - m_turtleInvStartX = turtleInvStartX; - this.inventory = inventory; - addProperties(properties); + addProperties( properties ); // Turtle inventory - for (int y = 0; y < 4; y++) { - for (int x = 0; x < 4; x++) { - addSlot(new Slot(inventory, x + y * 4, turtleInvStartX + 1 + x * 18, playerInvStartY + 1 + y * 18)); + for( int y = 0; y < 4; y++ ) + { + for( int x = 0; x < 4; x++ ) + { + addSlot( new Slot( inventory, x + y * 4, TURTLE_START_X + 1 + x * 18, PLAYER_START_Y + 1 + y * 18 ) ); } } // Player inventory - for (int y = 0; y < 3; y++) { - for (int x = 0; x < 9; x++) { - addSlot(new Slot(playerInventory, x + y * 9 + 9, 8 + x * 18, playerInvStartY + 1 + y * 18)); + for( int y = 0; y < 3; y++ ) + { + for( int x = 0; x < 9; x++ ) + { + addSlot( new Slot( playerInventory, x + y * 9 + 9, 8 + x * 18, PLAYER_START_Y + 1 + y * 18 ) ); } } // Player hotbar - for (int x = 0; x < 9; x++) { - addSlot(new Slot(playerInventory, x, 8 + x * 18, playerInvStartY + 3 * 18 + 5)); + for( int x = 0; x < 9; x++ ) + { + addSlot( new Slot( playerInventory, x, 8 + x * 18, PLAYER_START_Y + 3 * 18 + 5 ) ); } } - public ContainerTurtle(int id, PlayerInventory playerInventory, ITurtleAccess turtle, IComputer computer) { - this(id, playerInventory, turtle.getInventory(), new DefaultPropertyDelegate() { - @Override - public int get(int id) { - return id == PROPERTY_SLOT ? turtle.getSelectedSlot() : 0; - } - - @Override - public int size() { - return 1; - } - }); - this.computer = computer; + public ContainerTurtle( int id, PlayerInventory player, TurtleBrain turtle ) + { + this( + id, p -> turtle.getOwner().canPlayerUse( p ), turtle.getOwner().createServerComputer(), turtle.getFamily(), + player, turtle.getInventory(), (SingleIntArray) turtle::getSelectedSlot + ); } - public ContainerTurtle(int id, PlayerInventory playerInventory, Inventory inventory, PropertyDelegate properties) { - this(id, playerInventory, inventory, properties, 134, 175); + public ContainerTurtle(int id, PlayerInventory player, PacketByteBuf packetByteBuf) + { + this(id, player, new ComputerContainerData(packetByteBuf)); } - public int getSelectedSlot() { - return properties.get(PROPERTY_SLOT); + public ContainerTurtle( int id, PlayerInventory player, ComputerContainerData data ) + { + this( + id, x -> true, getComputer( player, data ), data.getFamily(), + player, new SimpleInventory( TileTurtle.INVENTORY_SIZE ), new ArrayPropertyDelegate( 1 ) + ); + } + + public int getSelectedSlot() + { + return properties.get( 0 ); } @Nonnull - private ItemStack tryItemMerge(PlayerEntity player, int slotNum, int firstSlot, int lastSlot, boolean reverse) { - Slot slot = slots.get(slotNum); + private ItemStack tryItemMerge( PlayerEntity player, int slotNum, int firstSlot, int lastSlot, boolean reverse ) + { + Slot slot = slots.get( slotNum ); ItemStack originalStack = ItemStack.EMPTY; - if (slot != null && slot.hasStack()) { + if( slot != null && slot.hasStack() ) + { ItemStack clickedStack = slot.getStack(); originalStack = clickedStack.copy(); - if (!insertItem(clickedStack, firstSlot, lastSlot, reverse)) { + if( !insertItem( clickedStack, firstSlot, lastSlot, reverse ) ) + { return ItemStack.EMPTY; } - if (clickedStack.isEmpty()) { - slot.setStack(ItemStack.EMPTY); - } else { + if( clickedStack.isEmpty() ) + { + slot.setStack( ItemStack.EMPTY ); + } + else + { slot.markDirty(); } - if (clickedStack.getCount() != originalStack.getCount()) { - slot.onTakeItem(player, clickedStack); - } else { + if( clickedStack.getCount() != originalStack.getCount() ) + { + slot.onTakeItem( player, clickedStack ); + } + else + { return ItemStack.EMPTY; } } @@ -120,35 +130,16 @@ public class ContainerTurtle extends ScreenHandler implements IContainerComputer @Nonnull @Override - public ItemStack transferSlot(@Nonnull PlayerEntity player, int slotNum) { - if (slotNum >= 0 && slotNum < 16) { - return tryItemMerge(player, slotNum, 16, 52, true); - } else if (slotNum >= 16) { - return tryItemMerge(player, slotNum, 0, 16, false); + public ItemStack transferSlot( @Nonnull PlayerEntity player, int slotNum ) + { + if( slotNum >= 0 && slotNum < 16 ) + { + return tryItemMerge( player, slotNum, 16, 52, true ); + } + else if( slotNum >= 16 ) + { + return tryItemMerge( player, slotNum, 0, 16, false ); } return ItemStack.EMPTY; } - - @Override - public boolean canUse(PlayerEntity player) { - return inventory.canPlayerUse(player); - } - - @Nullable - @Override - public IComputer getComputer() { - return this.computer; - } - - @Nonnull - @Override - public InputState getInput() { - return this.input; - } - - @Override - public void close(PlayerEntity player) { - super.close(player); - this.input.close(); - } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/items/ItemTurtle.java b/src/main/java/dan200/computercraft/shared/turtle/items/ItemTurtle.java index 16b44ef99..446d843e0 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/items/ItemTurtle.java +++ b/src/main/java/dan200/computercraft/shared/turtle/items/ItemTurtle.java @@ -102,29 +102,29 @@ public class ItemTurtle extends ItemComputerBase implements ITurtleItem } } - @Nullable - @Override - public String getCreatorModId( ItemStack stack ) - { - // Determine our "creator mod" from the upgrades. We attempt to find the first non-vanilla/non-CC - // upgrade (starting from the left). - - ITurtleUpgrade left = getUpgrade( stack, TurtleSide.LEFT ); - if( left != null ) - { - String mod = TurtleUpgrades.getOwner( left ); - if( mod != null && !mod.equals( ComputerCraft.MOD_ID ) ) return mod; - } - - ITurtleUpgrade right = getUpgrade( stack, TurtleSide.RIGHT ); - if( right != null ) - { - String mod = TurtleUpgrades.getOwner( right ); - if( mod != null && !mod.equals( ComputerCraft.MOD_ID ) ) return mod; - } - - return super.getCreatorModId( stack ); - } +// @Nullable +// @Override +// public String getCreatorModId( ItemStack stack ) +// { +// // Determine our "creator mod" from the upgrades. We attempt to find the first non-vanilla/non-CC +// // upgrade (starting from the left). +// +// ITurtleUpgrade left = getUpgrade( stack, TurtleSide.LEFT ); +// if( left != null ) +// { +// String mod = TurtleUpgrades.getOwner( left ); +// if( mod != null && !mod.equals( ComputerCraft.MOD_ID ) ) return mod; +// } +// +// ITurtleUpgrade right = getUpgrade( stack, TurtleSide.RIGHT ); +// if( right != null ) +// { +// String mod = TurtleUpgrades.getOwner( right ); +// if( mod != null && !mod.equals( ComputerCraft.MOD_ID ) ) return mod; +// } +// +// return super.getCreatorModId( stack ); +// } @Override public ItemStack withFamily( @Nonnull ItemStack stack, @Nonnull ComputerFamily family ) diff --git a/src/main/java/dan200/computercraft/shared/turtle/items/TurtleItemFactory.java b/src/main/java/dan200/computercraft/shared/turtle/items/TurtleItemFactory.java index cc77819c4..3d56787aa 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/items/TurtleItemFactory.java +++ b/src/main/java/dan200/computercraft/shared/turtle/items/TurtleItemFactory.java @@ -8,7 +8,7 @@ package dan200.computercraft.shared.turtle.items; import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.ITurtleUpgrade; import dan200.computercraft.api.turtle.TurtleSide; -import dan200.computercraft.shared.Registry; +import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.turtle.blocks.ITurtleTile; import net.minecraft.item.ItemStack; @@ -37,9 +37,9 @@ public final class TurtleItemFactory switch( family ) { case NORMAL: - return Registry.ModItems.TURTLE_NORMAL.get().create( id, label, colour, leftUpgrade, rightUpgrade, fuelLevel, overlay ); + return ComputerCraftRegistry.ModItems.TURTLE_NORMAL.create( id, label, colour, leftUpgrade, rightUpgrade, fuelLevel, overlay ); case ADVANCED: - return Registry.ModItems.TURTLE_ADVANCED.get().create( id, label, colour, leftUpgrade, rightUpgrade, fuelLevel, overlay ); + return ComputerCraftRegistry.ModItems.TURTLE_ADVANCED.create( id, label, colour, leftUpgrade, rightUpgrade, fuelLevel, overlay ); default: return ItemStack.EMPTY; } diff --git a/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleUpgradeRecipe.java b/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleUpgradeRecipe.java index bffb308a4..a9ff6e6ab 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleUpgradeRecipe.java +++ b/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleUpgradeRecipe.java @@ -44,12 +44,12 @@ public final class TurtleUpgradeRecipe extends SpecialCraftingRecipe @Override public boolean matches( @Nonnull CraftingInventory inventory, @Nonnull World world ) { - return !getCraftingResult( inventory ).isEmpty(); + return !craft( inventory ).isEmpty(); } @Nonnull @Override - public ItemStack getCraftingResult( @Nonnull CraftingInventory inventory ) + public ItemStack craft( @Nonnull CraftingInventory inventory ) { // Scan the grid for a row containing a turtle and 1 or 2 items ItemStack leftItem = ItemStack.EMPTY; diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/CraftingTablePeripheral.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/CraftingTablePeripheral.java index 44e0070e1..ebec3f562 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/upgrades/CraftingTablePeripheral.java +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/CraftingTablePeripheral.java @@ -33,7 +33,7 @@ public class CraftingTablePeripheral implements IPeripheral @Nonnull @Override - public String getType0() + public String getType() { return "workbench"; } diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleCraftingTable.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleCraftingTable.java index bbaef878a..28488458a 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleCraftingTable.java +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleCraftingTable.java @@ -16,8 +16,6 @@ import net.fabricmc.api.Environment; import net.minecraft.block.Blocks; import net.minecraft.client.util.ModelIdentifier; import net.minecraft.util.Identifier; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; import javax.annotation.Nonnull; diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleInventoryCrafting.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleInventoryCrafting.java index 73da35331..360bb2f7e 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleInventoryCrafting.java +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleInventoryCrafting.java @@ -16,8 +16,6 @@ import net.minecraft.recipe.RecipeType; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.collection.DefaultedList; import net.minecraft.world.World; -import net.minecraftforge.common.ForgeHooks; -import net.minecraftforge.fml.hooks.BasicEventHooks; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -93,11 +91,7 @@ public class TurtleInventoryCrafting extends CraftingInventory results.add( result ); result.onCraft( world, player, result.getCount() ); - BasicEventHooks.firePlayerCraftingEvent( player, result, this ); - - ForgeHooks.setCraftingPlayer( player ); DefaultedList remainders = recipe.getRemainingStacks( this ); - ForgeHooks.setCraftingPlayer( null ); for( int slot = 0; slot < remainders.size(); slot++ ) { diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleModem.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleModem.java index 8e33891d5..694359ce6 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleModem.java +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleModem.java @@ -8,7 +8,7 @@ package dan200.computercraft.shared.turtle.upgrades; import dan200.computercraft.api.client.TransformedModel; import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.turtle.*; -import dan200.computercraft.shared.Registry; +import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.peripheral.modem.ModemState; import dan200.computercraft.shared.peripheral.modem.wireless.WirelessModemPeripheral; import net.fabricmc.api.EnvType; @@ -20,8 +20,6 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; import javax.annotation.Nonnull; @@ -82,8 +80,8 @@ public class TurtleModem extends AbstractTurtleUpgrade super( id, TurtleUpgradeType.PERIPHERAL, advanced - ? Registry.ModBlocks.WIRELESS_MODEM_ADVANCED - : Registry.ModBlocks.WIRELESS_MODEM_NORMAL + ? ComputerCraftRegistry.ModBlocks.WIRELESS_MODEM_ADVANCED + : ComputerCraftRegistry.ModBlocks.WIRELESS_MODEM_NORMAL ); this.advanced = advanced; } diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleSpeaker.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleSpeaker.java index f2067b0e9..4050a03a5 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleSpeaker.java +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleSpeaker.java @@ -12,7 +12,7 @@ import dan200.computercraft.api.turtle.AbstractTurtleUpgrade; import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.TurtleSide; import dan200.computercraft.api.turtle.TurtleUpgradeType; -import dan200.computercraft.shared.Registry; +import dan200.computercraft.shared.ComputerCraftRegistry; import dan200.computercraft.shared.peripheral.speaker.SpeakerPeripheral; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @@ -21,8 +21,6 @@ import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; import javax.annotation.Nonnull; @@ -65,7 +63,7 @@ public class TurtleSpeaker extends AbstractTurtleUpgrade public TurtleSpeaker( Identifier id ) { - super( id, TurtleUpgradeType.PERIPHERAL, Registry.ModBlocks.SPEAKER ); + super( id, TurtleUpgradeType.PERIPHERAL, ComputerCraftRegistry.ModBlocks.SPEAKER ); } @Override diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java index 783aa8681..f25b63eaa 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java @@ -10,14 +10,18 @@ import dan200.computercraft.api.client.TransformedModel; import dan200.computercraft.api.turtle.*; import dan200.computercraft.api.turtle.event.TurtleAttackEvent; import dan200.computercraft.api.turtle.event.TurtleBlockEvent; +import dan200.computercraft.api.turtle.event.TurtleEvent; import dan200.computercraft.shared.TurtlePermissions; import dan200.computercraft.shared.turtle.core.TurtlePlaceCommand; import dan200.computercraft.shared.turtle.core.TurtlePlayer; import dan200.computercraft.shared.util.DropConsumer; +import dan200.computercraft.shared.util.FillableMatrix4f; import dan200.computercraft.shared.util.InventoryUtil; import dan200.computercraft.shared.util.WorldUtil; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.event.player.AttackEntityCallback; +import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; @@ -30,17 +34,15 @@ import net.minecraft.entity.decoration.ArmorStandEntity; import net.minecraft.fluid.FluidState; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; +import net.minecraft.server.world.BlockEvent; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Matrix4f; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.entity.player.AttackEntityEvent; -import net.minecraftforge.event.world.BlockEvent; import org.apache.commons.lang3.tuple.Pair; import javax.annotation.Nonnull; @@ -75,7 +77,7 @@ public class TurtleTool extends AbstractTurtleUpgrade public TransformedModel getModel( ITurtleAccess turtle, @Nonnull TurtleSide side ) { float xOffset = side == TurtleSide.LEFT ? -0.40625f : 0.40625f; - Matrix4f transform = new Matrix4f( new float[] { + Matrix4f transform = new FillableMatrix4f( new float[] { 0.0f, 0.0f, -1.0f, 1.0f + xOffset, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, @@ -102,10 +104,9 @@ public class TurtleTool extends AbstractTurtleUpgrade protected boolean canBreakBlock( BlockState state, World world, BlockPos pos, TurtlePlayer player ) { Block block = state.getBlock(); - return !state.isAir( world, pos ) + return !state.isAir() && block != Blocks.BEDROCK - && state.calcBlockBreakingDelta( player, world, pos ) > 0 - && block.canEntityDestroy( state, world, pos, player ); + && state.calcBlockBreakingDelta( player, world, pos ) > 0; } protected float getDamageMultiplier() @@ -133,13 +134,18 @@ public class TurtleTool extends AbstractTurtleUpgrade Entity hitEntity = hit.getKey(); // Fire several events to ensure we have permissions. - if( MinecraftForge.EVENT_BUS.post( new AttackEntityEvent( turtlePlayer, hitEntity ) ) || !hitEntity.isAttackable() ) + if(AttackEntityCallback.EVENT.invoker() + .interact(turtlePlayer, + world, + Hand.MAIN_HAND, + hitEntity, + null) == ActionResult.FAIL || !hitEntity.isAttackable()) { return TurtleCommandResult.failure( "Nothing to attack here" ); } TurtleAttackEvent attackEvent = new TurtleAttackEvent( turtle, turtlePlayer, hitEntity, this, side ); - if( MinecraftForge.EVENT_BUS.post( attackEvent ) ) + if( TurtleEvent.post( attackEvent ) ) { return TurtleCommandResult.failure( attackEvent.getFailureMessage() ); } @@ -211,7 +217,7 @@ public class TurtleTool extends AbstractTurtleUpgrade if( ComputerCraft.turtlesObeyBlockProtection ) { // Check spawn protection - if( MinecraftForge.EVENT_BUS.post( new BlockEvent.BreakEvent( world, blockPosition, state, turtlePlayer ) ) ) + if(PlayerBlockBreakEvents.BEFORE.invoker().beforeBlockBreak(world, turtlePlayer, blockPosition, state, null)) { return TurtleCommandResult.failure( "Cannot break protected block" ); } @@ -230,7 +236,7 @@ public class TurtleTool extends AbstractTurtleUpgrade // Fire the dig event, checking whether it was cancelled. TurtleBlockEvent.Dig digEvent = new TurtleBlockEvent.Dig( turtle, turtlePlayer, world, blockPosition, state, this, side ); - if( MinecraftForge.EVENT_BUS.post( digEvent ) ) + if( TurtleEvent.post( digEvent ) ) { return TurtleCommandResult.failure( digEvent.getFailureMessage() ); } @@ -247,12 +253,12 @@ public class TurtleTool extends AbstractTurtleUpgrade world.syncWorldEvent( 2001, blockPosition, Block.getRawIdFromState( state ) ); // Destroy the block - boolean canHarvest = state.canHarvestBlock( world, blockPosition, turtlePlayer ); - boolean canBreak = state.removedByPlayer( world, blockPosition, turtlePlayer, canHarvest, fluidState ); - if( canBreak ) state.getBlock().onBroken( world, blockPosition, state ); - if( canHarvest && canBreak ) + state.getBlock().onBroken( world, blockPosition, state ); + if( world.removeBlock(blockPosition, false) ) { - state.getBlock().afterBreak( world, turtlePlayer, blockPosition, state, tile, turtlePlayer.getMainHandStack() ); + state.getBlock().onBroken(world, blockPosition, state); + if (turtlePlayer.isUsingEffectiveTool(state)) + state.getBlock().afterBreak( world, turtlePlayer, blockPosition, state, tile, turtlePlayer.getMainHandStack() ); } stopConsuming( turtle ); diff --git a/src/main/java/dan200/computercraft/shared/util/BasicRecipeSerializer.java b/src/main/java/dan200/computercraft/shared/util/BasicRecipeSerializer.java deleted file mode 100644 index 2dd0f7423..000000000 --- a/src/main/java/dan200/computercraft/shared/util/BasicRecipeSerializer.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.shared.util; - -import net.minecraft.recipe.Recipe; -import net.minecraft.recipe.RecipeSerializer; -import net.minecraftforge.registries.ForgeRegistryEntry; - -/** - * A {@link IRecipeSerializer} which implements all the Forge registry entries. - * - * @param The reciep serializer - */ -public abstract class BasicRecipeSerializer> extends ForgeRegistryEntry> implements RecipeSerializer -{ -} diff --git a/src/main/java/dan200/computercraft/shared/util/CapabilityUtil.java b/src/main/java/dan200/computercraft/shared/util/CapabilityUtil.java deleted file mode 100644 index 7643eeb2c..000000000 --- a/src/main/java/dan200/computercraft/shared/util/CapabilityUtil.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.common.util.NonNullConsumer; - -import javax.annotation.Nullable; - -public final class CapabilityUtil -{ - private CapabilityUtil() - { - } - - @Nullable - public static LazyOptional invalidate( @Nullable LazyOptional cap ) - { - if( cap != null ) cap.invalidate(); - return null; - } - - public static void invalidate( @Nullable LazyOptional[] caps ) - { - if( caps == null ) return; - - for( int i = 0; i < caps.length; i++ ) - { - LazyOptional cap = caps[i]; - if( cap != null ) cap.invalidate(); - caps[i] = null; - } - } - - @Nullable - public static T unwrap( LazyOptional p, NonNullConsumer> invalidate ) - { - if( !p.isPresent() ) return null; - - p.addListener( invalidate ); - return p.orElseThrow( NullPointerException::new ); - } -} diff --git a/src/main/java/dan200/computercraft/shared/util/ColourUtils.java b/src/main/java/dan200/computercraft/shared/util/ColourUtils.java index 41eb93f6a..d70f5d0b5 100644 --- a/src/main/java/dan200/computercraft/shared/util/ColourUtils.java +++ b/src/main/java/dan200/computercraft/shared/util/ColourUtils.java @@ -5,47 +5,21 @@ */ package dan200.computercraft.shared.util; +import net.minecraft.item.DyeItem; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.tag.Tag; import net.minecraft.util.DyeColor; -import net.minecraftforge.common.Tags; import javax.annotation.Nullable; public final class ColourUtils { - @SuppressWarnings( { "unchecked", "rawtypes" } ) - private static final Tag[] DYES = new Tag[] { - Tags.Items.DYES_WHITE, - Tags.Items.DYES_ORANGE, - Tags.Items.DYES_MAGENTA, - Tags.Items.DYES_LIGHT_BLUE, - Tags.Items.DYES_YELLOW, - Tags.Items.DYES_LIME, - Tags.Items.DYES_PINK, - Tags.Items.DYES_GRAY, - Tags.Items.DYES_LIGHT_GRAY, - Tags.Items.DYES_CYAN, - Tags.Items.DYES_PURPLE, - Tags.Items.DYES_BLUE, - Tags.Items.DYES_BROWN, - Tags.Items.DYES_GREEN, - Tags.Items.DYES_RED, - Tags.Items.DYES_BLACK, - }; - @Nullable private ColourUtils() {} - public static DyeColor getStackColour( ItemStack stack ) - { - for( int i = 0; i < DYES.length; i++ ) - { - Tag dye = DYES[i]; - if( dye.contains( stack.getItem() ) ) return DyeColor.byId( i ); - } - - return null; + public static DyeColor getStackColour(ItemStack stack) { + Item item = stack.getItem(); + return item instanceof DyeItem ? ((DyeItem) item).getColor() : null; } } diff --git a/src/main/java/dan200/computercraft/shared/util/Config.java b/src/main/java/dan200/computercraft/shared/util/Config.java new file mode 100644 index 000000000..37439d095 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/util/Config.java @@ -0,0 +1,220 @@ +package dan200.computercraft.shared.util; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.concurrent.TimeUnit; + +import blue.endless.jankson.Comment; +import blue.endless.jankson.Jankson; +import blue.endless.jankson.JsonObject; +import blue.endless.jankson.api.SyntaxError; +import com.google.common.base.CaseFormat; +import com.google.common.base.Converter; +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.api.turtle.event.TurtleAction; +import dan200.computercraft.core.apis.AddressPredicate; +import dan200.computercraft.core.apis.http.websocket.Websocket; + +public class Config { + public static final transient int MODEM_MAX_RANGE = 100000; + public static final transient Config defaultConfig = new Config(); + private static transient Path configPath; + private static transient Config config; + public General general = new General(); + @Comment ("\nControls execution behaviour of computers. This is largely intended for fine-tuning " + "servers, and generally shouldn't need to be " + + "touched") public Execution execution = new Execution(); + @Comment ("\nControls the HTTP API") public Http http = new Http(); + @Comment ("\nVarious options relating to peripherals.") public Peripheral peripheral = new Peripheral(); + @Comment ("\nVarious options relating to turtles.") public Turtle turtle = new Turtle(); + + public static Config get() { + return config; + } + + public static void load(Path path) { + configPath = path; + + if (Files.exists(configPath)) { + Jankson jankson = Jankson.builder() + .build(); + try { + JsonObject jsonObject = jankson.load(Files.newInputStream(configPath)); + config = jankson.fromJson(jsonObject, Config.class); + } catch (IOException | SyntaxError e) { + config = new Config(); + ComputerCraft.log.error("Failed to load config! Use default config."); + e.printStackTrace(); + return; + } + } else { + config = new Config(); + } + save(); + sync(); + } + + public static void save() { + Jankson jankson = Jankson.builder() + .build(); + try { + String configData = jankson.toJson(config) + .toJson(true, true); + Files.write(configPath, configData.getBytes()); + } catch (IOException e) { + ComputerCraft.log.error("Failed to save config!"); + e.printStackTrace(); + } + } + + public static void sync() { + // General + ComputerCraft.computerSpaceLimit = config.general.computer_space_limit; + ComputerCraft.floppySpaceLimit = config.general.floppy_space_limit; + ComputerCraft.maximumFilesOpen = Math.max(0, config.general.maximum_open_files); + ComputerCraft.disable_lua51_features = config.general.disable_lua51_features; + ComputerCraft.default_computer_settings = config.general.default_computer_settings; + ComputerCraft.debug_enable = config.general.debug_enabled; + ComputerCraft.logPeripheralErrors = config.general.log_computer_errors; + + // Execution + ComputerCraft.computer_threads = Math.max(1, config.execution.computer_threads); + ComputerCraft.maxMainGlobalTime = TimeUnit.MILLISECONDS.toNanos(Math.max(1, config.execution.max_main_global_time)); + ComputerCraft.maxMainComputerTime = TimeUnit.MILLISECONDS.toNanos(Math.max(1, config.execution.max_main_computer_time)); + + // HTTP + ComputerCraft.http_enable = config.http.enabled; + ComputerCraft.http_websocket_enable = config.http.websocket_enabled; + ComputerCraft.http_whitelist = new AddressPredicate(config.http.whitelist); + ComputerCraft.http_blacklist = new AddressPredicate(config.http.blacklist); + + ComputerCraft.httpTimeout = Math.max(0, config.http.timeout); + ComputerCraft.httpMaxRequests = Math.max(1, config.http.max_requests); + ComputerCraft.httpMaxDownload = Math.max(0, config.http.max_download); + ComputerCraft.httpMaxUpload = Math.max(0, config.http.max_upload); + ComputerCraft.httpMaxWebsockets = Math.max(1, config.http.max_websockets); + ComputerCraft.httpMaxWebsocketMessage = Math.min(Math.max(0, config.http.max_websocket_message), Websocket.MAX_MESSAGE_SIZE); + + // Peripheral + ComputerCraft.enableCommandBlock = config.peripheral.command_block_enabled; + ComputerCraft.maxNotesPerTick = Math.max(1, config.peripheral.max_notes_per_tick); + ComputerCraft.modem_range = Math.min(Math.max(0, config.peripheral.modem_range), MODEM_MAX_RANGE); + ComputerCraft.modem_highAltitudeRange = Math.min(Math.max(0, config.peripheral.modem_high_altitude_range), MODEM_MAX_RANGE); + ComputerCraft.modem_rangeDuringStorm = Math.min(Math.max(0, config.peripheral.modem_range_during_storm), MODEM_MAX_RANGE); + ComputerCraft.modem_highAltitudeRangeDuringStorm = Math.min(Math.max(0, config.peripheral.modem_high_altitude_range_during_storm), MODEM_MAX_RANGE); + + // Turtles + ComputerCraft.turtlesNeedFuel = config.turtle.need_fuel; + ComputerCraft.turtleFuelLimit = Math.max(0, config.turtle.normal_fuel_limit); + ComputerCraft.advancedTurtleFuelLimit = Math.max(0, config.turtle.advanced_fuel_limit); + ComputerCraft.turtlesObeyBlockProtection = config.turtle.obey_block_protection; + ComputerCraft.turtlesCanPush = config.turtle.can_push; + + ComputerCraft.turtleDisabledActions.clear(); + Converter converter = CaseFormat.LOWER_CAMEL.converterTo(CaseFormat.UPPER_UNDERSCORE); + for (String value : config.turtle.disabled_actions) { + try { + ComputerCraft.turtleDisabledActions.add(TurtleAction.valueOf(converter.convert(value))); + } catch (IllegalArgumentException e) { + ComputerCraft.log.error("Unknown turtle action " + value); + } + } + } + + public static class General { + @Comment ("\nThe disk space limit for computers and turtles, in bytes") public int computer_space_limit = ComputerCraft.computerSpaceLimit; + + @Comment ("\nThe disk space limit for floppy disks, in bytes") public int floppy_space_limit = ComputerCraft.floppySpaceLimit; + + @Comment ("\nSet how many files a computer can have open at the same time. Set to 0 for unlimited.") public int maximum_open_files = + ComputerCraft.maximumFilesOpen; + + @Comment ("\nSet this to true to disable Lua 5.1 functions that will be removed in a future " + "update. Useful for ensuring forward " + + "compatibility of your programs now.") public boolean disable_lua51_features = ComputerCraft.disable_lua51_features; + + @Comment ("\nA comma separated list of default system settings to set on new computers. Example: " + "\"shell.autocomplete=false,lua" + + ".autocomplete=false,edit.autocomplete=false\" will disable all autocompletion") public String default_computer_settings = + ComputerCraft.default_computer_settings; + + @Comment ("\nEnable Lua's debug library. This is sandboxed to each computer, so is generally safe to be used by players.") public boolean debug_enabled = ComputerCraft.debug_enable; + + @Comment ("\nLog exceptions thrown by peripherals and other Lua objects.\n" + "This makes it easier for mod authors to debug problems, but may " + + "result in log spam should people use buggy methods.") public boolean log_computer_errors = ComputerCraft.logPeripheralErrors; + } + + public static class Execution { + @Comment ("\nSet the number of threads computers can run on. A higher number means more computers can " + "run at once, but may induce lag.\n" + + "Please note that some mods may not work with a thread count higher than 1. Use with caution.") public int computer_threads = + ComputerCraft.computer_threads; + + @Comment ("\nThe maximum time that can be spent executing tasks in a single tick, in milliseconds.\n" + "Note, we will quite possibly go over " + + "this limit, as there's no way to tell how long a will take - this aims " + "to be the upper bound of the average time.") public long max_main_global_time = TimeUnit.NANOSECONDS.toMillis( + ComputerCraft.maxMainGlobalTime); + + @Comment ("\nThe ideal maximum time a computer can execute for in a tick, in milliseconds.\n" + "Note, we will quite possibly go over this limit," + + " as there's no way to tell how long a will take - this aims " + "to be the upper bound of the average time.") public long max_main_computer_time = TimeUnit.NANOSECONDS.toMillis( + ComputerCraft.maxMainComputerTime); + } + + public static class Http { + @Comment ("\nEnable the \"http\" API on Computers (see \"http_whitelist\" and \"http_blacklist\" for " + "more fine grained control than this)") public boolean enabled = ComputerCraft.http_enable; + + @Comment ("\nEnable use of http websockets. This requires the \"http_enable\" option to also be true.") public boolean websocket_enabled = + ComputerCraft.http_websocket_enable; + + @Comment ("\nA list of wildcards for domains or IP ranges that can be accessed through the " + "\"http\" API on Computers.\n" + "Set this to " + + "\"*\" to access to the entire internet. Example: \"*.pastebin.com\" will restrict access to " + "just subdomains of pastebin.com.\n" + "You can use domain names (\"pastebin.com\"), wilcards (\"*.pastebin.com\") or CIDR notation (\"127.0.0.0/8\").") public String[] whitelist = ComputerCraft.DEFAULT_HTTP_WHITELIST.clone(); + + @Comment ("\nA list of wildcards for domains or IP ranges that cannot be accessed through the " + "\"http\" API on Computers.\n" + "If this is " + + "empty then all whitelisted domains will be accessible. Example: \"*.github.com\" will block " + "access to all subdomains of github" + + ".com.\n" + "You can use domain names (\"pastebin.com\"), wilcards (\"*.pastebin.com\") or CIDR notation (\"127.0.0.0/8\").") public String[] blacklist = ComputerCraft.DEFAULT_HTTP_BLACKLIST.clone(); + + @Comment ("\nThe period of time (in milliseconds) to wait before a HTTP request times out. Set to 0 for unlimited.") public int timeout = + ComputerCraft.httpTimeout; + + @Comment ("\nThe number of http requests a computer can make at one time. Additional requests " + "will be queued, and sent when the running " + + "requests have finished. Set to 0 for unlimited.") public int max_requests = ComputerCraft.httpMaxRequests; + + @Comment ("\nThe maximum size (in bytes) that a computer can download in a single request. " + "Note that responses may receive more data than " + + "allowed, but this data will not be returned to the client.") public long max_download = ComputerCraft.httpMaxDownload; + + @Comment ("\nThe maximum size (in bytes) that a computer can upload in a single request. This " + "includes headers and POST text.") public long max_upload = ComputerCraft.httpMaxUpload; + + @Comment ("\nThe number of websockets a computer can have open at one time. Set to 0 for unlimited.") public int max_websockets = + ComputerCraft.httpMaxWebsockets; + + @Comment ("\nThe maximum size (in bytes) that a computer can send or receive in one websocket packet.") public int max_websocket_message = + ComputerCraft.httpMaxWebsocketMessage; + } + + public static class Peripheral { + @Comment ("\n\nEnable Command Block peripheral support") public boolean command_block_enabled = ComputerCraft.enableCommandBlock; + + @Comment ("\nThe range of Wireless Modems at low altitude in clear weather, in meters") public int modem_range = ComputerCraft.modem_range; + + @Comment ("\nThe range of Wireless Modems at maximum altitude in clear weather, in meters") public int modem_high_altitude_range = + ComputerCraft.modem_highAltitudeRange; + + @Comment ("\nThe range of Wireless Modems at low altitude in stormy weather, in meters") public int modem_range_during_storm = + ComputerCraft.modem_rangeDuringStorm; + + @Comment ("\nThe range of Wireless Modems at maximum altitude in stormy weather, in meters") public int modem_high_altitude_range_during_storm = + ComputerCraft.modem_highAltitudeRangeDuringStorm; + + @Comment ("\nMaximum amount of notes a speaker can play at once") public int max_notes_per_tick = ComputerCraft.maxNotesPerTick; + } + + public static class Turtle { + @Comment ("\nSet whether Turtles require fuel to move") public boolean need_fuel = ComputerCraft.turtlesNeedFuel; + + @Comment ("\nThe fuel limit for Turtles") public int normal_fuel_limit = ComputerCraft.turtleFuelLimit; + + @Comment ("\nThe fuel limit for Advanced Turtles") public int advanced_fuel_limit = ComputerCraft.advancedTurtleFuelLimit; + + @Comment ("\nIf set to true, Turtles will be unable to build, dig, or enter protected " + "areas (such as near the server spawn point)") public boolean obey_block_protection = ComputerCraft.turtlesObeyBlockProtection; + + @Comment ("\nIf set to true, Turtles will push entities out of the way instead of stopping if " + "there is space to do so") public boolean can_push = ComputerCraft.turtlesCanPush; + + @Comment ("\nA list of turtle actions which are disabled.") public String[] disabled_actions = new String[0]; + } +} diff --git a/src/main/java/dan200/computercraft/shared/util/CreativeTabMain.java b/src/main/java/dan200/computercraft/shared/util/CreativeTabMain.java deleted file mode 100644 index 0f0fa999c..000000000 --- a/src/main/java/dan200/computercraft/shared/util/CreativeTabMain.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.shared.util; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.shared.Registry; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.item.ItemGroup; -import net.minecraft.item.ItemStack; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -import javax.annotation.Nonnull; - -public class CreativeTabMain extends ItemGroup -{ - public CreativeTabMain() - { - super( ComputerCraft.MOD_ID ); - } - - @Nonnull - @Override - @Environment(EnvType.CLIENT) - public ItemStack createIcon() - { - return new ItemStack( Registry.ModBlocks.COMPUTER_NORMAL.get() ); - } -} diff --git a/src/main/java/dan200/computercraft/shared/util/DropConsumer.java b/src/main/java/dan200/computercraft/shared/util/DropConsumer.java index 96cc72936..2b09cfd1f 100644 --- a/src/main/java/dan200/computercraft/shared/util/DropConsumer.java +++ b/src/main/java/dan200/computercraft/shared/util/DropConsumer.java @@ -5,24 +5,18 @@ */ package dan200.computercraft.shared.util; -import dan200.computercraft.ComputerCraft; import net.minecraft.entity.Entity; import net.minecraft.entity.ItemEntity; import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Box; import net.minecraft.world.World; -import net.minecraftforge.event.entity.EntityJoinWorldEvent; -import net.minecraftforge.event.entity.living.LivingDropsEvent; -import net.minecraftforge.eventbus.api.EventPriority; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; import java.util.function.Function; -@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID ) public final class DropConsumer { private DropConsumer() @@ -31,19 +25,21 @@ public final class DropConsumer private static Function dropConsumer; private static List remainingDrops; - private static World dropWorld; + private static WeakReference dropWorld; + private static BlockPos dropPos; private static Box dropBounds; - private static Entity dropEntity; + private static WeakReference dropEntity; public static void set( Entity entity, Function consumer ) { dropConsumer = consumer; remainingDrops = new ArrayList<>(); - dropEntity = entity; - dropWorld = entity.world; + dropEntity = new WeakReference<>( entity ); + dropWorld = new WeakReference<>( entity.world ); + dropPos = null; dropBounds = new Box( entity.getBlockPos() ).expand( 2, 2, 2 ); - entity.captureDrops( new ArrayList<>() ); + // entity.captureDrops( new ArrayList<>() ); } public static void set( World world, BlockPos pos, Function consumer ) @@ -51,7 +47,7 @@ public final class DropConsumer dropConsumer = consumer; remainingDrops = new ArrayList<>( 2 ); dropEntity = null; - dropWorld = world; + dropWorld = new WeakReference<>( world ); dropBounds = new Box( pos ).expand( 2, 2, 2 ); } @@ -74,24 +70,32 @@ public final class DropConsumer if( !remaining.isEmpty() ) remainingDrops.add( remaining ); } - @SubscribeEvent( priority = EventPriority.HIGHEST ) - public static void onEntitySpawn( EntityJoinWorldEvent event ) + public static boolean onHarvestDrops(World world, BlockPos pos, ItemStack stack) { + if( dropWorld != null && dropWorld.get() == world && dropPos != null && dropPos.equals( pos ) ) { + handleDrops(stack); + return true; + } + return false; + } + + public static boolean onEntitySpawn(Entity entity) { // Capture any nearby item spawns - if( dropWorld == event.getWorld() && event.getEntity() instanceof ItemEntity - && dropBounds.contains( event.getEntity().getPos() ) ) + if( dropWorld != null && dropWorld.get() == entity.getEntityWorld() && entity instanceof ItemEntity + && dropBounds.contains( entity.getPos() ) ) { - handleDrops( ((ItemEntity) event.getEntity()).getStack() ); - event.setCanceled( true ); + handleDrops( ((ItemEntity) entity).getStack() ); + return true; } + return false; } - @SubscribeEvent - public static void onLivingDrops( LivingDropsEvent drops ) + public static boolean onLivingDrops(Entity entity, ItemStack stack) { - if( dropEntity == null || drops.getEntity() != dropEntity ) return; - - for( ItemEntity drop : drops.getDrops() ) handleDrops( drop.getStack() ); - drops.setCanceled( true ); + if (dropEntity != null && entity == dropEntity.get()) { + handleDrops(stack); + return true; + } + return false; } } diff --git a/src/main/java/dan200/computercraft/shared/util/FillableMatrix4f.java b/src/main/java/dan200/computercraft/shared/util/FillableMatrix4f.java new file mode 100644 index 000000000..ffe05cec1 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/util/FillableMatrix4f.java @@ -0,0 +1,24 @@ +package dan200.computercraft.shared.util; + +import net.minecraft.util.math.Matrix4f; + +public class FillableMatrix4f extends Matrix4f { + public FillableMatrix4f(float[] input) { + a00 = input[0]; + a01 = input[1]; + a02 = input[2]; + a03 = input[3]; + a10 = input[4]; + a11 = input[5]; + a12 = input[6]; + a13 = input[7]; + a20 = input[8]; + a21 = input[9]; + a22 = input[10]; + a23 = input[11]; + a30 = input[12]; + a31 = input[13]; + a32 = input[14]; + a33 = input[15]; + } +} diff --git a/src/main/java/dan200/computercraft/shared/util/IDAssigner.java b/src/main/java/dan200/computercraft/shared/util/IDAssigner.java index 9ab33553c..4bb140ce5 100644 --- a/src/main/java/dan200/computercraft/shared/util/IDAssigner.java +++ b/src/main/java/dan200/computercraft/shared/util/IDAssigner.java @@ -9,9 +9,9 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; import dan200.computercraft.ComputerCraft; +import net.fabricmc.loader.api.FabricLoader; import net.minecraft.server.MinecraftServer; import net.minecraft.util.WorldSavePath; -import net.minecraftforge.fml.server.ServerLifecycleHooks; import java.io.File; import java.io.Reader; @@ -42,7 +42,7 @@ public final class IDAssigner public static File getDir() { - return ServerLifecycleHooks.getCurrentServer().getSavePath( FOLDER ).toFile(); + return FabricLoader.getInstance().getGameInstance() instanceof MinecraftServer ? ((MinecraftServer) FabricLoader.getInstance().getGameInstance()).getSavePath( FOLDER ).toFile() : null; } private static MinecraftServer getCachedServer() @@ -52,7 +52,7 @@ public final class IDAssigner MinecraftServer currentServer = server.get(); if( currentServer == null ) return null; - if( currentServer != ServerLifecycleHooks.getCurrentServer() ) return null; + if(FabricLoader.getInstance().getGameInstance() instanceof MinecraftServer && currentServer != FabricLoader.getInstance().getGameInstance() ) return null; return currentServer; } @@ -62,29 +62,25 @@ public final class IDAssigner if( currentServer == null ) { // The server has changed, refetch our ID map - server = new WeakReference<>( ServerLifecycleHooks.getCurrentServer() ); + if (FabricLoader.getInstance().getGameInstance() instanceof MinecraftServer) { + server = new WeakReference<>((MinecraftServer) FabricLoader.getInstance().getGameInstance()); - File dir = getDir(); - dir.mkdirs(); + File dir = getDir(); + dir.mkdirs(); - // Load our ID file from disk - idFile = new File( dir, "ids.json" ).toPath(); - if( Files.isRegularFile( idFile ) ) - { - try( Reader reader = Files.newBufferedReader( idFile, StandardCharsets.UTF_8 ) ) - { - ids = GSON.fromJson( reader, ID_TOKEN ); - } - catch( Exception e ) - { - ComputerCraft.log.error( "Cannot load id file '" + idFile + "'", e ); + // Load our ID file from disk + idFile = new File(dir, "ids.json").toPath(); + if (Files.isRegularFile(idFile)) { + try (Reader reader = Files.newBufferedReader(idFile, StandardCharsets.UTF_8)) { + ids = GSON.fromJson(reader, ID_TOKEN); + } catch (Exception e) { + ComputerCraft.log.error("Cannot load id file '" + idFile + "'", e); + ids = new HashMap<>(); + } + } else { ids = new HashMap<>(); } } - else - { - ids = new HashMap<>(); - } } Integer existing = ids.get( kind ); diff --git a/src/main/java/dan200/computercraft/shared/util/ImpostorRecipe.java b/src/main/java/dan200/computercraft/shared/util/ImpostorRecipe.java index 3a4862af0..7cff2753f 100644 --- a/src/main/java/dan200/computercraft/shared/util/ImpostorRecipe.java +++ b/src/main/java/dan200/computercraft/shared/util/ImpostorRecipe.java @@ -16,7 +16,6 @@ import net.minecraft.util.Identifier; import net.minecraft.util.JsonHelper; import net.minecraft.util.collection.DefaultedList; import net.minecraft.world.World; -import net.minecraftforge.common.crafting.CraftingHelper; import javax.annotation.Nonnull; @@ -57,14 +56,14 @@ public final class ImpostorRecipe extends ShapedRecipe return SERIALIZER; } - public static final RecipeSerializer SERIALIZER = new BasicRecipeSerializer() + public static final RecipeSerializer SERIALIZER = new RecipeSerializer() { @Override public ImpostorRecipe read( @Nonnull Identifier identifier, @Nonnull JsonObject json ) { String group = JsonHelper.getString( json, "group", "" ); ShapedRecipe recipe = RecipeSerializer.SHAPED.read( identifier, json ); - ItemStack result = CraftingHelper.getItemStack( JsonHelper.getObject( json, "result" ), true ); + ItemStack result = ShapedRecipe.getItemStack( JsonHelper.getObject( json, "result" ) ); return new ImpostorRecipe( identifier, group, recipe.getWidth(), recipe.getHeight(), recipe.getPreviewInputs(), result ); } @@ -83,8 +82,8 @@ public final class ImpostorRecipe extends ShapedRecipe @Override public void write( @Nonnull PacketByteBuf buf, @Nonnull ImpostorRecipe recipe ) { - buf.writeVarInt( recipe.getRecipeWidth() ); - buf.writeVarInt( recipe.getRecipeHeight() ); + buf.writeVarInt( recipe.getWidth() ); + buf.writeVarInt( recipe.getHeight() ); buf.writeString( recipe.getGroup() ); for( Ingredient ingredient : recipe.getPreviewInputs() ) ingredient.write( buf ); buf.writeItemStack( recipe.getOutput() ); diff --git a/src/main/java/dan200/computercraft/shared/util/ImpostorShapelessRecipe.java b/src/main/java/dan200/computercraft/shared/util/ImpostorShapelessRecipe.java index ca34188df..5869fab4d 100644 --- a/src/main/java/dan200/computercraft/shared/util/ImpostorShapelessRecipe.java +++ b/src/main/java/dan200/computercraft/shared/util/ImpostorShapelessRecipe.java @@ -13,12 +13,12 @@ import net.minecraft.item.ItemStack; import net.minecraft.network.PacketByteBuf; import net.minecraft.recipe.Ingredient; import net.minecraft.recipe.RecipeSerializer; +import net.minecraft.recipe.ShapedRecipe; import net.minecraft.recipe.ShapelessRecipe; import net.minecraft.util.Identifier; import net.minecraft.util.JsonHelper; import net.minecraft.util.collection.DefaultedList; import net.minecraft.world.World; -import net.minecraftforge.common.crafting.CraftingHelper; import javax.annotation.Nonnull; @@ -59,7 +59,7 @@ public final class ImpostorShapelessRecipe extends ShapelessRecipe return SERIALIZER; } - public static final RecipeSerializer SERIALIZER = new BasicRecipeSerializer() + public static final RecipeSerializer SERIALIZER = new RecipeSerializer() { @Override public ImpostorShapelessRecipe read( @Nonnull Identifier id, @Nonnull JsonObject json ) @@ -73,7 +73,7 @@ public final class ImpostorShapelessRecipe extends ShapelessRecipe throw new JsonParseException( "Too many ingredients for shapeless recipe the max is 9" ); } - ItemStack itemstack = CraftingHelper.getItemStack( JsonHelper.getObject( json, "result" ), true ); + ItemStack itemstack = ShapedRecipe.getItemStack( JsonHelper.getObject( json, "result" ) ); return new ImpostorShapelessRecipe( id, s, itemstack, ingredients ); } diff --git a/src/main/java/dan200/computercraft/shared/util/NBTUtil.java b/src/main/java/dan200/computercraft/shared/util/NBTUtil.java index 1190a181b..0cf7718e7 100644 --- a/src/main/java/dan200/computercraft/shared/util/NBTUtil.java +++ b/src/main/java/dan200/computercraft/shared/util/NBTUtil.java @@ -3,9 +3,14 @@ * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.shared.util; +import dan200.computercraft.ComputerCraft; +import net.minecraft.nbt.*; +import org.apache.commons.codec.binary.Hex; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.io.DataOutput; import java.io.DataOutputStream; import java.io.IOException; @@ -15,228 +20,207 @@ import java.security.NoSuchAlgorithmException; import java.util.HashMap; import java.util.Map; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import dan200.computercraft.ComputerCraft; -import org.apache.commons.codec.binary.Hex; - -import net.minecraft.nbt.AbstractNumberTag; -import net.minecraft.nbt.ByteArrayTag; -import net.minecraft.nbt.ByteTag; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.DoubleTag; -import net.minecraft.nbt.IntArrayTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.NbtIo; -import net.minecraft.nbt.StringTag; -import net.minecraft.nbt.Tag; - -import net.fabricmc.fabric.api.util.NbtType; - -public final class NBTUtil { - public static final int TAG_END = NbtType.END; - public static final int TAG_BYTE = NbtType.BYTE; - public static final int TAG_SHORT = NbtType.SHORT; - public static final int TAG_INT = NbtType.INT; - public static final int TAG_LONG = NbtType.LONG; - public static final int TAG_FLOAT = NbtType.FLOAT; - public static final int TAG_DOUBLE = NbtType.DOUBLE; - public static final int TAG_BYTE_ARRAY = NbtType.BYTE_ARRAY; - public static final int TAG_STRING = NbtType.STRING; - public static final int TAG_LIST = NbtType.LIST; - public static final int TAG_COMPOUND = NbtType.COMPOUND; - public static final int TAG_INT_ARRAY = NbtType.INT_ARRAY; - public static final int TAG_LONG_ARRAY = NbtType.LONG_ARRAY; - public static final int TAG_ANY_NUMERIC = NbtType.NUMBER; +public final class NBTUtil +{ + public static final int TAG_END = 0; + public static final int TAG_BYTE = 1; + public static final int TAG_SHORT = 2; + public static final int TAG_INT = 3; + public static final int TAG_LONG = 4; + public static final int TAG_FLOAT = 5; + public static final int TAG_DOUBLE = 6; + public static final int TAG_BYTE_ARRAY = 7; + public static final int TAG_STRING = 8; + public static final int TAG_LIST = 9; + public static final int TAG_COMPOUND = 10; + public static final int TAG_INT_ARRAY = 11; + public static final int TAG_LONG_ARRAY = 12; + public static final int TAG_ANY_NUMERIC = 99; private NBTUtil() {} - private static Tag toNBTTag(Object object) { - if (object == null) { - return null; - } - if (object instanceof Boolean) { - return ByteTag.of((byte) ((boolean) (Boolean) object ? 1 : 0)); - } - if (object instanceof Number) { - return DoubleTag.of(((Number) object).doubleValue()); - } - if (object instanceof String) { - return StringTag.of(object.toString()); - } - if (object instanceof Map) { + private static Tag toNBTTag( Object object ) + { + if( object == null ) return null; + if( object instanceof Boolean ) return ByteTag.of( (byte) ((boolean) (Boolean) object ? 1 : 0) ); + if( object instanceof Number ) return DoubleTag.of( ((Number) object).doubleValue() ); + if( object instanceof String ) return StringTag.of( object.toString() ); + if( object instanceof Map ) + { Map m = (Map) object; CompoundTag nbt = new CompoundTag(); int i = 0; - for (Map.Entry entry : m.entrySet()) { - Tag key = toNBTTag(entry.getKey()); - Tag value = toNBTTag(entry.getKey()); - if (key != null && value != null) { - nbt.put("k" + i, key); - nbt.put("v" + i, value); + for( Map.Entry entry : m.entrySet() ) + { + Tag key = toNBTTag( entry.getKey() ); + Tag value = toNBTTag( entry.getKey() ); + if( key != null && value != null ) + { + nbt.put( "k" + i, key ); + nbt.put( "v" + i, value ); i++; } } - nbt.putInt("len", m.size()); + nbt.putInt( "len", m.size() ); return nbt; } return null; } - public static CompoundTag encodeObjects(Object[] objects) { - if (objects == null || objects.length <= 0) { - return null; - } + public static CompoundTag encodeObjects( Object[] objects ) + { + if( objects == null || objects.length <= 0 ) return null; CompoundTag nbt = new CompoundTag(); - nbt.putInt("len", objects.length); - for (int i = 0; i < objects.length; i++) { - Tag child = toNBTTag(objects[i]); - if (child != null) { - nbt.put(Integer.toString(i), child); - } + nbt.putInt( "len", objects.length ); + for( int i = 0; i < objects.length; i++ ) + { + Tag child = toNBTTag( objects[i] ); + if( child != null ) nbt.put( Integer.toString( i ), child ); } return nbt; } - private static Object fromNBTTag(Tag tag) { - if (tag == null) { - return null; - } - switch (tag.getType()) { - case TAG_BYTE: - return ((ByteTag) tag).getByte() > 0; - case TAG_DOUBLE: - return ((DoubleTag) tag).getDouble(); - default: - case TAG_STRING: - return tag.asString(); - case TAG_COMPOUND: { - CompoundTag c = (CompoundTag) tag; - int len = c.getInt("len"); - Map map = new HashMap<>(len); - for (int i = 0; i < len; i++) { - Object key = fromNBTTag(c.get("k" + i)); - Object value = fromNBTTag(c.get("v" + i)); - if (key != null && value != null) { - map.put(key, value); + private static Object fromNBTTag( Tag tag ) + { + if( tag == null ) return null; + switch( tag.getType() ) + { + case TAG_BYTE: + return ((ByteTag) tag).getByte() > 0; + case TAG_DOUBLE: + return ((DoubleTag) tag).getDouble(); + default: + case TAG_STRING: + return tag.asString(); + case TAG_COMPOUND: + { + CompoundTag c = (CompoundTag) tag; + int len = c.getInt( "len" ); + Map map = new HashMap<>( len ); + for( int i = 0; i < len; i++ ) + { + Object key = fromNBTTag( c.get( "k" + i ) ); + Object value = fromNBTTag( c.get( "v" + i ) ); + if( key != null && value != null ) map.put( key, value ); } + return map; } - return map; - } } } - public static Object toLua(Tag tag) { - if (tag == null) { - return null; - } + public static Object toLua( Tag tag ) + { + if( tag == null ) return null; byte typeID = tag.getType(); - switch (typeID) { - case NBTUtil.TAG_BYTE: - case NBTUtil.TAG_SHORT: - case NBTUtil.TAG_INT: - case NBTUtil.TAG_LONG: - return ((AbstractNumberTag) tag).getLong(); - case NBTUtil.TAG_FLOAT: - case NBTUtil.TAG_DOUBLE: - return ((AbstractNumberTag) tag).getDouble(); - case NBTUtil.TAG_STRING: // String - return tag.asString(); - case NBTUtil.TAG_COMPOUND: // Compound + switch( typeID ) { - CompoundTag compound = (CompoundTag) tag; - Map map = new HashMap<>(compound.getSize()); - for (String key : compound.getKeys()) { - Object value = toLua(compound.get(key)); - if (value != null) { - map.put(key, value); + case TAG_BYTE: + case TAG_SHORT: + case TAG_INT: + case TAG_LONG: + return ((AbstractNumberTag) tag).getLong(); + case TAG_FLOAT: + case TAG_DOUBLE: + return ((AbstractNumberTag) tag).getDouble(); + case TAG_STRING: // String + return tag.asString(); + case TAG_COMPOUND: // Compound + { + CompoundTag compound = (CompoundTag) tag; + Map map = new HashMap<>( compound.getSize() ); + for( String key : compound.getKeys() ) + { + Object value = toLua( compound.get( key ) ); + if( value != null ) map.put( key, value ); } + return map; } - return map; - } - case NBTUtil.TAG_LIST: { - ListTag list = (ListTag) tag; - Map map = new HashMap<>(list.size()); - for (int i = 0; i < list.size(); i++) { - map.put(i, toLua(list.get(i))); + case TAG_LIST: + { + ListTag list = (ListTag) tag; + Map map = new HashMap<>( list.size() ); + for( int i = 0; i < list.size(); i++ ) map.put( i, toLua( list.get( i ) ) ); + return map; } - return map; - } - case NBTUtil.TAG_BYTE_ARRAY: { - byte[] array = ((ByteArrayTag) tag).getByteArray(); - Map map = new HashMap<>(array.length); - for (int i = 0; i < array.length; i++) { - map.put(i + 1, array[i]); + case TAG_BYTE_ARRAY: + { + byte[] array = ((ByteArrayTag) tag).getByteArray(); + Map map = new HashMap<>( array.length ); + for( int i = 0; i < array.length; i++ ) map.put( i + 1, array[i] ); + return map; } - return map; - } - case NBTUtil.TAG_INT_ARRAY: { - int[] array = ((IntArrayTag) tag).getIntArray(); - Map map = new HashMap<>(array.length); - for (int i = 0; i < array.length; i++) { - map.put(i + 1, array[i]); + case TAG_INT_ARRAY: + { + int[] array = ((IntArrayTag) tag).getIntArray(); + Map map = new HashMap<>( array.length ); + for( int i = 0; i < array.length; i++ ) map.put( i + 1, array[i] ); + return map; } - return map; - } - default: - return null; + default: + return null; } } - public static Object[] decodeObjects(CompoundTag tag) { - int len = tag.getInt("len"); - if (len <= 0) { - return null; - } + public static Object[] decodeObjects( CompoundTag tag ) + { + int len = tag.getInt( "len" ); + if( len <= 0 ) return null; Object[] objects = new Object[len]; - for (int i = 0; i < len; i++) { - String key = Integer.toString(i); - if (tag.contains(key)) { - objects[i] = fromNBTTag(tag.get(key)); + for( int i = 0; i < len; i++ ) + { + String key = Integer.toString( i ); + if( tag.contains( key ) ) + { + objects[i] = fromNBTTag( tag.get( key ) ); } } return objects; } @Nullable - public static String getNBTHash(@Nullable CompoundTag tag) { - if (tag == null) { - return null; - } + public static String getNBTHash( @Nullable CompoundTag tag ) + { + if( tag == null ) return null; - try { - MessageDigest digest = MessageDigest.getInstance("MD5"); - DataOutput output = new DataOutputStream(new DigestOutputStream(digest)); - NbtIo.write(tag, output); + try + { + MessageDigest digest = MessageDigest.getInstance( "MD5" ); + DataOutput output = new DataOutputStream( new DigestOutputStream( digest ) ); + NbtIo.write( tag, output ); byte[] hash = digest.digest(); - return new String(Hex.encodeHex(hash)); - } catch (NoSuchAlgorithmException | IOException e) { - ComputerCraft.log.error("Cannot hash NBT", e); + return new String( Hex.encodeHex( hash ) ); + } + catch( NoSuchAlgorithmException | IOException e ) + { + ComputerCraft.log.error( "Cannot hash NBT", e ); return null; } } - private static final class DigestOutputStream extends OutputStream { + private static final class DigestOutputStream extends OutputStream + { private final MessageDigest digest; - DigestOutputStream(MessageDigest digest) { + DigestOutputStream( MessageDigest digest ) + { this.digest = digest; } @Override - public void write(@Nonnull byte[] b, int off, int len) { - this.digest.update(b, off, len); + public void write( @Nonnull byte[] b, int off, int len ) + { + digest.update( b, off, len ); } @Override - public void write(int b) { - this.digest.update((byte) b); + public void write( int b ) + { + digest.update( (byte) b ); } } } diff --git a/src/main/java/dan200/computercraft/shared/util/NullStorage.java b/src/main/java/dan200/computercraft/shared/util/NullStorage.java deleted file mode 100644 index 737fc0986..000000000 --- a/src/main/java/dan200/computercraft/shared/util/NullStorage.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -import net.minecraft.nbt.Tag; -import net.minecraft.util.math.Direction; -import net.minecraftforge.common.capabilities.Capability; - -public class NullStorage implements Capability.IStorage -{ - @Override - public Tag writeNBT( Capability capability, T instance, Direction side ) - { - return null; - } - - @Override - public void readNBT( Capability capability, T instance, Direction side, Tag base ) - { - } -} diff --git a/src/main/java/dan200/computercraft/shared/util/RedstoneUtil.java b/src/main/java/dan200/computercraft/shared/util/RedstoneUtil.java index 26258c43d..808879afe 100644 --- a/src/main/java/dan200/computercraft/shared/util/RedstoneUtil.java +++ b/src/main/java/dan200/computercraft/shared/util/RedstoneUtil.java @@ -9,7 +9,6 @@ import net.minecraft.block.BlockState; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; -import net.minecraftforge.event.ForgeEventFactory; import java.util.EnumSet; @@ -19,8 +18,6 @@ public final class RedstoneUtil { // Propagate ordinary output. See BlockRedstoneDiode.notifyNeighbors BlockState block = world.getBlockState( pos ); - if( ForgeEventFactory.onNeighborNotify( world, pos, block, EnumSet.of( side ), false ).isCanceled() ) return; - BlockPos neighbourPos = pos.offset( side ); world.updateNeighbor( neighbourPos, block.getBlock(), pos ); world.updateNeighborsExcept( neighbourPos, block.getBlock(), side.getOpposite() ); diff --git a/src/main/java/dan200/computercraft/shared/util/ServiceUtil.java b/src/main/java/dan200/computercraft/shared/util/ServiceUtil.java deleted file mode 100644 index 6ff2d898e..000000000 --- a/src/main/java/dan200/computercraft/shared/util/ServiceUtil.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.ComputerCraftAPI; -import net.minecraftforge.fml.ModList; -import org.objectweb.asm.Type; - -import java.util.List; -import java.util.ServiceLoader; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; - -public final class ServiceUtil -{ - private static final Type AUTO_SERVICE = Type.getType( "Lcom/google/auto/service/AutoService;" ); - - private ServiceUtil() - { - } - - public static Stream loadServices( Class target ) - { - return StreamSupport.stream( ServiceLoader.load( target, ServiceUtil.class.getClassLoader() ).spliterator(), false ); - } - - public static Stream loadServicesForge( Class target ) - { - Type type = Type.getType( target ); - ClassLoader loader = ComputerCraftAPI.class.getClassLoader(); - return ModList.get().getAllScanData().stream() - .flatMap( x -> x.getAnnotations().stream() ) - .filter( x -> x.getAnnotationType().equals( AUTO_SERVICE ) ) - .filter( x -> { - Object value = x.getAnnotationData().get( "value" ); - return value instanceof List && ((List) value).contains( type ); - } ) - .flatMap( x -> { - try - { - Class klass = loader.loadClass( x.getClassType().getClassName() ); - if( !target.isAssignableFrom( klass ) ) - { - ComputerCraft.log.error( "{} is not a subtype of {}", x.getClassType().getClassName(), target.getName() ); - return Stream.empty(); - } - - Class casted = klass.asSubclass( target ); - return Stream.of( casted.newInstance() ); - } - catch( ReflectiveOperationException e ) - { - ComputerCraft.log.error( "Cannot load {}", x.getClassType(), e ); - return Stream.empty(); - } - } ); - } -} diff --git a/src/main/java/dan200/computercraft/shared/util/SidedCaps.java b/src/main/java/dan200/computercraft/shared/util/SidedCaps.java deleted file mode 100644 index 25875c0cd..000000000 --- a/src/main/java/dan200/computercraft/shared/util/SidedCaps.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -import net.minecraft.util.math.Direction; -import net.minecraftforge.common.util.LazyOptional; - -import javax.annotation.Nullable; -import java.util.function.Function; - -/** - * Provides a constant (but invalidate-able) capability for each side. - * - * @param The type of the produced capability. - */ -public final class SidedCaps -{ - private final Function factory; - private final boolean allowNull; - private T[] values; - private LazyOptional[] caps; - - private SidedCaps( Function factory, boolean allowNull ) - { - this.factory = factory; - this.allowNull = allowNull; - } - - public static SidedCaps ofNonNull( Function factory ) - { - return new SidedCaps<>( factory, false ); - } - - public static SidedCaps ofNullable( Function factory ) - { - return new SidedCaps<>( factory, true ); - } - - @SuppressWarnings( { "unchecked", "rawtypes" } ) - public LazyOptional get( @Nullable Direction direction ) - { - if( direction == null && !allowNull ) return LazyOptional.empty(); - int index = direction == null ? 6 : direction.ordinal(); - - LazyOptional[] caps = this.caps; - if( caps == null ) - { - caps = this.caps = new LazyOptional[allowNull ? 7 : 6]; - values = (T[]) new Object[caps.length]; - } - - LazyOptional cap = caps[index]; - return cap == null ? caps[index] = LazyOptional.of( () -> { - T[] values = this.values; - T value = values[index]; - return value == null ? values[index] = factory.apply( direction ) : value; - } ) : cap; - } - - public void invalidate() - { - if( caps != null ) CapabilityUtil.invalidate( caps ); - } -} diff --git a/src/main/java/dan200/computercraft/shared/util/TickScheduler.java b/src/main/java/dan200/computercraft/shared/util/TickScheduler.java index 27ae25e47..5b4534af1 100644 --- a/src/main/java/dan200/computercraft/shared/util/TickScheduler.java +++ b/src/main/java/dan200/computercraft/shared/util/TickScheduler.java @@ -6,25 +6,18 @@ package dan200.computercraft.shared.util; import com.google.common.collect.MapMaker; -import dan200.computercraft.ComputerCraft; import dan200.computercraft.shared.common.TileGeneric; import net.minecraft.block.entity.BlockEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -import net.minecraftforge.event.TickEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; import java.util.Collections; import java.util.Iterator; import java.util.Set; /** - * A thread-safe version of {@link ITickList#scheduleTick(BlockPos, Object, int)}. - * * We use this when modems and other peripherals change a block in a different thread. */ -@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID ) public final class TickScheduler { private TickScheduler() @@ -43,11 +36,8 @@ public final class TickScheduler if( world != null && !world.isClient ) toTick.add( tile ); } - @SubscribeEvent - public static void tick( TickEvent.ServerTickEvent event ) + public static void tick() { - if( event.phase != TickEvent.Phase.START ) return; - Iterator iterator = toTick.iterator(); while( iterator.hasNext() ) { @@ -57,7 +47,7 @@ public final class TickScheduler World world = tile.getWorld(); BlockPos pos = tile.getPos(); - if( world != null && pos != null && world.isAreaLoaded( pos, 0 ) && world.getBlockEntity( pos ) == tile ) + if( world != null && pos != null && world.isChunkLoaded(pos) && world.getBlockEntity( pos ) == tile ) { world.getBlockTickScheduler().schedule( pos, tile.getCachedState().getBlock(), 0 ); } diff --git a/src/main/java/dan200/computercraft/shared/util/WorldUtil.java b/src/main/java/dan200/computercraft/shared/util/WorldUtil.java index d26b9ec4b..c7149ecd7 100644 --- a/src/main/java/dan200/computercraft/shared/util/WorldUtil.java +++ b/src/main/java/dan200/computercraft/shared/util/WorldUtil.java @@ -18,7 +18,6 @@ import net.minecraft.util.math.Vec3d; import net.minecraft.util.shape.VoxelShape; import net.minecraft.world.RaycastContext; import net.minecraft.world.World; -import net.minecraftforge.common.ForgeMod; import org.apache.commons.lang3.tuple.Pair; import javax.annotation.Nonnull; @@ -143,7 +142,7 @@ public final class WorldUtil public static Vec3d getRayEnd( PlayerEntity player ) { - double reach = player.getAttributeInstance( ForgeMod.REACH_DISTANCE.get() ).getValue(); + double reach = 5; Vec3d look = player.getRotationVector(); return getRayStart( player ).add( look.x * reach, look.y * reach, look.z * reach ); } diff --git a/src/main/resources/computercraft.accesswidener b/src/main/resources/computercraft.accesswidener index 23c47860f..21cb2868f 100644 --- a/src/main/resources/computercraft.accesswidener +++ b/src/main/resources/computercraft.accesswidener @@ -12,3 +12,6 @@ accessible field net/minecraft/entity/Entity pos Lnet/minecraft/util/math/Vec3d; extendable method net/minecraft/entity/Entity getCameraPosVec (F)Lnet/minecraft/util/math/Vec3d; accessible method net/minecraft/screen/ScreenHandlerType (Lnet/minecraft/screen/ScreenHandlerType$Factory;)V accessible class net/minecraft/screen/ScreenHandlerType$Factory +accessible method net/minecraft/client/render/model/json/ModelOverrideList ()V +extendable class net/minecraft/util/math/Matrix4f +accessible method net/minecraft/util/WorldSavePath (Ljava/lang/String;)V diff --git a/src/main/resources/computercraft.client.json b/src/main/resources/computercraft.client.json new file mode 100644 index 000000000..723f9ef77 --- /dev/null +++ b/src/main/resources/computercraft.client.json @@ -0,0 +1,15 @@ +{ + "required": true, + "package": "dan200.computercraft.shared.mixin", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "MixinHeldItemRenderer", + "MixinItemFrameEntityRenderer", + "MixinMinecraftGame", + "MixinScreen", + "MixinWorldRenderer" + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/src/main/resources/computercraft.common.json b/src/main/resources/computercraft.common.json new file mode 100644 index 000000000..3d0c652eb --- /dev/null +++ b/src/main/resources/computercraft.common.json @@ -0,0 +1,14 @@ +{ + "required": true, + "package": "dan200.computercraft.shared.mixin", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "MixinBlock", + "MixinEntity", + "MixinServerWorld", + "MixinWorld" + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/src/main/resources/computercraft.mixin.json b/src/main/resources/computercraft.mixin.json deleted file mode 100644 index 36bfc91b4..000000000 --- a/src/main/resources/computercraft.mixin.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "required": true, - "minVersion": "0.8", - "package": "dan200.computercraft.mixin", - "compatibilityLevel": "JAVA_8", - "mixins": [ - "BlockEntityTypeAccessor", - "ScreenHandlerTypeAccessor" - ], - "client": [ - ], - "injectors": { - "defaultRequire": 1 - } -} diff --git a/src/test/java/dan200/computercraft/core/ComputerTestDelegate.java b/src/test/java/dan200/computercraft/core/ComputerTestDelegate.java index 86cbd6c03..20621dec2 100644 --- a/src/test/java/dan200/computercraft/core/ComputerTestDelegate.java +++ b/src/test/java/dan200/computercraft/core/ComputerTestDelegate.java @@ -1,22 +1,27 @@ /* * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission. + * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core; import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.filesystem.IWritableMount; import dan200.computercraft.api.lua.ILuaAPI; -import dan200.computercraft.api.lua.ILuaContext; import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.LuaFunction; +import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.core.computer.BasicEnvironment; import dan200.computercraft.core.computer.Computer; +import dan200.computercraft.core.computer.ComputerSide; import dan200.computercraft.core.computer.MainThread; import dan200.computercraft.core.filesystem.FileMount; import dan200.computercraft.core.filesystem.FileSystemException; import dan200.computercraft.core.terminal.Terminal; +import dan200.computercraft.shared.peripheral.modem.ModemState; +import dan200.computercraft.shared.peripheral.modem.wireless.WirelessModemPeripheral; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.junit.jupiter.api.*; @@ -25,20 +30,21 @@ import org.opentest4j.AssertionFailedError; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.io.BufferedWriter; import java.io.File; import java.io.IOException; import java.io.Writer; import java.nio.channels.Channels; import java.nio.channels.WritableByteChannel; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; import java.util.stream.Stream; -import static dan200.computercraft.core.apis.ArgumentHelper.getTable; -import static dan200.computercraft.core.apis.ArgumentHelper.getType; +import static dan200.computercraft.api.lua.LuaValues.getType; /** * Loads tests from {@code test-rom/spec} and executes them. @@ -53,6 +59,8 @@ import static dan200.computercraft.core.apis.ArgumentHelper.getType; */ public class ComputerTestDelegate { + private static final File REPORT_PATH = new File( "test-files/luacov.report.out" ); + private static final Logger LOG = LogManager.getLogger( ComputerTestDelegate.class ); private static final long TICK_TIME = TimeUnit.MILLISECONDS.toNanos( 50 ); @@ -72,14 +80,17 @@ public class ComputerTestDelegate private final Condition hasFinished = lock.newCondition(); private boolean finished = false; + private Map> finishedWith; @BeforeEach public void before() throws IOException { ComputerCraft.logPeripheralErrors = true; + if( REPORT_PATH.delete() ) ComputerCraft.log.info( "Deleted previous coverage report." ); + Terminal term = new Terminal( 78, 20 ); - IWritableMount mount = new FileMount( new File( "test-files/mount" ), Long.MAX_VALUE ); + IWritableMount mount = new FileMount( new File( "test-files/mount" ), 10_000_000 ); // Remove any existing files List children = new ArrayList<>(); @@ -87,195 +98,21 @@ public class ComputerTestDelegate for( String child : children ) mount.delete( child ); // And add our startup file - try( WritableByteChannel channel = mount.openChannelForWrite( "startup.lua" ); + try( WritableByteChannel channel = mount.openForWrite( "startup.lua" ); Writer writer = Channels.newWriter( channel, StandardCharsets.UTF_8.newEncoder(), -1 ) ) { - writer.write( "loadfile('test/mcfly.lua', _ENV)('test/spec') cct_test.finish()" ); + writer.write( "loadfile('test-rom/mcfly.lua', nil, _ENV)('test-rom/spec') cct_test.finish()" ); } computer = new Computer( new BasicEnvironment( mount ), term, 0 ); - computer.addApi( new ILuaAPI() - { - @Override - public String[] getNames() - { - return new String[] { "cct_test" }; - } - - @Nonnull - @Override - public String[] getMethodNames() - { - return new String[] { "start", "submit", "finish" }; - } - - @Override - public void startup() - { - try - { - computer.getAPIEnvironment().getFileSystem().mount( - "test-rom", "test", - BasicEnvironment.createMount( ComputerTestDelegate.class, "test-rom", "test" ) - ); - } - catch( FileSystemException e ) - { - throw new IllegalStateException( e ); - } - } - - @Nullable - @Override - public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments ) throws LuaException, InterruptedException - { - switch( method ) - { - case 0: // start: Submit several tests and signal for #get to run - { - LOG.info( "Received tests from computer" ); - DynamicNodeBuilder root = new DynamicNodeBuilder( "" ); - for( Object key : getTable( arguments, 0 ).keySet() ) - { - if( !(key instanceof String) ) throw new LuaException( "Non-key string " + getType( key ) ); - - String name = (String) key; - String[] parts = name.split( "\0" ); - DynamicNodeBuilder builder = root; - for( int i = 0; i < parts.length - 1; i++ ) builder = builder.get( parts[i] ); - builder.runs( parts[parts.length - 1], () -> { - // Run it - lock.lockInterruptibly(); - try - { - // Set the current test - runResult = null; - runFinished = false; - currentTest = name; - - // Tell the computer to run it - LOG.info( "Starting '{}'", formatName( name ) ); - computer.queueEvent( "cct_test_run", new Object[] { name } ); - - long remaining = TIMEOUT; - while( remaining > 0 && computer.isOn() && !runFinished ) - { - tick(); - - long waiting = hasRun.awaitNanos( TICK_TIME ); - if( waiting > 0 ) break; - remaining -= TICK_TIME; - } - - LOG.info( "Finished '{}'", formatName( name ) ); - - if( remaining <= 0 ) - { - throw new IllegalStateException( "Timed out waiting for test" ); - } - else if( !computer.isOn() ) - { - throw new IllegalStateException( "Computer turned off mid-execution" ); - } - - if( runResult != null ) throw runResult; - } - finally - { - lock.unlock(); - currentTest = null; - } - } ); - } - - lock.lockInterruptibly(); - try - { - tests = root; - hasTests.signal(); - } - finally - { - lock.unlock(); - } - - return null; - } - case 1: // submit: Submit the result of a test, allowing the test executor to continue - { - Map tbl = getTable( arguments, 0 ); - String name = (String) tbl.get( "name" ); - String status = (String) tbl.get( "status" ); - String message = (String) tbl.get( "message" ); - String trace = (String) tbl.get( "trace" ); - - StringBuilder wholeMessage = new StringBuilder(); - if( message != null ) wholeMessage.append( message ); - if( trace != null ) - { - if( wholeMessage.length() != 0 ) wholeMessage.append( '\n' ); - wholeMessage.append( trace ); - } - - lock.lockInterruptibly(); - try - { - LOG.info( "'{}' finished with {}", formatName( name ), status ); - - // Skip if a test mismatch - if( !name.equals( currentTest ) ) - { - LOG.warn( "Skipping test '{}', as we're currently executing '{}'", formatName( name ), formatName( currentTest ) ); - return null; - } - - switch( status ) - { - case "ok": - case "pending": - break; - case "fail": - runResult = new AssertionFailedError( wholeMessage.toString() ); - break; - case "error": - runResult = new IllegalStateException( wholeMessage.toString() ); - break; - } - - runFinished = true; - hasRun.signal(); - } - finally - { - lock.unlock(); - } - - return null; - } - case 2: // finish: Signal to after that execution has finished - LOG.info( "Finished" ); - lock.lockInterruptibly(); - try - { - finished = true; - hasFinished.signal(); - } - finally - { - lock.unlock(); - } - return null; - default: - return null; - } - } - } ); + computer.getEnvironment().setPeripheral( ComputerSide.TOP, new FakeModem() ); + computer.addApi( new CctTestAPI() ); computer.turnOn(); } @AfterEach - public void after() throws InterruptedException + public void after() throws InterruptedException, IOException { try { @@ -310,6 +147,15 @@ public class ComputerTestDelegate // And shutdown computer.shutdown(); } + + if( finishedWith != null ) + { + REPORT_PATH.getParentFile().mkdirs(); + try( BufferedWriter writer = Files.newBufferedWriter( REPORT_PATH.toPath() ) ) + { + // new LuaCoverage( finishedWith ).write( writer ); + } + } } @TestFactory @@ -417,4 +263,227 @@ public class ComputerTestDelegate { return name.replace( "\0", " -> " ); } + + private static class FakeModem extends WirelessModemPeripheral + { + FakeModem() + { + super( new ModemState(), true ); + } + + @Nonnull + @Override + @SuppressWarnings( "ConstantConditions" ) + public World getWorld() + { + return null; + } + + @Nonnull + @Override + public Vec3d getPosition() + { + return Vec3d.ZERO; + } + + @Override + public boolean equals( @Nullable IPeripheral other ) + { + return this == other; + } + } + + public class CctTestAPI implements ILuaAPI + { + @Override + public String[] getNames() + { + return new String[] { "cct_test" }; + } + + @Override + public void startup() + { + try + { + computer.getAPIEnvironment().getFileSystem().mount( + "test-rom", "test-rom", + BasicEnvironment.createMount( ComputerTestDelegate.class, "test-rom", "test" ) + ); + } + catch( FileSystemException e ) + { + throw new IllegalStateException( e ); + } + } + + @LuaFunction + public final void start( Map tests ) throws LuaException + { + // Submit several tests and signal for #get to run + LOG.info( "Received tests from computer" ); + DynamicNodeBuilder root = new DynamicNodeBuilder( "" ); + for( Object key : tests.keySet() ) + { + if( !(key instanceof String) ) throw new LuaException( "Non-key string " + getType( key ) ); + + String name = (String) key; + String[] parts = name.split( "\0" ); + DynamicNodeBuilder builder = root; + for( int i = 0; i < parts.length - 1; i++ ) builder = builder.get( parts[i] ); + builder.runs( parts[parts.length - 1], () -> { + // Run it + lock.lockInterruptibly(); + try + { + // Set the current test + runResult = null; + runFinished = false; + currentTest = name; + + // Tell the computer to run it + LOG.info( "Starting '{}'", formatName( name ) ); + computer.queueEvent( "cct_test_run", new Object[] { name } ); + + long remaining = TIMEOUT; + while( remaining > 0 && computer.isOn() && !runFinished ) + { + tick(); + + long waiting = hasRun.awaitNanos( TICK_TIME ); + if( waiting > 0 ) break; + remaining -= TICK_TIME; + } + + LOG.info( "Finished '{}'", formatName( name ) ); + + if( remaining <= 0 ) + { + throw new IllegalStateException( "Timed out waiting for test" ); + } + else if( !computer.isOn() ) + { + throw new IllegalStateException( "Computer turned off mid-execution" ); + } + + if( runResult != null ) throw runResult; + } + finally + { + lock.unlock(); + currentTest = null; + } + } ); + } + + try + { + lock.lockInterruptibly(); + } + catch( InterruptedException e ) + { + throw new RuntimeException( e ); + } + try + { + ComputerTestDelegate.this.tests = root; + hasTests.signal(); + } + finally + { + lock.unlock(); + } + } + + @LuaFunction + public final void submit( Map tbl ) + { + // Submit the result of a test, allowing the test executor to continue + String name = (String) tbl.get( "name" ); + if( name == null ) + { + ComputerCraft.log.error( "Oh no: {}", tbl ); + } + String status = (String) tbl.get( "status" ); + String message = (String) tbl.get( "message" ); + String trace = (String) tbl.get( "trace" ); + + StringBuilder wholeMessage = new StringBuilder(); + if( message != null ) wholeMessage.append( message ); + if( trace != null ) + { + if( wholeMessage.length() != 0 ) wholeMessage.append( '\n' ); + wholeMessage.append( trace ); + } + + try + { + lock.lockInterruptibly(); + } + catch( InterruptedException e ) + { + throw new RuntimeException( e ); + } + try + { + LOG.info( "'{}' finished with {}", formatName( name ), status ); + + // Skip if a test mismatch + if( !name.equals( currentTest ) ) + { + LOG.warn( "Skipping test '{}', as we're currently executing '{}'", formatName( name ), formatName( currentTest ) ); + return; + } + + switch( status ) + { + case "ok": + case "pending": + break; + case "fail": + runResult = new AssertionFailedError( wholeMessage.toString() ); + break; + case "error": + runResult = new IllegalStateException( wholeMessage.toString() ); + break; + } + + runFinished = true; + hasRun.signal(); + } + finally + { + lock.unlock(); + } + } + + @LuaFunction + public final void finish( Optional> result ) + { + @SuppressWarnings( "unchecked" ) + Map> finishedResult = (Map>) result.orElse( null ); + LOG.info( "Finished" ); + + // Signal to after that execution has finished + try + { + lock.lockInterruptibly(); + } + catch( InterruptedException e ) + { + throw new RuntimeException( e ); + } + try + { + finished = true; + if( finishedResult != null ) finishedWith = finishedResult; + + hasFinished.signal(); + } + finally + { + lock.unlock(); + } + } + } } diff --git a/src/test/java/dan200/computercraft/core/apis/ObjectWrapper.java b/src/test/java/dan200/computercraft/core/apis/ObjectWrapper.java index 878bb7a71..a01cc639a 100644 --- a/src/test/java/dan200/computercraft/core/apis/ObjectWrapper.java +++ b/src/test/java/dan200/computercraft/core/apis/ObjectWrapper.java @@ -1,57 +1,51 @@ /* * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission. + * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.apis; -import dan200.computercraft.api.lua.ILuaContext; -import dan200.computercraft.api.lua.ILuaObject; -import dan200.computercraft.api.lua.ILuaTask; -import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.*; +import dan200.computercraft.core.asm.LuaMethod; +import dan200.computercraft.core.asm.NamedMethod; import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; public class ObjectWrapper implements ILuaContext { - private final ILuaObject object; - private final String[] methods; + private final Object object; + private final Map methodMap; - public ObjectWrapper( ILuaObject object ) + public ObjectWrapper( Object object ) { this.object = object; - this.methods = object.getMethodNames(); - } + String[] dynamicMethods = object instanceof IDynamicLuaObject + ? Objects.requireNonNull( ((IDynamicLuaObject) object).getMethodNames(), "Methods cannot be null" ) + : LuaMethod.EMPTY_METHODS; - private int findMethod( String method ) - { - for( int i = 0; i < methods.length; i++ ) + List> methods = LuaMethod.GENERATOR.getMethods( object.getClass() ); + + Map methodMap = this.methodMap = new HashMap<>( methods.size() + dynamicMethods.length ); + for( int i = 0; i < dynamicMethods.length; i++ ) { - if( method.equals( methods[i] ) ) return i; + methodMap.put( dynamicMethods[i], LuaMethod.DYNAMIC.get( i ) ); + } + for( NamedMethod method : methods ) + { + methodMap.put( method.getName(), method.getMethod() ); } - return -1; - } - - public boolean hasMethod( String method ) - { - return findMethod( method ) >= 0; } public Object[] call( String name, Object... args ) throws LuaException { - int method = findMethod( name ); - if( method < 0 ) throw new IllegalStateException( "No such method '" + name + "'" ); + LuaMethod method = methodMap.get( name ); + if( method == null ) throw new IllegalStateException( "No such method '" + name + "'" ); - try - { - return object.callMethod( this, method, args ); - } - catch( InterruptedException e ) - { - throw new IllegalStateException( "Should never be interrupted", e ); - } + return method.apply( object, this, new ObjectArguments( args ) ).getResult(); } @SuppressWarnings( "unchecked" ) @@ -65,34 +59,6 @@ public class ObjectWrapper implements ILuaContext return klass.cast( call( name, args )[0] ); } - @Nonnull - @Override - public Object[] pullEvent( @Nullable String filter ) - { - throw new IllegalStateException( "Method should never yield" ); - } - - @Nonnull - @Override - public Object[] pullEventRaw( @Nullable String filter ) - { - throw new IllegalStateException( "Method should never yield" ); - } - - @Nonnull - @Override - public Object[] yield( @Nullable Object[] arguments ) - { - throw new IllegalStateException( "Method should never yield" ); - } - - @Nullable - @Override - public Object[] executeMainThreadTask( @Nonnull ILuaTask task ) - { - throw new IllegalStateException( "Method should never yield" ); - } - @Override public long issueMainThreadTask( @Nonnull ILuaTask task ) { diff --git a/src/test/java/dan200/computercraft/core/apis/handles/BinaryReadableHandleTest.java b/src/test/java/dan200/computercraft/core/apis/handles/BinaryReadableHandleTest.java index 37f3f4905..ad272c9aa 100644 --- a/src/test/java/dan200/computercraft/core/apis/handles/BinaryReadableHandleTest.java +++ b/src/test/java/dan200/computercraft/core/apis/handles/BinaryReadableHandleTest.java @@ -1,15 +1,15 @@ /* * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission. + * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.apis.handles; import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.core.apis.ObjectWrapper; import org.junit.jupiter.api.Test; +import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.Arrays; @@ -28,17 +28,16 @@ public class BinaryReadableHandleTest public void testReadShortComplete() throws LuaException { ObjectWrapper wrapper = fromLength( 10 ); - assertEquals( 5, wrapper.callOf( "read", 5 ).length ); + assertEquals( 5, wrapper.callOf( "read", 5 ).remaining() ); } @Test public void testReadShortPartial() throws LuaException { ObjectWrapper wrapper = fromLength( 5 ); - assertEquals( 5, wrapper.callOf( "read", 10 ).length ); + assertEquals( 5, wrapper.callOf( "read", 10 ).remaining() ); } - @Test public void testReadLongComplete() throws LuaException { @@ -57,13 +56,13 @@ public class BinaryReadableHandleTest public void testReadLongPartialSmaller() throws LuaException { ObjectWrapper wrapper = fromLength( 1000 ); - assertEquals( 1000, wrapper.callOf( "read", 11000 ).length ); + assertEquals( 1000, wrapper.callOf( "read", 11000 ).remaining() ); } @Test public void testReadLine() throws LuaException { - ObjectWrapper wrapper = new ObjectWrapper( new BinaryReadableHandle( new ArrayByteChannel( "hello\r\nworld\r!".getBytes( StandardCharsets.UTF_8 ) ) ) ); + ObjectWrapper wrapper = new ObjectWrapper( BinaryReadableHandle.of( new ArrayByteChannel( "hello\r\nworld\r!".getBytes( StandardCharsets.UTF_8 ) ) ) ); assertArrayEquals( "hello".getBytes( StandardCharsets.UTF_8 ), wrapper.callOf( "readLine" ) ); assertArrayEquals( "world\r!".getBytes( StandardCharsets.UTF_8 ), wrapper.callOf( "readLine" ) ); assertNull( wrapper.call( "readLine" ) ); @@ -72,7 +71,7 @@ public class BinaryReadableHandleTest @Test public void testReadLineTrailing() throws LuaException { - ObjectWrapper wrapper = new ObjectWrapper( new BinaryReadableHandle( new ArrayByteChannel( "hello\r\nworld\r!".getBytes( StandardCharsets.UTF_8 ) ) ) ); + ObjectWrapper wrapper = new ObjectWrapper( BinaryReadableHandle.of( new ArrayByteChannel( "hello\r\nworld\r!".getBytes( StandardCharsets.UTF_8 ) ) ) ); assertArrayEquals( "hello\r\n".getBytes( StandardCharsets.UTF_8 ), wrapper.callOf( "readLine", true ) ); assertArrayEquals( "world\r!".getBytes( StandardCharsets.UTF_8 ), wrapper.callOf( "readLine", true ) ); assertNull( wrapper.call( "readLine", true ) ); @@ -82,6 +81,6 @@ public class BinaryReadableHandleTest { byte[] input = new byte[length]; Arrays.fill( input, (byte) 'A' ); - return new ObjectWrapper( new BinaryReadableHandle( new ArrayByteChannel( input ) ) ); + return new ObjectWrapper( BinaryReadableHandle.of( new ArrayByteChannel( input ) ) ); } } diff --git a/src/test/java/dan200/computercraft/core/apis/handles/EncodedReadableHandleTest.java b/src/test/java/dan200/computercraft/core/apis/handles/EncodedReadableHandleTest.java index 78d8e1d06..5c3e57da0 100644 --- a/src/test/java/dan200/computercraft/core/apis/handles/EncodedReadableHandleTest.java +++ b/src/test/java/dan200/computercraft/core/apis/handles/EncodedReadableHandleTest.java @@ -1,9 +1,8 @@ /* * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission. + * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.apis.handles; import dan200.computercraft.api.lua.LuaException; diff --git a/src/test/java/dan200/computercraft/core/computer/BasicEnvironment.java b/src/test/java/dan200/computercraft/core/computer/BasicEnvironment.java index e9dc940c4..ccdcc751b 100644 --- a/src/test/java/dan200/computercraft/core/computer/BasicEnvironment.java +++ b/src/test/java/dan200/computercraft/core/computer/BasicEnvironment.java @@ -1,9 +1,8 @@ /* * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission. + * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.computer; import dan200.computercraft.ComputerCraft; @@ -13,6 +12,7 @@ import dan200.computercraft.core.filesystem.FileMount; import dan200.computercraft.core.filesystem.JarMount; import dan200.computercraft.core.filesystem.MemoryMount; +import javax.annotation.Nonnull; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -22,7 +22,7 @@ import java.net.URISyntaxException; import java.net.URL; /** - * A very basic environment + * A very basic environment. */ public class BasicEnvironment implements IComputerEnvironment { @@ -74,10 +74,18 @@ public class BasicEnvironment implements IComputerEnvironment return ComputerCraft.computerSpaceLimit; } + @Nonnull @Override public String getHostString() { - return "ComputerCraft ${version} (Test environment)"; + return "ComputerCraft 1.0 (Test environment)"; + } + + @Nonnull + @Override + public String getUserAgent() + { + return "ComputerCraft/1.0"; } @Override @@ -92,10 +100,9 @@ public class BasicEnvironment implements IComputerEnvironment return ComputerCraft.class.getClassLoader().getResourceAsStream( "data/" + domain + "/" + subPath ); } - public static IMount createMount( Class klass, String path, String fallback ) { - File file = getContainingFile(klass); + File file = getContainingFile( klass ); if( file.isFile() ) { @@ -117,7 +124,7 @@ public class BasicEnvironment implements IComputerEnvironment while( baseFile != null && !wholeFile.exists() ) { baseFile = baseFile.getParentFile(); - wholeFile = new File( baseFile, "resources/" + fallback + "/" + path ); + wholeFile = new File( baseFile, "src/" + fallback + "/resources/" + path ); } if( !wholeFile.exists() ) throw new IllegalStateException( "Cannot find ROM mount at " + file ); @@ -127,7 +134,7 @@ public class BasicEnvironment implements IComputerEnvironment } - private static File getContainingFile(Class klass) + private static File getContainingFile( Class klass ) { String path = klass.getProtectionDomain().getCodeSource().getLocation().getPath(); int bangIndex = path.indexOf( "!" ); diff --git a/src/test/java/dan200/computercraft/core/computer/ComputerBootstrap.java b/src/test/java/dan200/computercraft/core/computer/ComputerBootstrap.java index 7d0091cd5..e2deba3cb 100644 --- a/src/test/java/dan200/computercraft/core/computer/ComputerBootstrap.java +++ b/src/test/java/dan200/computercraft/core/computer/ComputerBootstrap.java @@ -1,24 +1,20 @@ /* * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission. + * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.computer; import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.filesystem.IMount; import dan200.computercraft.api.filesystem.IWritableMount; +import dan200.computercraft.api.lua.IArguments; import dan200.computercraft.api.lua.ILuaAPI; -import dan200.computercraft.api.lua.ILuaContext; import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.core.apis.ArgumentHelper; +import dan200.computercraft.api.lua.LuaFunction; import dan200.computercraft.core.filesystem.MemoryMount; import dan200.computercraft.core.terminal.Terminal; import org.junit.jupiter.api.Assertions; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.Arrays; import java.util.function.Consumer; @@ -28,20 +24,26 @@ import java.util.function.Consumer; public class ComputerBootstrap { private static final int TPS = 20; - private static final int MAX_TIME = 10; + public static final int MAX_TIME = 10; - public static void run( String program ) + public static void run( String program, Consumer setup, int maxTimes ) { MemoryMount mount = new MemoryMount() .addFile( "test.lua", program ) - .addFile( "startup", "assertion.assert(pcall(loadfile('test.lua', _ENV))) os.shutdown()" ); + .addFile( "startup.lua", "assertion.assert(pcall(loadfile('test.lua', nil, _ENV))) os.shutdown()" ); - run( mount, x -> {} ); + run( mount, setup, maxTimes ); } - public static void run( IWritableMount mount, Consumer setup ) + public static void run( String program, int maxTimes ) + { + run( program, x -> { }, maxTimes ); + } + + public static void run( IWritableMount mount, Consumer setup, int maxTicks ) { ComputerCraft.logPeripheralErrors = true; + ComputerCraft.maxMainComputerTime = ComputerCraft.maxMainGlobalTime = Integer.MAX_VALUE; Terminal term = new Terminal( ComputerCraft.terminalWidth_computer, ComputerCraft.terminalHeight_computer ); final Computer computer = new Computer( new BasicEnvironment( mount ), term, 0 ); @@ -56,7 +58,7 @@ public class ComputerBootstrap computer.turnOn(); boolean everOn = false; - for( int tick = 0; tick < TPS * MAX_TIME; tick++ ) + for( int tick = 0; tick < TPS * maxTicks; tick++ ) { long start = System.currentTimeMillis(); @@ -101,7 +103,7 @@ public class ComputerBootstrap } } - private static class AssertApi implements ILuaAPI + public static class AssertApi implements ILuaAPI { boolean didAssert; String message; @@ -112,39 +114,25 @@ public class ComputerBootstrap return new String[] { "assertion" }; } - @Nonnull - @Override - public String[] getMethodNames() + @LuaFunction + public final void log( IArguments arguments ) { - return new String[] { "assert", "log" }; + ComputerCraft.log.info( "[Computer] {}", Arrays.toString( arguments.getAll() ) ); } - @Nullable - @Override - public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments ) throws LuaException, InterruptedException + @LuaFunction( "assert" ) + public final Object[] doAssert( IArguments arguments ) throws LuaException { - switch( method ) + didAssert = true; + + Object arg = arguments.get( 0 ); + if( arg == null || arg == Boolean.FALSE ) { - case 0: // assert - { - didAssert = true; - - Object arg = arguments.length >= 1 ? arguments[0] : null; - if( arg == null || arg == Boolean.FALSE ) - { - message = ArgumentHelper.optString( arguments, 1, "Assertion failed" ); - throw new LuaException( message ); - } - - return arguments; - } - case 1: - ComputerCraft.log.info( "[Computer] {}", Arrays.toString( arguments ) ); - return null; - - default: - return null; + message = arguments.optString( 1, "Assertion failed" ); + throw new LuaException( message ); } + + return arguments.getAll(); } } } diff --git a/src/test/java/dan200/computercraft/core/computer/ComputerTest.java b/src/test/java/dan200/computercraft/core/computer/ComputerTest.java index da04d058b..830e27305 100644 --- a/src/test/java/dan200/computercraft/core/computer/ComputerTest.java +++ b/src/test/java/dan200/computercraft/core/computer/ComputerTest.java @@ -1,14 +1,19 @@ /* * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission. + * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.computer; +import com.google.common.io.CharStreams; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.Objects; + import static java.time.Duration.ofSeconds; import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively; @@ -20,7 +25,7 @@ public class ComputerTest assertTimeoutPreemptively( ofSeconds( 20 ), () -> { try { - ComputerBootstrap.run( "print('Hello') while true do end" ); + ComputerBootstrap.run( "print('Hello') while true do end", ComputerBootstrap.MAX_TIME ); } catch( AssertionError e ) { @@ -31,4 +36,14 @@ public class ComputerTest Assertions.fail( "Expected computer to timeout" ); } ); } + + public static void main( String[] args ) throws Exception + { + InputStream stream = ComputerTest.class.getClassLoader().getResourceAsStream( "benchmark.lua" ); + try( InputStreamReader reader = new InputStreamReader( Objects.requireNonNull( stream ), StandardCharsets.UTF_8 ) ) + { + String contents = CharStreams.toString( reader ); + ComputerBootstrap.run( contents, 1000 ); + } + } } diff --git a/src/test/java/dan200/computercraft/core/filesystem/FileSystemTest.java b/src/test/java/dan200/computercraft/core/filesystem/FileSystemTest.java index abff129e8..73aaaccda 100644 --- a/src/test/java/dan200/computercraft/core/filesystem/FileSystemTest.java +++ b/src/test/java/dan200/computercraft/core/filesystem/FileSystemTest.java @@ -1,9 +1,8 @@ /* * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission. + * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.filesystem; import com.google.common.io.Files; @@ -26,6 +25,10 @@ public class FileSystemTest /** * Ensures writing a file truncates it. + * + * @throws FileSystemException When the file system cannot be constructed. + * @throws LuaException When Lua functions fail. + * @throws IOException When reading and writing from strings */ @Test public void testWriteTruncates() throws FileSystemException, LuaException, IOException @@ -40,7 +43,7 @@ public class FileSystemTest wrapper.call( "close" ); } - assertEquals( "This is a long line", Files.toString( new File( ROOT, "out.txt" ), StandardCharsets.UTF_8 ) ); + assertEquals( "This is a long line", Files.asCharSource( new File( ROOT, "out.txt" ), StandardCharsets.UTF_8 ).read() ); { FileSystemWrapper writer = fs.openForWrite( "out.txt", false, EncodedWritableHandle::openUtf8 ); @@ -49,6 +52,6 @@ public class FileSystemTest wrapper.call( "close" ); } - assertEquals( "Tiny line", Files.toString( new File( ROOT, "out.txt" ), StandardCharsets.UTF_8 ) ); + assertEquals( "Tiny line", Files.asCharSource( new File( ROOT, "out.txt" ), StandardCharsets.UTF_8 ).read() ); } } diff --git a/src/test/java/dan200/computercraft/core/filesystem/JarMountTest.java b/src/test/java/dan200/computercraft/core/filesystem/JarMountTest.java index 4a13b825f..fbc36dcb8 100644 --- a/src/test/java/dan200/computercraft/core/filesystem/JarMountTest.java +++ b/src/test/java/dan200/computercraft/core/filesystem/JarMountTest.java @@ -1,9 +1,8 @@ /* * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission. + * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.filesystem; import com.google.common.io.ByteStreams; @@ -14,22 +13,27 @@ import org.junit.jupiter.api.Test; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStream; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; import java.nio.charset.StandardCharsets; +import java.nio.file.attribute.BasicFileAttributes; +import java.nio.file.attribute.FileTime; +import java.time.Instant; +import java.time.temporal.ChronoUnit; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import static org.junit.jupiter.api.Assertions.*; -@SuppressWarnings( "deprecation" ) public class JarMountTest { private static final File ZIP_FILE = new File( "test-files/jar-mount.zip" ); + private static final FileTime MODIFY_TIME = FileTime.from( Instant.EPOCH.plus( 2, ChronoUnit.DAYS ) ); + @BeforeAll public static void before() throws IOException { - if( ZIP_FILE.exists() ) return; ZIP_FILE.getParentFile().mkdirs(); try( ZipOutputStream stream = new ZipOutputStream( new FileOutputStream( ZIP_FILE ) ) ) @@ -37,7 +41,7 @@ public class JarMountTest stream.putNextEntry( new ZipEntry( "dir/" ) ); stream.closeEntry(); - stream.putNextEntry( new ZipEntry( "dir/file.lua" ) ); + stream.putNextEntry( new ZipEntry( "dir/file.lua" ).setLastModifiedTime( MODIFY_TIME ) ); stream.write( "print('testing')".getBytes( StandardCharsets.UTF_8 ) ); stream.closeEntry(); } @@ -64,9 +68,9 @@ public class JarMountTest { IMount mount = new JarMount( ZIP_FILE, "dir/file.lua" ); byte[] contents; - try( InputStream stream = mount.openForRead( "" ) ) + try( ReadableByteChannel stream = mount.openForRead( "" ) ) { - contents = ByteStreams.toByteArray( stream ); + contents = ByteStreams.toByteArray( Channels.newInputStream( stream ) ); } assertEquals( new String( contents, StandardCharsets.UTF_8 ), "print('testing')" ); @@ -77,11 +81,28 @@ public class JarMountTest { IMount mount = new JarMount( ZIP_FILE, "dir" ); byte[] contents; - try( InputStream stream = mount.openForRead( "file.lua" ) ) + try( ReadableByteChannel stream = mount.openForRead( "file.lua" ) ) { - contents = ByteStreams.toByteArray( stream ); + contents = ByteStreams.toByteArray( Channels.newInputStream( stream ) ); } assertEquals( new String( contents, StandardCharsets.UTF_8 ), "print('testing')" ); } + + @Test + public void fileAttributes() throws IOException + { + BasicFileAttributes attributes = new JarMount( ZIP_FILE, "dir" ).getAttributes( "file.lua" ); + assertFalse( attributes.isDirectory() ); + assertEquals( "print('testing')".length(), attributes.size() ); + assertEquals( MODIFY_TIME, attributes.lastModifiedTime() ); + } + + @Test + public void directoryAttributes() throws IOException + { + BasicFileAttributes attributes = new JarMount( ZIP_FILE, "dir" ).getAttributes( "" ); + assertTrue( attributes.isDirectory() ); + assertEquals( 0, attributes.size() ); + } } diff --git a/src/test/java/dan200/computercraft/core/filesystem/MemoryMount.java b/src/test/java/dan200/computercraft/core/filesystem/MemoryMount.java index 60070a4d0..bd16104ac 100644 --- a/src/test/java/dan200/computercraft/core/filesystem/MemoryMount.java +++ b/src/test/java/dan200/computercraft/core/filesystem/MemoryMount.java @@ -1,19 +1,24 @@ /* * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission. + * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.filesystem; import dan200.computercraft.api.filesystem.IWritableMount; +import dan200.computercraft.core.apis.handles.ArrayByteChannel; import javax.annotation.Nonnull; -import java.io.*; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; import java.util.*; /** - * Mounts in memory + * In-memory file mounts. */ public class MemoryMount implements IWritableMount { @@ -62,10 +67,9 @@ public class MemoryMount implements IWritableMount @Nonnull @Override - @Deprecated - public OutputStream openForWrite( @Nonnull final String path ) + public WritableByteChannel openForWrite( @Nonnull final String path ) { - return new ByteArrayOutputStream() + return Channels.newChannel( new ByteArrayOutputStream() { @Override public void close() throws IOException @@ -73,13 +77,12 @@ public class MemoryMount implements IWritableMount super.close(); files.put( path, toByteArray() ); } - }; + } ); } @Nonnull @Override - @Deprecated - public OutputStream openForAppend( @Nonnull final String path ) throws IOException + public WritableByteChannel openForAppend( @Nonnull final String path ) throws IOException { ByteArrayOutputStream stream = new ByteArrayOutputStream() { @@ -94,7 +97,7 @@ public class MemoryMount implements IWritableMount byte[] current = files.get( path ); if( current != null ) stream.write( current ); - return stream; + return Channels.newChannel( stream ); } @Override @@ -132,10 +135,9 @@ public class MemoryMount implements IWritableMount @Nonnull @Override - @Deprecated - public InputStream openForRead( @Nonnull String path ) + public ReadableByteChannel openForRead( @Nonnull String path ) { - return new ByteArrayInputStream( files.get( path ) ); + return new ArrayByteChannel( files.get( path ) ); } public MemoryMount addFile( String file, String contents ) diff --git a/src/test/java/dan200/computercraft/core/filesystem/ResourceMountTest.java b/src/test/java/dan200/computercraft/core/filesystem/ResourceMountTest.java index 1910b7be8..e77b7b074 100644 --- a/src/test/java/dan200/computercraft/core/filesystem/ResourceMountTest.java +++ b/src/test/java/dan200/computercraft/core/filesystem/ResourceMountTest.java @@ -1,15 +1,11 @@ /* * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2018. Do not distribute without permission. + * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.core.filesystem; import dan200.computercraft.api.filesystem.IMount; -import net.minecraft.resource.DirectoryResourcePack; -import net.minecraft.resource.ReloadableResourceManagerImpl; -import net.minecraft.resource.ResourceType; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -29,10 +25,10 @@ public class ResourceMountTest @BeforeEach public void before() { - ReloadableResourceManagerImpl manager = new ReloadableResourceManagerImpl( ResourceType.SERVER_DATA, null ); - manager.addPack( new DirectoryResourcePack( new File( "src/main/resources" ) ) ); - - mount = new ResourceMount( "computercraft", "lua/rom", manager ); +// ReloadableResourceManager manager = new SimpleResourceReloadListener(ResourceType.SERVER_DATA); +// manager.addResourcePack( new FolderPack( new File( "src/main/resources" ) ) ); +// +// mount = ResourceMount.get( "computercraft", "lua/rom", manager ); } @Test @@ -43,7 +39,7 @@ public class ResourceMountTest files.sort( Comparator.naturalOrder() ); assertEquals( - Arrays.asList( "apis", "autorun", "help", "modules", "programs", "startup.lua" ), + Arrays.asList( "apis", "autorun", "help", "modules", "motd.txt", "programs", "startup.lua" ), files ); } diff --git a/src/test/java/dan200/computercraft/shared/wired/NetworkTest.java b/src/test/java/dan200/computercraft/shared/wired/NetworkTest.java index dfcda75ab..b11f6e50f 100644 --- a/src/test/java/dan200/computercraft/shared/wired/NetworkTest.java +++ b/src/test/java/dan200/computercraft/shared/wired/NetworkTest.java @@ -1,21 +1,17 @@ /* * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission. + * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. * Send enquiries to dratcliffe@gmail.com */ - package dan200.computercraft.shared.wired; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import dan200.computercraft.api.ComputerCraftAPI; -import dan200.computercraft.api.lua.ILuaContext; -import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.api.network.wired.IWiredElement; import dan200.computercraft.api.network.wired.IWiredNetwork; import dan200.computercraft.api.network.wired.IWiredNetworkChange; import dan200.computercraft.api.network.wired.IWiredNode; -import dan200.computercraft.api.peripheral.IComputerAccess; import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.shared.util.DirectionUtil; import net.minecraft.util.math.BlockPos; @@ -245,14 +241,14 @@ public class NetworkTest assertEquals( Sets.newHashSet(), cE.allPeripherals().keySet(), "C's peripheral set should be empty" ); } + private static final int BRUTE_SIZE = 16; + private static final int TOGGLE_CONNECTION_TIMES = 5; + private static final int TOGGLE_NODE_TIMES = 5; + @Test @Disabled( "Takes a long time to run, mostly for stress testing" ) public void testLarge() { - final int BRUTE_SIZE = 16; - final int TOGGLE_CONNECTION_TIMES = 5; - final int TOGGLE_NODE_TIMES = 5; - Grid grid = new Grid<>( BRUTE_SIZE ); grid.map( ( existing, pos ) -> new NetworkElement( null, null, "n_" + pos ).getNode() ); @@ -316,7 +312,7 @@ public class NetworkTest } } - private static class NetworkElement implements IWiredElement + private static final class NetworkElement implements IWiredElement { private final World world; private final Vec3d position; @@ -393,25 +389,11 @@ public class NetworkTest { @Nonnull @Override - public String getType0() + public String getType() { return "test"; } - @Nonnull - @Override - public String[] getMethodNames() - { - return new String[0]; - } - - @Nullable - @Override - public Object[] callMethod( @Nonnull IComputerAccess computer, @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments ) throws LuaException, InterruptedException - { - return new Object[0]; - } - @Override public boolean equals( @Nullable IPeripheral other ) { @@ -425,26 +407,12 @@ public class NetworkTest private final T[] box; @SuppressWarnings( "unchecked" ) - public Grid( int size ) + Grid( int size ) { this.size = size; this.box = (T[]) new Object[size * size * size]; } - public void set( BlockPos pos, T elem ) - { - int x = pos.getX(), y = pos.getY(), z = pos.getZ(); - - if( x >= 0 && x < size && y >= 0 && y < size && z >= 0 && z < size ) - { - box[x * size * size + y * size + z] = elem; - } - else - { - throw new IndexOutOfBoundsException( pos.toString() ); - } - } - public T get( BlockPos pos ) { int x = pos.getX(), y = pos.getY(), z = pos.getZ();