mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-01-19 05:32:55 +00:00
Start work on curtailing our global state
The last 4 or 5 commits have simplified things. I can now have some unnecessary complexity as a treat! This is some initial work on better tying the lifecycle of computers (and ComputerCraft) related state to the lifecycle of the current Minecraft server. - Move server-wide methods in IComputerEnvironment (such as creating resource mounts) into a separate interface. - Add a new ServerContext class, which now holds the ID Assigner, server computer registry, and some other tiny bits and bobs. This can only be accessed by ServerContect.get(MinecraftServer), forcing slightly better discipline for how we use these globals. This does allow us to nuke some of the ugliest bits in IDAssigner. Even if it makes things much longer!
This commit is contained in:
parent
cee60cdb5b
commit
b663028f42
@ -24,13 +24,13 @@ import dan200.computercraft.core.asm.GenericMethod;
|
|||||||
import dan200.computercraft.core.filesystem.FileMount;
|
import dan200.computercraft.core.filesystem.FileMount;
|
||||||
import dan200.computercraft.core.filesystem.ResourceMount;
|
import dan200.computercraft.core.filesystem.ResourceMount;
|
||||||
import dan200.computercraft.shared.*;
|
import dan200.computercraft.shared.*;
|
||||||
|
import dan200.computercraft.shared.computer.core.ServerContext;
|
||||||
import dan200.computercraft.shared.peripheral.generic.GenericPeripheralProvider;
|
import dan200.computercraft.shared.peripheral.generic.GenericPeripheralProvider;
|
||||||
import dan200.computercraft.shared.peripheral.generic.data.DetailProviders;
|
import dan200.computercraft.shared.peripheral.generic.data.DetailProviders;
|
||||||
import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork;
|
import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork;
|
||||||
import dan200.computercraft.shared.util.IDAssigner;
|
|
||||||
import dan200.computercraft.shared.wired.WiredNode;
|
import dan200.computercraft.shared.wired.WiredNode;
|
||||||
import net.minecraft.resources.IReloadableResourceManager;
|
|
||||||
import net.minecraft.resources.IResourceManager;
|
import net.minecraft.resources.IResourceManager;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
@ -59,9 +59,9 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static InputStream getResourceFile( String domain, String subPath )
|
public static InputStream getResourceFile( MinecraftServer server, String domain, String subPath )
|
||||||
{
|
{
|
||||||
IReloadableResourceManager manager = (IReloadableResourceManager) ServerLifecycleHooks.getCurrentServer().getDataPackRegistries().getResourceManager();
|
IResourceManager manager = server.getDataPackRegistries().getResourceManager();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return manager.getResource( new ResourceLocation( domain, subPath ) ).getInputStream();
|
return manager.getResource( new ResourceLocation( domain, subPath ) ).getInputStream();
|
||||||
@ -85,7 +85,7 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
|||||||
@Override
|
@Override
|
||||||
public int createUniqueNumberedSaveDir( @Nonnull World world, @Nonnull String parentSubPath )
|
public int createUniqueNumberedSaveDir( @Nonnull World world, @Nonnull String parentSubPath )
|
||||||
{
|
{
|
||||||
return IDAssigner.getNextId( parentSubPath );
|
return ServerContext.get( world.getServer() ).getNextId( parentSubPath );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -93,7 +93,7 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return new FileMount( new File( IDAssigner.getDir(), subPath ), capacity );
|
return new FileMount( new File( ServerContext.get( world.getServer() ).storageDir().toFile(), subPath ), capacity );
|
||||||
}
|
}
|
||||||
catch( Exception e )
|
catch( Exception e )
|
||||||
{
|
{
|
||||||
|
@ -207,7 +207,7 @@ public class HTTPAPI implements ILuaAPI
|
|||||||
|
|
||||||
if( !headers.contains( HttpHeaderNames.USER_AGENT ) )
|
if( !headers.contains( HttpHeaderNames.USER_AGENT ) )
|
||||||
{
|
{
|
||||||
headers.set( HttpHeaderNames.USER_AGENT, apiEnvironment.getComputerEnvironment().getUserAgent() );
|
headers.set( HttpHeaderNames.USER_AGENT, apiEnvironment.getGlobalEnvironment().getUserAgent() );
|
||||||
}
|
}
|
||||||
return headers;
|
return headers;
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,9 @@ package dan200.computercraft.core.apis;
|
|||||||
|
|
||||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
import dan200.computercraft.api.peripheral.IWorkMonitor;
|
import dan200.computercraft.api.peripheral.IWorkMonitor;
|
||||||
|
import dan200.computercraft.core.computer.ComputerEnvironment;
|
||||||
import dan200.computercraft.core.computer.ComputerSide;
|
import dan200.computercraft.core.computer.ComputerSide;
|
||||||
import dan200.computercraft.core.computer.IComputerEnvironment;
|
import dan200.computercraft.core.computer.GlobalEnvironment;
|
||||||
import dan200.computercraft.core.filesystem.FileSystem;
|
import dan200.computercraft.core.filesystem.FileSystem;
|
||||||
import dan200.computercraft.core.terminal.Terminal;
|
import dan200.computercraft.core.terminal.Terminal;
|
||||||
import dan200.computercraft.core.tracking.TrackingField;
|
import dan200.computercraft.core.tracking.TrackingField;
|
||||||
@ -29,7 +30,10 @@ public interface IAPIEnvironment
|
|||||||
int getComputerID();
|
int getComputerID();
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
IComputerEnvironment getComputerEnvironment();
|
ComputerEnvironment getComputerEnvironment();
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
GlobalEnvironment getGlobalEnvironment();
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
IWorkMonitor getMainThreadMonitor();
|
IWorkMonitor getMainThreadMonitor();
|
||||||
|
@ -9,7 +9,7 @@ import dan200.computercraft.api.lua.IArguments;
|
|||||||
import dan200.computercraft.api.lua.ILuaAPI;
|
import dan200.computercraft.api.lua.ILuaAPI;
|
||||||
import dan200.computercraft.api.lua.LuaException;
|
import dan200.computercraft.api.lua.LuaException;
|
||||||
import dan200.computercraft.api.lua.LuaFunction;
|
import dan200.computercraft.api.lua.LuaFunction;
|
||||||
import dan200.computercraft.core.computer.IComputerEnvironment;
|
import dan200.computercraft.core.computer.ComputerEnvironment;
|
||||||
import dan200.computercraft.core.terminal.Terminal;
|
import dan200.computercraft.core.terminal.Terminal;
|
||||||
import dan200.computercraft.shared.util.Colour;
|
import dan200.computercraft.shared.util.Colour;
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ import javax.annotation.Nonnull;
|
|||||||
public class TermAPI extends TermMethods implements ILuaAPI
|
public class TermAPI extends TermMethods implements ILuaAPI
|
||||||
{
|
{
|
||||||
private final Terminal terminal;
|
private final Terminal terminal;
|
||||||
private final IComputerEnvironment environment;
|
private final ComputerEnvironment environment;
|
||||||
|
|
||||||
public TermAPI( IAPIEnvironment environment )
|
public TermAPI( IAPIEnvironment environment )
|
||||||
{
|
{
|
||||||
|
@ -36,7 +36,8 @@ public class Computer
|
|||||||
private String label = null;
|
private String label = null;
|
||||||
|
|
||||||
// Read-only fields about the computer
|
// Read-only fields about the computer
|
||||||
private final IComputerEnvironment environment;
|
private final ComputerEnvironment computerEnvironment;
|
||||||
|
private final GlobalEnvironment globalEnvironment;
|
||||||
private final Terminal terminal;
|
private final Terminal terminal;
|
||||||
private final ComputerExecutor executor;
|
private final ComputerExecutor executor;
|
||||||
private final MainThreadExecutor serverExecutor;
|
private final MainThreadExecutor serverExecutor;
|
||||||
@ -49,20 +50,26 @@ public class Computer
|
|||||||
private boolean startRequested;
|
private boolean startRequested;
|
||||||
private int ticksSinceStart = -1;
|
private int ticksSinceStart = -1;
|
||||||
|
|
||||||
public Computer( IComputerEnvironment environment, Terminal terminal, int id )
|
public Computer( GlobalEnvironment globalEnvironment, ComputerEnvironment environment, Terminal terminal, int id )
|
||||||
{
|
{
|
||||||
if( id < 0 ) throw new IllegalStateException( "Id has not been assigned" );
|
if( id < 0 ) throw new IllegalStateException( "Id has not been assigned" );
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.environment = environment;
|
this.globalEnvironment = globalEnvironment;
|
||||||
|
this.computerEnvironment = environment;
|
||||||
this.terminal = terminal;
|
this.terminal = terminal;
|
||||||
|
|
||||||
executor = new ComputerExecutor( this );
|
executor = new ComputerExecutor( this );
|
||||||
serverExecutor = new MainThreadExecutor( this );
|
serverExecutor = new MainThreadExecutor( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
IComputerEnvironment getComputerEnvironment()
|
ComputerEnvironment getComputerEnvironment()
|
||||||
{
|
{
|
||||||
return environment;
|
return computerEnvironment;
|
||||||
|
}
|
||||||
|
|
||||||
|
GlobalEnvironment getGlobalEnvironment()
|
||||||
|
{
|
||||||
|
return globalEnvironment;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileSystem getFileSystem()
|
FileSystem getFileSystem()
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||||
|
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
||||||
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
|
*/
|
||||||
|
package dan200.computercraft.core.computer;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.filesystem.IWritableMount;
|
||||||
|
import dan200.computercraft.core.filesystem.FileMount;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
public interface ComputerEnvironment
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the current in-game day.
|
||||||
|
*
|
||||||
|
* @return The current day.
|
||||||
|
*/
|
||||||
|
int getDay();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current in-game time of day.
|
||||||
|
*
|
||||||
|
* @return The current time.
|
||||||
|
*/
|
||||||
|
double getTimeOfDay();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct the mount for this computer's user-writable data.
|
||||||
|
*
|
||||||
|
* @return The constructed mount or {@code null} if the mount could not be created.
|
||||||
|
* @see FileMount
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
IWritableMount createRootMount();
|
||||||
|
}
|
@ -340,7 +340,7 @@ final class ComputerExecutor
|
|||||||
|
|
||||||
private IMount getRomMount()
|
private IMount getRomMount()
|
||||||
{
|
{
|
||||||
return computer.getComputerEnvironment().createResourceMount( "computercraft", "lua/rom" );
|
return computer.getGlobalEnvironment().createResourceMount( "computercraft", "lua/rom" );
|
||||||
}
|
}
|
||||||
|
|
||||||
private IWritableMount getRootMount()
|
private IWritableMount getRootMount()
|
||||||
@ -382,7 +382,7 @@ final class ComputerExecutor
|
|||||||
InputStream biosStream = null;
|
InputStream biosStream = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
biosStream = computer.getComputerEnvironment().createResourceFile( "computercraft", "lua/bios.lua" );
|
biosStream = computer.getGlobalEnvironment().createResourceFile( "computercraft", "lua/bios.lua" );
|
||||||
}
|
}
|
||||||
catch( Exception ignored )
|
catch( Exception ignored )
|
||||||
{
|
{
|
||||||
|
@ -73,11 +73,18 @@ public final class Environment implements IAPIEnvironment
|
|||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public IComputerEnvironment getComputerEnvironment()
|
public ComputerEnvironment getComputerEnvironment()
|
||||||
{
|
{
|
||||||
return computer.getComputerEnvironment();
|
return computer.getComputerEnvironment();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public GlobalEnvironment getGlobalEnvironment()
|
||||||
|
{
|
||||||
|
return computer.getGlobalEnvironment();
|
||||||
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public IWorkMonitor getMainThreadMonitor()
|
public IWorkMonitor getMainThreadMonitor()
|
||||||
|
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||||
|
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
||||||
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
|
*/
|
||||||
|
package dan200.computercraft.core.computer;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.filesystem.IMount;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The global environment in which computers reside.
|
||||||
|
*/
|
||||||
|
public interface GlobalEnvironment
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get a "host" string describing the program hosting CC. It should be of the form {@literal ComputerCraft
|
||||||
|
* $CC_VERSION ($HOST)}, where {@literal $HOST} is a user-defined string such as {@literal Minecraft 1.19}.
|
||||||
|
*
|
||||||
|
* @return The host string.
|
||||||
|
*/
|
||||||
|
String getHostString();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the HTTP user-agent to use for requests. This should be similar to {@link #getHostString()} , but in the form
|
||||||
|
* of a HTTP User-Agent.
|
||||||
|
*
|
||||||
|
* @return The HTTP
|
||||||
|
*/
|
||||||
|
String getUserAgent();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a mount from mod-provided resources.
|
||||||
|
*
|
||||||
|
* @param domain The domain (i.e. mod id) providing resources.
|
||||||
|
* @param subPath The path to these resources under the domain.
|
||||||
|
* @return The created mount or {@code null} if it could not be created.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
IMount createResourceMount( String domain, String subPath );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a single mod-provided file.
|
||||||
|
*
|
||||||
|
* @param domain The domain (i.e. mod id) providing resources.
|
||||||
|
* @param subPath The path to these files under the domain.
|
||||||
|
* @return The opened file or {@code null} if it could not be opened.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
InputStream createResourceFile( String domain, String subPath );
|
||||||
|
}
|
@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
|
||||||
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
|
||||||
*/
|
|
||||||
package dan200.computercraft.core.computer;
|
|
||||||
|
|
||||||
import dan200.computercraft.api.filesystem.IMount;
|
|
||||||
import dan200.computercraft.api.filesystem.IWritableMount;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
public interface IComputerEnvironment
|
|
||||||
{
|
|
||||||
int getDay();
|
|
||||||
|
|
||||||
double getTimeOfDay();
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
String getHostString();
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
String getUserAgent();
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
IWritableMount createRootMount();
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
IMount createResourceMount( String domain, String subPath );
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
InputStream createResourceFile( String domain, String subPath );
|
|
||||||
}
|
|
@ -110,7 +110,7 @@ public class CobaltLuaMachine implements ILuaMachine
|
|||||||
|
|
||||||
// Add version globals
|
// Add version globals
|
||||||
globals.rawset( "_VERSION", valueOf( "Lua 5.1" ) );
|
globals.rawset( "_VERSION", valueOf( "Lua 5.1" ) );
|
||||||
globals.rawset( "_HOST", valueOf( computer.getAPIEnvironment().getComputerEnvironment().getHostString() ) );
|
globals.rawset( "_HOST", valueOf( computer.getAPIEnvironment().getGlobalEnvironment().getHostString() ) );
|
||||||
globals.rawset( "_CC_DEFAULT_SETTINGS", valueOf( ComputerCraft.defaultComputerSettings ) );
|
globals.rawset( "_CC_DEFAULT_SETTINGS", valueOf( ComputerCraft.defaultComputerSettings ) );
|
||||||
if( ComputerCraft.disableLua51Features )
|
if( ComputerCraft.disableLua51Features )
|
||||||
{
|
{
|
||||||
|
@ -12,7 +12,7 @@ import dan200.computercraft.core.filesystem.ResourceMount;
|
|||||||
import dan200.computercraft.core.tracking.ComputerMBean;
|
import dan200.computercraft.core.tracking.ComputerMBean;
|
||||||
import dan200.computercraft.core.tracking.Tracking;
|
import dan200.computercraft.core.tracking.Tracking;
|
||||||
import dan200.computercraft.shared.command.CommandComputerCraft;
|
import dan200.computercraft.shared.command.CommandComputerCraft;
|
||||||
import dan200.computercraft.shared.computer.core.ServerComputerRegistry;
|
import dan200.computercraft.shared.computer.core.ServerContext;
|
||||||
import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork;
|
import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork;
|
||||||
import net.minecraft.entity.EntityType;
|
import net.minecraft.entity.EntityType;
|
||||||
import net.minecraft.loot.ConstantRange;
|
import net.minecraft.loot.ConstantRange;
|
||||||
@ -27,6 +27,7 @@ import net.minecraftforge.eventbus.api.SubscribeEvent;
|
|||||||
import net.minecraftforge.fml.common.Mod;
|
import net.minecraftforge.fml.common.Mod;
|
||||||
import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
|
import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
|
||||||
import net.minecraftforge.fml.event.server.FMLServerStoppedEvent;
|
import net.minecraftforge.fml.event.server.FMLServerStoppedEvent;
|
||||||
|
import net.minecraftforge.fml.server.ServerLifecycleHooks;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@ -52,7 +53,7 @@ public final class CommonHooks
|
|||||||
if( event.phase == TickEvent.Phase.START )
|
if( event.phase == TickEvent.Phase.START )
|
||||||
{
|
{
|
||||||
MainThread.executePendingTasks();
|
MainThread.executePendingTasks();
|
||||||
ServerComputerRegistry.INSTANCE.update();
|
ServerContext.get( ServerLifecycleHooks.getCurrentServer() ).registry().update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,6 +73,7 @@ public final class CommonHooks
|
|||||||
}
|
}
|
||||||
|
|
||||||
resetState();
|
resetState();
|
||||||
|
ServerContext.create( server );
|
||||||
ComputerMBean.registerTracker();
|
ComputerMBean.registerTracker();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +85,7 @@ public final class CommonHooks
|
|||||||
|
|
||||||
private static void resetState()
|
private static void resetState()
|
||||||
{
|
{
|
||||||
ServerComputerRegistry.INSTANCE.reset();
|
ServerContext.close();
|
||||||
MainThread.reset();
|
MainThread.reset();
|
||||||
WirelessNetwork.resetNetworks();
|
WirelessNetwork.resetNetworks();
|
||||||
Tracking.reset();
|
Tracking.reset();
|
||||||
|
@ -6,14 +6,14 @@
|
|||||||
package dan200.computercraft.shared.command;
|
package dan200.computercraft.shared.command;
|
||||||
|
|
||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.ComputerCraft;
|
||||||
import dan200.computercraft.shared.util.IDAssigner;
|
import dan200.computercraft.shared.computer.core.ServerContext;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.util.Util;
|
import net.minecraft.util.Util;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.client.event.ClientChatEvent;
|
import net.minecraftforge.client.event.ClientChatEvent;
|
||||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
import net.minecraftforge.fml.common.Mod;
|
import net.minecraftforge.fml.common.Mod;
|
||||||
import net.minecraftforge.fml.server.ServerLifecycleHooks;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
@ -37,8 +37,8 @@ public final class ClientCommands
|
|||||||
// Emulate the command on the client side
|
// Emulate the command on the client side
|
||||||
if( event.getMessage().startsWith( OPEN_COMPUTER ) )
|
if( event.getMessage().startsWith( OPEN_COMPUTER ) )
|
||||||
{
|
{
|
||||||
MinecraftServer server = ServerLifecycleHooks.getCurrentServer();
|
MinecraftServer server = Minecraft.getInstance().getSingleplayerServer();
|
||||||
if( server == null || server.isDedicatedServer() ) return;
|
if( server == null ) return;
|
||||||
|
|
||||||
event.setCanceled( true );
|
event.setCanceled( true );
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ public final class ClientCommands
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
File file = new File( IDAssigner.getDir(), "computer/" + id );
|
File file = new File( ServerContext.get( server ).storageDir().toFile(), "computer/" + id );
|
||||||
if( !file.isDirectory() ) return;
|
if( !file.isDirectory() ) return;
|
||||||
|
|
||||||
Util.getPlatform().openFile( file );
|
Util.getPlatform().openFile( file );
|
||||||
|
@ -18,10 +18,9 @@ import dan200.computercraft.core.tracking.TrackingField;
|
|||||||
import dan200.computercraft.shared.command.text.TableBuilder;
|
import dan200.computercraft.shared.command.text.TableBuilder;
|
||||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||||
import dan200.computercraft.shared.computer.core.ServerComputerRegistry;
|
import dan200.computercraft.shared.computer.core.ServerContext;
|
||||||
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
|
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
|
||||||
import dan200.computercraft.shared.network.container.ComputerContainerData;
|
import dan200.computercraft.shared.network.container.ComputerContainerData;
|
||||||
import dan200.computercraft.shared.util.IDAssigner;
|
|
||||||
import net.minecraft.command.CommandSource;
|
import net.minecraft.command.CommandSource;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
@ -75,7 +74,7 @@ public final class CommandComputerCraft
|
|||||||
TableBuilder table = new TableBuilder( DUMP_LIST_ID, "Computer", "On", "Position" );
|
TableBuilder table = new TableBuilder( DUMP_LIST_ID, "Computer", "On", "Position" );
|
||||||
|
|
||||||
CommandSource source = context.getSource();
|
CommandSource source = context.getSource();
|
||||||
List<ServerComputer> computers = new ArrayList<>( ServerComputerRegistry.INSTANCE.getComputers() );
|
List<ServerComputer> computers = new ArrayList<>( ServerContext.get( source.getServer() ).registry().getComputers() );
|
||||||
|
|
||||||
// Unless we're on a server, limit the number of rows we can send.
|
// Unless we're on a server, limit the number of rows we can send.
|
||||||
World world = source.getLevel();
|
World world = source.getLevel();
|
||||||
@ -140,7 +139,7 @@ public final class CommandComputerCraft
|
|||||||
|
|
||||||
.then( command( "shutdown" )
|
.then( command( "shutdown" )
|
||||||
.requires( UserLevel.OWNER_OP )
|
.requires( UserLevel.OWNER_OP )
|
||||||
.argManyValue( "computers", manyComputers(), s -> ServerComputerRegistry.INSTANCE.getComputers() )
|
.argManyValue( "computers", manyComputers(), s -> ServerContext.get( s.getServer() ).registry().getComputers() )
|
||||||
.executes( ( context, computerSelectors ) -> {
|
.executes( ( context, computerSelectors ) -> {
|
||||||
int shutdown = 0;
|
int shutdown = 0;
|
||||||
Set<ServerComputer> computers = unwrap( context.getSource(), computerSelectors );
|
Set<ServerComputer> computers = unwrap( context.getSource(), computerSelectors );
|
||||||
@ -155,7 +154,7 @@ public final class CommandComputerCraft
|
|||||||
|
|
||||||
.then( command( "turn-on" )
|
.then( command( "turn-on" )
|
||||||
.requires( UserLevel.OWNER_OP )
|
.requires( UserLevel.OWNER_OP )
|
||||||
.argManyValue( "computers", manyComputers(), s -> ServerComputerRegistry.INSTANCE.getComputers() )
|
.argManyValue( "computers", manyComputers(), s -> ServerContext.get( s.getServer() ).registry().getComputers() )
|
||||||
.executes( ( context, computerSelectors ) -> {
|
.executes( ( context, computerSelectors ) -> {
|
||||||
int on = 0;
|
int on = 0;
|
||||||
Set<ServerComputer> computers = unwrap( context.getSource(), computerSelectors );
|
Set<ServerComputer> computers = unwrap( context.getSource(), computerSelectors );
|
||||||
@ -327,7 +326,7 @@ public final class CommandComputerCraft
|
|||||||
|
|
||||||
if( UserLevel.OWNER.test( source ) && isPlayer( source ) )
|
if( UserLevel.OWNER.test( source ) && isPlayer( source ) )
|
||||||
{
|
{
|
||||||
ITextComponent linkPath = linkStorage( computerId );
|
ITextComponent linkPath = linkStorage( source, computerId );
|
||||||
if( linkPath != null ) out.append( " " ).append( linkPath );
|
if( linkPath != null ) out.append( " " ).append( linkPath );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,9 +349,9 @@ public final class CommandComputerCraft
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ITextComponent linkStorage( int id )
|
private static ITextComponent linkStorage( CommandSource source, int id )
|
||||||
{
|
{
|
||||||
File file = new File( IDAssigner.getDir(), "computer/" + id );
|
File file = new File( ServerContext.get( source.getServer() ).storageDir().toFile(), "computer/" + id );
|
||||||
if( !file.isDirectory() ) return null;
|
if( !file.isDirectory() ) return null;
|
||||||
|
|
||||||
return link(
|
return link(
|
||||||
@ -382,7 +381,7 @@ public final class CommandComputerCraft
|
|||||||
|
|
||||||
Map<Computer, ServerComputer> lookup = new HashMap<>();
|
Map<Computer, ServerComputer> lookup = new HashMap<>();
|
||||||
int maxId = 0, maxInstance = 0;
|
int maxId = 0, maxInstance = 0;
|
||||||
for( ServerComputer server : ServerComputerRegistry.INSTANCE.getComputers() )
|
for( ServerComputer server : ServerContext.get( source.getServer() ).registry().getComputers() )
|
||||||
{
|
{
|
||||||
lookup.put( server.getComputer(), server );
|
lookup.put( server.getComputer(), server );
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ import com.mojang.brigadier.suggestion.Suggestions;
|
|||||||
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
||||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||||
import dan200.computercraft.shared.computer.core.ServerComputerRegistry;
|
import dan200.computercraft.shared.computer.core.ServerContext;
|
||||||
import net.minecraft.command.CommandSource;
|
import net.minecraft.command.CommandSource;
|
||||||
import net.minecraft.command.arguments.IArgumentSerializer;
|
import net.minecraft.command.arguments.IArgumentSerializer;
|
||||||
import net.minecraft.network.PacketBuffer;
|
import net.minecraft.network.PacketBuffer;
|
||||||
@ -89,7 +89,7 @@ public final class ComputersArgumentType implements ArgumentType<ComputersArgume
|
|||||||
{
|
{
|
||||||
int instance = reader.readInt();
|
int instance = reader.readInt();
|
||||||
computers = s -> {
|
computers = s -> {
|
||||||
ServerComputer computer = ServerComputerRegistry.INSTANCE.get( instance );
|
ServerComputer computer = ServerContext.get( s.getServer() ).registry().get( instance );
|
||||||
return computer == null ? Collections.emptyList() : Collections.singletonList( computer );
|
return computer == null ? Collections.emptyList() : Collections.singletonList( computer );
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -124,18 +124,18 @@ public final class ComputersArgumentType implements ArgumentType<ComputersArgume
|
|||||||
return suggestOnServer( context, builder, s -> {
|
return suggestOnServer( context, builder, s -> {
|
||||||
if( remaining.startsWith( "@" ) )
|
if( remaining.startsWith( "@" ) )
|
||||||
{
|
{
|
||||||
suggestComputers( builder, remaining, x -> {
|
suggestComputers( s.getSource(), builder, remaining, x -> {
|
||||||
String label = x.getLabel();
|
String label = x.getLabel();
|
||||||
return label == null ? null : "@" + label;
|
return label == null ? null : "@" + label;
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
else if( remaining.startsWith( "#" ) )
|
else if( remaining.startsWith( "#" ) )
|
||||||
{
|
{
|
||||||
suggestComputers( builder, remaining, c -> "#" + c.getID() );
|
suggestComputers( s.getSource(), builder, remaining, c -> "#" + c.getID() );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
suggestComputers( builder, remaining, c -> Integer.toString( c.getInstanceID() ) );
|
suggestComputers( s.getSource(), builder, remaining, c -> Integer.toString( c.getInstanceID() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.buildFuture();
|
return builder.buildFuture();
|
||||||
@ -148,10 +148,10 @@ public final class ComputersArgumentType implements ArgumentType<ComputersArgume
|
|||||||
return EXAMPLES;
|
return EXAMPLES;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void suggestComputers( SuggestionsBuilder builder, String remaining, Function<ServerComputer, String> renderer )
|
private static void suggestComputers( CommandSource source, SuggestionsBuilder builder, String remaining, Function<ServerComputer, String> renderer )
|
||||||
{
|
{
|
||||||
remaining = remaining.toLowerCase( Locale.ROOT );
|
remaining = remaining.toLowerCase( Locale.ROOT );
|
||||||
for( ServerComputer computer : ServerComputerRegistry.INSTANCE.getComputers() )
|
for( ServerComputer computer : ServerContext.get( source.getServer() ).registry().getComputers() )
|
||||||
{
|
{
|
||||||
String converted = renderer.apply( computer );
|
String converted = renderer.apply( computer );
|
||||||
if( converted != null && converted.toLowerCase( Locale.ROOT ).startsWith( remaining ) )
|
if( converted != null && converted.toLowerCase( Locale.ROOT ).startsWith( remaining ) )
|
||||||
@ -163,7 +163,7 @@ public final class ComputersArgumentType implements ArgumentType<ComputersArgume
|
|||||||
|
|
||||||
private static ComputersSupplier getComputers( Predicate<ServerComputer> predicate )
|
private static ComputersSupplier getComputers( Predicate<ServerComputer> predicate )
|
||||||
{
|
{
|
||||||
return s -> Collections.unmodifiableList( ServerComputerRegistry.INSTANCE
|
return s -> Collections.unmodifiableList( ServerContext.get( s.getServer() ).registry()
|
||||||
.getComputers()
|
.getComputers()
|
||||||
.stream()
|
.stream()
|
||||||
.filter( predicate )
|
.filter( predicate )
|
||||||
|
@ -14,7 +14,7 @@ import dan200.computercraft.shared.common.TileGeneric;
|
|||||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||||
import dan200.computercraft.shared.computer.core.ComputerState;
|
import dan200.computercraft.shared.computer.core.ComputerState;
|
||||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||||
import dan200.computercraft.shared.computer.core.ServerComputerRegistry;
|
import dan200.computercraft.shared.computer.core.ServerContext;
|
||||||
import dan200.computercraft.shared.network.container.ComputerContainerData;
|
import dan200.computercraft.shared.network.container.ComputerContainerData;
|
||||||
import dan200.computercraft.shared.util.DirectionUtil;
|
import dan200.computercraft.shared.util.DirectionUtil;
|
||||||
import dan200.computercraft.shared.util.IDAssigner;
|
import dan200.computercraft.shared.util.IDAssigner;
|
||||||
@ -378,7 +378,7 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
|||||||
|
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
|
|
||||||
ServerComputer computer = ServerComputerRegistry.INSTANCE.get( instanceID );
|
ServerComputer computer = ServerContext.get( getLevel().getServer() ).registry().get( instanceID );
|
||||||
if( computer == null )
|
if( computer == null )
|
||||||
{
|
{
|
||||||
if( computerID < 0 )
|
if( computerID < 0 )
|
||||||
@ -400,7 +400,7 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
|||||||
@Nullable
|
@Nullable
|
||||||
public ServerComputer getServerComputer()
|
public ServerComputer getServerComputer()
|
||||||
{
|
{
|
||||||
return getLevel().isClientSide ? null : ServerComputerRegistry.INSTANCE.get( instanceID );
|
return getLevel().isClientSide ? null : ServerContext.get( getLevel().getServer() ).registry().get( instanceID );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Networking stuff
|
// Networking stuff
|
||||||
|
@ -6,16 +6,14 @@
|
|||||||
package dan200.computercraft.shared.computer.core;
|
package dan200.computercraft.shared.computer.core;
|
||||||
|
|
||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.ComputerCraft;
|
||||||
import dan200.computercraft.ComputerCraftAPIImpl;
|
|
||||||
import dan200.computercraft.api.ComputerCraftAPI;
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
import dan200.computercraft.api.filesystem.IMount;
|
|
||||||
import dan200.computercraft.api.filesystem.IWritableMount;
|
import dan200.computercraft.api.filesystem.IWritableMount;
|
||||||
import dan200.computercraft.api.lua.ILuaAPI;
|
import dan200.computercraft.api.lua.ILuaAPI;
|
||||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
import dan200.computercraft.core.apis.IAPIEnvironment;
|
import dan200.computercraft.core.apis.IAPIEnvironment;
|
||||||
import dan200.computercraft.core.computer.Computer;
|
import dan200.computercraft.core.computer.Computer;
|
||||||
|
import dan200.computercraft.core.computer.ComputerEnvironment;
|
||||||
import dan200.computercraft.core.computer.ComputerSide;
|
import dan200.computercraft.core.computer.ComputerSide;
|
||||||
import dan200.computercraft.core.computer.IComputerEnvironment;
|
|
||||||
import dan200.computercraft.core.terminal.Terminal;
|
import dan200.computercraft.core.terminal.Terminal;
|
||||||
import dan200.computercraft.shared.computer.menu.ComputerMenu;
|
import dan200.computercraft.shared.computer.menu.ComputerMenu;
|
||||||
import dan200.computercraft.shared.network.NetworkHandler;
|
import dan200.computercraft.shared.network.NetworkHandler;
|
||||||
@ -27,14 +25,11 @@ import net.minecraft.inventory.container.Container;
|
|||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.server.ServerWorld;
|
import net.minecraft.world.server.ServerWorld;
|
||||||
import net.minecraftforge.versions.mcp.MCPVersion;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public class ServerComputer implements InputHandler, IComputerEnvironment
|
public class ServerComputer implements InputHandler, ComputerEnvironment
|
||||||
{
|
{
|
||||||
private final int instanceID;
|
private final int instanceID;
|
||||||
|
|
||||||
@ -55,10 +50,11 @@ public class ServerComputer implements InputHandler, IComputerEnvironment
|
|||||||
this.world = world;
|
this.world = world;
|
||||||
this.family = family;
|
this.family = family;
|
||||||
|
|
||||||
instanceID = ServerComputerRegistry.INSTANCE.getUnusedInstanceID();
|
ServerContext context = ServerContext.get( world.getServer() );
|
||||||
|
instanceID = context.registry().getUnusedInstanceID();
|
||||||
terminal = new Terminal( terminalWidth, terminalHeight, family != ComputerFamily.NORMAL, this::markTerminalChanged );
|
terminal = new Terminal( terminalWidth, terminalHeight, family != ComputerFamily.NORMAL, this::markTerminalChanged );
|
||||||
|
|
||||||
computer = new Computer( this, terminal, computerID );
|
computer = new Computer( context.environment(), this, terminal, computerID );
|
||||||
computer.setLabel( label );
|
computer.setLabel( label );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,7 +136,7 @@ public class ServerComputer implements InputHandler, IComputerEnvironment
|
|||||||
|
|
||||||
public int register()
|
public int register()
|
||||||
{
|
{
|
||||||
ServerComputerRegistry.INSTANCE.add( instanceID, this );
|
ServerContext.get( world.getServer() ).registry().add( instanceID, this );
|
||||||
return instanceID;
|
return instanceID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,7 +148,7 @@ public class ServerComputer implements InputHandler, IComputerEnvironment
|
|||||||
public void close()
|
public void close()
|
||||||
{
|
{
|
||||||
unload();
|
unload();
|
||||||
ServerComputerRegistry.INSTANCE.remove( instanceID );
|
ServerContext.get( world.getServer() ).registry().remove( instanceID );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendToAllInteracting( Function<Container, NetworkMessage> createPacket )
|
private void sendToAllInteracting( Function<Container, NetworkMessage> createPacket )
|
||||||
@ -285,30 +281,4 @@ public class ServerComputer implements InputHandler, IComputerEnvironment
|
|||||||
{
|
{
|
||||||
return ComputerCraftAPI.createSaveDirMount( world, "computer/" + computer.getID(), ComputerCraft.computerSpaceLimit );
|
return ComputerCraftAPI.createSaveDirMount( world, "computer/" + computer.getID(), ComputerCraft.computerSpaceLimit );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public IMount createResourceMount( String domain, String subPath )
|
|
||||||
{
|
|
||||||
return ComputerCraftAPI.createResourceMount( domain, subPath );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public InputStream createResourceFile( String domain, String subPath )
|
|
||||||
{
|
|
||||||
return ComputerCraftAPIImpl.getResourceFile( domain, subPath );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public String getHostString()
|
|
||||||
{
|
|
||||||
return String.format( "ComputerCraft %s (Minecraft %s)", ComputerCraftAPI.getInstalledVersion(), MCPVersion.getMCVersion() );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public String getUserAgent()
|
|
||||||
{
|
|
||||||
return ComputerCraft.MOD_ID + "/" + ComputerCraftAPI.getInstalledVersion();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -16,9 +16,8 @@ import java.util.Random;
|
|||||||
public class ServerComputerRegistry
|
public class ServerComputerRegistry
|
||||||
{
|
{
|
||||||
private static final Random RANDOM = new Random();
|
private static final Random RANDOM = new Random();
|
||||||
public static final ServerComputerRegistry INSTANCE = new ServerComputerRegistry();
|
|
||||||
|
|
||||||
private int sessionId = RANDOM.nextInt();
|
private final int sessionId = RANDOM.nextInt();
|
||||||
private final Int2ObjectMap<ServerComputer> computers = new Int2ObjectOpenHashMap<>();
|
private final Int2ObjectMap<ServerComputer> computers = new Int2ObjectOpenHashMap<>();
|
||||||
private int nextInstanceId;
|
private int nextInstanceId;
|
||||||
|
|
||||||
@ -82,11 +81,10 @@ public class ServerComputerRegistry
|
|||||||
computers.remove( instanceID );
|
computers.remove( instanceID );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reset()
|
void close()
|
||||||
{
|
{
|
||||||
for( ServerComputer computer : getComputers() ) computer.unload();
|
for( ServerComputer computer : getComputers() ) computer.unload();
|
||||||
computers.clear();
|
computers.clear();
|
||||||
sessionId = RANDOM.nextInt();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<ServerComputer> getComputers()
|
public Collection<ServerComputer> getComputers()
|
||||||
|
@ -0,0 +1,183 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||||
|
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
||||||
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
|
*/
|
||||||
|
package dan200.computercraft.shared.computer.core;
|
||||||
|
|
||||||
|
import dan200.computercraft.ComputerCraft;
|
||||||
|
import dan200.computercraft.ComputerCraftAPIImpl;
|
||||||
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
|
import dan200.computercraft.api.filesystem.IMount;
|
||||||
|
import dan200.computercraft.core.computer.GlobalEnvironment;
|
||||||
|
import dan200.computercraft.shared.CommonHooks;
|
||||||
|
import dan200.computercraft.shared.util.IDAssigner;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraft.world.storage.FolderName;
|
||||||
|
import net.minecraftforge.versions.mcp.MCPVersion;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores ComputerCraft's server-side state for the lifetime of a {@link MinecraftServer}.
|
||||||
|
* <p>
|
||||||
|
* This is effectively a glorified singleton, holding references to most global state ComputerCraft stores
|
||||||
|
* (for instance, {@linkplain IDAssigner ID assignment} and {@linkplain ServerComputerRegistry running computers}. Its
|
||||||
|
* main purpose is to offer a single point of resetting the state ({@link ServerContext#close()} and ensure disciplined
|
||||||
|
* access to the current state, by ensuring callers have a {@link MinecraftServer} to hand.
|
||||||
|
*
|
||||||
|
* @see CommonHooks for where the context is created and torn down.
|
||||||
|
*/
|
||||||
|
public final class ServerContext
|
||||||
|
{
|
||||||
|
private static final FolderName FOLDER = new FolderName( ComputerCraft.MOD_ID );
|
||||||
|
|
||||||
|
private static @Nullable ServerContext instance;
|
||||||
|
|
||||||
|
private final MinecraftServer server;
|
||||||
|
|
||||||
|
private final ServerComputerRegistry registry = new ServerComputerRegistry();
|
||||||
|
private final GlobalEnvironment environment;
|
||||||
|
private final IDAssigner idAssigner;
|
||||||
|
private final Path storageDir;
|
||||||
|
|
||||||
|
private ServerContext( MinecraftServer server )
|
||||||
|
{
|
||||||
|
this.server = server;
|
||||||
|
storageDir = server.getWorldPath( FOLDER );
|
||||||
|
environment = new Environment( server );
|
||||||
|
idAssigner = new IDAssigner( storageDir.resolve( "ids.json" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start a new server context from the currently running Minecraft server.
|
||||||
|
*
|
||||||
|
* @param server The currently running Minecraft server.
|
||||||
|
* @throws IllegalStateException If a context is already present.
|
||||||
|
*/
|
||||||
|
public static void create( MinecraftServer server )
|
||||||
|
{
|
||||||
|
if( ServerContext.instance != null ) throw new IllegalStateException( "ServerContext already exists!" );
|
||||||
|
ServerContext.instance = new ServerContext( server );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops the current server context, resetting any state and terminating all computers.
|
||||||
|
*/
|
||||||
|
public static void close()
|
||||||
|
{
|
||||||
|
ServerContext instance = ServerContext.instance;
|
||||||
|
if( instance == null ) return;
|
||||||
|
|
||||||
|
instance.registry.close();
|
||||||
|
|
||||||
|
ServerContext.instance = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the {@link ServerContext} instance for the currently running Minecraft server.
|
||||||
|
*
|
||||||
|
* @param server The current server.
|
||||||
|
* @return The current server context.
|
||||||
|
*/
|
||||||
|
public static ServerContext get( MinecraftServer server )
|
||||||
|
{
|
||||||
|
Objects.requireNonNull( server, "Server cannot be null" );
|
||||||
|
|
||||||
|
ServerContext instance = ServerContext.instance;
|
||||||
|
if( instance == null ) throw new IllegalStateException( "ServerContext has not been started yet" );
|
||||||
|
if( instance.server != server )
|
||||||
|
{
|
||||||
|
throw new IllegalStateException( "Incorrect server given. Did ServerContext shutdown correctly?" );
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current {@link GlobalEnvironment} computers should run under.
|
||||||
|
*
|
||||||
|
* @return The current {@link GlobalEnvironment}.
|
||||||
|
*/
|
||||||
|
GlobalEnvironment environment()
|
||||||
|
{
|
||||||
|
return environment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current {@link ServerComputerRegistry}.
|
||||||
|
*
|
||||||
|
* @return The global computer registry.
|
||||||
|
*/
|
||||||
|
public ServerComputerRegistry registry()
|
||||||
|
{
|
||||||
|
return registry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the next available ID for a particular kind (for instance, a computer or particular peripheral type).
|
||||||
|
* <p>
|
||||||
|
* IDs are assigned incrementally, with the last assigned ID being stored in {@code ids.json} in our root
|
||||||
|
* {@linkplain #storageDir() storage folder}.
|
||||||
|
*
|
||||||
|
* @param kind The kind we're assigning an ID for, for instance {@code "computer"} or {@code "peripheral.monitor"}.
|
||||||
|
* @return The next available ID.
|
||||||
|
* @see ComputerCraftAPI#createUniqueNumberedSaveDir(World, String)
|
||||||
|
*/
|
||||||
|
public int getNextId( String kind )
|
||||||
|
{
|
||||||
|
return idAssigner.getNextId( kind );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the directory used for all ComputerCraft related information. This includes the computer/peripheral id store,
|
||||||
|
* and all computer data.
|
||||||
|
*
|
||||||
|
* @return The storge directory for ComputerCraft.
|
||||||
|
*/
|
||||||
|
public Path storageDir()
|
||||||
|
{
|
||||||
|
return storageDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class Environment implements GlobalEnvironment
|
||||||
|
{
|
||||||
|
private final MinecraftServer server;
|
||||||
|
|
||||||
|
Environment( MinecraftServer server )
|
||||||
|
{
|
||||||
|
this.server = server;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IMount createResourceMount( String domain, String subPath )
|
||||||
|
{
|
||||||
|
return ComputerCraftAPI.createResourceMount( domain, subPath );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream createResourceFile( String domain, String subPath )
|
||||||
|
{
|
||||||
|
return ComputerCraftAPIImpl.getResourceFile( server, domain, subPath );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String getHostString()
|
||||||
|
{
|
||||||
|
return String.format( "ComputerCraft %s (Minecraft %s)", ComputerCraftAPI.getInstalledVersion(), MCPVersion.getMCVersion() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String getUserAgent()
|
||||||
|
{
|
||||||
|
return ComputerCraft.MOD_ID + "/" + ComputerCraftAPI.getInstalledVersion();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,7 +9,7 @@ import dan200.computercraft.shared.Registry;
|
|||||||
import dan200.computercraft.shared.computer.blocks.TileCommandComputer;
|
import dan200.computercraft.shared.computer.blocks.TileCommandComputer;
|
||||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||||
import dan200.computercraft.shared.computer.core.ServerComputerRegistry;
|
import dan200.computercraft.shared.computer.core.ServerContext;
|
||||||
import dan200.computercraft.shared.network.container.ComputerContainerData;
|
import dan200.computercraft.shared.network.container.ComputerContainerData;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.entity.player.PlayerInventory;
|
import net.minecraft.entity.player.PlayerInventory;
|
||||||
@ -31,7 +31,7 @@ public class ContainerViewComputer extends ComputerMenuWithoutInventory
|
|||||||
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 this computer no longer exists then discard it.
|
||||||
if( ServerComputerRegistry.INSTANCE.get( computer.getInstanceID() ) != computer )
|
if( ServerContext.get( computer.getWorld().getServer() ).registry().get( computer.getInstanceID() ) != computer )
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ package dan200.computercraft.shared.peripheral.modem.wired;
|
|||||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
import dan200.computercraft.shared.Peripherals;
|
import dan200.computercraft.shared.Peripherals;
|
||||||
import dan200.computercraft.shared.Registry;
|
import dan200.computercraft.shared.Registry;
|
||||||
import dan200.computercraft.shared.util.IDAssigner;
|
import dan200.computercraft.shared.computer.core.ServerContext;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
@ -74,7 +74,7 @@ public final class WiredModemLocalPeripheral
|
|||||||
else if( id < 0 || !type.equals( this.type ) )
|
else if( id < 0 || !type.equals( this.type ) )
|
||||||
{
|
{
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.id = IDAssigner.getNextId( "peripheral." + type );
|
this.id = ServerContext.get( world.getServer() ).getNextId( "peripheral." + type );
|
||||||
}
|
}
|
||||||
|
|
||||||
return oldPeripheral == null || !oldPeripheral.equals( peripheral );
|
return oldPeripheral == null || !oldPeripheral.equals( peripheral );
|
||||||
|
@ -53,7 +53,7 @@ public class PocketComputerMenuProvider implements INamedContainerProvider
|
|||||||
isTypingOnly ? Registry.ModContainers.POCKET_COMPUTER_NO_TERM.get() : Registry.ModContainers.POCKET_COMPUTER.get(), id, inventory,
|
isTypingOnly ? Registry.ModContainers.POCKET_COMPUTER_NO_TERM.get() : Registry.ModContainers.POCKET_COMPUTER.get(), id, inventory,
|
||||||
p -> {
|
p -> {
|
||||||
ItemStack stack = p.getItemInHand( hand );
|
ItemStack stack = p.getItemInHand( hand );
|
||||||
return stack.getItem() == item && ItemPocketComputer.getServerComputer( stack ) == computer;
|
return stack.getItem() == item && ItemPocketComputer.getServerComputer( entity.level.getServer(), stack ) == computer;
|
||||||
},
|
},
|
||||||
computer, item.getFamily()
|
computer, item.getFamily()
|
||||||
);
|
);
|
||||||
|
@ -16,6 +16,7 @@ import dan200.computercraft.shared.PocketUpgrades;
|
|||||||
import dan200.computercraft.shared.common.IColouredItem;
|
import dan200.computercraft.shared.common.IColouredItem;
|
||||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||||
import dan200.computercraft.shared.computer.core.ServerComputerRegistry;
|
import dan200.computercraft.shared.computer.core.ServerComputerRegistry;
|
||||||
|
import dan200.computercraft.shared.computer.core.ServerContext;
|
||||||
import dan200.computercraft.shared.computer.items.IComputerItem;
|
import dan200.computercraft.shared.computer.items.IComputerItem;
|
||||||
import dan200.computercraft.shared.network.container.ComputerContainerData;
|
import dan200.computercraft.shared.network.container.ComputerContainerData;
|
||||||
import dan200.computercraft.shared.pocket.apis.PocketAPI;
|
import dan200.computercraft.shared.pocket.apis.PocketAPI;
|
||||||
@ -31,6 +32,7 @@ import net.minecraft.item.Item;
|
|||||||
import net.minecraft.item.ItemGroup;
|
import net.minecraft.item.ItemGroup;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.util.ActionResult;
|
import net.minecraft.util.ActionResult;
|
||||||
import net.minecraft.util.ActionResultType;
|
import net.minecraft.util.ActionResultType;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.util.Hand;
|
||||||
@ -140,7 +142,7 @@ public class ItemPocketComputer extends Item implements IComputerItem, IMedia, I
|
|||||||
{
|
{
|
||||||
if( entity.level.isClientSide ) return false;
|
if( entity.level.isClientSide ) return false;
|
||||||
|
|
||||||
PocketServerComputer computer = getServerComputer( stack );
|
PocketServerComputer computer = getServerComputer( entity.level.getServer(), stack );
|
||||||
if( computer != null && tick( stack, entity.level, entity, computer ) ) entity.setItem( stack.copy() );
|
if( computer != null && tick( stack, entity.level, entity, computer ) ) entity.setItem( stack.copy() );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -228,7 +230,8 @@ public class ItemPocketComputer extends Item implements IComputerItem, IMedia, I
|
|||||||
|
|
||||||
int sessionID = getSessionID( stack );
|
int sessionID = getSessionID( stack );
|
||||||
|
|
||||||
PocketServerComputer computer = (PocketServerComputer) ServerComputerRegistry.INSTANCE.get( sessionID, getInstanceID( stack ) );
|
ServerComputerRegistry registry = ServerContext.get( world.getServer() ).registry();
|
||||||
|
PocketServerComputer computer = (PocketServerComputer) registry.get( sessionID, getInstanceID( stack ) );
|
||||||
if( computer == null )
|
if( computer == null )
|
||||||
{
|
{
|
||||||
int computerID = getComputerID( stack );
|
int computerID = getComputerID( stack );
|
||||||
@ -241,7 +244,7 @@ public class ItemPocketComputer extends Item implements IComputerItem, IMedia, I
|
|||||||
computer = new PocketServerComputer( world, getComputerID( stack ), getLabel( stack ), getFamily() );
|
computer = new PocketServerComputer( world, getComputerID( stack ), getLabel( stack ), getFamily() );
|
||||||
|
|
||||||
setInstanceID( stack, computer.register() );
|
setInstanceID( stack, computer.register() );
|
||||||
setSessionID( stack, ServerComputerRegistry.INSTANCE.getSessionID() );
|
setSessionID( stack, registry.getSessionID() );
|
||||||
|
|
||||||
computer.updateValues( entity, stack, getUpgrade( stack ) );
|
computer.updateValues( entity, stack, getUpgrade( stack ) );
|
||||||
computer.addAPI( new PocketAPI( computer ) );
|
computer.addAPI( new PocketAPI( computer ) );
|
||||||
@ -256,9 +259,9 @@ public class ItemPocketComputer extends Item implements IComputerItem, IMedia, I
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static PocketServerComputer getServerComputer( @Nonnull ItemStack stack )
|
public static PocketServerComputer getServerComputer( MinecraftServer server, @Nonnull ItemStack stack )
|
||||||
{
|
{
|
||||||
return (PocketServerComputer) ServerComputerRegistry.INSTANCE.get( getSessionID( stack ), getInstanceID( stack ) );
|
return (PocketServerComputer) ServerContext.get( server ).registry().get( getSessionID( stack ), getInstanceID( stack ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// IComputerItem implementation
|
// IComputerItem implementation
|
||||||
|
@ -9,14 +9,11 @@ import com.google.gson.Gson;
|
|||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.ComputerCraft;
|
||||||
import net.minecraft.server.MinecraftServer;
|
|
||||||
import net.minecraft.world.storage.FolderName;
|
|
||||||
import net.minecraftforge.fml.server.ServerLifecycleHooks;
|
|
||||||
|
|
||||||
import java.io.File;
|
import javax.annotation.Nullable;
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
@ -28,61 +25,22 @@ public final class IDAssigner
|
|||||||
{
|
{
|
||||||
public static final String COMPUTER = "computer";
|
public static final String COMPUTER = "computer";
|
||||||
|
|
||||||
private static final FolderName FOLDER = new FolderName( ComputerCraft.MOD_ID );
|
|
||||||
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
|
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
|
||||||
private static final Type ID_TOKEN = new TypeToken<Map<String, Integer>>()
|
private static final Type ID_TOKEN = new TypeToken<Map<String, Integer>>()
|
||||||
{
|
{
|
||||||
}.getType();
|
}.getType();
|
||||||
|
|
||||||
private IDAssigner()
|
private final Path idFile;
|
||||||
|
private @Nullable Map<String, Integer> ids;
|
||||||
|
|
||||||
|
public IDAssigner( Path path )
|
||||||
{
|
{
|
||||||
|
idFile = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Map<String, Integer> ids;
|
public synchronized int getNextId( String kind )
|
||||||
private static WeakReference<MinecraftServer> server;
|
|
||||||
private static Path idFile;
|
|
||||||
|
|
||||||
public static File getDir()
|
|
||||||
{
|
{
|
||||||
return ServerLifecycleHooks.getCurrentServer().getWorldPath( FOLDER ).toFile();
|
if( ids == null ) ids = loadIds();
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean hasServerChanged()
|
|
||||||
{
|
|
||||||
if( server == null ) return true;
|
|
||||||
|
|
||||||
MinecraftServer currentServer = server.get();
|
|
||||||
return currentServer == null || currentServer != ServerLifecycleHooks.getCurrentServer();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static synchronized int getNextId( String kind )
|
|
||||||
{
|
|
||||||
if( hasServerChanged() )
|
|
||||||
{
|
|
||||||
// The server has changed, refetch our ID map
|
|
||||||
server = new WeakReference<>( ServerLifecycleHooks.getCurrentServer() );
|
|
||||||
|
|
||||||
File dir = getDir();
|
|
||||||
dir.mkdirs();
|
|
||||||
|
|
||||||
// Load our ID file from disk
|
|
||||||
Map<String, Integer> newIds = null;
|
|
||||||
idFile = new File( dir, "ids.json" ).toPath();
|
|
||||||
if( Files.isRegularFile( idFile ) )
|
|
||||||
{
|
|
||||||
try( Reader reader = Files.newBufferedReader( idFile, StandardCharsets.UTF_8 ) )
|
|
||||||
{
|
|
||||||
newIds = GSON.fromJson( reader, ID_TOKEN );
|
|
||||||
}
|
|
||||||
catch( Exception e )
|
|
||||||
{
|
|
||||||
ComputerCraft.log.error( "Cannot load id file '" + idFile + "'", e );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( newIds == null ) newIds = new HashMap<>();
|
|
||||||
ids = newIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
Integer existing = ids.get( kind );
|
Integer existing = ids.get( kind );
|
||||||
int next = existing == null ? 0 : existing + 1;
|
int next = existing == null ? 0 : existing + 1;
|
||||||
@ -93,11 +51,39 @@ public final class IDAssigner
|
|||||||
{
|
{
|
||||||
GSON.toJson( ids, writer );
|
GSON.toJson( ids, writer );
|
||||||
}
|
}
|
||||||
catch( Exception e )
|
catch( IOException e )
|
||||||
{
|
{
|
||||||
ComputerCraft.log.error( "Cannot update ID file '" + idFile + "'", e );
|
ComputerCraft.log.error( "Cannot update ID file '{}'", idFile, e );
|
||||||
}
|
}
|
||||||
|
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Map<String, Integer> loadIds()
|
||||||
|
{
|
||||||
|
if( Files.isRegularFile( idFile ) )
|
||||||
|
{
|
||||||
|
try( Reader reader = Files.newBufferedReader( idFile, StandardCharsets.UTF_8 ) )
|
||||||
|
{
|
||||||
|
return GSON.fromJson( reader, ID_TOKEN );
|
||||||
|
}
|
||||||
|
catch( Exception e )
|
||||||
|
{
|
||||||
|
ComputerCraft.log.error( "Cannot load id file '" + idFile + "'", e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Files.createDirectories( idFile.getParent() );
|
||||||
|
}
|
||||||
|
catch( IOException e )
|
||||||
|
{
|
||||||
|
ComputerCraft.log.error( "Cannot create owning directory, IDs will not be persisted", e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new HashMap<>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,8 @@ public class ComputerTestDelegate
|
|||||||
writer.write( "loadfile('test-rom/mcfly.lua', nil, _ENV)('test-rom/spec') cct_test.finish()" );
|
writer.write( "loadfile('test-rom/mcfly.lua', nil, _ENV)('test-rom/spec') cct_test.finish()" );
|
||||||
}
|
}
|
||||||
|
|
||||||
computer = new Computer( new BasicEnvironment( mount ), term, 0 );
|
BasicEnvironment environment = new BasicEnvironment( mount );
|
||||||
|
computer = new Computer( environment, environment, term, 0 );
|
||||||
computer.getEnvironment().setPeripheral( ComputerSide.TOP, new FakeModem() );
|
computer.getEnvironment().setPeripheral( ComputerSide.TOP, new FakeModem() );
|
||||||
computer.addApi( new CctTestAPI() );
|
computer.addApi( new CctTestAPI() );
|
||||||
|
|
||||||
|
@ -6,8 +6,9 @@ import dan200.computercraft.api.lua.MethodResult
|
|||||||
import dan200.computercraft.api.peripheral.IPeripheral
|
import dan200.computercraft.api.peripheral.IPeripheral
|
||||||
import dan200.computercraft.api.peripheral.IWorkMonitor
|
import dan200.computercraft.api.peripheral.IWorkMonitor
|
||||||
import dan200.computercraft.core.computer.BasicEnvironment
|
import dan200.computercraft.core.computer.BasicEnvironment
|
||||||
|
import dan200.computercraft.core.computer.ComputerEnvironment
|
||||||
import dan200.computercraft.core.computer.ComputerSide
|
import dan200.computercraft.core.computer.ComputerSide
|
||||||
import dan200.computercraft.core.computer.IComputerEnvironment
|
import dan200.computercraft.core.computer.GlobalEnvironment
|
||||||
import dan200.computercraft.core.filesystem.FileSystem
|
import dan200.computercraft.core.filesystem.FileSystem
|
||||||
import dan200.computercraft.core.terminal.Terminal
|
import dan200.computercraft.core.terminal.Terminal
|
||||||
import dan200.computercraft.core.tracking.TrackingField
|
import dan200.computercraft.core.tracking.TrackingField
|
||||||
@ -23,7 +24,8 @@ abstract class NullApiEnvironment : IAPIEnvironment {
|
|||||||
private val computerEnv = BasicEnvironment()
|
private val computerEnv = BasicEnvironment()
|
||||||
|
|
||||||
override fun getComputerID(): Int = 0
|
override fun getComputerID(): Int = 0
|
||||||
override fun getComputerEnvironment(): IComputerEnvironment = computerEnv
|
override fun getComputerEnvironment(): ComputerEnvironment = computerEnv
|
||||||
|
override fun getGlobalEnvironment(): GlobalEnvironment = computerEnv
|
||||||
override fun getMainThreadMonitor(): IWorkMonitor = throw IllegalStateException("Work monitor not available")
|
override fun getMainThreadMonitor(): IWorkMonitor = throw IllegalStateException("Work monitor not available")
|
||||||
override fun getTerminal(): Terminal = throw IllegalStateException("Terminal not available")
|
override fun getTerminal(): Terminal = throw IllegalStateException("Terminal not available")
|
||||||
override fun getFileSystem(): FileSystem = throw IllegalStateException("Terminal not available")
|
override fun getFileSystem(): FileSystem = throw IllegalStateException("Terminal not available")
|
||||||
|
@ -24,7 +24,7 @@ import java.net.URL;
|
|||||||
/**
|
/**
|
||||||
* A very basic environment.
|
* A very basic environment.
|
||||||
*/
|
*/
|
||||||
public class BasicEnvironment implements IComputerEnvironment
|
public class BasicEnvironment implements ComputerEnvironment, GlobalEnvironment
|
||||||
{
|
{
|
||||||
private final IWritableMount mount;
|
private final IWritableMount mount;
|
||||||
|
|
||||||
|
@ -46,7 +46,8 @@ public class ComputerBootstrap
|
|||||||
ComputerCraft.maxMainComputerTime = ComputerCraft.maxMainGlobalTime = Integer.MAX_VALUE;
|
ComputerCraft.maxMainComputerTime = ComputerCraft.maxMainGlobalTime = Integer.MAX_VALUE;
|
||||||
|
|
||||||
Terminal term = new Terminal( ComputerCraft.computerTermWidth, ComputerCraft.computerTermHeight, true );
|
Terminal term = new Terminal( ComputerCraft.computerTermWidth, ComputerCraft.computerTermHeight, true );
|
||||||
final Computer computer = new Computer( new BasicEnvironment( mount ), term, 0 );
|
BasicEnvironment environment = new BasicEnvironment( mount );
|
||||||
|
final Computer computer = new Computer( environment, environment, term, 0 );
|
||||||
|
|
||||||
AssertApi api = new AssertApi();
|
AssertApi api = new AssertApi();
|
||||||
computer.addApi( api );
|
computer.addApi( api );
|
||||||
|
@ -55,7 +55,8 @@ public class FakeComputerManager
|
|||||||
@Nonnull
|
@Nonnull
|
||||||
public static Computer create()
|
public static Computer create()
|
||||||
{
|
{
|
||||||
Computer computer = new Computer( new BasicEnvironment(), new Terminal( 51, 19, true ), 0 );
|
BasicEnvironment environment = new BasicEnvironment();
|
||||||
|
Computer computer = new Computer( environment, environment, new Terminal( 51, 19, true ), 0 );
|
||||||
machines.put( computer, new ConcurrentLinkedQueue<>() );
|
machines.put( computer, new ConcurrentLinkedQueue<>() );
|
||||||
return computer;
|
return computer;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user