mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-08-31 01:27:55 +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