mirror of
				https://github.com/SquidDev-CC/CC-Tweaked
				synced 2025-10-30 21:23:00 +00:00 
			
		
		
		
	It now compiles.
This commit is contained in:
		| @@ -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' | ||||
|   | ||||
| @@ -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<AddressRule> 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<AddressRule> 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<TurtleAction> 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(); | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -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<IWiredElement> 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; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -218,7 +218,7 @@ public final class ComputerCraftAPI | ||||
|      * @see IWiredElement#getNode() | ||||
|      */ | ||||
|     @Nonnull | ||||
|     public static Optional<IWiredElement> 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<IWiredElement> getWiredElementAt( @Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull Direction side ); | ||||
|         IWiredElement getWiredElementAt( @Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull Direction side ); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
							
								
								
									
										21
									
								
								src/main/java/dan200/computercraft/api/lua/ILuaObject.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/main/java/dan200/computercraft/api/lua/ILuaObject.java
									
									
									
									
									
										Normal file
									
								
							| @@ -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; | ||||
| } | ||||
| @@ -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. | ||||
|   | ||||
| @@ -34,5 +34,5 @@ public interface IPeripheralProvider | ||||
|      * @see dan200.computercraft.api.ComputerCraftAPI#registerPeripheralProvider(IPeripheralProvider) | ||||
|      */ | ||||
|     @Nonnull | ||||
|     Optional<IPeripheral> getPeripheral( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side ); | ||||
|     IPeripheral getPeripheral( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side ); | ||||
| } | ||||
|   | ||||
| @@ -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) { | ||||
|   | ||||
| @@ -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<T extends ScreenHandler & IContainerComputer> extends HandledScreen<T> { | ||||
| import javax.annotation.Nonnull; | ||||
|  | ||||
| import static dan200.computercraft.client.render.ComputerBorderRenderer.BORDER; | ||||
| import static dan200.computercraft.client.render.ComputerBorderRenderer.MARGIN; | ||||
|  | ||||
| public final class GuiComputer<T extends ContainerComputerBase> extends HandledScreen<T> | ||||
| { | ||||
|     private final ComputerFamily family; | ||||
|     private final ClientComputer computer; | ||||
|     private final int termWidth; | ||||
| @@ -43,102 +37,123 @@ public final class GuiComputer<T extends ScreenHandler & IContainerComputer> 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<ContainerComputer> create( ContainerComputer container, PlayerInventory inventory, Text component ) | ||||
|     { | ||||
|         return new GuiComputer<>( | ||||
|             container, inventory, component, | ||||
|             ComputerCraft.terminalWidth_computer, ComputerCraft.terminalHeight_computer | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     public static GuiComputer<ContainerComputer> create(int id, TileComputer computer, PlayerInventory player) { | ||||
|         return create(new ContainerComputer(id, computer), player, computer.getDisplayName()); | ||||
|     public static GuiComputer<ContainerPocketComputer> createPocket( ContainerPocketComputer container, PlayerInventory inventory, Text component ) | ||||
|     { | ||||
|         return new GuiComputer<>( | ||||
|             container, inventory, component, | ||||
|             ComputerCraft.terminalWidth_pocketComputer, ComputerCraft.terminalHeight_pocketComputer | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     public static GuiComputer<ContainerComputer> create(ContainerComputer container, PlayerInventory inventory, Text component) { | ||||
|         return new GuiComputer<>(container, inventory, container.getFamily(), component, ComputerCraft.computerTermWidth, ComputerCraft.computerTermHeight); | ||||
|     public static GuiComputer<ContainerViewComputer> 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. | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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<ContainerDiskDrive> | ||||
| { | ||||
|     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 | ||||
|   | ||||
| @@ -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<ContainerPocketComputer> | ||||
| { | ||||
|     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; | ||||
|     } | ||||
| } | ||||
| @@ -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<ContainerPrinter> | ||||
| { | ||||
|     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 | ||||
|   | ||||
| @@ -30,9 +30,9 @@ public class GuiPrintout extends HandledScreen<ContainerHeldItem> | ||||
|     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; | ||||
|  | ||||
|   | ||||
| @@ -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<ContainerTurtle> | ||||
|     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<ContainerTurtle> | ||||
|         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<ContainerTurtle> | ||||
|             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 | ||||
|             ); | ||||
|         } | ||||
|   | ||||
| @@ -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<? extends Item>... items) { | ||||
|         Identifier id = new Identifier(ComputerCraft.MOD_ID, name); | ||||
|         for (Supplier<? extends Item> 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.<ContainerComputer, GuiComputer<ContainerComputer>>register(ComputerCraftRegistry.ModContainers.COMPUTER, GuiComputer::create); | ||||
|         ScreenRegistry.<ContainerPocketComputer, GuiComputer<ContainerPocketComputer>>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.<ContainerViewComputer, GuiComputer<ContainerViewComputer>>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(); | ||||
| //            } | ||||
| //        } | ||||
| //    } | ||||
| } | ||||
|   | ||||
| @@ -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; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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 ) | ||||
|     { | ||||
|   | ||||
| @@ -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 | ||||
|         { | ||||
|   | ||||
| @@ -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 ) | ||||
|   | ||||
| @@ -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 <em>whole</em> 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<Direction> 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 ) | ||||
|   | ||||
| @@ -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<TileTurtle> | ||||
|         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<TileTurtle> | ||||
|         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<TileTurtle> | ||||
|     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<TileTurtle> | ||||
|             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 ); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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<TurtleModelLoader.TurtleModel> | ||||
| { | ||||
|     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<TurtleModel> | ||||
|     { | ||||
|         private final Identifier family; | ||||
|  | ||||
|         private TurtleModel( Identifier family ) | ||||
|         { | ||||
|             this.family = family; | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public Collection<SpriteIdentifier> getTextures( IModelConfiguration owner, Function<Identifier, UnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors ) | ||||
|         { | ||||
|             Set<SpriteIdentifier> 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<SpriteIdentifier, Sprite> spriteGetter, ModelBakeSettings transform, ModelOverrideList overrides, Identifier modelLocation ) | ||||
|         { | ||||
|             return new TurtleSmartItemModel( | ||||
|                 bakery.getBakedModel( family, transform, spriteGetter ), | ||||
|                 bakery.getBakedModel( COLOUR_TURTLE_MODEL, transform, spriteGetter ) | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -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<BakedQuad> getQuads( BlockState state, Direction side, @Nonnull Random rand ) | ||||
|     { | ||||
|         return getQuads( state, side, rand, EmptyModelData.INSTANCE ); | ||||
|     } | ||||
|  | ||||
|     @Nonnull | ||||
|     @Override | ||||
|     public List<BakedQuad> getQuads( BlockState state, Direction side, @Nonnull Random rand, @Nonnull IModelData data ) | ||||
|     { | ||||
|         if( side != null ) | ||||
|         { | ||||
| @@ -70,20 +61,20 @@ public class TurtleMultiModel implements BakedModel | ||||
|         ArrayList<BakedQuad> 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() ); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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<TurtlePlayer> | ||||
|         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; | ||||
|     } | ||||
|   | ||||
| @@ -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<BakedQuad> getQuads( BlockState state, Direction facing, @Nonnull Random rand, @Nonnull IModelData data ) | ||||
|     { | ||||
|         return familyModel.getQuads( state, facing, rand, data ); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public boolean useAmbientOcclusion() | ||||
|     { | ||||
|   | ||||
| @@ -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<Pattern> wildcards; | ||||
|     private final List<HostRange> ranges; | ||||
|     public AddressPredicate(String... filters) { | ||||
|         this(Arrays.asList(filters)); | ||||
|     } | ||||
|  | ||||
|     public AddressPredicate(Iterable<? extends String> filters) { | ||||
|         List<Pattern> wildcards = this.wildcards = new ArrayList<>(); | ||||
|         List<HostRange> 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; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -155,7 +155,7 @@ public class HTTPAPI implements ILuaAPI | ||||
|     @LuaFunction | ||||
|     public final Object[] websocket( String address, Optional<Map<?, ?>> headerTbl ) throws LuaException | ||||
|     { | ||||
|         if( !ComputerCraft.httpWebsocketEnabled ) | ||||
|         if( !ComputerCraft.http_websocket_enable ) | ||||
|         { | ||||
|             throw new LuaException( "Websocket connections are disabled" ); | ||||
|         } | ||||
|   | ||||
| @@ -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 ); | ||||
|         } | ||||
|   | ||||
| @@ -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 <T> boolean check( UnmodifiableConfig config, String field, Class<T> 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 <T extends Enum<T>> boolean checkEnum( UnmodifiableConfig config, String field, Class<T> 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 <T> Optional<T> get( UnmodifiableConfig config, String field, Class<T> klass ) | ||||
|     { | ||||
|         Object value = config.get( field ); | ||||
|         return klass.isInstance( value ) ? Optional.of( klass.cast( value ) ) : Optional.empty(); | ||||
|     } | ||||
|  | ||||
|     private static <T extends Enum<T>> Optional<T> getEnum( UnmodifiableConfig config, String field, Class<T> klass ) | ||||
|     { | ||||
|         return get( config, field, String.class ).map( x -> parseEnum( klass, x ) ); | ||||
|     } | ||||
|  | ||||
|     @Nullable | ||||
|     private static <T extends Enum<T>> T parseEnum( Class<T> 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 <T> boolean check( UnmodifiableConfig config, String field, Class<T> 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 <T extends Enum<T>> boolean checkEnum( UnmodifiableConfig config, String field, Class<T> 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 <T> Optional<T> get( UnmodifiableConfig config, String field, Class<T> klass ) | ||||
| //    { | ||||
| //        Object value = config.get( field ); | ||||
| //        return klass.isInstance( value ) ? Optional.of( klass.cast( value ) ) : Optional.empty(); | ||||
| //    } | ||||
| // | ||||
| //    private static <T extends Enum<T>> Optional<T> getEnum( UnmodifiableConfig config, String field, Class<T> klass ) | ||||
| //    { | ||||
| //        return get( config, field, String.class ).map( x -> parseEnum( klass, x ) ); | ||||
| //    } | ||||
| // | ||||
| //    @Nullable | ||||
| //    private static <T extends Enum<T>> T parseEnum( Class<T> klass, String x ) | ||||
| //    { | ||||
| //        for( T value : klass.getEnumConstants() ) | ||||
| //        { | ||||
| //            if( value.name().equalsIgnoreCase( x ) ) return value; | ||||
| //        } | ||||
| //        return null; | ||||
| //    } | ||||
| } | ||||
|   | ||||
| @@ -203,7 +203,7 @@ public class HttpRequest extends Resource<HttpRequest> | ||||
|         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 ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -188,7 +188,7 @@ public final class HttpRequestHandler extends SimpleChannelInboundHandler<HttpOb | ||||
|     @Override | ||||
|     public void exceptionCaught( ChannelHandlerContext ctx, Throwable cause ) | ||||
|     { | ||||
|         if( ComputerCraft.logComputerErrors ) ComputerCraft.log.error( "Error handling HTTP response", cause ); | ||||
|         if( ComputerCraft.logPeripheralErrors ) ComputerCraft.log.error( "Error handling HTTP response", cause ); | ||||
|         request.failure( cause ); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -180,7 +180,7 @@ public class Websocket extends Resource<Websocket> | ||||
|         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 ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -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<Stream<GenericSource>> sources ) | ||||
|     { | ||||
|   | ||||
| @@ -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() ) | ||||
|   | ||||
| @@ -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() ) | ||||
|   | ||||
| @@ -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<ReloadableResourceManager> 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<Void> 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<IResourceType> 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); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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 ); | ||||
|             } | ||||
|   | ||||
| @@ -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, | ||||
|                     } ); | ||||
|   | ||||
| @@ -65,7 +65,7 @@ class ResultInterpreterFunction extends ResumableVarArgFunction<ResultInterprete | ||||
|         } | ||||
|         catch( Throwable t ) | ||||
|         { | ||||
|             if( ComputerCraft.logComputerErrors ) | ||||
|             if( ComputerCraft.logPeripheralErrors ) | ||||
|             { | ||||
|                 ComputerCraft.log.error( "Error calling " + name + " on " + instance, t ); | ||||
|             } | ||||
| @@ -96,7 +96,7 @@ class ResultInterpreterFunction extends ResumableVarArgFunction<ResultInterprete | ||||
|         } | ||||
|         catch( Throwable t ) | ||||
|         { | ||||
|             if( ComputerCraft.logComputerErrors ) | ||||
|             if( ComputerCraft.logPeripheralErrors ) | ||||
|             { | ||||
|                 ComputerCraft.log.error( "Error calling " + name + " on " + container.callback, t ); | ||||
|             } | ||||
|   | ||||
| @@ -1,29 +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.shared.proxy.ComputerCraftProxyCommon; | ||||
| import net.minecraft.data.DataGenerator; | ||||
| import net.minecraft.data.server.BlockTagsProvider; | ||||
| import net.minecraftforge.eventbus.api.SubscribeEvent; | ||||
| import net.minecraftforge.fml.common.Mod; | ||||
| import net.minecraftforge.fml.event.lifecycle.GatherDataEvent; | ||||
|  | ||||
| @Mod.EventBusSubscriber( bus = Mod.EventBusSubscriber.Bus.MOD ) | ||||
| public class Generators | ||||
| { | ||||
|     @SubscribeEvent | ||||
|     public static void gather( GatherDataEvent event ) | ||||
|     { | ||||
|         ComputerCraftProxyCommon.registerLoot(); | ||||
|  | ||||
|         DataGenerator generator = event.getGenerator(); | ||||
|         generator.install( new Recipes( generator ) ); | ||||
|         generator.install( new LootTables( generator ) ); | ||||
|         generator.install( new Tags( generator, new BlockTagsProvider( generator ) ) ); | ||||
|     } | ||||
| } | ||||
| @@ -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.common.collect.Multimap; | ||||
| import com.google.gson.Gson; | ||||
| import com.google.gson.GsonBuilder; | ||||
| import dan200.computercraft.ComputerCraft; | ||||
| import net.minecraft.data.DataCache; | ||||
| import net.minecraft.data.DataGenerator; | ||||
| import net.minecraft.data.DataProvider; | ||||
| import net.minecraft.loot.LootManager; | ||||
| import net.minecraft.loot.LootTable; | ||||
| import net.minecraft.loot.LootTableReporter; | ||||
| import net.minecraft.loot.context.LootContextTypes; | ||||
| import net.minecraft.util.Identifier; | ||||
| import javax.annotation.Nonnull; | ||||
| import java.io.IOException; | ||||
| import java.nio.file.Path; | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
| import java.util.function.BiConsumer; | ||||
|  | ||||
| /** | ||||
|  * An alternative to {@link net.minecraft.data.LootTableProvider}, with a more flexible interface. | ||||
|  */ | ||||
| public abstract class LootTableProvider implements DataProvider | ||||
| { | ||||
|     private static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(); | ||||
|  | ||||
|     private final DataGenerator generator; | ||||
|  | ||||
|     public LootTableProvider( DataGenerator generator ) | ||||
|     { | ||||
|         this.generator = generator; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void run( @Nonnull DataCache cache ) | ||||
|     { | ||||
|         Map<Identifier, LootTable> 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<String, String> 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<Identifier, LootTable> 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" ); | ||||
|     } | ||||
| } | ||||
| @@ -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<Identifier, LootTable> 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 <T extends Block> void basicDrop( BiConsumer<Identifier, LootTable> add, RegistryObject<T> 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 <T extends Block> void computerDrop( BiConsumer<Identifier, LootTable> add, RegistryObject<T> 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() ); | ||||
|     } | ||||
| } | ||||
| @@ -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<RecipeJsonProvider> wrap( RecipeSerializer<?> serializer, Consumer<RecipeJsonProvider> original ) | ||||
|     { | ||||
|         return x -> original.accept( new RecipeWrapper( x, null, serializer ) ); | ||||
|     } | ||||
|  | ||||
|     public static Consumer<RecipeJsonProvider> wrap( RecipeSerializer<?> serializer, Consumer<RecipeJsonProvider> original, CompoundTag resultData ) | ||||
|     { | ||||
|         return x -> original.accept( new RecipeWrapper( x, resultData, serializer ) ); | ||||
|     } | ||||
|  | ||||
|     public static Consumer<RecipeJsonProvider> wrap( RecipeSerializer<?> serializer, Consumer<RecipeJsonProvider> original, Consumer<CompoundTag> 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(); | ||||
|     } | ||||
| } | ||||
| @@ -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<RecipeJsonProvider> 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<RecipeJsonProvider> 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<RecipeJsonProvider> 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<RecipeJsonProvider> 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<RecipeJsonProvider> 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<Item> stack ) | ||||
|     { | ||||
|         return InventoryChangedCriterion.Conditions.items( ItemPredicate.Builder.create().tag( stack ).build() ); | ||||
|     } | ||||
|  | ||||
|     private static InventoryChangedCriterion.Conditions inventoryChange( ItemConvertible... stack ) | ||||
|     { | ||||
|         return InventoryChangedCriterion.Conditions.items( stack ); | ||||
|     } | ||||
| } | ||||
| @@ -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<Item> PIGLIN_LOVED = ItemTags.PIGLIN_LOVED; | ||||
|  | ||||
|     public static class CCTags | ||||
|     { | ||||
|         public static final Tag.Identified<Item> COMPUTER = item( "computer" ); | ||||
|         public static final Tag.Identified<Item> TURTLE = item( "turtle" ); | ||||
|         public static final Tag.Identified<Item> WIRED_MODEM = item( "wired_modem" ); | ||||
|         public static final Tag.Identified<Item> 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> item( String name ) | ||||
|     { | ||||
|         return ItemTags.register( new Identifier( ComputerCraft.MOD_ID, name ).toString() ); | ||||
|     } | ||||
| } | ||||
| @@ -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 <T extends BlockEntity> BlockEntityType<T> callCreate(String string, BlockEntityType.Builder<T> builder) { throw new UnsupportedOperationException(); } | ||||
| } | ||||
| @@ -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 <T extends ScreenHandler> ScreenHandlerType<T> callRegister(String id, ScreenHandlerType.Factory<T> factory) { throw new UnsupportedOperationException(); } | ||||
| } | ||||
| @@ -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<TileWiredModemFull> WIRED_MODEM_FULL = ofBlock(ModBlocks.WIRED_MODEM_FULL, TileWiredModemFull::new); | ||||
|         public static final BlockEntityType<TileCable> CABLE = ofBlock(ModBlocks.CABLE, TileCable::new); | ||||
| 
 | ||||
|         public static final BlockEntityType<TileWirelessModem> WIRELESS_MODEM_NORMAL = ofBlock(ModBlocks.WIRELESS_EM_NORMAL, f -> new TileWirelessModem(f, | ||||
|         public static final BlockEntityType<TileWirelessModem> WIRELESS_MODEM_NORMAL = ofBlock(ModBlocks.WIRELESS_MODEM_NORMAL, f -> new TileWirelessModem(f, | ||||
|                                                                                                                                                         false)); | ||||
|         public static final BlockEntityType<TileWirelessModem> WIRELESS_MODEM_ADVANCED = ofBlock(ModBlocks.WIRELESS_EM_ADVANCED, f -> new TileWirelessModem(f, true)); | ||||
|         public static final BlockEntityType<TileWirelessModem> 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 <B extends ScreenHandler, T extends ScreenHandlerType<B>> 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 <T extends ScreenHandler> ScreenHandlerType<T> registerSimple(String id, ScreenHandlerRegistry.SimpleClientHandlerFactory<T> function) { | ||||
|             return ScreenHandlerRegistry.registerSimple(new Identifier(MOD_ID, id), function); | ||||
|         } | ||||
| 
 | ||||
|         public static final ScreenHandlerType<ContainerComputer> COMPUTER = register("computer", | ||||
|                                                                                      ContainerData.toType(ComputerContainerData::new, | ||||
|                                                                                                           ContainerComputer::new)); | ||||
|         private static <T extends ScreenHandler> ScreenHandlerType<T> registerExtended(String id, ScreenHandlerRegistry.ExtendedClientHandlerFactory<T> function) { | ||||
|             return ScreenHandlerRegistry.registerExtended(new Identifier(MOD_ID, id), function); | ||||
|         } | ||||
| 
 | ||||
|         public static final ScreenHandlerType<ContainerPocketComputer> POCKET_COMPUTER = register("pocket_computer", | ||||
|                                                                                                   ContainerData.toType(ComputerContainerData::new, | ||||
|                                                                                                                        ContainerPocketComputer::new)); | ||||
|         public static final ScreenHandlerType<ContainerComputer> COMPUTER = registerExtended("computer", ContainerComputer::new); | ||||
| 
 | ||||
|         public static final ScreenHandlerType<ContainerTurtle> TURTLE = register("turtle", | ||||
|                                                                                  ContainerData.toType(ComputerContainerData::new, | ||||
|                                                                                                       ContainerTurtle::new)); | ||||
|         public static final ScreenHandlerType<ContainerPocketComputer> POCKET_COMPUTER = registerExtended("pocket_computer", ContainerPocketComputer::new); | ||||
| 
 | ||||
|         public static final ScreenHandlerType<ContainerTurtle> TURTLE = registerExtended("turtle", ContainerTurtle::new); | ||||
| 
 | ||||
| 
 | ||||
|         public static final ScreenHandlerType<ContainerDiskDrive> DISK_DRIVE = register("disk_drive", | ||||
|                                                                                         new ScreenHandlerType<>(ContainerDiskDrive::new)); | ||||
|         public static final ScreenHandlerType<ContainerDiskDrive> DISK_DRIVE = registerSimple("disk_drive", ContainerDiskDrive::new); | ||||
| 
 | ||||
|         public static final ScreenHandlerType<ContainerPrinter> PRINTER = register("printer", new ScreenHandlerType<>(ContainerPrinter::new)); | ||||
|         public static final ScreenHandlerType<ContainerPrinter> PRINTER = registerSimple("printer", ContainerPrinter::new); | ||||
| 
 | ||||
|         public static final ScreenHandlerType<ContainerHeldItem> PRINTOUT = register("printout", | ||||
|                                                                                      ContainerData.toType(HeldItemContainerData::new, | ||||
|                                                                                                           ContainerHeldItem::createPrintout)); | ||||
|         public static final ScreenHandlerType<ContainerHeldItem> PRINTOUT = registerExtended("printout", ContainerHeldItem::createPrintout); | ||||
| 
 | ||||
|         public static final ScreenHandlerType<ContainerViewComputer> VIEW_COMPUTER = register("view_computer", | ||||
|                                                                                               ContainerData.toType(ViewComputerContainerData::new, | ||||
|                                                                                                                    ContainerViewComputer::new)); | ||||
|         public static final ScreenHandlerType<ContainerViewComputer> VIEW_COMPUTER = registerExtended("view_computer", ContainerViewComputer::new); | ||||
|     } | ||||
| } | ||||
| @@ -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<Integer> computerSpaceLimit; | ||||
|     private static final ConfigValue<Integer> floppySpaceLimit; | ||||
|     private static final ConfigValue<Integer> maximumFilesOpen; | ||||
|     private static final ConfigValue<Boolean> disableLua51Features; | ||||
|     private static final ConfigValue<String> defaultComputerSettings; | ||||
|     private static final ConfigValue<Boolean> debugEnabled; | ||||
|     private static final ConfigValue<Boolean> logComputerErrors; | ||||
|     private static final ConfigValue<Boolean> commandRequireCreative; | ||||
|  | ||||
|     private static final ConfigValue<Integer> computerThreads; | ||||
|     private static final ConfigValue<Integer> maxMainGlobalTime; | ||||
|     private static final ConfigValue<Integer> maxMainComputerTime; | ||||
|  | ||||
|     private static final ConfigValue<Boolean> httpEnabled; | ||||
|     private static final ConfigValue<Boolean> httpWebsocketEnabled; | ||||
|     private static final ConfigValue<List<? extends UnmodifiableConfig>> httpRules; | ||||
|  | ||||
|     private static final ConfigValue<Integer> httpMaxRequests; | ||||
|     private static final ConfigValue<Integer> httpMaxWebsockets; | ||||
|  | ||||
|     private static final ConfigValue<Boolean> commandBlockEnabled; | ||||
|     private static final ConfigValue<Integer> modemRange; | ||||
|     private static final ConfigValue<Integer> modemHighAltitudeRange; | ||||
|     private static final ConfigValue<Integer> modemRangeDuringStorm; | ||||
|     private static final ConfigValue<Integer> modemHighAltitudeRangeDuringStorm; | ||||
|     private static final ConfigValue<Integer> maxNotesPerTick; | ||||
|     private static final ConfigValue<Integer> monitorBandwidth; | ||||
|  | ||||
|     private static final ConfigValue<Boolean> turtlesNeedFuel; | ||||
|     private static final ConfigValue<Integer> turtleFuelLimit; | ||||
|     private static final ConfigValue<Integer> advancedTurtleFuelLimit; | ||||
|     private static final ConfigValue<Boolean> turtlesObeyBlockProtection; | ||||
|     private static final ConfigValue<Boolean> turtlesCanPush; | ||||
|     private static final ConfigValue<List<? extends String>> turtleDisabledActions; | ||||
|  | ||||
|     private static final ConfigValue<Integer> computerTermWidth; | ||||
|     private static final ConfigValue<Integer> computerTermHeight; | ||||
|  | ||||
|     private static final ConfigValue<Integer> pocketTermWidth; | ||||
|     private static final ConfigValue<Integer> pocketTermHeight; | ||||
|  | ||||
|     private static final ConfigValue<Integer> monitorWidth; | ||||
|     private static final ConfigValue<Integer> monitorHeight; | ||||
|  | ||||
|     private static final ConfigValue<Boolean> genericPeripheral; | ||||
|  | ||||
|     private static final ConfigValue<MonitorRenderer> monitorRenderer; | ||||
|     private static final ConfigValue<Integer> 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<String, String> 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; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -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<IPeripheralProvider> 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<IPeripheral> 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 ); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -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 ) | ||||
|   | ||||
| @@ -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"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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; | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -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<ServerCommandSource> dispatcher ) | ||||
|     public static void register( CommandDispatcher<ServerCommandSource> 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() ) ); | ||||
|                             } | ||||
|                         } | ||||
|  | ||||
|   | ||||
| @@ -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 ) | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -174,7 +174,7 @@ public final class ComputersArgumentType implements ArgumentType<ComputersArgume | ||||
|     { | ||||
|  | ||||
|         @Override | ||||
|         public void write( @Nonnull ComputersArgumentType arg, @Nonnull PacketByteBuf buf ) | ||||
|         public void toPacket( @Nonnull ComputersArgumentType arg, @Nonnull PacketByteBuf buf ) | ||||
|         { | ||||
|             buf.writeBoolean( arg.requireSome ); | ||||
|         } | ||||
| @@ -187,7 +187,7 @@ public final class ComputersArgumentType implements ArgumentType<ComputersArgume | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public void write( @Nonnull ComputersArgumentType arg, @Nonnull JsonObject json ) | ||||
|         public void toJson( @Nonnull ComputersArgumentType arg, @Nonnull JsonObject json ) | ||||
|         { | ||||
|             json.addProperty( "requireSome", arg.requireSome ); | ||||
|         } | ||||
|   | ||||
| @@ -127,7 +127,7 @@ public final class RepeatArgumentType<T, U> implements ArgumentType<List<T>> | ||||
|     public static class Serializer implements ArgumentSerializer<RepeatArgumentType<?, ?>> | ||||
|     { | ||||
|         @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<T, U> implements ArgumentType<List<T>> | ||||
|         } | ||||
|  | ||||
|         @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", "<<cannot serialize>>" ); // TODO: Potentially serialize this using reflection. | ||||
|   | ||||
| @@ -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<? extends TileGeneric> 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(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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; | ||||
|  | ||||
|   | ||||
| @@ -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<ContainerHeldItem> 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); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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<? extends TileGeneric> 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 ); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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<String, Object> 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<Object, Object> table = new HashMap<>(); | ||||
|         table.put("name", | ||||
|             Registry.BLOCK.getId(block) | ||||
|                 .toString()); | ||||
|         table.put("world", world.getRegistryKey()); | ||||
|  | ||||
|         Map<Object, Object> stateTable = new HashMap<>(); | ||||
|         for (ImmutableMap.Entry<Property<?>, 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. | ||||
|      * | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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<T extends TileComputerBase> 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<T extends TileComputerBase> extends Bloc | ||||
|             if( !result.isEmpty() ) return result; | ||||
|         } | ||||
|  | ||||
|         return super.getPickBlock( state, target, world, pos, player ); | ||||
|         return super.getPickStack(world, pos, state); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|   | ||||
| @@ -33,7 +33,7 @@ public class ComputerPeripheral implements IPeripheral | ||||
|  | ||||
|     @Nonnull | ||||
|     @Override | ||||
|     public String getType0() | ||||
|     public String getType() | ||||
|     { | ||||
|         return type; | ||||
|     } | ||||
|   | ||||
| @@ -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<IPeripheral> peripheral; | ||||
|  | ||||
|     public TileComputer( ComputerFamily family, BlockEntityType<? extends TileComputer> 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; | ||||
|   | ||||
| @@ -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<? extends TileGeneric> type, ComputerFamily family) { | ||||
|         super(type); | ||||
|     public TileComputerBase( BlockEntityType<? extends TileGeneric> 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()); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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 ) | ||||
|   | ||||
| @@ -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); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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<? extends ContainerComputerBase> type, int id, PlayerInventory player, ComputerContainerData data ) | ||||
|     protected ContainerComputerBase(ScreenHandlerType<? extends ContainerComputerBase> 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 ) | ||||
|   | ||||
| @@ -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; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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; | ||||
|         } | ||||
|   | ||||
| @@ -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<T extends ComputerFamilyRecipe> extends BasicRecipeSerializer<T> | ||||
|     { | ||||
|     public abstract static class Serializer<T extends ComputerFamilyRecipe> implements RecipeSerializer<T> { | ||||
|         protected abstract T create( Identifier identifier, String group, int width, int height, DefaultedList<Ingredient> ingredients, ItemStack result, ComputerFamily family ); | ||||
|  | ||||
|         @Nonnull | ||||
|   | ||||
| @@ -28,7 +28,7 @@ public final class ConstantLootConditionSerializer<T extends LootCondition> 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 ) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 ) | ||||
|     { | ||||
|   | ||||
| @@ -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() | ||||
|   | ||||
| @@ -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 ); | ||||
|  | ||||
|   | ||||
| @@ -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(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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(); | ||||
|  | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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); | ||||
| } | ||||
| @@ -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(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -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<ItemEntity> callbackInfo) { | ||||
|         if (DropConsumer.onLivingDrops((Entity) (Object) this, stack)) { | ||||
|             callbackInfo.setReturnValue(null); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -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(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -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(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -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(); | ||||
|     } | ||||
| } | ||||
| @@ -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(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -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<Boolean> callbackInfo) { | ||||
|         if (DropConsumer.onEntitySpawn(entity)) { | ||||
|             callbackInfo.setReturnValue(false); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -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<BlockEntity> entities, CallbackInfo info) { | ||||
|         if (this.iteratingTickingBlockEntities) { | ||||
|             for (BlockEntity entity : entities) { | ||||
|                 setWorld(entity, this); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -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(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -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 ) ) ); | ||||
|     } | ||||
| } | ||||
| @@ -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<BiConsumer<PacketContext, PacketByteBuf>> packetReaders = new Int2ObjectOpenHashMap<>(); | ||||
|     private static final Object2IntMap<Class<?>> 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 <T>       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 <T extends NetworkMessage> void registerMainThread( int id, NetworkDirection direction, Supplier<T> factory ) | ||||
|     { | ||||
|         registerMainThread( id, direction, getType( factory ), buf -> { | ||||
|     private static <T extends NetworkMessage> void registerMainThread(int id, Supplier<T> 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 <T>       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 <T extends NetworkMessage> void registerMainThread( int id, NetworkDirection direction, Class<T> type, Function<PacketByteBuf, T> 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 <T extends NetworkMessage> void registerMainThread(int id, Class<T> type, Function<PacketByteBuf, T> 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 <T> Class<T> getType( Supplier<T> supplier ) | ||||
|     { | ||||
|         return (Class<T>) supplier.get().getClass(); | ||||
|     @SuppressWarnings ("unchecked") | ||||
|     private static <T> Class<T> getType(Supplier<T> supplier) { | ||||
|         return (Class<T>) 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))); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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. | ||||
|   | ||||
| @@ -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 ); | ||||
|     } | ||||
|   | ||||
| @@ -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 ); | ||||
|     } | ||||
|   | ||||
| @@ -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() ); | ||||
|     } | ||||
|   | ||||
| @@ -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 ); | ||||
|     } | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user
	 Jacob Farley
					Jacob Farley