1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-08-28 00:12:16 +00:00

make gui work

This commit is contained in:
shedaniel 2020-09-01 23:41:50 +08:00
parent c54c8c3ea6
commit b95083c77e
17 changed files with 56 additions and 972 deletions

View File

@ -41,6 +41,9 @@ dependencies {
modImplementation "me.shedaniel.cloth:config-2:${cloth_config_version}"
modImplementation "io.github.prospector:modmenu:${modmenu_version}"
modApi "me.shedaniel.cloth.api:cloth-utils-v1:${project.cloth_api_version}"
include "me.shedaniel.cloth.api:cloth-utils-v1:${project.cloth_api_version}"
implementation "blue.endless:jankson:${jankson_version}"
implementation 'com.google.code.findbugs:jsr305:3.0.2'

View File

@ -11,3 +11,4 @@ fabric_api_version=0.19.0+build.398-1.16
fabric_loader_version=0.9.2+build.206
jankson_version=1.2.0
modmenu_version=1.14.6+
cloth_api_version=1.4.5

View File

@ -26,6 +26,7 @@ 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 me.shedaniel.cloth.api.utils.v1.GameInstanceUtils;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.resource.ReloadableResourceManager;
@ -40,7 +41,6 @@ import javax.annotation.Nonnull;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Optional;
public final class ComputerCraftAPIImpl implements IComputerCraftAPI
{
@ -54,8 +54,9 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
public static InputStream getResourceFile( String domain, String subPath )
{
if (FabricLoader.getInstance().getGameInstance() instanceof MinecraftServer) {
ReloadableResourceManager manager = (ReloadableResourceManager) ((MinecraftServer) FabricLoader.getInstance().getGameInstance()).getDataPackManager();
MinecraftServer server = GameInstanceUtils.getServer();
if (server != null) {
ReloadableResourceManager manager = (ReloadableResourceManager) server.serverResourceManager.getResourceManager();
try {
return manager.getResource(new Identifier(domain, subPath)).getInputStream();
} catch (IOException ignored) {
@ -97,8 +98,10 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
@Override
public IMount createResourceMount( @Nonnull String domain, @Nonnull String subPath )
{
if (FabricLoader.getInstance().getGameInstance() instanceof MinecraftServer) {
ReloadableResourceManager manager = (ReloadableResourceManager) ((MinecraftServer) FabricLoader.getInstance().getGameInstance()).getDataPackManager();
MinecraftServer server = GameInstanceUtils.getServer();
if ( server != null )
{
ReloadableResourceManager manager = (ReloadableResourceManager) server.serverResourceManager.getResourceManager();
ResourceMount mount = ResourceMount.get(domain, subPath, manager);
return mount.exists("") ? mount : null;
}

View File

@ -8,8 +8,10 @@ package dan200.computercraft.shared;
import static net.minecraft.util.registry.Registry.BLOCK_ENTITY_TYPE;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.common.ContainerHeldItem;
@ -70,11 +72,11 @@ public final class ComputerCraftRegistry {
public static void init() {
Object[] o = {
ModTiles.CABLE,
ModBlocks.CABLE,
ModItems.CABLE,
ModEntities.TURTLE_PLAYER,
ModContainers.COMPUTER,
ModTiles.CABLE
};
}
@ -135,33 +137,33 @@ public final class ComputerCraftRegistry {
public static class ModTiles {
private static <T extends BlockEntity> BlockEntityType<T> ofBlock(Block block, String id, Function<BlockEntityType<T>, T> factory) {
return Registry.register(BLOCK_ENTITY_TYPE, new Identifier(MOD_ID, id), FixedPointTileEntityType.create(block, factory));
private static <T extends BlockEntity> BlockEntityType<T> ofBlock( Supplier<Block> block, String id, Function<BlockEntityType<T>, T> factory) {
return Registry.register(BLOCK_ENTITY_TYPE, new Identifier(MOD_ID, id), FixedPointTileEntityType.create( Objects.requireNonNull(block), factory));
}
public static final BlockEntityType<TileMonitor> MONITOR_NORMAL = ofBlock(ModBlocks.MONITOR_NORMAL, "monitor_normal",f -> new TileMonitor(f, false));
public static final BlockEntityType<TileMonitor> MONITOR_ADVANCED = ofBlock(ModBlocks.MONITOR_ADVANCED, "monitor_advanced",f -> new TileMonitor(f, true));
public static final BlockEntityType<TileMonitor> MONITOR_NORMAL = ofBlock(() ->ModBlocks.MONITOR_NORMAL, "monitor_normal",f -> new TileMonitor(f, false));
public static final BlockEntityType<TileMonitor> MONITOR_ADVANCED = ofBlock(() ->ModBlocks.MONITOR_ADVANCED, "monitor_advanced",f -> new TileMonitor(f, true));
public static final BlockEntityType<TileComputer> COMPUTER_NORMAL = ofBlock(ModBlocks.COMPUTER_NORMAL,"computer_normal",
public static final BlockEntityType<TileComputer> COMPUTER_NORMAL = ofBlock(() ->ModBlocks.COMPUTER_NORMAL,"computer_normal",
f -> new TileComputer(ComputerFamily.NORMAL, f));
public static final BlockEntityType<TileComputer> COMPUTER_ADVANCED = ofBlock(ModBlocks.COMPUTER_ADVANCED,"computer_advanced",
public static final BlockEntityType<TileComputer> COMPUTER_ADVANCED = ofBlock(() ->ModBlocks.COMPUTER_ADVANCED,"computer_advanced",
f -> new TileComputer(ComputerFamily.ADVANCED, f));
public static final BlockEntityType<TileCommandComputer> COMPUTER_COMMAND = ofBlock(ModBlocks.COMPUTER_COMMAND, "computer_command",
public static final BlockEntityType<TileCommandComputer> COMPUTER_COMMAND = ofBlock(() ->ModBlocks.COMPUTER_COMMAND, "computer_command",
f -> new TileCommandComputer(ComputerFamily.COMMAND, f));
public static final BlockEntityType<TileTurtle> TURTLE_NORMAL = ofBlock(ModBlocks.TURTLE_NORMAL, "turtle_normal",f -> new TileTurtle(f, ComputerFamily.NORMAL));
public static final BlockEntityType<TileTurtle> TURTLE_ADVANCED = ofBlock(ModBlocks.TURTLE_ADVANCED,"turtle_advanced",
public static final BlockEntityType<TileTurtle> TURTLE_NORMAL = ofBlock(() ->ModBlocks.TURTLE_NORMAL, "turtle_normal",f -> new TileTurtle(f, ComputerFamily.NORMAL));
public static final BlockEntityType<TileTurtle> TURTLE_ADVANCED = ofBlock(() ->ModBlocks.TURTLE_ADVANCED,"turtle_advanced",
f -> new TileTurtle(f, ComputerFamily.ADVANCED));
public static final BlockEntityType<TileSpeaker> SPEAKER = ofBlock(ModBlocks.SPEAKER, "speaker",TileSpeaker::new);
public static final BlockEntityType<TileDiskDrive> DISK_DRIVE = ofBlock(ModBlocks.DISK_DRIVE, "disk_drive",TileDiskDrive::new);
public static final BlockEntityType<TilePrinter> PRINTER = ofBlock(ModBlocks.PRINTER, "printer",TilePrinter::new);
public static final BlockEntityType<TileWiredModemFull> WIRED_MODEM_FULL = ofBlock(ModBlocks.WIRED_MODEM_FULL,"wired_modem_full", TileWiredModemFull::new);
public static final BlockEntityType<TileCable> CABLE = ofBlock(ModBlocks.CABLE, "cable",TileCable::new);
public static final BlockEntityType<TileSpeaker> SPEAKER = ofBlock(() ->ModBlocks.SPEAKER, "speaker",TileSpeaker::new);
public static final BlockEntityType<TileDiskDrive> DISK_DRIVE = ofBlock(() ->ModBlocks.DISK_DRIVE, "disk_drive",TileDiskDrive::new);
public static final BlockEntityType<TilePrinter> PRINTER = ofBlock(() ->ModBlocks.PRINTER, "printer",TilePrinter::new);
public static final BlockEntityType<TileWiredModemFull> WIRED_MODEM_FULL = ofBlock(() ->ModBlocks.WIRED_MODEM_FULL,"wired_modem_full", TileWiredModemFull::new);
public static final BlockEntityType<TileCable> CABLE = ofBlock(() -> ModBlocks.CABLE, "cable",TileCable::new);
public static final BlockEntityType<TileWirelessModem> WIRELESS_MODEM_NORMAL = ofBlock(ModBlocks.WIRELESS_MODEM_NORMAL,"wireless_modem_normal",
public static final BlockEntityType<TileWirelessModem> WIRELESS_MODEM_NORMAL = ofBlock(() ->ModBlocks.WIRELESS_MODEM_NORMAL,"wireless_modem_normal",
f -> new TileWirelessModem(f, false));
public static final BlockEntityType<TileWirelessModem> WIRELESS_MODEM_ADVANCED = ofBlock(ModBlocks.WIRELESS_MODEM_ADVANCED,"wireless_modem_advanced",
public static final BlockEntityType<TileWirelessModem> WIRELESS_MODEM_ADVANCED = ofBlock(() ->ModBlocks.WIRELESS_MODEM_ADVANCED,"wireless_modem_advanced",
f -> new TileWirelessModem(f, true));
}

View File

@ -22,6 +22,7 @@ import dan200.computercraft.shared.network.NetworkMessage;
import dan200.computercraft.shared.network.client.ComputerDataClientMessage;
import dan200.computercraft.shared.network.client.ComputerDeletedClientMessage;
import dan200.computercraft.shared.network.client.ComputerTerminalClientMessage;
import me.shedaniel.cloth.api.utils.v1.GameInstanceUtils;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.nbt.CompoundTag;
@ -163,15 +164,16 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput
if( hasOutputChanged() || force )
{
// Send computer state to all clients
if (FabricLoader.getInstance().getGameInstance() instanceof MinecraftServer)
NetworkHandler.sendToAllPlayers((MinecraftServer) FabricLoader.getInstance().getGameInstance(), createComputerPacket() );
MinecraftServer server = GameInstanceUtils.getServer();
if ( server != null )
NetworkHandler.sendToAllPlayers(server, createComputerPacket() );
}
if( hasTerminalChanged() || force )
{
if (FabricLoader.getInstance().getGameInstance() instanceof MinecraftServer) {
MinecraftServer server = GameInstanceUtils.getServer();
if ( server != null ) {
// Send terminal state to clients who are currently interacting with the computer.
MinecraftServer server = (MinecraftServer) FabricLoader.getInstance().getGameInstance();
NetworkMessage packet = null;
for (PlayerEntity player : server.getPlayerManager().getPlayerList()) {
@ -199,8 +201,9 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput
public void broadcastDelete()
{
// Send deletion to client
if (FabricLoader.getInstance().getGameInstance() instanceof MinecraftServer)
NetworkHandler.sendToAllPlayers((MinecraftServer) FabricLoader.getInstance().getGameInstance(), new ComputerDeletedClientMessage( getInstanceID() ) );
MinecraftServer server = GameInstanceUtils.getServer();
if ( server != null )
NetworkHandler.sendToAllPlayers(server, new ComputerDeletedClientMessage( getInstanceID() ) );
}
public void setID( int id )

View File

@ -15,6 +15,7 @@ import net.minecraft.screen.ScreenHandler;
import net.minecraft.screen.ScreenHandlerType;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Objects;
import java.util.function.Predicate;
public class ContainerComputerBase extends ScreenHandler implements IContainerComputer
@ -28,13 +29,13 @@ public class ContainerComputerBase extends ScreenHandler implements IContainerCo
{
super( type, id );
this.canUse = canUse;
this.computer = computer;
this.computer = Objects.requireNonNull(computer);
this.family = family;
}
protected ContainerComputerBase(ScreenHandlerType<? extends ContainerComputerBase> type, int id, PlayerInventory player, PacketByteBuf packetByteBuf)
{
this( type, id, x -> true, getComputer( player, new ComputerContainerData((PacketByteBuf) packetByteBuf.copy()) ), new ComputerContainerData(packetByteBuf).getFamily() );
this( type, id, x -> true, getComputer( player, new ComputerContainerData(new PacketByteBuf( packetByteBuf.copy() )) ), new ComputerContainerData(packetByteBuf).getFamily() );
}
protected static IComputer getComputer( PlayerInventory player, ComputerContainerData data )

View File

@ -1,39 +0,0 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.integration.crafttweaker;
import com.blamejared.crafttweaker.api.logger.ILogger;
/**
* Logger which tracks if it has any messages.
*/
public final class TrackingLogger
{
private final ILogger logger;
private boolean ok = true;
public TrackingLogger( ILogger logger )
{
this.logger = logger;
}
public boolean isOk()
{
return ok;
}
public void warning( String message )
{
ok = false;
logger.warning( message );
}
public void error( String message )
{
ok = false;
logger.error( message );
}
}

View File

@ -1,71 +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.integration.crafttweaker;
import com.blamejared.crafttweaker.api.CraftTweakerAPI;
import com.blamejared.crafttweaker.api.annotations.ZenRegister;
import com.blamejared.crafttweaker.api.item.IItemStack;
import dan200.computercraft.shared.integration.crafttweaker.actions.AddTurtleTool;
import dan200.computercraft.shared.integration.crafttweaker.actions.RemoveTurtleUpgradeByItem;
import dan200.computercraft.shared.integration.crafttweaker.actions.RemoveTurtleUpgradeByName;
import org.openzen.zencode.java.ZenCodeType;
@ZenRegister
@ZenCodeType.Name( "dan200.computercraft.turtle" )
public class TurtleTweaker
{
/**
* Remove a turtle upgrade with the given id.
*
* @param upgrade The ID of the to remove
*/
@ZenCodeType.Method
public static void removeUpgrade( String upgrade )
{
CraftTweakerAPI.apply( new RemoveTurtleUpgradeByName( upgrade ) );
}
/**
* Remove a turtle upgrade crafted with the given item stack".
*
* @param stack The stack with which the upgrade is crafted.
*/
@ZenCodeType.Method
public static void removeUpgrade( IItemStack stack )
{
CraftTweakerAPI.apply( new RemoveTurtleUpgradeByItem( stack.getInternal() ) );
}
/**
* Add a new turtle tool with the given id, which crafts and acts using the given stack.
*
* @param id The new upgrade's ID
* @param stack The stack used for crafting the upgrade and used by the turtle as a tool.
*/
@ZenCodeType.Method
public static void addTool( String id, IItemStack stack )
{
addTool( id, stack, stack, "tool" );
}
@ZenCodeType.Method
public static void addTool( String id, IItemStack craftingStack, IItemStack toolStack )
{
addTool( id, craftingStack, toolStack, "tool" );
}
@ZenCodeType.Method
public static void addTool( String id, IItemStack stack, String kind )
{
addTool( id, stack, stack, kind );
}
@ZenCodeType.Method
public static void addTool( String id, IItemStack craftingStack, IItemStack toolStack, String kind )
{
CraftTweakerAPI.apply( new AddTurtleTool( id, craftingStack.getInternal(), toolStack.getInternal(), kind ) );
}
}

View File

@ -1,126 +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.integration.crafttweaker.actions;
import com.blamejared.crafttweaker.api.actions.IUndoableAction;
import com.blamejared.crafttweaker.api.logger.ILogger;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.shared.TurtleUpgrades;
import dan200.computercraft.shared.integration.crafttweaker.TrackingLogger;
import dan200.computercraft.shared.turtle.upgrades.*;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraftforge.fml.LogicalSide;
import java.util.HashMap;
import java.util.Map;
/**
* Register a new turtle tool.
*/
public class AddTurtleTool implements IUndoableAction
{
private interface Factory
{
TurtleTool create( Identifier location, ItemStack craftItem, ItemStack toolItem );
}
private static final Map<String, Factory> kinds = new HashMap<>();
static
{
kinds.put( "tool", TurtleTool::new );
kinds.put( "axe", TurtleAxe::new );
kinds.put( "hoe", TurtleHoe::new );
kinds.put( "shovel", TurtleShovel::new );
kinds.put( "sword", TurtleSword::new );
}
private final String id;
private final ItemStack craftItem;
private final ItemStack toolItem;
private final String kind;
private ITurtleUpgrade upgrade;
public AddTurtleTool( String id, ItemStack craftItem, ItemStack toolItem, String kind )
{
this.id = id;
this.craftItem = craftItem;
this.toolItem = toolItem;
this.kind = kind;
}
@Override
public void apply()
{
ITurtleUpgrade upgrade = this.upgrade;
if( upgrade == null )
{
Factory factory = kinds.get( kind );
if( factory == null )
{
ComputerCraft.log.error( "Unknown turtle upgrade kind '{}' (this should have been rejected by verify!)", kind );
return;
}
upgrade = this.upgrade = factory.create( new Identifier( id ), craftItem, toolItem );
}
try
{
TurtleUpgrades.register( upgrade );
}
catch( RuntimeException e )
{
ComputerCraft.log.error( "Registration of turtle tool failed", e );
}
}
@Override
public String describe()
{
return String.format( "Add new turtle %s '%s' (crafted with '%s', uses a '%s')", kind, id, craftItem, toolItem );
}
@Override
public void undo()
{
if( upgrade != null ) TurtleUpgrades.remove( upgrade );
}
@Override
public String describeUndo()
{
return String.format( "Removing turtle upgrade %s.", id );
}
public boolean validate( ILogger logger )
{
TrackingLogger trackLog = new TrackingLogger( logger );
if( craftItem.isEmpty() ) trackLog.warning( "Crafting item stack is empty." );
if( craftItem.hasTag() && !craftItem.getTag().isEmpty() ) trackLog.warning( "Crafting item has NBT." );
if( toolItem.isEmpty() ) trackLog.error( "Tool item stack is empty." );
if( !kinds.containsKey( kind ) ) trackLog.error( String.format( "Unknown kind '%s'.", kind ) );
if( TurtleUpgrades.get( id ) != null )
{
trackLog.error( String.format( "An upgrade with the same name ('%s') has already been registered.", id ) );
}
return trackLog.isOk();
}
@Override
public boolean shouldApplyOn( LogicalSide side )
{
return true;
}
}

View File

@ -1,70 +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.integration.crafttweaker.actions;
import com.blamejared.crafttweaker.api.actions.IUndoableAction;
import com.blamejared.crafttweaker.api.logger.ILogger;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.shared.TurtleUpgrades;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fml.LogicalSide;
/**
* Removes a turtle upgrade crafted with the given stack.
*/
public class RemoveTurtleUpgradeByItem implements IUndoableAction
{
private final ItemStack stack;
private ITurtleUpgrade upgrade;
public RemoveTurtleUpgradeByItem( ItemStack stack )
{
this.stack = stack;
}
@Override
public void apply()
{
ITurtleUpgrade upgrade = this.upgrade = TurtleUpgrades.get( stack );
if( upgrade != null ) TurtleUpgrades.disable( upgrade );
}
@Override
public String describe()
{
return String.format( "Remove turtle upgrades crafted with '%s'", stack );
}
@Override
public void undo()
{
if( this.upgrade != null ) TurtleUpgrades.enable( upgrade );
}
@Override
public String describeUndo()
{
return String.format( "Adding back turtle upgrades crafted with '%s'", stack );
}
@Override
public boolean validate( ILogger logger )
{
if( TurtleUpgrades.get( stack ) == null )
{
logger.error( String.format( "Unknown turtle upgrade crafted with '%s'.", stack ) );
return false;
}
return true;
}
@Override
public boolean shouldApplyOn( LogicalSide side )
{
return true;
}
}

View File

@ -1,69 +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.integration.crafttweaker.actions;
import com.blamejared.crafttweaker.api.actions.IUndoableAction;
import com.blamejared.crafttweaker.api.logger.ILogger;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.shared.TurtleUpgrades;
import net.minecraftforge.fml.LogicalSide;
/**
* Removes a turtle upgrade with the given id.
*/
public class RemoveTurtleUpgradeByName implements IUndoableAction
{
private final String id;
private ITurtleUpgrade upgrade;
public RemoveTurtleUpgradeByName( String id )
{
this.id = id;
}
@Override
public void apply()
{
ITurtleUpgrade upgrade = this.upgrade = TurtleUpgrades.get( id );
if( upgrade != null ) TurtleUpgrades.disable( upgrade );
}
@Override
public String describe()
{
return String.format( "Remove turtle upgrade '%s'", id );
}
@Override
public void undo()
{
if( this.upgrade != null ) TurtleUpgrades.enable( upgrade );
}
@Override
public String describeUndo()
{
return String.format( "Adding back turtle upgrade '%s'", id );
}
@Override
public boolean validate( ILogger logger )
{
if( TurtleUpgrades.get( id ) == null )
{
logger.error( String.format( "Unknown turtle upgrade '%s'.", id ) );
return false;
}
return true;
}
@Override
public boolean shouldApplyOn( LogicalSide side )
{
return true;
}
}

View File

@ -1,156 +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.integration.jei;
import dan200.computercraft.ComputerCraft;
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.ComputerCraftRegistry;
import dan200.computercraft.shared.TurtleUpgrades;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.media.items.ItemDisk;
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import dan200.computercraft.shared.pocket.items.PocketComputerItemFactory;
import dan200.computercraft.shared.turtle.items.ITurtleItem;
import dan200.computercraft.shared.turtle.items.TurtleItemFactory;
import mezz.jei.api.IModPlugin;
import mezz.jei.api.JeiPlugin;
import mezz.jei.api.constants.VanillaRecipeCategoryUid;
import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.ingredients.subtypes.ISubtypeInterpreter;
import mezz.jei.api.recipe.IRecipeManager;
import mezz.jei.api.recipe.category.IRecipeCategory;
import mezz.jei.api.registration.IAdvancedRegistration;
import mezz.jei.api.registration.ISubtypeRegistration;
import mezz.jei.api.runtime.IJeiRuntime;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.recipe.Recipe;
import net.minecraft.util.Identifier;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.List;
import static dan200.computercraft.shared.integration.jei.RecipeResolver.MAIN_FAMILIES;
@JeiPlugin
public class JEIComputerCraft implements IModPlugin
{
@Nonnull
@Override
public Identifier getPluginUid()
{
return new Identifier( ComputerCraft.MOD_ID, "jei" );
}
@Override
public void registerItemSubtypes( ISubtypeRegistration subtypeRegistry )
{
subtypeRegistry.registerSubtypeInterpreter( ComputerCraftRegistry.ModItems.TURTLE_NORMAL.get(), turtleSubtype );
subtypeRegistry.registerSubtypeInterpreter( ComputerCraftRegistry.ModItems.TURTLE_ADVANCED.get(), turtleSubtype );
subtypeRegistry.registerSubtypeInterpreter( ComputerCraftRegistry.ModItems.POCKET_COMPUTER_NORMAL.get(), pocketSubtype );
subtypeRegistry.registerSubtypeInterpreter( ComputerCraftRegistry.ModItems.POCKET_COMPUTER_ADVANCED.get(), pocketSubtype );
subtypeRegistry.registerSubtypeInterpreter( ComputerCraftRegistry.ModItems.DISK.get(), diskSubtype );
}
@Override
public void registerAdvanced( IAdvancedRegistration registry )
{
registry.addRecipeManagerPlugin( new RecipeResolver() );
}
@Override
public void onRuntimeAvailable( IJeiRuntime runtime )
{
IRecipeManager registry = runtime.getRecipeManager();
// Register all turtles/pocket computers (not just vanilla upgrades) as upgrades on JEI.
List<ItemStack> upgradeItems = new ArrayList<>();
for( ComputerFamily family : MAIN_FAMILIES )
{
TurtleUpgrades.getUpgrades()
.filter( x -> TurtleUpgrades.suitableForFamily( family, x ) )
.map( x -> TurtleItemFactory.create( -1, null, -1, family, null, x, 0, null ) )
.forEach( upgradeItems::add );
for( IPocketUpgrade upgrade : PocketUpgrades.getUpgrades() )
{
upgradeItems.add( PocketComputerItemFactory.create( -1, null, -1, family, upgrade ) );
}
}
runtime.getIngredientManager().addIngredientsAtRuntime( VanillaTypes.ITEM, upgradeItems );
// Hide all upgrade recipes
IRecipeCategory<?> category = (IRecipeCategory<?>) registry.getRecipeCategory( VanillaRecipeCategoryUid.CRAFTING );
if( category != null )
{
for( Object wrapper : registry.getRecipes( category ) )
{
if( !(wrapper instanceof Recipe) ) continue;
Identifier id = ((Recipe) wrapper).getId();
if( id.getNamespace().equals( ComputerCraft.MOD_ID )
&& (id.getPath().startsWith( "generated/turtle_" ) || id.getPath().startsWith( "generated/pocket_" )) )
{
registry.hideRecipe( wrapper, VanillaRecipeCategoryUid.CRAFTING );
}
}
}
}
/**
* Distinguishes turtles by upgrades and family.
*/
private static final ISubtypeInterpreter turtleSubtype = stack -> {
Item item = stack.getItem();
if( !(item instanceof ITurtleItem) ) return "";
ITurtleItem turtle = (ITurtleItem) item;
StringBuilder name = new StringBuilder();
// Add left and right upgrades to the identifier
ITurtleUpgrade left = turtle.getUpgrade( stack, TurtleSide.LEFT );
ITurtleUpgrade right = turtle.getUpgrade( stack, TurtleSide.RIGHT );
if( left != null ) name.append( left.getUpgradeID() );
if( left != null && right != null ) name.append( '|' );
if( right != null ) name.append( right.getUpgradeID() );
return name.toString();
};
/**
* Distinguishes pocket computers by upgrade and family.
*/
private static final ISubtypeInterpreter pocketSubtype = stack -> {
Item item = stack.getItem();
if( !(item instanceof ItemPocketComputer) ) return "";
StringBuilder name = new StringBuilder();
// Add the upgrade to the identifier
IPocketUpgrade upgrade = ItemPocketComputer.getUpgrade( stack );
if( upgrade != null ) name.append( upgrade.getUpgradeID() );
return name.toString();
};
/**
* Distinguishes disks by colour.
*/
private static final ISubtypeInterpreter diskSubtype = stack -> {
Item item = stack.getItem();
if( !(item instanceof ItemDisk) ) return "";
ItemDisk disk = (ItemDisk) item;
int colour = disk.getColour( stack );
return colour == -1 ? "" : String.format( "%06x", colour );
};
}

View File

@ -1,401 +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.integration.jei;
import dan200.computercraft.ComputerCraft;
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.TurtleUpgrades;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import dan200.computercraft.shared.pocket.items.PocketComputerItemFactory;
import dan200.computercraft.shared.turtle.items.ITurtleItem;
import dan200.computercraft.shared.turtle.items.TurtleItemFactory;
import dan200.computercraft.shared.util.InventoryUtil;
import mezz.jei.api.constants.VanillaRecipeCategoryUid;
import mezz.jei.api.recipe.IFocus;
import mezz.jei.api.recipe.advanced.IRecipeManagerPlugin;
import mezz.jei.api.recipe.category.IRecipeCategory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.recipe.Ingredient;
import net.minecraft.recipe.RecipeSerializer;
import net.minecraft.recipe.ShapedRecipe;
import net.minecraft.util.Identifier;
import net.minecraft.util.collection.DefaultedList;
import javax.annotation.Nonnull;
import java.util.*;
import static net.minecraft.recipe.Ingredient.ofStacks;
import static net.minecraft.util.collection.DefaultedList.copyOf;
class RecipeResolver implements IRecipeManagerPlugin
{
static final ComputerFamily[] MAIN_FAMILIES = new ComputerFamily[] { ComputerFamily.NORMAL, ComputerFamily.ADVANCED };
private final Map<Item, List<UpgradeInfo>> upgradeItemLookup = new HashMap<>();
private final List<UpgradeInfo> pocketUpgrades = new ArrayList<>();
private final List<UpgradeInfo> turtleUpgrades = new ArrayList<>();
private boolean initialised = false;
/**
* Build a cache of items which are used for turtle and pocket computer upgrades.
*/
private void setupCache()
{
if( initialised ) return;
initialised = true;
TurtleUpgrades.getUpgrades().forEach( upgrade -> {
ItemStack stack = upgrade.getCraftingItem();
if( stack.isEmpty() ) return;
UpgradeInfo info = new UpgradeInfo( stack, upgrade );
upgradeItemLookup.computeIfAbsent( stack.getItem(), k -> new ArrayList<>( 1 ) ).add( info );
turtleUpgrades.add( info );
} );
for( IPocketUpgrade upgrade : PocketUpgrades.getUpgrades() )
{
ItemStack stack = upgrade.getCraftingItem();
if( stack.isEmpty() ) continue;
UpgradeInfo info = new UpgradeInfo( stack, upgrade );
upgradeItemLookup.computeIfAbsent( stack.getItem(), k -> new ArrayList<>( 1 ) ).add( info );
pocketUpgrades.add( info );
}
}
private boolean hasUpgrade( @Nonnull ItemStack stack )
{
if( stack.isEmpty() ) return false;
setupCache();
List<UpgradeInfo> upgrades = upgradeItemLookup.get( stack.getItem() );
if( upgrades == null ) return false;
for( UpgradeInfo upgrade : upgrades )
{
ItemStack craftingStack = upgrade.stack;
if( !craftingStack.isEmpty() && InventoryUtil.areItemsSimilar( stack, craftingStack ) ) return true;
}
return false;
}
@Nonnull
@Override
public <V> List<Identifier> getRecipeCategoryUids( @Nonnull IFocus<V> focus )
{
V value = focus.getValue();
if( !(value instanceof ItemStack) ) return Collections.emptyList();
ItemStack stack = (ItemStack) value;
switch( focus.getMode() )
{
case INPUT:
return stack.getItem() instanceof ITurtleItem || stack.getItem() instanceof ItemPocketComputer ||
hasUpgrade( stack )
? Collections.singletonList( VanillaRecipeCategoryUid.CRAFTING )
: Collections.emptyList();
case OUTPUT:
return stack.getItem() instanceof ITurtleItem || stack.getItem() instanceof ItemPocketComputer
? Collections.singletonList( VanillaRecipeCategoryUid.CRAFTING )
: Collections.emptyList();
default:
return Collections.emptyList();
}
}
@Nonnull
@Override
public <T, V> List<T> getRecipes( @Nonnull IRecipeCategory<T> recipeCategory, @Nonnull IFocus<V> focus )
{
if( !(focus.getValue() instanceof ItemStack) || !recipeCategory.getUid().equals( VanillaRecipeCategoryUid.CRAFTING ) )
{
return Collections.emptyList();
}
ItemStack stack = (ItemStack) focus.getValue();
switch( focus.getMode() )
{
case INPUT:
return cast( findRecipesWithInput( stack ) );
case OUTPUT:
return cast( findRecipesWithOutput( stack ) );
default:
return Collections.emptyList();
}
}
@Nonnull
@Override
public <T> List<T> getRecipes( @Nonnull IRecipeCategory<T> recipeCategory )
{
return Collections.emptyList();
}
@Nonnull
private List<Shaped> findRecipesWithInput( @Nonnull ItemStack stack )
{
setupCache();
if( stack.getItem() instanceof ITurtleItem )
{
// Suggest possible upgrades which can be applied to this turtle
ITurtleItem item = (ITurtleItem) stack.getItem();
ITurtleUpgrade left = item.getUpgrade( stack, TurtleSide.LEFT );
ITurtleUpgrade right = item.getUpgrade( stack, TurtleSide.RIGHT );
if( left != null && right != null ) return Collections.emptyList();
List<Shaped> recipes = new ArrayList<>();
Ingredient ingredient = ofStacks( stack );
for( UpgradeInfo upgrade : turtleUpgrades )
{
// The turtle is facing towards us, so upgrades on the left are actually crafted on the right.
if( left == null )
{
recipes.add( horizontal( copyOf( Ingredient.EMPTY, ingredient, upgrade.ingredient ), turtleWith( stack, upgrade.turtle, right ) ) );
}
if( right == null )
{
recipes.add( horizontal( copyOf( Ingredient.EMPTY, upgrade.ingredient, ingredient ), turtleWith( stack, left, upgrade.turtle ) ) );
}
}
return cast( recipes );
}
else if( stack.getItem() instanceof ItemPocketComputer )
{
// Suggest possible upgrades which can be applied to this turtle
IPocketUpgrade back = ItemPocketComputer.getUpgrade( stack );
if( back != null ) return Collections.emptyList();
List<Shaped> recipes = new ArrayList<>();
Ingredient ingredient = ofStacks( stack );
for( UpgradeInfo upgrade : pocketUpgrades )
{
recipes.add( vertical( copyOf( Ingredient.EMPTY, ingredient, upgrade.ingredient ), pocketWith( stack, upgrade.pocket ) ) );
}
return recipes;
}
else
{
List<UpgradeInfo> upgrades = upgradeItemLookup.get( stack.getItem() );
if( upgrades == null ) return Collections.emptyList();
List<Shaped> recipes = null;
boolean multiple = false;
Ingredient ingredient = ofStacks( stack );
for( UpgradeInfo upgrade : upgrades )
{
ItemStack craftingStack = upgrade.stack;
if( craftingStack.isEmpty() || !InventoryUtil.areItemsSimilar( stack, craftingStack ) )
{
continue;
}
if( recipes == null )
{
recipes = upgrade.getRecipes();
}
else
{
if( !multiple )
{
multiple = true;
recipes = new ArrayList<>( recipes );
}
recipes.addAll( upgrade.getRecipes() );
}
}
return recipes == null ? Collections.emptyList() : recipes;
}
}
@Nonnull
private static List<Shaped> findRecipesWithOutput( @Nonnull ItemStack stack )
{
// Find which upgrade this item currently has, an so how we could build it.
if( stack.getItem() instanceof ITurtleItem )
{
ITurtleItem item = (ITurtleItem) stack.getItem();
List<Shaped> recipes = new ArrayList<>( 0 );
ITurtleUpgrade left = item.getUpgrade( stack, TurtleSide.LEFT );
ITurtleUpgrade right = item.getUpgrade( stack, TurtleSide.RIGHT );
// The turtle is facing towards us, so upgrades on the left are actually crafted on the right.
if( left != null )
{
recipes.add( horizontal(
copyOf( Ingredient.EMPTY, ofStacks( turtleWith( stack, null, right ) ), ofStacks( left.getCraftingItem() ) ),
stack
) );
}
if( right != null )
{
recipes.add( horizontal(
copyOf( Ingredient.EMPTY, ofStacks( right.getCraftingItem() ), ofStacks( turtleWith( stack, left, null ) ) ),
stack
) );
}
return cast( recipes );
}
else if( stack.getItem() instanceof ItemPocketComputer )
{
List<Shaped> recipes = new ArrayList<>( 0 );
IPocketUpgrade back = ItemPocketComputer.getUpgrade( stack );
if( back != null )
{
recipes.add( vertical(
copyOf( Ingredient.EMPTY, ofStacks( back.getCraftingItem() ), ofStacks( pocketWith( stack, null ) ) ),
stack
) );
}
return cast( recipes );
}
else
{
return Collections.emptyList();
}
}
@SuppressWarnings( { "unchecked", "rawtypes" } )
private static <T, U> List<T> cast( List<U> from )
{
return (List) from;
}
private static ItemStack turtleWith( ItemStack stack, ITurtleUpgrade left, ITurtleUpgrade right )
{
ITurtleItem item = (ITurtleItem) stack.getItem();
return TurtleItemFactory.create(
item.getComputerID( stack ), item.getLabel( stack ), item.getColour( stack ), item.getFamily(),
left, right, item.getFuelLevel( stack ), item.getOverlay( stack )
);
}
private static ItemStack pocketWith( ItemStack stack, IPocketUpgrade back )
{
ItemPocketComputer item = (ItemPocketComputer) stack.getItem();
return PocketComputerItemFactory.create(
item.getComputerID( stack ), item.getLabel( stack ), item.getColour( stack ), item.getFamily(),
back
);
}
private static Shaped vertical( DefaultedList<Ingredient> input, ItemStack result )
{
return new Shaped( 1, input.size(), input, result );
}
private static Shaped horizontal( DefaultedList<Ingredient> input, ItemStack result )
{
return new Shaped( input.size(), 1, input, result );
}
private static class Shaped extends ShapedRecipe
{
private static final Identifier ID = new Identifier( ComputerCraft.MOD_ID, "impostor" );
Shaped( int width, int height, DefaultedList<Ingredient> input, ItemStack output )
{
super( ID, null, width, height, input, output );
}
@Nonnull
@Override
public Identifier getId()
{
return null;
}
@Nonnull
@Override
public RecipeSerializer<?> getSerializer()
{
throw new IllegalStateException( "Should not serialise the JEI recipe" );
}
}
private static final class Upgrade<T>
{
final T upgrade;
final ItemStack stack;
final Ingredient ingredient;
private Upgrade( T upgrade, ItemStack stack )
{
this.upgrade = upgrade;
this.stack = stack;
ingredient = ofStacks( stack );
}
}
private static class UpgradeInfo
{
final ItemStack stack;
final Ingredient ingredient;
final ITurtleUpgrade turtle;
final IPocketUpgrade pocket;
ArrayList<Shaped> recipes;
UpgradeInfo( ItemStack stack, ITurtleUpgrade turtle )
{
this.stack = stack;
ingredient = ofStacks( stack );
this.turtle = turtle;
pocket = null;
}
UpgradeInfo( ItemStack stack, IPocketUpgrade pocket )
{
this.stack = stack;
ingredient = ofStacks( stack );
turtle = null;
this.pocket = pocket;
}
List<Shaped> getRecipes()
{
ArrayList<Shaped> recipes = this.recipes;
if( recipes != null ) return recipes;
recipes = this.recipes = new ArrayList<>( 4 );
for( ComputerFamily family : MAIN_FAMILIES )
{
if( turtle != null && TurtleUpgrades.suitableForFamily( family, turtle ) )
{
recipes.add( horizontal(
copyOf( Ingredient.EMPTY, ingredient, ofStacks( TurtleItemFactory.create( -1, null, -1, family, null, null, 0, null ) ) ),
TurtleItemFactory.create( -1, null, -1, family, null, turtle, 0, null )
) );
}
if( pocket != null )
{
recipes.add( vertical(
copyOf( Ingredient.EMPTY, ingredient, ofStacks( PocketComputerItemFactory.create( -1, null, -1, family, null ) ) ),
PocketComputerItemFactory.create( -1, null, -1, family, pocket )
) );
}
}
recipes.trimToSize();
return recipes;
}
}
}

View File

@ -14,7 +14,7 @@ import net.minecraft.network.PacketByteBuf;
import net.minecraft.util.Identifier;
public class ComputerContainerData implements ContainerData {
private static final Identifier IDENTIFIER = new Identifier(ComputerCraft.MOD_ID, "computerContainerData");
private static final Identifier IDENTIFIER = new Identifier(ComputerCraft.MOD_ID, "computer_container_data");
private int id;
private ComputerFamily family;

View File

@ -20,15 +20,15 @@ import java.util.function.Supplier;
*/
public final class FixedPointTileEntityType<T extends BlockEntity> extends BlockEntityType<T>
{
private final Block block;
private final Supplier<Block> block;
private FixedPointTileEntityType( Block block, Supplier<T> builder )
private FixedPointTileEntityType( Supplier<Block> block, Supplier<T> builder )
{
super( builder, Collections.emptySet(), null );
this.block = block;
}
public static <T extends BlockEntity> FixedPointTileEntityType<T> create( Block block, Function<BlockEntityType<T>, T> builder )
public static <T extends BlockEntity> FixedPointTileEntityType<T> create( Supplier<Block> block, Function<BlockEntityType<T>, T> builder )
{
return new FixedPointSupplier<>( block, builder ).factory;
}
@ -36,7 +36,7 @@ public final class FixedPointTileEntityType<T extends BlockEntity> extends Block
@Override
public boolean supports( @Nonnull Block block )
{
return block == this.block;
return block == this.block.get();
}
private static final class FixedPointSupplier<T extends BlockEntity> implements Supplier<T>
@ -44,7 +44,7 @@ public final class FixedPointTileEntityType<T extends BlockEntity> extends Block
final FixedPointTileEntityType<T> factory;
private final Function<BlockEntityType<T>, T> builder;
private FixedPointSupplier( Block block, Function<BlockEntityType<T>, T> builder )
private FixedPointSupplier( Supplier<Block> block, Function<BlockEntityType<T>, T> builder )
{
factory = new FixedPointTileEntityType<>( block, this );
this.builder = builder;

View File

@ -9,6 +9,7 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import dan200.computercraft.ComputerCraft;
import me.shedaniel.cloth.api.utils.v1.GameInstanceUtils;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.WorldSavePath;
@ -42,7 +43,7 @@ public final class IDAssigner
public static File getDir()
{
return FabricLoader.getInstance().getGameInstance() instanceof MinecraftServer ? ((MinecraftServer) FabricLoader.getInstance().getGameInstance()).getSavePath( FOLDER ).toFile() : null;
return GameInstanceUtils.getServer().getSavePath( FOLDER ).toFile();
}
private static MinecraftServer getCachedServer()
@ -52,7 +53,7 @@ public final class IDAssigner
MinecraftServer currentServer = server.get();
if( currentServer == null ) return null;
if(FabricLoader.getInstance().getGameInstance() instanceof MinecraftServer && currentServer != FabricLoader.getInstance().getGameInstance() ) return null;
if( currentServer != GameInstanceUtils.getServer() ) return null;
return currentServer;
}
@ -62,8 +63,9 @@ public final class IDAssigner
if( currentServer == null )
{
// The server has changed, refetch our ID map
if (FabricLoader.getInstance().getGameInstance() instanceof MinecraftServer) {
server = new WeakReference<>((MinecraftServer) FabricLoader.getInstance().getGameInstance());
if ( GameInstanceUtils.getServer() != null )
{
server = new WeakReference<>( GameInstanceUtils.getServer() );
File dir = getDir();
dir.mkdirs();

View File

@ -15,3 +15,4 @@ accessible class net/minecraft/screen/ScreenHandlerType$Factory
accessible method net/minecraft/client/render/model/json/ModelOverrideList <init> ()V
extendable class net/minecraft/util/math/Matrix4f
accessible method net/minecraft/util/WorldSavePath <init> (Ljava/lang/String;)V
accessible field net/minecraft/server/MinecraftServer serverResourceManager Lnet/minecraft/resource/ServerResourceManager;