Added network tunnel devices.
This commit is contained in:
@@ -14,4 +14,5 @@ public final class DeviceTypes {
|
||||
@ObjectHolder("card") public static DeviceType CARD = null;
|
||||
@ObjectHolder("robot_module") public static DeviceType ROBOT_MODULE = null;
|
||||
@ObjectHolder("floppy") public static DeviceType FLOPPY = null;
|
||||
@ObjectHolder("network_tunnel") public static DeviceType NETWORK_TUNNEL = null;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
package li.cil.oc2.client;
|
||||
|
||||
import li.cil.oc2.api.bus.device.DeviceType;
|
||||
import li.cil.oc2.client.gui.ComputerContainerScreen;
|
||||
import li.cil.oc2.client.gui.ComputerTerminalScreen;
|
||||
import li.cil.oc2.client.gui.RobotContainerScreen;
|
||||
import li.cil.oc2.client.gui.RobotTerminalScreen;
|
||||
import li.cil.oc2.client.gui.*;
|
||||
import li.cil.oc2.client.item.CustomItemColors;
|
||||
import li.cil.oc2.client.item.CustomItemModelProperties;
|
||||
import li.cil.oc2.client.model.BusCableModelLoader;
|
||||
@@ -55,6 +52,7 @@ public final class ClientSetup {
|
||||
MenuScreens.register(Containers.COMPUTER_TERMINAL.get(), ComputerTerminalScreen::new);
|
||||
MenuScreens.register(Containers.ROBOT.get(), RobotContainerScreen::new);
|
||||
MenuScreens.register(Containers.ROBOT_TERMINAL.get(), RobotTerminalScreen::new);
|
||||
MenuScreens.register(Containers.NETWORK_TUNNEL.get(), NetworkTunnelScreen::new);
|
||||
|
||||
ItemBlockRenderTypes.setRenderLayer(Blocks.BUS_CABLE.get(), renderType -> true);
|
||||
Minecraft.getInstance().getBlockColors().register(new BusCableBlockColor(), Blocks.BUS_CABLE.get());
|
||||
|
||||
78
src/main/java/li/cil/oc2/client/gui/NetworkTunnelScreen.java
Normal file
78
src/main/java/li/cil/oc2/client/gui/NetworkTunnelScreen.java
Normal file
@@ -0,0 +1,78 @@
|
||||
package li.cil.oc2.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import li.cil.oc2.client.gui.widget.ImageButton;
|
||||
import li.cil.oc2.common.container.NetworkTunnelContainer;
|
||||
import li.cil.oc2.common.network.Network;
|
||||
import li.cil.oc2.common.network.message.NetworkTunnelLinkMessage;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
|
||||
import static li.cil.oc2.common.util.TranslationUtils.text;
|
||||
|
||||
public final class NetworkTunnelScreen extends AbstractModContainerScreen<NetworkTunnelContainer> {
|
||||
private static final int LINK_BUTTON_LEFT = 48;
|
||||
private static final int LINK_BUTTON_TOP = 78;
|
||||
|
||||
private static final Component LINK_BUTTON_CAPTION = text("gui.{mod}.network_tunnel.link");
|
||||
|
||||
private ImageButton linkButton;
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
public NetworkTunnelScreen(final NetworkTunnelContainer container, final Inventory inventory, final Component title) {
|
||||
super(container, inventory, title);
|
||||
|
||||
imageWidth = Sprites.NETWORK_TUNNEL_SCREEN.width;
|
||||
imageHeight = Sprites.NETWORK_TUNNEL_SCREEN.height;
|
||||
inventoryLabelY = imageHeight - 94;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void render(final PoseStack stack, final int mouseX, final int mouseY, final float partialTicks) {
|
||||
renderBackground(stack);
|
||||
|
||||
linkButton.active = getMenu().hasLinkSlotItem();
|
||||
|
||||
super.render(stack, mouseX, mouseY, partialTicks);
|
||||
renderTooltip(stack, mouseX, mouseY);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
|
||||
linkButton = addRenderableWidget(new ImageButton(
|
||||
leftPos + LINK_BUTTON_LEFT, topPos + LINK_BUTTON_TOP,
|
||||
Sprites.NETWORK_TUNNEL_LINK_BUTTON_INACTIVE.width, Sprites.NETWORK_TUNNEL_LINK_BUTTON_INACTIVE.height,
|
||||
Sprites.NETWORK_TUNNEL_LINK_BUTTON_INACTIVE,
|
||||
Sprites.NETWORK_TUNNEL_LINK_BUTTON_ACTIVE) {
|
||||
@Override
|
||||
public void onPress() {
|
||||
super.onPress();
|
||||
createTunnel();
|
||||
}
|
||||
}).withMessage(LINK_BUTTON_CAPTION);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderBg(final PoseStack stack, final float partialTicks, final int mouseX, final int mouseY) {
|
||||
RenderSystem.setShader(GameRenderer::getPositionTexShader);
|
||||
RenderSystem.setShaderColor(1, 1, 1, 1);
|
||||
|
||||
Sprites.NETWORK_TUNNEL_SCREEN.draw(stack, leftPos, topPos);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
private void createTunnel() {
|
||||
final NetworkTunnelLinkMessage message = new NetworkTunnelLinkMessage(getMenu().containerId);
|
||||
Network.INSTANCE.sendToServer(message);
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ public final class Sprites {
|
||||
public static final Sprite TERMINAL_SCREEN = new Sprite(TERMINAL_SCREEN_TEXTURE);
|
||||
public static final Sprite BUS_INTERFACE_SCREEN = new Sprite(BUS_INTERFACE_SCREEN_TEXTURE);
|
||||
public static final Sprite NETWORK_INTERFACE_CARD_SCREEN = new Sprite(NETWORK_INTERFACE_CARD_SCREEN_TEXTURE);
|
||||
public static final Sprite NETWORK_TUNNEL_SCREEN = new Sprite(NETWORK_TUNNEL_SCREEN_TEXTURE);
|
||||
|
||||
public static final Sprite TERMINAL_FOCUSED = new Sprite(TERMINAL_FOCUSED_TEXTURE);
|
||||
public static final Sprite SLOT_SELECTION = new Sprite(SLOT_SELECTION_TEXTURE, 18, 18, 0, 0);
|
||||
@@ -34,6 +35,9 @@ public final class Sprites {
|
||||
public static final Sprite INVENTORY_BUTTON_INACTIVE = new Sprite(INVENTORY_BUTTON_TEXTURE, 12, 12, 1, 1);
|
||||
public static final Sprite INVENTORY_BUTTON_ACTIVE = new Sprite(INVENTORY_BUTTON_TEXTURE, 12, 12, 15, 1);
|
||||
|
||||
public static final Sprite NETWORK_TUNNEL_LINK_BUTTON_INACTIVE = new Sprite(NETWORK_TUNNEL_LINK_BUTTON_TEXTURE, 80, 20, 0, 0);
|
||||
public static final Sprite NETWORK_TUNNEL_LINK_BUTTON_ACTIVE = new Sprite(NETWORK_TUNNEL_LINK_BUTTON_TEXTURE, 80, 20, 0, 20);
|
||||
|
||||
public static final Sprite CONFIRM_PRESSED = new Sprite(CONFIRM_BUTTON_TEXTURE, 12, 12, 14, 1);
|
||||
public static final Sprite CONFIRM_BASE = new Sprite(CONFIRM_BUTTON_TEXTURE, 12, 12, 1, 1);
|
||||
public static final Sprite CANCEL_PRESSED = new Sprite(CANCEL_BUTTON_TEXTURE, 12, 12, 14, 1);
|
||||
|
||||
@@ -8,6 +8,7 @@ public final class Textures {
|
||||
public static final Texture TERMINAL_SCREEN_TEXTURE = new Texture("textures/gui/widget/terminal_screen.png", 336, 208);
|
||||
public static final Texture BUS_INTERFACE_SCREEN_TEXTURE = new Texture("textures/gui/widget/bus_interface_screen.png", 240, 30);
|
||||
public static final Texture NETWORK_INTERFACE_CARD_SCREEN_TEXTURE = new Texture("textures/gui/widget/network_interface_card_screen.png", 176, 130);
|
||||
public static final Texture NETWORK_TUNNEL_SCREEN_TEXTURE = new Texture("textures/gui/widget/network_tunnel_screen.png", 176, 197);
|
||||
|
||||
public static final Texture TERMINAL_FOCUSED_TEXTURE = new Texture("textures/gui/overlay/terminal_focused.png", 336, 208);
|
||||
public static final Texture SLOT_SELECTION_TEXTURE = new Texture("textures/gui/overlay/slot_selection.png", 18, 270);
|
||||
@@ -27,4 +28,5 @@ public final class Textures {
|
||||
public static final Texture POWER_BUTTON_TEXTURE = new Texture("textures/gui/widget/power_button.png", 42, 14);
|
||||
public static final Texture INPUT_BUTTON_TEXTURE = new Texture("textures/gui/widget/input_button.png", 42, 14);
|
||||
public static final Texture INVENTORY_BUTTON_TEXTURE = new Texture("textures/gui/widget/inventory_button.png", 28, 14);
|
||||
public static final Texture NETWORK_TUNNEL_LINK_BUTTON_TEXTURE = new Texture("textures/gui/widget/network_tunnel_link_button.png", 80, 40);
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ public final class Config {
|
||||
@Path("energy.items") public static int soundCardEnergyPerTick = 1;
|
||||
@Path("energy.items") public static int blockOperationsModuleEnergyPerTick = 2;
|
||||
@Path("energy.items") public static int inventoryOperationsModuleEnergyPerTick = 1;
|
||||
@Path("energy.items") public static int networkTunnelEnergyPerTick = 2;
|
||||
|
||||
@Path("gameplay") public static ResourceLocation blockOperationsModuleToolTier = TierSortingRegistry.getName(Tiers.DIAMOND);
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ public final class DeviceTypes {
|
||||
register(ItemTags.DEVICES_CARD);
|
||||
register(ItemTags.DEVICES_ROBOT_MODULE);
|
||||
register(ItemTags.DEVICES_FLOPPY);
|
||||
register(ItemTags.DEVICES_NETWORK_TUNNEL);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
package li.cil.oc2.common.bus.device.item;
|
||||
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import li.cil.oc2.api.bus.device.vm.VMDeviceLoadResult;
|
||||
import li.cil.oc2.api.bus.device.vm.context.VMContext;
|
||||
import li.cil.oc2.api.capabilities.NetworkInterface;
|
||||
import li.cil.oc2.common.item.NetworkTunnelItem;
|
||||
import li.cil.oc2.common.util.TickUtils;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.event.TickEvent;
|
||||
import net.minecraftforge.event.server.ServerStoppedEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.*;
|
||||
|
||||
public final class NetworkTunnelItemDevice extends AbstractNetworkInterfaceItemDevice {
|
||||
public NetworkTunnelItemDevice(final ItemStack identity) {
|
||||
super(identity);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability(final Capability<T> cap, @Nullable final Direction side) {
|
||||
return LazyOptional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VMDeviceLoadResult mount(final VMContext context) {
|
||||
final VMDeviceLoadResult result = super.mount(context);
|
||||
if (result.wasSuccessful()) {
|
||||
NetworkTunnelItem.getTunnelId(identity).ifPresent(id ->
|
||||
TunnelManager.registerEndpoint(id, getNetworkInterface()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unmount() {
|
||||
super.unmount();
|
||||
TunnelManager.unregisterEndpoint(getNetworkInterface());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
@Mod.EventBusSubscriber
|
||||
private static final class TunnelManager {
|
||||
private static final int BYTES_PER_TICK = 32 * 1024 / TickUtils.toTicks(Duration.ofSeconds(1)); // bytes / sec -> bytes / tick
|
||||
private static final int MIN_ETHERNET_FRAME_SIZE = 42;
|
||||
|
||||
private static final BiMap<UUID, Set<NetworkInterface>> TUNNELS = HashBiMap.create();
|
||||
|
||||
public static void registerEndpoint(final UUID id, final NetworkInterface networkInterface) {
|
||||
TUNNELS.computeIfAbsent(id, unused -> new HashSet<>())
|
||||
.add(networkInterface);
|
||||
}
|
||||
|
||||
public static void unregisterEndpoint(final NetworkInterface networkInterface) {
|
||||
for (final Set<NetworkInterface> tunnel : TUNNELS.values()) {
|
||||
tunnel.remove(networkInterface);
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void handleServerTick(final TickEvent.ServerTickEvent event) {
|
||||
if (event.phase == TickEvent.Phase.START) {
|
||||
pumpMessages();
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void handleServerStopped(final ServerStoppedEvent event) {
|
||||
TUNNELS.clear();
|
||||
}
|
||||
|
||||
private static void pumpMessages() {
|
||||
final Iterator<Set<NetworkInterface>> iterator = TUNNELS.values().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
final Set<NetworkInterface> tunnel = iterator.next();
|
||||
if (tunnel.isEmpty()) {
|
||||
iterator.remove();
|
||||
} else {
|
||||
pumpMessages(tunnel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void pumpMessages(final Collection<NetworkInterface> tunnel) {
|
||||
for (final NetworkInterface source : tunnel) {
|
||||
int byteBudget = BYTES_PER_TICK;
|
||||
byte[] frame;
|
||||
while ((frame = source.readEthernetFrame()) != null && byteBudget > 0) {
|
||||
byteBudget -= Math.max(frame.length, MIN_ETHERNET_FRAME_SIZE); // Avoid bogus packets messing with us.
|
||||
for (final NetworkInterface destination : tunnel) {
|
||||
if (destination != source) {
|
||||
destination.writeEthernetFrame(source, frame, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,10 +39,12 @@ public final class Providers {
|
||||
ITEM_DEVICE_PROVIDERS.register("flash_memory_custom", FlashMemoryWithExternalDataItemDeviceProvider::new);
|
||||
ITEM_DEVICE_PROVIDERS.register("redstone_interface_card", RedstoneInterfaceCardItemDeviceProvider::new);
|
||||
ITEM_DEVICE_PROVIDERS.register("network_interface_card", NetworkInterfaceCardItemDeviceProvider::new);
|
||||
ITEM_DEVICE_PROVIDERS.register("network_tunnel_card", NetworkTunnelCardItemDeviceProvider::new);
|
||||
ITEM_DEVICE_PROVIDERS.register("file_import_export_card", FileImportExportCardItemDeviceProvider::new);
|
||||
ITEM_DEVICE_PROVIDERS.register("sound_card", SoundCardItemDeviceProvider::new);
|
||||
|
||||
ITEM_DEVICE_PROVIDERS.register("inventory_operations_module", InventoryOperationsModuleDeviceProvider::new);
|
||||
ITEM_DEVICE_PROVIDERS.register("block_operations_module", BlockOperationsModuleDeviceProvider::new);
|
||||
ITEM_DEVICE_PROVIDERS.register("network_tunnel_module", NetworkTunnelModuleItemDeviceProvider::new);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package li.cil.oc2.common.bus.device.provider.item;
|
||||
|
||||
import li.cil.oc2.api.bus.device.ItemDevice;
|
||||
import li.cil.oc2.api.bus.device.provider.ItemDeviceQuery;
|
||||
import li.cil.oc2.common.Config;
|
||||
import li.cil.oc2.common.bus.device.item.NetworkTunnelItemDevice;
|
||||
import li.cil.oc2.common.bus.device.provider.util.AbstractItemDeviceProvider;
|
||||
import li.cil.oc2.common.item.Items;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public final class NetworkTunnelCardItemDeviceProvider extends AbstractItemDeviceProvider {
|
||||
public NetworkTunnelCardItemDeviceProvider() {
|
||||
super(Items.NETWORK_TUNNEL_CARD);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected Optional<ItemDevice> getItemDevice(final ItemDeviceQuery query) {
|
||||
return Optional.of(new NetworkTunnelItemDevice(query.getItemStack()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getItemDeviceEnergyConsumption(final ItemDeviceQuery query) {
|
||||
return Config.networkTunnelEnergyPerTick;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package li.cil.oc2.common.bus.device.provider.item;
|
||||
|
||||
import li.cil.oc2.api.bus.device.ItemDevice;
|
||||
import li.cil.oc2.api.bus.device.provider.ItemDeviceQuery;
|
||||
import li.cil.oc2.common.Config;
|
||||
import li.cil.oc2.common.bus.device.item.NetworkTunnelItemDevice;
|
||||
import li.cil.oc2.common.bus.device.provider.util.AbstractItemDeviceProvider;
|
||||
import li.cil.oc2.common.item.Items;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public final class NetworkTunnelModuleItemDeviceProvider extends AbstractItemDeviceProvider {
|
||||
public NetworkTunnelModuleItemDeviceProvider() {
|
||||
super(Items.NETWORK_TUNNEL_MODULE);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected Optional<ItemDevice> getItemDevice(final ItemDeviceQuery query) {
|
||||
return Optional.of(new NetworkTunnelItemDevice(query.getItemStack()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getItemDeviceEnergyConsumption(final ItemDeviceQuery query) {
|
||||
return Config.networkTunnelEnergyPerTick;
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ public final class Containers {
|
||||
public static final RegistryObject<MenuType<ComputerTerminalContainer>> COMPUTER_TERMINAL = CONTAINERS.register("computer_terminal", () -> IForgeMenuType.create(ComputerTerminalContainer::createClient));
|
||||
public static final RegistryObject<MenuType<RobotInventoryContainer>> ROBOT = CONTAINERS.register("robot", () -> IForgeMenuType.create(RobotInventoryContainer::createClient));
|
||||
public static final RegistryObject<MenuType<RobotTerminalContainer>> ROBOT_TERMINAL = CONTAINERS.register("robot_terminal", () -> IForgeMenuType.create(RobotTerminalContainer::createClient));
|
||||
public static final RegistryObject<MenuType<NetworkTunnelContainer>> NETWORK_TUNNEL = CONTAINERS.register("network_tunnel", () -> IForgeMenuType.create(NetworkTunnelContainer::createClient));
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package li.cil.oc2.common.container;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import li.cil.oc2.api.bus.device.DeviceType;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.inventory.InventoryMenu;
|
||||
import net.minecraft.world.inventory.Slot;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public final class DeviceTypeSlot extends Slot {
|
||||
private final DeviceType deviceType;
|
||||
|
||||
public DeviceTypeSlot(final Container container, final DeviceType deviceType, final int index, final int x, final int y) {
|
||||
super(container, index, x, y);
|
||||
this.deviceType = deviceType;
|
||||
}
|
||||
|
||||
public DeviceType getDeviceType() {
|
||||
return deviceType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mayPlace(@NotNull final ItemStack stack) {
|
||||
return super.mayPlace(stack) && stack.is(deviceType.getTag());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Pair<ResourceLocation, ResourceLocation> getNoItemIcon() {
|
||||
if (hasItem()) {
|
||||
return super.getNoItemIcon();
|
||||
} else {
|
||||
return Pair.of(InventoryMenu.BLOCK_ATLAS, deviceType.getBackgroundIcon());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package li.cil.oc2.common.container;
|
||||
|
||||
import li.cil.oc2.api.bus.device.DeviceTypes;
|
||||
import li.cil.oc2.common.item.NetworkTunnelItem;
|
||||
import li.cil.oc2.common.tags.ItemTags;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.MenuProvider;
|
||||
import net.minecraft.world.SimpleContainer;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.network.NetworkHooks;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public final class NetworkTunnelContainer extends AbstractContainer {
|
||||
public static void createServer(final ServerPlayer player, final InteractionHand hand) {
|
||||
NetworkHooks.openGui(player, new MenuProvider() {
|
||||
@Override
|
||||
public Component getDisplayName() {
|
||||
return player.getItemInHand(hand).getItem().getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractContainerMenu createMenu(final int id, final Inventory inventory, final Player player) {
|
||||
return new NetworkTunnelContainer(id, player, hand);
|
||||
}
|
||||
}, b -> b.writeEnum(hand));
|
||||
}
|
||||
|
||||
public static NetworkTunnelContainer createClient(final int id, final Inventory inventory, final FriendlyByteBuf data) {
|
||||
final InteractionHand hand = data.readEnum(InteractionHand.class);
|
||||
final Player player = inventory.player;
|
||||
return new NetworkTunnelContainer(id, player, hand);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
private final Player player;
|
||||
private final InteractionHand hand;
|
||||
private final Container linkSlot = new SimpleContainer(1);
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
private NetworkTunnelContainer(final int id, final Player player, final InteractionHand hand) {
|
||||
super(Containers.NETWORK_TUNNEL.get(), id);
|
||||
this.player = player;
|
||||
this.hand = hand;
|
||||
|
||||
createPlayerInventoryAndHotbarSlots(player.getInventory(), 8, 115);
|
||||
|
||||
addSlot(new LockedSlot(player.getInventory(), getHandSlot(), 80, 25));
|
||||
addSlot(new DeviceTypeSlot(linkSlot, DeviceTypes.NETWORK_TUNNEL, 0, 80, 51));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
public boolean hasLinkSlotItem() {
|
||||
return !linkSlot.getItem(0).isEmpty();
|
||||
}
|
||||
|
||||
public void createTunnel() {
|
||||
final ItemStack tunnelA = player.getItemInHand(hand);
|
||||
final ItemStack tunnelB = linkSlot.getItem(0);
|
||||
|
||||
if (tunnelA.isEmpty() ||
|
||||
tunnelB.isEmpty() ||
|
||||
!tunnelA.is(ItemTags.DEVICES_NETWORK_TUNNEL) ||
|
||||
!tunnelB.is(ItemTags.DEVICES_NETWORK_TUNNEL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final UUID id = UUID.randomUUID();
|
||||
NetworkTunnelItem.setTunnelId(tunnelA, id);
|
||||
NetworkTunnelItem.setTunnelId(tunnelB, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removed(final Player player) {
|
||||
super.removed(player);
|
||||
|
||||
if (!player.getLevel().isClientSide()) {
|
||||
clearContainer(player, linkSlot);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stillValid(final Player player) {
|
||||
return player.getItemInHand(hand).is(ItemTags.DEVICES_NETWORK_TUNNEL);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected boolean isSlotLocked(final Inventory inventory, final int slot) {
|
||||
return inventory.getItem(slot) == player.getItemInHand(hand);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
private int getHandSlot() {
|
||||
final Inventory inventory = player.getInventory();
|
||||
for (int slot = 0; slot < inventory.getContainerSize(); slot++) {
|
||||
if (inventory.getItem(slot) == player.getItemInHand(hand)) {
|
||||
return slot;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -64,11 +64,13 @@ public final class Items {
|
||||
|
||||
public static final RegistryObject<Item> REDSTONE_INTERFACE_CARD = register("redstone_interface_card");
|
||||
public static final RegistryObject<Item> NETWORK_INTERFACE_CARD = register("network_interface_card", NetworkInterfaceCardItem::new);
|
||||
public static final RegistryObject<Item> NETWORK_TUNNEL_CARD = register("network_tunnel_card", NetworkTunnelItem::new);
|
||||
public static final RegistryObject<Item> FILE_IMPORT_EXPORT_CARD = register("file_import_export_card");
|
||||
public static final RegistryObject<Item> SOUND_CARD = register("sound_card");
|
||||
|
||||
public static final RegistryObject<Item> INVENTORY_OPERATIONS_MODULE = register("inventory_operations_module");
|
||||
public static final RegistryObject<Item> BLOCK_OPERATIONS_MODULE = register("block_operations_module", BlockOperationsModule::new);
|
||||
public static final RegistryObject<Item> NETWORK_TUNNEL_MODULE = register("network_tunnel_module", NetworkTunnelItem::new);
|
||||
|
||||
public static final RegistryObject<Item> TRANSISTOR = register("transistor", ModItem::new);
|
||||
public static final RegistryObject<Item> CIRCUIT_BOARD = register("circuit_board", ModItem::new);
|
||||
|
||||
78
src/main/java/li/cil/oc2/common/item/NetworkTunnelItem.java
Normal file
78
src/main/java/li/cil/oc2/common/item/NetworkTunnelItem.java
Normal file
@@ -0,0 +1,78 @@
|
||||
package li.cil.oc2.common.item;
|
||||
|
||||
import li.cil.oc2.common.container.NetworkTunnelContainer;
|
||||
import li.cil.oc2.common.util.ItemStackUtils;
|
||||
import li.cil.oc2.common.util.TextFormatUtils;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.network.chat.TranslatableComponent;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.util.StringUtil;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResultHolder;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.TooltipFlag;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import static li.cil.oc2.common.util.TranslationUtils.key;
|
||||
|
||||
public final class NetworkTunnelItem extends ModItem {
|
||||
private static final String TUNNEL_ID_TAG_NAME = "tunnel";
|
||||
private static final String TUNNEL_ID_TEXT = key("tooltip.{mod}.network_tunnel_id");
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
public NetworkTunnelItem() {
|
||||
super(createProperties().stacksTo(1));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
public static Optional<UUID> getTunnelId(final ItemStack stack) {
|
||||
final CompoundTag tag = ItemStackUtils.getModDataTag(stack);
|
||||
if (tag.hasUUID(TUNNEL_ID_TAG_NAME)) {
|
||||
return Optional.of(tag.getUUID(TUNNEL_ID_TAG_NAME));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public static void setTunnelId(final ItemStack stack, final UUID value) {
|
||||
ItemStackUtils.getOrCreateModDataTag(stack).putUUID(TUNNEL_ID_TAG_NAME, value);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void appendHoverText(final ItemStack stack, @Nullable final Level level, final List<Component> tooltip, final TooltipFlag flag) {
|
||||
super.appendHoverText(stack, level, tooltip, flag);
|
||||
getTunnelId(stack).ifPresent(id -> {
|
||||
final String idString = StringUtil.truncateStringIfNecessary(id.toString(), 8 + 3, true);
|
||||
final MutableComponent idComponent = TextFormatUtils.withFormat(idString, ChatFormatting.GREEN);
|
||||
tooltip.add(new TranslatableComponent(TUNNEL_ID_TEXT, idComponent).withStyle(ChatFormatting.GRAY));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResultHolder<ItemStack> use(final Level level, final Player player, final InteractionHand hand) {
|
||||
if (!level.isClientSide() && player instanceof ServerPlayer serverPlayer) {
|
||||
openContainerScreen(serverPlayer, hand);
|
||||
}
|
||||
|
||||
return InteractionResultHolder.sidedSuccess(player.getItemInHand(hand), level.isClientSide());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
private void openContainerScreen(final ServerPlayer player, final InteractionHand hand) {
|
||||
NetworkTunnelContainer.createServer(player, hand);
|
||||
}
|
||||
}
|
||||
@@ -68,6 +68,7 @@ public final class Network {
|
||||
registerMessage(BusCableFacadeMessage.class, BusCableFacadeMessage::new, NetworkDirection.PLAY_TO_CLIENT);
|
||||
|
||||
registerMessage(NetworkInterfaceCardConfigurationMessage.class, NetworkInterfaceCardConfigurationMessage::new, NetworkDirection.PLAY_TO_SERVER);
|
||||
registerMessage(NetworkTunnelLinkMessage.class, NetworkTunnelLinkMessage::new, NetworkDirection.PLAY_TO_SERVER);
|
||||
}
|
||||
|
||||
public static <T> void sendToClientsTrackingChunk(final T message, final LevelChunk chunk) {
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package li.cil.oc2.common.network.message;
|
||||
|
||||
import li.cil.oc2.common.container.NetworkTunnelContainer;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
public final class NetworkTunnelLinkMessage extends AbstractMessage {
|
||||
private int containerId;
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
public NetworkTunnelLinkMessage(final int containerId) {
|
||||
this.containerId = containerId;
|
||||
}
|
||||
|
||||
public NetworkTunnelLinkMessage(final FriendlyByteBuf buffer) {
|
||||
super(buffer);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void fromBytes(final FriendlyByteBuf buffer) {
|
||||
containerId = buffer.readVarInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBytes(final FriendlyByteBuf buffer) {
|
||||
buffer.writeVarInt(containerId);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected void handleMessage(final NetworkEvent.Context context) {
|
||||
final ServerPlayer player = context.getSender();
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final AbstractContainerMenu container = player.containerMenu;
|
||||
if (container.containerId != containerId) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (container instanceof NetworkTunnelContainer networkTunnelContainer) {
|
||||
networkTunnelContainer.createTunnel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ public final class ItemTags {
|
||||
public static final Tags.IOptionalNamedTag<Item> DEVICES_CARD = tag("devices/card");
|
||||
public static final Tags.IOptionalNamedTag<Item> DEVICES_ROBOT_MODULE = tag("devices/robot_module");
|
||||
public static final Tags.IOptionalNamedTag<Item> DEVICES_FLOPPY = tag("devices/floppy");
|
||||
public static final Tags.IOptionalNamedTag<Item> DEVICES_NETWORK_TUNNEL = tag("devices/network_tunnel");
|
||||
|
||||
public static final Tags.IOptionalNamedTag<Item> CABLES = tag("cables");
|
||||
public static final Tags.IOptionalNamedTag<Item> WRENCHES = tag("wrenches");
|
||||
|
||||
@@ -43,9 +43,11 @@ public final class ModItemModelProvider extends ItemModelProvider {
|
||||
simple(Items.NETWORK_INTERFACE_CARD);
|
||||
simple(Items.FILE_IMPORT_EXPORT_CARD);
|
||||
simple(Items.SOUND_CARD);
|
||||
simple(Items.NETWORK_TUNNEL_CARD);
|
||||
|
||||
simple(Items.INVENTORY_OPERATIONS_MODULE);
|
||||
simple(Items.BLOCK_OPERATIONS_MODULE);
|
||||
simple(Items.NETWORK_TUNNEL_MODULE);
|
||||
|
||||
simple(Items.TRANSISTOR);
|
||||
simple(Items.CIRCUIT_BOARD);
|
||||
|
||||
@@ -53,11 +53,17 @@ public final class ModItemTagsProvider extends ItemTagsProvider {
|
||||
Items.REDSTONE_INTERFACE_CARD.get(),
|
||||
Items.NETWORK_INTERFACE_CARD.get(),
|
||||
Items.FILE_IMPORT_EXPORT_CARD.get(),
|
||||
Items.SOUND_CARD.get()
|
||||
Items.SOUND_CARD.get(),
|
||||
Items.NETWORK_TUNNEL_CARD.get()
|
||||
);
|
||||
tag(DEVICES_ROBOT_MODULE).add(
|
||||
Items.INVENTORY_OPERATIONS_MODULE.get(),
|
||||
Items.BLOCK_OPERATIONS_MODULE.get()
|
||||
Items.BLOCK_OPERATIONS_MODULE.get(),
|
||||
Items.NETWORK_TUNNEL_MODULE.get()
|
||||
);
|
||||
tag(DEVICES_NETWORK_TUNNEL).add(
|
||||
Items.NETWORK_TUNNEL_CARD.get(),
|
||||
Items.NETWORK_TUNNEL_MODULE.get()
|
||||
);
|
||||
|
||||
tag(WRENCHES).add(Items.WRENCH.get());
|
||||
@@ -73,7 +79,9 @@ public final class ModItemTagsProvider extends ItemTagsProvider {
|
||||
Items.FLASH_MEMORY.get(),
|
||||
Items.FLASH_MEMORY_CUSTOM.get(),
|
||||
Items.NETWORK_INTERFACE_CARD.get(),
|
||||
Items.DISK_DRIVE.get()
|
||||
Items.DISK_DRIVE.get(),
|
||||
Items.NETWORK_TUNNEL_CARD.get(),
|
||||
Items.NETWORK_TUNNEL_MODULE.get()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,6 +273,17 @@ public final class ModRecipesProvider extends RecipeProvider {
|
||||
.unlockedBy("has_computer", inventoryChange(Items.COMPUTER.get()))
|
||||
.save(consumer);
|
||||
|
||||
ShapedRecipeBuilder
|
||||
.shaped(Items.NETWORK_TUNNEL_CARD.get())
|
||||
.pattern("IET")
|
||||
.pattern(" B ")
|
||||
.define('E', Tags.Items.ENDER_PEARLS)
|
||||
.define('I', Tags.Items.INGOTS_IRON)
|
||||
.define('T', Items.TRANSISTOR.get())
|
||||
.define('B', Items.CIRCUIT_BOARD.get())
|
||||
.unlockedBy("has_computer", inventoryChange(Items.COMPUTER.get()))
|
||||
.save(consumer);
|
||||
|
||||
ShapedRecipeBuilder
|
||||
.shaped(Items.FILE_IMPORT_EXPORT_CARD.get())
|
||||
.pattern("IET")
|
||||
@@ -329,6 +340,17 @@ public final class ModRecipesProvider extends RecipeProvider {
|
||||
.unlockedBy("has_robot", inventoryChange(Items.ROBOT.get()))
|
||||
.save(consumer);
|
||||
|
||||
ShapedRecipeBuilder
|
||||
.shaped(Items.NETWORK_TUNNEL_MODULE.get())
|
||||
.pattern("TEG")
|
||||
.pattern(" B ")
|
||||
.define('T', Items.TRANSISTOR.get())
|
||||
.define('E', Tags.Items.ENDER_PEARLS)
|
||||
.define('G', Tags.Items.INGOTS_GOLD)
|
||||
.define('B', Items.CIRCUIT_BOARD.get())
|
||||
.unlockedBy("has_robot", inventoryChange(Items.ROBOT.get()))
|
||||
.save(consumer);
|
||||
|
||||
|
||||
ShapedRecipeBuilder
|
||||
.shaped(Items.TRANSISTOR.get(), 8)
|
||||
|
||||
@@ -11,7 +11,9 @@ This index lists all documented items. If you're looking for a block, see the [b
|
||||
- [Memory](memory.md)
|
||||
- [Network Cable](network_cable.md)
|
||||
- [Network Interface Card](network_interface_card.md)
|
||||
- [Network Tunnel Card](network_tunnel_card.md)
|
||||
- [Network Tunnel Module](network_tunnel_module.md)
|
||||
- [Redstone Interface Card](redstone_interface_card.md)
|
||||
- [Robot](robot.md)
|
||||
- [Scrench](wrench.md)
|
||||
- [Sound Card](sound_card.md)
|
||||
- [Sound Card](sound_card.md)
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
# Network Tunnel Card
|
||||

|
||||
|
||||
The network tunnel card allows [computers](../block/computer.md) to send messages to and receive messages from another tunnel device (tunnel cards and [tunnel modules](network_tunnel_module.md)) linked to the card.
|
||||
|
||||
Computers *have to be shut down* before installing or removing this component. Installing it while the computer is running will have no effect, removing it may lead to system errors.
|
||||
|
||||
To link two tunnel devices, open their configuration interface (use while holding), and insert the other tunnel device to link to. This allows linking any two network tunnel devices.
|
||||
|
||||
When using the default Linux distribution, this device will provide a regular ethernet device. Network setup can either be performed manually, or using the convenience script `setup-network.lua`. This script provides the option to either use a fixed-address setup, or a DHCP setup. For a DHCP setup, exactly one computer in the network must act as a DHCP server.
|
||||
|
||||
After initial setup, use the command `ifconfig` to see the currently used IP address.
|
||||
@@ -0,0 +1,12 @@
|
||||
# Network Tunnel Module
|
||||

|
||||
|
||||
The network tunnel module allows [robots](robot.md) to send messages to and receive messages from another tunnel device (tunnel modules and [tunnel cards](network_tunnel_card.md)) linked to the module.
|
||||
|
||||
Robots *have to be shut down* before installing or removing this component. Installing it while the robot is running will have no effect, removing it may lead to system errors.
|
||||
|
||||
To link two tunnel devices, open their configuration interface (use while holding), and insert the other tunnel device to link to. This allows linking any two network tunnel devices.
|
||||
|
||||
When using the default Linux distribution, this device will provide a regular ethernet device. Network setup can either be performed manually, or using the convenience script `setup-network.lua`. This script provides the option to either use a fixed-address setup, or a DHCP setup. For a DHCP setup, exactly one computer in the network must act as a DHCP server.
|
||||
|
||||
After initial setup, use the command `ifconfig` to see the currently used IP address.
|
||||
@@ -40,6 +40,8 @@
|
||||
"item.oc2.network_interface_card": "Network Interface Card",
|
||||
"item.oc2.network_interface_card.desc": "Sends and receives network packets via attached Network Connectors.",
|
||||
"item.oc2.network_interface_card.is_configured": "Has connectivity configuration.",
|
||||
"item.oc2.network_tunnel_card": "Network Tunnel Card",
|
||||
"item.oc2.network_tunnel_card.desc": "Sends and receives network packets to a linked device.",
|
||||
"item.oc2.file_import_export_card": "File Import/Export Card",
|
||||
"item.oc2.file_import_export_card.desc": "Imports and exports files from and into your real file system.",
|
||||
"item.oc2.robot": "Robot",
|
||||
@@ -50,6 +52,8 @@
|
||||
"item.oc2.block_operations_module.desc": "Breaks and places blocks.",
|
||||
"item.oc2.sound_card": "Sound Card",
|
||||
"item.oc2.sound_card.desc": "Plays various sounds from its highly realistic sound bank.",
|
||||
"item.oc2.network_tunnel_module": "Network Tunnel Module",
|
||||
"item.oc2.network_tunnel_module.desc": "Sends and receives network packets to a linked device.",
|
||||
|
||||
"item.oc2.transistor": "Transistor",
|
||||
"item.oc2.transistor.desc": "Crafting material.",
|
||||
@@ -92,6 +96,8 @@
|
||||
"gui.oc2.network_interface_card.connectivity.disabled": "Disabled",
|
||||
"gui.oc2.network_interface_card.info": "Drag to rotate. Click faces to toggle connectivity.",
|
||||
|
||||
"gui.oc2.network_tunnel.link": "Link",
|
||||
|
||||
"manual.oc2.home": "Home",
|
||||
"manual.oc2.blocks": "Blocks",
|
||||
"manual.oc2.items": "Items",
|
||||
@@ -110,6 +116,7 @@
|
||||
"tooltip.oc2.energyConsumption": "Energy Consumption: %s/t",
|
||||
"tooltip.oc2.confirm": "Confirm",
|
||||
"tooltip.oc2.cancel": "Cancel",
|
||||
"tooltip.oc2.network_tunnel_id": "Tunnel: %s",
|
||||
|
||||
"subtitles.oc2.computer": "Computer fans running",
|
||||
"subtitles.oc2.floppy": "Floppy access",
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:item/generated",
|
||||
"textures": {
|
||||
"layer0": "oc2:item/network_tunnel_card"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:item/generated",
|
||||
"textures": {
|
||||
"layer0": "oc2:item/network_tunnel_module"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"parent": "minecraft:recipes/root",
|
||||
"rewards": {
|
||||
"recipes": [
|
||||
"oc2:network_tunnel_card"
|
||||
]
|
||||
},
|
||||
"criteria": {
|
||||
"has_computer": {
|
||||
"trigger": "minecraft:inventory_changed",
|
||||
"conditions": {
|
||||
"items": [
|
||||
{
|
||||
"items": [
|
||||
"oc2:computer"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"has_the_recipe": {
|
||||
"trigger": "minecraft:recipe_unlocked",
|
||||
"conditions": {
|
||||
"recipe": "oc2:network_tunnel_card"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requirements": [
|
||||
[
|
||||
"has_computer",
|
||||
"has_the_recipe"
|
||||
]
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"parent": "minecraft:recipes/root",
|
||||
"rewards": {
|
||||
"recipes": [
|
||||
"oc2:network_tunnel_module"
|
||||
]
|
||||
},
|
||||
"criteria": {
|
||||
"has_robot": {
|
||||
"trigger": "minecraft:inventory_changed",
|
||||
"conditions": {
|
||||
"items": [
|
||||
{
|
||||
"items": [
|
||||
"oc2:robot"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"has_the_recipe": {
|
||||
"trigger": "minecraft:recipe_unlocked",
|
||||
"conditions": {
|
||||
"recipe": "oc2:network_tunnel_module"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requirements": [
|
||||
[
|
||||
"has_robot",
|
||||
"has_the_recipe"
|
||||
]
|
||||
]
|
||||
}
|
||||
24
src/main/resources/data/oc2/recipes/network_tunnel_card.json
Normal file
24
src/main/resources/data/oc2/recipes/network_tunnel_card.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"pattern": [
|
||||
"IET",
|
||||
" B "
|
||||
],
|
||||
"key": {
|
||||
"E": {
|
||||
"tag": "forge:ender_pearls"
|
||||
},
|
||||
"I": {
|
||||
"tag": "forge:ingots/iron"
|
||||
},
|
||||
"T": {
|
||||
"item": "oc2:transistor"
|
||||
},
|
||||
"B": {
|
||||
"item": "oc2:circuit_board"
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"item": "oc2:network_tunnel_card"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"pattern": [
|
||||
"TEG",
|
||||
" B "
|
||||
],
|
||||
"key": {
|
||||
"T": {
|
||||
"item": "oc2:transistor"
|
||||
},
|
||||
"E": {
|
||||
"tag": "forge:ender_pearls"
|
||||
},
|
||||
"G": {
|
||||
"tag": "forge:ingots/gold"
|
||||
},
|
||||
"B": {
|
||||
"item": "oc2:circuit_board"
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"item": "oc2:network_tunnel_module"
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,8 @@
|
||||
"oc2:flash_memory",
|
||||
"oc2:flash_memory_buildroot",
|
||||
"oc2:network_interface_card",
|
||||
"oc2:disk_drive"
|
||||
"oc2:disk_drive",
|
||||
"oc2:network_tunnel_card",
|
||||
"oc2:network_tunnel_module"
|
||||
]
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
"oc2:redstone_interface_card",
|
||||
"oc2:network_interface_card",
|
||||
"oc2:file_import_export_card",
|
||||
"oc2:sound_card"
|
||||
"oc2:sound_card",
|
||||
"oc2:network_tunnel_card"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
"oc2:network_tunnel_card",
|
||||
"oc2:network_tunnel_module"
|
||||
]
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
"replace": false,
|
||||
"values": [
|
||||
"oc2:inventory_operations_module",
|
||||
"oc2:block_operations_module"
|
||||
"oc2:block_operations_module",
|
||||
"oc2:network_tunnel_module"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user