mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-11-04 23:53:01 +00:00
Merge as much code from CC-Tweaked/mc-1.18.x into CC:R as possible.
Hopefully this will make tracking changes and merging future CC: Tweaked development easier! A lot of this is making whitespace and method ordering even with Tweaked to bring down the diffs, but it also fast forwards us to CC:T 1.99.0 features.
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
image:
|
image:
|
||||||
file: .gitpod.Dockerfile
|
file: config/gitpod/Dockerfile
|
||||||
|
|
||||||
ports:
|
ports:
|
||||||
- port: 25565
|
- port: 25565
|
||||||
@@ -7,12 +7,14 @@ ports:
|
|||||||
|
|
||||||
vscode:
|
vscode:
|
||||||
extensions:
|
extensions:
|
||||||
|
- eamodio.gitlens
|
||||||
|
- github.vscode-pull-request-github
|
||||||
- ms-azuretools.vscode-docker
|
- ms-azuretools.vscode-docker
|
||||||
- redhat.java
|
- redhat.java
|
||||||
- richardwillis.vscode-gradle
|
- richardwillis.vscode-gradle
|
||||||
- vscjava.vscode-java-debug
|
- vscjava.vscode-java-debug
|
||||||
- vscode.github
|
- vscode.github
|
||||||
|
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
- init: ./gradlew
|
- name: Setup pre-commit hool
|
||||||
|
init: pre-commit install --config config/pre-commit/config.yml --allow-missing-config
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ dependencies {
|
|||||||
testImplementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.5.21'
|
testImplementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.5.21'
|
||||||
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.1'
|
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.1'
|
||||||
|
|
||||||
cctJavadoc 'cc.tweaked:cct-javadoc:1.4.1'
|
cctJavadoc 'cc.tweaked:cct-javadoc:1.4.2'
|
||||||
}
|
}
|
||||||
|
|
||||||
processResources {
|
processResources {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
module: [kind=event] redstone
|
module: [kind=event] redstone
|
||||||
---
|
---
|
||||||
|
|
||||||
The @{redstone} event is fired whenever any redstone inputs on the computer change.
|
The @{event!redstone} event is fired whenever any redstone inputs on the computer change.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
Prints a message when a redstone input changes:
|
Prints a message when a redstone input changes:
|
||||||
|
|||||||
@@ -3,12 +3,11 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft;
|
package dan200.computercraft;
|
||||||
|
|
||||||
import dan200.computercraft.core.apis.http.options.Action;
|
import dan200.computercraft.core.apis.http.options.Action;
|
||||||
import dan200.computercraft.core.apis.http.options.AddressRule;
|
import dan200.computercraft.core.apis.http.options.AddressRule;
|
||||||
import dan200.computercraft.shared.ComputerCraftRegistry.ModBlocks;
|
import dan200.computercraft.shared.Registry.ModBlocks;
|
||||||
import dan200.computercraft.shared.common.ColourableRecipe;
|
import dan200.computercraft.shared.common.ColourableRecipe;
|
||||||
import dan200.computercraft.shared.computer.core.ClientComputerRegistry;
|
import dan200.computercraft.shared.computer.core.ClientComputerRegistry;
|
||||||
import dan200.computercraft.shared.computer.core.ServerComputerRegistry;
|
import dan200.computercraft.shared.computer.core.ServerComputerRegistry;
|
||||||
@@ -37,24 +36,20 @@ import net.minecraft.world.item.ItemStack;
|
|||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import static dan200.computercraft.shared.ComputerCraftRegistry.init;
|
import static dan200.computercraft.shared.Registry.init;
|
||||||
|
|
||||||
public final class ComputerCraft implements ModInitializer
|
public final class ComputerCraft implements ModInitializer
|
||||||
{
|
{
|
||||||
public static final String MOD_ID = "computercraft";
|
public static final String MOD_ID = "computercraft";
|
||||||
|
|
||||||
// Configuration fields
|
|
||||||
public static int computerSpaceLimit = 1000 * 1000;
|
public static int computerSpaceLimit = 1000 * 1000;
|
||||||
public static int floppySpaceLimit = 125 * 1000;
|
public static int floppySpaceLimit = 125 * 1000;
|
||||||
public static int maximumFilesOpen = 128;
|
public static int maximumFilesOpen = 128;
|
||||||
public static boolean disableLua51Features = false;
|
public static boolean disableLua51Features = false;
|
||||||
public static String defaultComputerSettings = "";
|
public static String defaultComputerSettings = "";
|
||||||
public static boolean debugEnable = true;
|
|
||||||
public static boolean logComputerErrors = true;
|
public static boolean logComputerErrors = true;
|
||||||
public static boolean commandRequireCreative = true;
|
public static boolean commandRequireCreative = true;
|
||||||
|
|
||||||
@@ -64,10 +59,11 @@ public final class ComputerCraft implements ModInitializer
|
|||||||
|
|
||||||
public static boolean httpEnabled = true;
|
public static boolean httpEnabled = true;
|
||||||
public static boolean httpWebsocketEnabled = true;
|
public static boolean httpWebsocketEnabled = true;
|
||||||
public static List<AddressRule> httpRules = Collections.unmodifiableList( Arrays.asList(
|
public static List<AddressRule> httpRules = List.of(
|
||||||
AddressRule.parse( "$private", null, Action.DENY.toPartial() ),
|
AddressRule.parse( "$private", null, Action.DENY.toPartial() ),
|
||||||
AddressRule.parse( "*", null, Action.ALLOW.toPartial() )
|
AddressRule.parse( "*", null, Action.ALLOW.toPartial() )
|
||||||
) );
|
);
|
||||||
|
|
||||||
public static int httpMaxRequests = 16;
|
public static int httpMaxRequests = 16;
|
||||||
public static int httpMaxWebsockets = 4;
|
public static int httpMaxWebsockets = 4;
|
||||||
public static int httpDownloadBandwidth = 32 * 1024 * 1024;
|
public static int httpDownloadBandwidth = 32 * 1024 * 1024;
|
||||||
@@ -80,7 +76,6 @@ public final class ComputerCraft implements ModInitializer
|
|||||||
public static int modemHighAltitudeRangeDuringStorm = 384;
|
public static int modemHighAltitudeRangeDuringStorm = 384;
|
||||||
public static int maxNotesPerTick = 8;
|
public static int maxNotesPerTick = 8;
|
||||||
public static MonitorRenderer monitorRenderer = MonitorRenderer.BEST;
|
public static MonitorRenderer monitorRenderer = MonitorRenderer.BEST;
|
||||||
public static double monitorDistanceSq = 4096;
|
|
||||||
public static int monitorDistance = 65;
|
public static int monitorDistance = 65;
|
||||||
public static long monitorBandwidth = 1_000_000;
|
public static long monitorBandwidth = 1_000_000;
|
||||||
|
|
||||||
@@ -98,6 +93,7 @@ public final class ComputerCraft implements ModInitializer
|
|||||||
|
|
||||||
public static int pocketTermWidth = 26;
|
public static int pocketTermWidth = 26;
|
||||||
public static int pocketTermHeight = 20;
|
public static int pocketTermHeight = 20;
|
||||||
|
|
||||||
public static int monitorWidth = 8;
|
public static int monitorWidth = 8;
|
||||||
public static int monitorHeight = 6;
|
public static int monitorHeight = 6;
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft;
|
package dan200.computercraft;
|
||||||
|
|
||||||
import dan200.computercraft.api.ComputerCraftAPI.IComputerCraftAPI;
|
import dan200.computercraft.api.ComputerCraftAPI.IComputerCraftAPI;
|
||||||
@@ -35,7 +34,6 @@ import net.fabricmc.loader.api.FabricLoader;
|
|||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.server.MinecraftServer;
|
|
||||||
import net.minecraft.server.packs.resources.ReloadableResourceManager;
|
import net.minecraft.server.packs.resources.ReloadableResourceManager;
|
||||||
import net.minecraft.world.level.BlockGetter;
|
import net.minecraft.world.level.BlockGetter;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
@@ -59,36 +57,24 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
|||||||
|
|
||||||
public static InputStream getResourceFile( String domain, String subPath )
|
public static InputStream getResourceFile( String domain, String subPath )
|
||||||
{
|
{
|
||||||
MinecraftServer server = GameInstanceUtils.getServer();
|
ReloadableResourceManager manager = (ReloadableResourceManager) ((MinecraftServerAccess) GameInstanceUtils.getServer()).callGetResourceManager();
|
||||||
if( server != null )
|
try
|
||||||
{
|
{
|
||||||
ReloadableResourceManager manager = (ReloadableResourceManager) ((MinecraftServerAccess) server).callGetResourceManager();
|
return manager.getResource( new ResourceLocation( domain, subPath ) ).getInputStream();
|
||||||
try
|
}
|
||||||
{
|
catch( IOException ignored )
|
||||||
return manager.getResource( new ResourceLocation( domain, subPath ) )
|
{
|
||||||
.getInputStream();
|
return null;
|
||||||
}
|
|
||||||
catch( IOException ignored )
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public String getInstalledVersion()
|
public String getInstalledVersion()
|
||||||
{
|
{
|
||||||
if( version != null )
|
if( version != null ) return version;
|
||||||
{
|
return version = FabricLoader.getInstance().getModContainer( ComputerCraft.MOD_ID )
|
||||||
return version;
|
.map( x -> x.getMetadata().getVersion().toString() )
|
||||||
}
|
|
||||||
return version = FabricLoader.getInstance()
|
|
||||||
.getModContainer( ComputerCraft.MOD_ID )
|
|
||||||
.map( x -> x.getMetadata()
|
|
||||||
.getVersion()
|
|
||||||
.toString() )
|
|
||||||
.orElse( "unknown" );
|
.orElse( "unknown" );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,14 +100,9 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
|||||||
@Override
|
@Override
|
||||||
public IMount createResourceMount( @Nonnull String domain, @Nonnull String subPath )
|
public IMount createResourceMount( @Nonnull String domain, @Nonnull String subPath )
|
||||||
{
|
{
|
||||||
MinecraftServer server = GameInstanceUtils.getServer();
|
ReloadableResourceManager manager = (ReloadableResourceManager) ((MinecraftServerAccess) GameInstanceUtils.getServer()).callGetResourceManager();
|
||||||
if( server != null )
|
ResourceMount mount = ResourceMount.get( domain, subPath, manager );
|
||||||
{
|
return mount.exists( "" ) ? mount : null;
|
||||||
ReloadableResourceManager manager = (ReloadableResourceManager) ((MinecraftServerAccess) server).callGetResourceManager();
|
|
||||||
ResourceMount mount = ResourceMount.get( domain, subPath, manager );
|
|
||||||
return mount.exists( "" ) ? mount : null;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -130,12 +111,24 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
|||||||
Peripherals.register( provider );
|
Peripherals.register( provider );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerGenericSource( @Nonnull GenericSource source )
|
||||||
|
{
|
||||||
|
GenericMethod.register( source );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerTurtleUpgrade( @Nonnull ITurtleUpgrade upgrade )
|
public void registerTurtleUpgrade( @Nonnull ITurtleUpgrade upgrade )
|
||||||
{
|
{
|
||||||
TurtleUpgrades.register( upgrade );
|
TurtleUpgrades.register( upgrade );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerPocketUpgrade( @Nonnull IPocketUpgrade upgrade )
|
||||||
|
{
|
||||||
|
PocketUpgrades.register( upgrade );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerBundledRedstoneProvider( @Nonnull IBundledRedstoneProvider provider )
|
public void registerBundledRedstoneProvider( @Nonnull IBundledRedstoneProvider provider )
|
||||||
{
|
{
|
||||||
@@ -154,18 +147,6 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
|||||||
MediaProviders.register( provider );
|
MediaProviders.register( provider );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void registerPocketUpgrade( @Nonnull IPocketUpgrade upgrade )
|
|
||||||
{
|
|
||||||
PocketUpgrades.register( upgrade );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void registerGenericSource( @Nonnull GenericSource source )
|
|
||||||
{
|
|
||||||
GenericMethod.register( source );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public IPacketNetwork getWirelessNetwork()
|
public IPacketNetwork getWirelessNetwork()
|
||||||
|
|||||||
@@ -36,19 +36,14 @@ import javax.annotation.Nullable;
|
|||||||
*/
|
*/
|
||||||
public final class ComputerCraftAPI
|
public final class ComputerCraftAPI
|
||||||
{
|
{
|
||||||
|
public static final String MOD_ID = "computercraft";
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public static String getInstalledVersion()
|
public static String getInstalledVersion()
|
||||||
{
|
{
|
||||||
return getInstance().getInstalledVersion();
|
return getInstance().getInstalledVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
@Deprecated
|
|
||||||
public static String getAPIVersion()
|
|
||||||
{
|
|
||||||
return getInstalledVersion();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a numbered directory in a subfolder of the save directory for a given world, and returns that number.
|
* Creates a numbered directory in a subfolder of the save directory for a given world, and returns that number.
|
||||||
*
|
*
|
||||||
@@ -139,9 +134,9 @@ public final class ComputerCraftAPI
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a new turtle turtle for use in ComputerCraft. After calling this,
|
* Registers a new turtle upgrade for use in ComputerCraft. After calling this,
|
||||||
* users should be able to craft Turtles with your new turtle. It is recommended to call
|
* users should be able to craft Turtles with your upgrade's ItemStack. It is
|
||||||
* this during the load() method of your mod.
|
* recommended to call this during the load() method of your mod.
|
||||||
*
|
*
|
||||||
* @param upgrade The turtle upgrade to register.
|
* @param upgrade The turtle upgrade to register.
|
||||||
* @see ITurtleUpgrade
|
* @see ITurtleUpgrade
|
||||||
@@ -151,6 +146,19 @@ public final class ComputerCraftAPI
|
|||||||
getInstance().registerTurtleUpgrade( upgrade );
|
getInstance().registerTurtleUpgrade( upgrade );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a new pocket upgrade for use in ComputerCraft. After calling this,
|
||||||
|
* users should be able to craft pocket computers with your upgrade's ItemStack. It is
|
||||||
|
* recommended to call this during the load() method of your mod.
|
||||||
|
*
|
||||||
|
* @param upgrade The pocket upgrade to register.
|
||||||
|
* @see IPocketUpgrade
|
||||||
|
*/
|
||||||
|
public static void registerPocketUpgrade( @Nonnull IPocketUpgrade upgrade )
|
||||||
|
{
|
||||||
|
getInstance().registerPocketUpgrade( upgrade );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a bundled redstone provider to provide bundled redstone output for blocks.
|
* Registers a bundled redstone provider to provide bundled redstone output for blocks.
|
||||||
*
|
*
|
||||||
@@ -188,11 +196,6 @@ public final class ComputerCraftAPI
|
|||||||
getInstance().registerMediaProvider( provider );
|
getInstance().registerMediaProvider( provider );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void registerPocketUpgrade( @Nonnull IPocketUpgrade upgrade )
|
|
||||||
{
|
|
||||||
getInstance().registerPocketUpgrade( upgrade );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt to get the game-wide wireless network.
|
* Attempt to get the game-wide wireless network.
|
||||||
*
|
*
|
||||||
@@ -273,14 +276,13 @@ public final class ComputerCraftAPI
|
|||||||
|
|
||||||
void registerTurtleUpgrade( @Nonnull ITurtleUpgrade upgrade );
|
void registerTurtleUpgrade( @Nonnull ITurtleUpgrade upgrade );
|
||||||
|
|
||||||
|
void registerPocketUpgrade( @Nonnull IPocketUpgrade upgrade );
|
||||||
|
|
||||||
void registerBundledRedstoneProvider( @Nonnull IBundledRedstoneProvider provider );
|
void registerBundledRedstoneProvider( @Nonnull IBundledRedstoneProvider provider );
|
||||||
|
|
||||||
int getBundledRedstoneOutput( @Nonnull Level world, @Nonnull BlockPos pos, @Nonnull Direction side );
|
int getBundledRedstoneOutput( @Nonnull Level world, @Nonnull BlockPos pos, @Nonnull Direction side );
|
||||||
|
|
||||||
void registerMediaProvider( @Nonnull IMediaProvider provider );
|
void registerMediaProvider( @Nonnull IMediaProvider provider );
|
||||||
|
|
||||||
void registerPocketUpgrade( @Nonnull IPocketUpgrade upgrade );
|
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
IPacketNetwork getWirelessNetwork();
|
IPacketNetwork getWirelessNetwork();
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||||
|
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
||||||
|
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||||
|
*/
|
||||||
|
package dan200.computercraft.api;
|
||||||
|
|
||||||
|
import dan200.computercraft.ComputerCraft;
|
||||||
|
import net.fabricmc.fabric.api.tag.TagFactory;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.tags.Tag;
|
||||||
|
import net.minecraft.world.item.Item;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tags provided by ComputerCraft.
|
||||||
|
*/
|
||||||
|
public class ComputerCraftTags
|
||||||
|
{
|
||||||
|
public static class Items
|
||||||
|
{
|
||||||
|
public static final Tag.Named<Item> COMPUTER = make( "computer" );
|
||||||
|
public static final Tag.Named<Item> TURTLE = make( "turtle" );
|
||||||
|
public static final Tag.Named<Item> WIRED_MODEM = make( "wired_modem" );
|
||||||
|
public static final Tag.Named<Item> MONITOR = make( "monitor" );
|
||||||
|
|
||||||
|
private static Tag.Named<Item> make( String name )
|
||||||
|
{
|
||||||
|
return TagFactory.ITEM.create( new ResourceLocation( ComputerCraft.MOD_ID, name ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Blocks
|
||||||
|
{
|
||||||
|
public static final Tag.Named<Block> COMPUTER = make( "computer" );
|
||||||
|
public static final Tag.Named<Block> TURTLE = make( "turtle" );
|
||||||
|
public static final Tag.Named<Block> WIRED_MODEM = make( "wired_modem" );
|
||||||
|
public static final Tag.Named<Block> MONITOR = make( "monitor" );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blocks which can be broken by any turtle tool.
|
||||||
|
*/
|
||||||
|
public static final Tag.Named<Block> TURTLE_ALWAYS_BREAKABLE = make( "turtle_always_breakable" );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blocks which can be broken by the default shovel tool.
|
||||||
|
*/
|
||||||
|
public static final Tag.Named<Block> TURTLE_SHOVEL_BREAKABLE = make( "turtle_shovel_harvestable" );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blocks which can be broken with the default sword tool.
|
||||||
|
*/
|
||||||
|
public static final Tag.Named<Block> TURTLE_SWORD_BREAKABLE = make( "turtle_sword_harvestable" );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blocks which can be broken with the default hoe tool.
|
||||||
|
*/
|
||||||
|
public static final Tag.Named<Block> TURTLE_HOE_BREAKABLE = make( "turtle_hoe_harvestable" );
|
||||||
|
|
||||||
|
private static Tag.Named<Block> make( String name )
|
||||||
|
{
|
||||||
|
return TagFactory.BLOCK.create( new ResourceLocation( ComputerCraft.MOD_ID, name ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
||||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.api.client;
|
package dan200.computercraft.api.client;
|
||||||
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import dan200.computercraft.api.lua.LuaFunction;
|
|||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The interface that defines a peripheral.
|
* The interface that defines a peripheral.
|
||||||
@@ -30,6 +32,18 @@ public interface IPeripheral
|
|||||||
@Nonnull
|
@Nonnull
|
||||||
String getType();
|
String getType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return additional types/traits associated with this object.
|
||||||
|
*
|
||||||
|
* @return A collection of additional object traits.
|
||||||
|
* @see PeripheralType#getAdditionalTypes()
|
||||||
|
*/
|
||||||
|
@Nonnull
|
||||||
|
default Set<String> getAdditionalTypes()
|
||||||
|
{
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is called when when a computer is attaching to the peripheral.
|
* Is called when when a computer is attaching to the peripheral.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -6,9 +6,13 @@
|
|||||||
package dan200.computercraft.api.peripheral;
|
package dan200.computercraft.api.peripheral;
|
||||||
|
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of a {@link GenericPeripheral}.
|
* The type of a {@link GenericPeripheral}.
|
||||||
@@ -18,13 +22,19 @@ import javax.annotation.Nullable;
|
|||||||
*/
|
*/
|
||||||
public final class PeripheralType
|
public final class PeripheralType
|
||||||
{
|
{
|
||||||
private static final PeripheralType UNTYPED = new PeripheralType( null );
|
private static final PeripheralType UNTYPED = new PeripheralType( null, Collections.emptySet() );
|
||||||
|
|
||||||
private final String type;
|
private final String type;
|
||||||
|
private final Set<String> additionalTypes;
|
||||||
|
|
||||||
public PeripheralType( String type )
|
public PeripheralType( String type, Set<String> additionalTypes )
|
||||||
{
|
{
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
this.additionalTypes = additionalTypes;
|
||||||
|
if( additionalTypes.contains( null ) )
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException( "All additional types must be non-null" );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -46,7 +56,55 @@ public final class PeripheralType
|
|||||||
public static PeripheralType ofType( @Nonnull String type )
|
public static PeripheralType ofType( @Nonnull String type )
|
||||||
{
|
{
|
||||||
if( Strings.isNullOrEmpty( type ) ) throw new IllegalArgumentException( "type cannot be null or empty" );
|
if( Strings.isNullOrEmpty( type ) ) throw new IllegalArgumentException( "type cannot be null or empty" );
|
||||||
return new PeripheralType( type );
|
return new PeripheralType( type, Collections.emptySet() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new non-empty peripheral type with additional traits.
|
||||||
|
*
|
||||||
|
* @param type The name of the type.
|
||||||
|
* @param additionalTypes Additional types, or "traits" of this peripheral. For instance, {@literal "inventory"}.
|
||||||
|
* @return The constructed peripheral type.
|
||||||
|
*/
|
||||||
|
public static PeripheralType ofType( @Nonnull String type, Collection<String> additionalTypes )
|
||||||
|
{
|
||||||
|
if( Strings.isNullOrEmpty( type ) ) throw new IllegalArgumentException( "type cannot be null or empty" );
|
||||||
|
return new PeripheralType( type, ImmutableSet.copyOf( additionalTypes ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new non-empty peripheral type with additional traits.
|
||||||
|
*
|
||||||
|
* @param type The name of the type.
|
||||||
|
* @param additionalTypes Additional types, or "traits" of this peripheral. For instance, {@literal "inventory"}.
|
||||||
|
* @return The constructed peripheral type.
|
||||||
|
*/
|
||||||
|
public static PeripheralType ofType( @Nonnull String type, @Nonnull String... additionalTypes )
|
||||||
|
{
|
||||||
|
if( Strings.isNullOrEmpty( type ) ) throw new IllegalArgumentException( "type cannot be null or empty" );
|
||||||
|
return new PeripheralType( type, ImmutableSet.copyOf( additionalTypes ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new peripheral type with no primary type but additional traits.
|
||||||
|
*
|
||||||
|
* @param additionalTypes Additional types, or "traits" of this peripheral. For instance, {@literal "inventory"}.
|
||||||
|
* @return The constructed peripheral type.
|
||||||
|
*/
|
||||||
|
public static PeripheralType ofAdditional( Collection<String> additionalTypes )
|
||||||
|
{
|
||||||
|
return new PeripheralType( null, ImmutableSet.copyOf( additionalTypes ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new peripheral type with no primary type but additional traits.
|
||||||
|
*
|
||||||
|
* @param additionalTypes Additional types, or "traits" of this peripheral. For instance, {@literal "inventory"}.
|
||||||
|
* @return The constructed peripheral type.
|
||||||
|
*/
|
||||||
|
public static PeripheralType ofAdditional( @Nonnull String... additionalTypes )
|
||||||
|
{
|
||||||
|
return new PeripheralType( null, ImmutableSet.copyOf( additionalTypes ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -59,4 +117,15 @@ public final class PeripheralType
|
|||||||
{
|
{
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get any additional types or "traits" of this peripheral. These effectively act as a standard set of interfaces
|
||||||
|
* a peripheral might have.
|
||||||
|
*
|
||||||
|
* @return All additional types.
|
||||||
|
*/
|
||||||
|
public Set<String> getAdditionalTypes()
|
||||||
|
{
|
||||||
|
return additionalTypes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
package dan200.computercraft.api.pocket;
|
package dan200.computercraft.api.pocket;
|
||||||
|
|
||||||
import dan200.computercraft.api.ComputerCraftAPI;
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
import dan200.computercraft.api.IUpgradeBase;
|
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
||||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
|
|
||||||
|
|||||||
@@ -3,18 +3,13 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
||||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.api.turtle;
|
package dan200.computercraft.api.turtle;
|
||||||
|
|
||||||
import dan200.computercraft.shared.util.NonNullSupplier;
|
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
||||||
import net.minecraft.Util;
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.item.Item;
|
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.level.ItemLike;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A base class for {@link ITurtleUpgrade}s.
|
* A base class for {@link ITurtleUpgrade}s.
|
||||||
@@ -26,9 +21,9 @@ public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade
|
|||||||
private final ResourceLocation id;
|
private final ResourceLocation id;
|
||||||
private final TurtleUpgradeType type;
|
private final TurtleUpgradeType type;
|
||||||
private final String adjective;
|
private final String adjective;
|
||||||
private final NonNullSupplier<ItemStack> stack;
|
private final ItemStack stack;
|
||||||
|
|
||||||
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, String adjective, NonNullSupplier<ItemStack> stack )
|
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, String adjective, ItemStack stack )
|
||||||
{
|
{
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
@@ -36,39 +31,9 @@ public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade
|
|||||||
this.stack = stack;
|
this.stack = stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, NonNullSupplier<ItemStack> stack )
|
|
||||||
{
|
|
||||||
this( id, type, Util.makeDescriptionId( "upgrade", id ) + ".adjective", stack );
|
|
||||||
}
|
|
||||||
|
|
||||||
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, String adjective, ItemStack stack )
|
|
||||||
{
|
|
||||||
this( id, type, adjective, () -> stack );
|
|
||||||
}
|
|
||||||
|
|
||||||
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, ItemStack stack )
|
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, ItemStack stack )
|
||||||
{
|
{
|
||||||
this( id, type, () -> stack );
|
this( id, type, IUpgradeBase.getDefaultAdjective( id ), stack );
|
||||||
}
|
|
||||||
|
|
||||||
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, String adjective, ItemLike item )
|
|
||||||
{
|
|
||||||
this( id, type, adjective, new CachedStack( () -> item ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, ItemLike item )
|
|
||||||
{
|
|
||||||
this( id, type, new CachedStack( () -> item ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, String adjective, Supplier<? extends ItemLike> item )
|
|
||||||
{
|
|
||||||
this( id, type, adjective, new CachedStack( item ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, Supplier<? extends ItemLike> item )
|
|
||||||
{
|
|
||||||
this( id, type, new CachedStack( item ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@@ -96,32 +61,6 @@ public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade
|
|||||||
@Override
|
@Override
|
||||||
public final ItemStack getCraftingItem()
|
public final ItemStack getCraftingItem()
|
||||||
{
|
{
|
||||||
return stack.get();
|
return stack;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A supplier which converts an item into an item stack.
|
|
||||||
*
|
|
||||||
* Constructing item stacks is somewhat expensive due to attaching capabilities. We cache it if given a consistent item.
|
|
||||||
*/
|
|
||||||
private static final class CachedStack implements NonNullSupplier<ItemStack>
|
|
||||||
{
|
|
||||||
private final Supplier<? extends ItemLike> provider;
|
|
||||||
private Item item;
|
|
||||||
private ItemStack stack;
|
|
||||||
|
|
||||||
CachedStack( Supplier<? extends ItemLike> provider )
|
|
||||||
{
|
|
||||||
this.provider = provider;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public ItemStack get()
|
|
||||||
{
|
|
||||||
Item item = provider.get().asItem();
|
|
||||||
if( item == this.item && stack != null ) return stack;
|
|
||||||
return stack = new ItemStack( this.item = item );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
package dan200.computercraft.api.turtle;
|
package dan200.computercraft.api.turtle;
|
||||||
|
|
||||||
import dan200.computercraft.api.ComputerCraftAPI;
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
import dan200.computercraft.api.IUpgradeBase;
|
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
||||||
import dan200.computercraft.api.client.TransformedModel;
|
import dan200.computercraft.api.client.TransformedModel;
|
||||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
import net.fabricmc.api.EnvType;
|
import net.fabricmc.api.EnvType;
|
||||||
|
|||||||
@@ -3,10 +3,11 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
||||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||||
*/
|
*/
|
||||||
package dan200.computercraft.api;
|
package dan200.computercraft.api.upgrades;
|
||||||
|
|
||||||
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
||||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||||
|
import net.minecraft.Util;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
@@ -81,4 +82,18 @@ public interface IUpgradeBase
|
|||||||
if( craftingShareTag == null ) return shareTag.isEmpty();
|
if( craftingShareTag == null ) return shareTag.isEmpty();
|
||||||
return shareTag.equals( craftingShareTag );
|
return shareTag.equals( craftingShareTag );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a suitable default unlocalised adjective for an upgrade ID. This converts "modid:some_upgrade" to
|
||||||
|
* "upgrade.modid.some_upgrade.adjective".
|
||||||
|
*
|
||||||
|
* @param id The upgrade ID.
|
||||||
|
* @return The generated adjective.
|
||||||
|
* @see #getUnlocalisedAdjective()
|
||||||
|
*/
|
||||||
|
@Nonnull
|
||||||
|
static String getDefaultAdjective( @Nonnull ResourceLocation id )
|
||||||
|
{
|
||||||
|
return Util.makeDescriptionId( "upgrade", id ) + ".adjective";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -3,11 +3,10 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.client;
|
package dan200.computercraft.client;
|
||||||
|
|
||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.ComputerCraft;
|
||||||
import dan200.computercraft.shared.ComputerCraftRegistry;
|
import dan200.computercraft.shared.Registry;
|
||||||
import dan200.computercraft.shared.common.IColouredItem;
|
import dan200.computercraft.shared.common.IColouredItem;
|
||||||
import dan200.computercraft.shared.media.items.ItemDisk;
|
import dan200.computercraft.shared.media.items.ItemDisk;
|
||||||
import dan200.computercraft.shared.media.items.ItemTreasureDisk;
|
import dan200.computercraft.shared.media.items.ItemTreasureDisk;
|
||||||
@@ -34,6 +33,7 @@ import java.util.function.Consumer;
|
|||||||
public final class ClientRegistry
|
public final class ClientRegistry
|
||||||
{
|
{
|
||||||
private static final String[] EXTRA_MODELS = new String[] {
|
private static final String[] EXTRA_MODELS = new String[] {
|
||||||
|
// Turtle upgrades
|
||||||
"turtle_modem_normal_off_left",
|
"turtle_modem_normal_off_left",
|
||||||
"turtle_modem_normal_on_left",
|
"turtle_modem_normal_on_left",
|
||||||
"turtle_modem_normal_off_right",
|
"turtle_modem_normal_off_right",
|
||||||
@@ -49,6 +49,7 @@ public final class ClientRegistry
|
|||||||
"turtle_speaker_upgrade_left",
|
"turtle_speaker_upgrade_left",
|
||||||
"turtle_speaker_upgrade_right",
|
"turtle_speaker_upgrade_right",
|
||||||
|
|
||||||
|
// Turtle block renderer
|
||||||
"turtle_colour",
|
"turtle_colour",
|
||||||
"turtle_elf_overlay",
|
"turtle_elf_overlay",
|
||||||
};
|
};
|
||||||
@@ -85,10 +86,10 @@ public final class ClientRegistry
|
|||||||
{
|
{
|
||||||
ColorProviderRegistry.ITEM.register( ( stack, layer ) -> {
|
ColorProviderRegistry.ITEM.register( ( stack, layer ) -> {
|
||||||
return layer == 1 ? ((ItemDisk) stack.getItem()).getColour( stack ) : 0xFFFFFF;
|
return layer == 1 ? ((ItemDisk) stack.getItem()).getColour( stack ) : 0xFFFFFF;
|
||||||
}, ComputerCraftRegistry.ModItems.DISK );
|
}, Registry.ModItems.DISK );
|
||||||
|
|
||||||
ColorProviderRegistry.ITEM.register( ( stack, layer ) -> layer == 1 ? ItemTreasureDisk.getColour( stack ) : 0xFFFFFF,
|
ColorProviderRegistry.ITEM.register( ( stack, layer ) -> layer == 1 ? ItemTreasureDisk.getColour( stack ) : 0xFFFFFF,
|
||||||
ComputerCraftRegistry.ModItems.TREASURE_DISK );
|
Registry.ModItems.TREASURE_DISK );
|
||||||
|
|
||||||
ColorProviderRegistry.ITEM.register( ( stack, layer ) -> {
|
ColorProviderRegistry.ITEM.register( ( stack, layer ) -> {
|
||||||
switch( layer )
|
switch( layer )
|
||||||
@@ -102,12 +103,12 @@ public final class ClientRegistry
|
|||||||
int light = ItemPocketComputer.getLightState( stack );
|
int light = ItemPocketComputer.getLightState( stack );
|
||||||
return light == -1 ? Colour.BLACK.getHex() : light;
|
return light == -1 ? Colour.BLACK.getHex() : light;
|
||||||
}
|
}
|
||||||
}, ComputerCraftRegistry.ModItems.POCKET_COMPUTER_NORMAL, ComputerCraftRegistry.ModItems.POCKET_COMPUTER_ADVANCED );
|
}, Registry.ModItems.POCKET_COMPUTER_NORMAL, Registry.ModItems.POCKET_COMPUTER_ADVANCED );
|
||||||
|
|
||||||
// Setup turtle colours
|
// Setup turtle colours
|
||||||
ColorProviderRegistry.ITEM.register( ( stack, tintIndex ) -> tintIndex == 0 ? ((IColouredItem) stack.getItem()).getColour( stack ) : 0xFFFFFF,
|
ColorProviderRegistry.ITEM.register( ( stack, tintIndex ) -> tintIndex == 0 ? ((IColouredItem) stack.getItem()).getColour( stack ) : 0xFFFFFF,
|
||||||
ComputerCraftRegistry.ModBlocks.TURTLE_NORMAL,
|
Registry.ModBlocks.TURTLE_NORMAL,
|
||||||
ComputerCraftRegistry.ModBlocks.TURTLE_ADVANCED );
|
Registry.ModBlocks.TURTLE_ADVANCED );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static BakedModel bake( ModelBakery loader, UnbakedModel model, ResourceLocation identifier )
|
private static BakedModel bake( ModelBakery loader, UnbakedModel model, ResourceLocation identifier )
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.client;
|
package dan200.computercraft.client;
|
||||||
|
|
||||||
import dan200.computercraft.fabric.mixin.ChatComponentAccess;
|
import dan200.computercraft.fabric.mixin.ChatComponentAccess;
|
||||||
@@ -25,17 +24,19 @@ public class ClientTableFormatter implements TableFormatter
|
|||||||
{
|
{
|
||||||
public static final ClientTableFormatter INSTANCE = new ClientTableFormatter();
|
public static final ClientTableFormatter INSTANCE = new ClientTableFormatter();
|
||||||
|
|
||||||
private static Int2IntOpenHashMap lastHeights = new Int2IntOpenHashMap();
|
private static final Int2IntOpenHashMap lastHeights = new Int2IntOpenHashMap();
|
||||||
|
|
||||||
|
private static Font renderer()
|
||||||
|
{
|
||||||
|
return Minecraft.getInstance().font;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public Component getPadding( Component component, int width )
|
public Component getPadding( Component component, int width )
|
||||||
{
|
{
|
||||||
int extraWidth = width - getWidth( component );
|
int extraWidth = width - getWidth( component );
|
||||||
if( extraWidth <= 0 )
|
if( extraWidth <= 0 ) return null;
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Font renderer = renderer();
|
Font renderer = renderer();
|
||||||
|
|
||||||
@@ -46,11 +47,6 @@ public class ClientTableFormatter implements TableFormatter
|
|||||||
return ChatHelpers.coloured( StringUtils.repeat( ' ', spaces ) + StringUtils.repeat( (char) 712, extra ), ChatFormatting.GRAY );
|
return ChatHelpers.coloured( StringUtils.repeat( ' ', spaces ) + StringUtils.repeat( (char) 712, extra ), ChatFormatting.GRAY );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Font renderer()
|
|
||||||
{
|
|
||||||
return Minecraft.getInstance().font;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getColumnPadding()
|
public int getColumnPadding()
|
||||||
{
|
{
|
||||||
@@ -71,7 +67,7 @@ public class ClientTableFormatter implements TableFormatter
|
|||||||
|
|
||||||
// TODO: Trim the text if it goes over the allowed length
|
// TODO: Trim the text if it goes over the allowed length
|
||||||
// int maxWidth = MathHelper.floor( chat.getChatWidth() / chat.getScale() );
|
// int maxWidth = MathHelper.floor( chat.getChatWidth() / chat.getScale() );
|
||||||
// List<ITextProperties> list = RenderComponentsUtil.func_238505_a_( component, maxWidth, mc.fontRenderer );
|
// List<ITextProperties> list = RenderComponentsUtil.wrapComponents( component, maxWidth, mc.fontRenderer );
|
||||||
// if( !list.isEmpty() ) chat.printChatMessageWithOptionalDeletion( list.get( 0 ), id );
|
// if( !list.isEmpty() ) chat.printChatMessageWithOptionalDeletion( list.get( 0 ), id );
|
||||||
((ChatComponentAccess) chat).callAddMessage( component, id );
|
((ChatComponentAccess) chat).callAddMessage( component, id );
|
||||||
}
|
}
|
||||||
@@ -86,10 +82,7 @@ public class ClientTableFormatter implements TableFormatter
|
|||||||
int height = TableFormatter.super.display( table );
|
int height = TableFormatter.super.display( table );
|
||||||
lastHeights.put( table.getId(), height );
|
lastHeights.put( table.getId(), height );
|
||||||
|
|
||||||
for( int i = height; i < lastHeight; i++ )
|
for( int i = height; i < lastHeight; i++ ) ((ChatComponentAccess) chat).callRemoveById( i + table.getId() );
|
||||||
{
|
|
||||||
((ChatComponentAccess) chat).callRemoveById( i + table.getId() );
|
|
||||||
}
|
|
||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.client;
|
package dan200.computercraft.client;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ import java.util.List;
|
|||||||
|
|
||||||
public abstract class ComputerScreenBase<T extends ContainerComputerBase> extends AbstractContainerScreen<T>
|
public abstract class ComputerScreenBase<T extends ContainerComputerBase> extends AbstractContainerScreen<T>
|
||||||
{
|
{
|
||||||
|
|
||||||
private static final Component OK = new TranslatableComponent( "gui.ok" );
|
private static final Component OK = new TranslatableComponent( "gui.ok" );
|
||||||
private static final Component CANCEL = new TranslatableComponent( "gui.cancel" );
|
private static final Component CANCEL = new TranslatableComponent( "gui.cancel" );
|
||||||
private static final Component OVERWRITE = new TranslatableComponent( "gui.computercraft.upload.overwrite_button" );
|
private static final Component OVERWRITE = new TranslatableComponent( "gui.computercraft.upload.overwrite_button" );
|
||||||
@@ -94,6 +93,7 @@ public abstract class ComputerScreenBase<T extends ContainerComputerBase> extend
|
|||||||
return super.keyPressed( key, scancode, modifiers );
|
return super.keyPressed( key, scancode, modifiers );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void render( @Nonnull PoseStack stack, int mouseX, int mouseY, float partialTicks )
|
public final void render( @Nonnull PoseStack stack, int mouseX, int mouseY, float partialTicks )
|
||||||
{
|
{
|
||||||
@@ -105,9 +105,11 @@ public abstract class ComputerScreenBase<T extends ContainerComputerBase> extend
|
|||||||
@Override
|
@Override
|
||||||
public final boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY )
|
public final boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY )
|
||||||
{
|
{
|
||||||
return getFocused() != null && getFocused().mouseDragged( x, y, button, deltaX, deltaY ) || super.mouseDragged( x, y, button, deltaX, deltaY );
|
return (getFocused() != null && getFocused().mouseDragged( x, y, button, deltaX, deltaY ))
|
||||||
|
|| super.mouseDragged( x, y, button, deltaX, deltaY );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void renderLabels( @Nonnull PoseStack transform, int mouseX, int mouseY )
|
protected void renderLabels( @Nonnull PoseStack transform, int mouseX, int mouseY )
|
||||||
{
|
{
|
||||||
@@ -207,7 +209,7 @@ public abstract class ComputerScreenBase<T extends ContainerComputerBase> extend
|
|||||||
|
|
||||||
private void continueUpload()
|
private void continueUpload()
|
||||||
{
|
{
|
||||||
if( minecraft.screen instanceof OptionScreen ) ((OptionScreen) minecraft.screen).disable();
|
if( minecraft.screen instanceof OptionScreen screen ) screen.disable();
|
||||||
NetworkHandler.sendToServer( new ContinueUploadMessage( computer.getInstanceID(), true ) );
|
NetworkHandler.sendToServer( new ContinueUploadMessage( computer.getInstanceID(), true ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,5 +226,4 @@ public abstract class ComputerScreenBase<T extends ContainerComputerBase> extend
|
|||||||
() -> minecraft.setScreen( this )
|
() -> minecraft.setScreen( this )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,19 +3,17 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.client.gui;
|
package dan200.computercraft.client.gui;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.vertex.Tesselator;
|
||||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||||
import com.mojang.math.Matrix4f;
|
import com.mojang.math.Matrix4f;
|
||||||
import com.mojang.math.Transformation;
|
|
||||||
import dan200.computercraft.client.FrameInfo;
|
import dan200.computercraft.client.FrameInfo;
|
||||||
import dan200.computercraft.client.render.RenderTypes;
|
import dan200.computercraft.client.render.RenderTypes;
|
||||||
import dan200.computercraft.core.terminal.Terminal;
|
import dan200.computercraft.core.terminal.Terminal;
|
||||||
import dan200.computercraft.core.terminal.TextBuffer;
|
import dan200.computercraft.core.terminal.TextBuffer;
|
||||||
import dan200.computercraft.shared.util.Colour;
|
import dan200.computercraft.shared.util.Colour;
|
||||||
import dan200.computercraft.shared.util.Palette;
|
import dan200.computercraft.shared.util.Palette;
|
||||||
import net.minecraft.client.Minecraft;
|
|
||||||
import net.minecraft.client.renderer.MultiBufferSource;
|
import net.minecraft.client.renderer.MultiBufferSource;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
@@ -24,25 +22,138 @@ import javax.annotation.Nullable;
|
|||||||
|
|
||||||
import static dan200.computercraft.client.render.RenderTypes.FULL_BRIGHT_LIGHTMAP;
|
import static dan200.computercraft.client.render.RenderTypes.FULL_BRIGHT_LIGHTMAP;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles rendering fixed width text and computer terminals.
|
||||||
|
*
|
||||||
|
* This class has several modes of usage:
|
||||||
|
* <ul>
|
||||||
|
* <li>{@link #drawString}: Drawing basic text without a terminal (such as for printouts). Unlike the other methods,
|
||||||
|
* this accepts a lightmap coordinate as, unlike terminals, printed pages render fullbright.</li>
|
||||||
|
* <li>{@link #drawTerminalWithoutCursor}/{@link #drawCursor}: Draw a terminal without a cursor and then draw the cursor
|
||||||
|
* separately. This is used by the monitor renderer to render the terminal to a VBO and draw the cursor dynamically.
|
||||||
|
* </li>
|
||||||
|
* <li>{@link #drawTerminal}: Draw a terminal with a cursor. This is used by the various computer GUIs to render the
|
||||||
|
* whole term.</li>
|
||||||
|
* <li>{@link #drawBlocker}: When rendering a terminal using {@link RenderTypes#TERMINAL_WITHOUT_DEPTH} you need to
|
||||||
|
* render an additional "depth blocker" on top of the monitor.</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
public final class FixedWidthFontRenderer
|
public final class FixedWidthFontRenderer
|
||||||
{
|
{
|
||||||
|
public static final ResourceLocation FONT = new ResourceLocation( "computercraft", "textures/gui/term_font.png" );
|
||||||
|
|
||||||
public static final int FONT_HEIGHT = 9;
|
public static final int FONT_HEIGHT = 9;
|
||||||
public static final int FONT_WIDTH = 6;
|
public static final int FONT_WIDTH = 6;
|
||||||
public static final float WIDTH = 256.0f;
|
public static final float WIDTH = 256.0f;
|
||||||
|
|
||||||
public static final float BACKGROUND_START = (WIDTH - 6.0f) / WIDTH;
|
public static final float BACKGROUND_START = (WIDTH - 6.0f) / WIDTH;
|
||||||
public static final float BACKGROUND_END = (WIDTH - 4.0f) / WIDTH;
|
public static final float BACKGROUND_END = (WIDTH - 4.0f) / WIDTH;
|
||||||
private static final Matrix4f IDENTITY = Transformation.identity()
|
|
||||||
.getMatrix();
|
|
||||||
public static final ResourceLocation FONT = new ResourceLocation( "computercraft", "textures/gui/term_font.png" );
|
|
||||||
|
|
||||||
|
|
||||||
private FixedWidthFontRenderer()
|
private FixedWidthFontRenderer()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void drawString( @Nonnull Matrix4f transform, @Nonnull VertexConsumer renderer, float x, float y, @Nonnull TextBuffer text,
|
public static float toGreyscale( double[] rgb )
|
||||||
@Nonnull TextBuffer textColour, @Nullable TextBuffer backgroundColour, @Nonnull Palette palette, boolean greyscale,
|
{
|
||||||
float leftMarginSize, float rightMarginSize, int light )
|
return (float) ((rgb[0] + rgb[1] + rgb[2]) / 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getColour( char c, Colour def )
|
||||||
|
{
|
||||||
|
return 15 - Terminal.getColour( c, def );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void drawChar( Matrix4f transform, VertexConsumer buffer, float x, float y, int index, float r, float g, float b, int light )
|
||||||
|
{
|
||||||
|
// Short circuit to avoid the common case - the texture should be blank here after all.
|
||||||
|
if( index == '\0' || index == ' ' ) return;
|
||||||
|
|
||||||
|
int column = index % 16;
|
||||||
|
int row = index / 16;
|
||||||
|
|
||||||
|
int xStart = 1 + column * (FONT_WIDTH + 2);
|
||||||
|
int yStart = 1 + row * (FONT_HEIGHT + 2);
|
||||||
|
|
||||||
|
buffer.vertex( transform, x, y, 0f ).color( r, g, b, 1.0f ).uv( xStart / WIDTH, yStart / WIDTH ).uv2( light ).endVertex();
|
||||||
|
buffer.vertex( transform, x, y + FONT_HEIGHT, 0f ).color( r, g, b, 1.0f ).uv( xStart / WIDTH, (yStart + FONT_HEIGHT) / WIDTH ).uv2( light ).endVertex();
|
||||||
|
buffer.vertex( transform, x + FONT_WIDTH, y, 0f ).color( r, g, b, 1.0f ).uv( (xStart + FONT_WIDTH) / WIDTH, yStart / WIDTH ).uv2( light ).endVertex();
|
||||||
|
buffer.vertex( transform, x + FONT_WIDTH, y, 0f ).color( r, g, b, 1.0f ).uv( (xStart + FONT_WIDTH) / WIDTH, yStart / WIDTH ).uv2( light ).endVertex();
|
||||||
|
buffer.vertex( transform, x, y + FONT_HEIGHT, 0f ).color( r, g, b, 1.0f ).uv( xStart / WIDTH, (yStart + FONT_HEIGHT) / WIDTH ).uv2( light ).endVertex();
|
||||||
|
buffer.vertex( transform, x + FONT_WIDTH, y + FONT_HEIGHT, 0f ).color( r, g, b, 1.0f ).uv( (xStart + FONT_WIDTH) / WIDTH, (yStart + FONT_HEIGHT) / WIDTH ).uv2( light ).endVertex();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void drawQuad( Matrix4f transform, VertexConsumer buffer, float x, float y, float width, float height, float r, float g, float b )
|
||||||
|
{
|
||||||
|
buffer.vertex( transform, x, y, 0 ).color( r, g, b, 1.0f ).uv( BACKGROUND_START, BACKGROUND_START ).endVertex();
|
||||||
|
buffer.vertex( transform, x, y + height, 0 ).color( r, g, b, 1.0f ).uv( BACKGROUND_START, BACKGROUND_END ).endVertex();
|
||||||
|
buffer.vertex( transform, x + width, y, 0 ).color( r, g, b, 1.0f ).uv( BACKGROUND_END, BACKGROUND_START ).endVertex();
|
||||||
|
buffer.vertex( transform, x + width, y, 0 ).color( r, g, b, 1.0f ).uv( BACKGROUND_END, BACKGROUND_START ).endVertex();
|
||||||
|
buffer.vertex( transform, x, y + height, 0 ).color( r, g, b, 1.0f ).uv( BACKGROUND_START, BACKGROUND_END ).endVertex();
|
||||||
|
buffer.vertex( transform, x + width, y + height, 0 ).color( r, g, b, 1.0f ).uv( BACKGROUND_END, BACKGROUND_END ).endVertex();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void drawQuad( Matrix4f transform, VertexConsumer buffer, float x, float y, float width, float height, Palette palette, boolean greyscale, char colourIndex )
|
||||||
|
{
|
||||||
|
double[] colour = palette.getColour( getColour( colourIndex, Colour.BLACK ) );
|
||||||
|
float r, g, b;
|
||||||
|
if( greyscale )
|
||||||
|
{
|
||||||
|
r = g = b = toGreyscale( colour );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
r = (float) colour[0];
|
||||||
|
g = (float) colour[1];
|
||||||
|
b = (float) colour[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
drawQuad( transform, buffer, x, y, width, height, r, g, b );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void drawBackground(
|
||||||
|
@Nonnull Matrix4f transform, @Nonnull VertexConsumer renderer, float x, float y,
|
||||||
|
@Nonnull TextBuffer backgroundColour, @Nonnull Palette palette, boolean greyscale,
|
||||||
|
float leftMarginSize, float rightMarginSize, float height
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if( leftMarginSize > 0 )
|
||||||
|
{
|
||||||
|
drawQuad( transform, renderer, x - leftMarginSize, y, leftMarginSize, height, palette, greyscale, backgroundColour.charAt( 0 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( rightMarginSize > 0 )
|
||||||
|
{
|
||||||
|
drawQuad( transform, renderer, x + backgroundColour.length() * FONT_WIDTH, y, rightMarginSize, height, palette, greyscale, backgroundColour.charAt( backgroundColour.length() - 1 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Batch together runs of identical background cells.
|
||||||
|
int blockStart = 0;
|
||||||
|
char blockColour = '\0';
|
||||||
|
for( int i = 0; i < backgroundColour.length(); i++ )
|
||||||
|
{
|
||||||
|
char colourIndex = backgroundColour.charAt( i );
|
||||||
|
if( colourIndex == blockColour ) continue;
|
||||||
|
|
||||||
|
if( blockColour != '\0' )
|
||||||
|
{
|
||||||
|
drawQuad( transform, renderer, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (i - blockStart), height, palette, greyscale, blockColour );
|
||||||
|
}
|
||||||
|
|
||||||
|
blockColour = colourIndex;
|
||||||
|
blockStart = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( blockColour != '\0' )
|
||||||
|
{
|
||||||
|
drawQuad( transform, renderer, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (backgroundColour.length() - blockStart), height, palette, greyscale, blockColour );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void drawString(
|
||||||
|
@Nonnull Matrix4f transform, @Nonnull VertexConsumer renderer, float x, float y,
|
||||||
|
@Nonnull TextBuffer text, @Nonnull TextBuffer textColour, @Nullable TextBuffer backgroundColour,
|
||||||
|
@Nonnull Palette palette, boolean greyscale, float leftMarginSize, float rightMarginSize, int light
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if( backgroundColour != null )
|
if( backgroundColour != null )
|
||||||
{
|
{
|
||||||
@@ -66,223 +177,49 @@ public final class FixedWidthFontRenderer
|
|||||||
|
|
||||||
// Draw char
|
// Draw char
|
||||||
int index = text.charAt( i );
|
int index = text.charAt( i );
|
||||||
if( index > 255 )
|
if( index > 255 ) index = '?';
|
||||||
{
|
|
||||||
index = '?';
|
|
||||||
}
|
|
||||||
drawChar( transform, renderer, x + i * FONT_WIDTH, y, index, r, g, b, light );
|
drawChar( transform, renderer, x + i * FONT_WIDTH, y, index, r, g, b, light );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void drawBackground( @Nonnull Matrix4f transform, @Nonnull VertexConsumer renderer, float x, float y,
|
public static void drawTerminalWithoutCursor(
|
||||||
@Nonnull TextBuffer backgroundColour, @Nonnull Palette palette, boolean greyscale, float leftMarginSize,
|
@Nonnull Matrix4f transform, @Nonnull VertexConsumer buffer, float x, float y,
|
||||||
float rightMarginSize, float height )
|
@Nonnull Terminal terminal, boolean greyscale,
|
||||||
{
|
float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize
|
||||||
if( leftMarginSize > 0 )
|
)
|
||||||
{
|
|
||||||
drawQuad( transform, renderer, x - leftMarginSize, y, leftMarginSize, height, palette, greyscale, backgroundColour.charAt( 0 ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( rightMarginSize > 0 )
|
|
||||||
{
|
|
||||||
drawQuad( transform,
|
|
||||||
renderer,
|
|
||||||
x + backgroundColour.length() * FONT_WIDTH,
|
|
||||||
y,
|
|
||||||
rightMarginSize,
|
|
||||||
height,
|
|
||||||
palette,
|
|
||||||
greyscale,
|
|
||||||
backgroundColour.charAt( backgroundColour.length() - 1 ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Batch together runs of identical background cells.
|
|
||||||
int blockStart = 0;
|
|
||||||
char blockColour = '\0';
|
|
||||||
for( int i = 0; i < backgroundColour.length(); i++ )
|
|
||||||
{
|
|
||||||
char colourIndex = backgroundColour.charAt( i );
|
|
||||||
if( colourIndex == blockColour )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( blockColour != '\0' )
|
|
||||||
{
|
|
||||||
drawQuad( transform, renderer, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (i - blockStart), height, palette, greyscale, blockColour );
|
|
||||||
}
|
|
||||||
|
|
||||||
blockColour = colourIndex;
|
|
||||||
blockStart = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( blockColour != '\0' )
|
|
||||||
{
|
|
||||||
drawQuad( transform,
|
|
||||||
renderer,
|
|
||||||
x + blockStart * FONT_WIDTH,
|
|
||||||
y,
|
|
||||||
FONT_WIDTH * (backgroundColour.length() - blockStart),
|
|
||||||
height,
|
|
||||||
palette,
|
|
||||||
greyscale,
|
|
||||||
blockColour );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getColour( char c, Colour def )
|
|
||||||
{
|
|
||||||
return 15 - Terminal.getColour( c, def );
|
|
||||||
}
|
|
||||||
|
|
||||||
public static float toGreyscale( double[] rgb )
|
|
||||||
{
|
|
||||||
return (float) ((rgb[0] + rgb[1] + rgb[2]) / 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void drawChar( Matrix4f transform, VertexConsumer buffer, float x, float y, int index, float r, float g, float b, int light )
|
|
||||||
{
|
|
||||||
// Short circuit to avoid the common case - the texture should be blank here after all.
|
|
||||||
if( index == '\0' || index == ' ' )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int column = index % 16;
|
|
||||||
int row = index / 16;
|
|
||||||
|
|
||||||
int xStart = 1 + column * (FONT_WIDTH + 2);
|
|
||||||
int yStart = 1 + row * (FONT_HEIGHT + 2);
|
|
||||||
|
|
||||||
buffer.vertex( transform, x, y, 0f )
|
|
||||||
.color( r, g, b, 1.0f )
|
|
||||||
.uv( xStart / WIDTH, yStart / WIDTH )
|
|
||||||
.uv2( light )
|
|
||||||
.endVertex();
|
|
||||||
buffer.vertex( transform, x, y + FONT_HEIGHT, 0f )
|
|
||||||
.color( r, g, b, 1.0f )
|
|
||||||
.uv( xStart / WIDTH, (yStart + FONT_HEIGHT) / WIDTH )
|
|
||||||
.uv2( light )
|
|
||||||
.endVertex();
|
|
||||||
buffer.vertex( transform, x + FONT_WIDTH, y, 0f )
|
|
||||||
.color( r, g, b, 1.0f )
|
|
||||||
.uv( (xStart + FONT_WIDTH) / WIDTH, yStart / WIDTH )
|
|
||||||
.uv2( light )
|
|
||||||
.endVertex();
|
|
||||||
buffer.vertex( transform, x + FONT_WIDTH, y, 0f )
|
|
||||||
.color( r, g, b, 1.0f )
|
|
||||||
.uv( (xStart + FONT_WIDTH) / WIDTH, yStart / WIDTH )
|
|
||||||
.uv2( light )
|
|
||||||
.endVertex();
|
|
||||||
buffer.vertex( transform, x, y + FONT_HEIGHT, 0f )
|
|
||||||
.color( r, g, b, 1.0f )
|
|
||||||
.uv( xStart / WIDTH, (yStart + FONT_HEIGHT) / WIDTH )
|
|
||||||
.uv2( light )
|
|
||||||
.endVertex();
|
|
||||||
buffer.vertex( transform, x + FONT_WIDTH, y + FONT_HEIGHT, 0f )
|
|
||||||
.color( r, g, b, 1.0f )
|
|
||||||
.uv( (xStart + FONT_WIDTH) / WIDTH, (yStart + FONT_HEIGHT) / WIDTH )
|
|
||||||
.uv2( light )
|
|
||||||
.endVertex();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void drawQuad( Matrix4f transform, VertexConsumer buffer, float x, float y, float width, float height, Palette palette,
|
|
||||||
boolean greyscale, char colourIndex )
|
|
||||||
{
|
|
||||||
double[] colour = palette.getColour( getColour( colourIndex, Colour.BLACK ) );
|
|
||||||
float r, g, b;
|
|
||||||
if( greyscale )
|
|
||||||
{
|
|
||||||
r = g = b = toGreyscale( colour );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
r = (float) colour[0];
|
|
||||||
g = (float) colour[1];
|
|
||||||
b = (float) colour[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
drawQuad( transform, buffer, x, y, width, height, r, g, b );
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void drawQuad( Matrix4f transform, VertexConsumer buffer, float x, float y, float width, float height, float r, float g, float b )
|
|
||||||
{
|
|
||||||
buffer.vertex( transform, x, y, 0 )
|
|
||||||
.color( r, g, b, 1.0f )
|
|
||||||
.uv( BACKGROUND_START, BACKGROUND_START )
|
|
||||||
.endVertex();
|
|
||||||
buffer.vertex( transform, x, y + height, 0 )
|
|
||||||
.color( r, g, b, 1.0f )
|
|
||||||
.uv( BACKGROUND_START, BACKGROUND_END )
|
|
||||||
.endVertex();
|
|
||||||
buffer.vertex( transform, x + width, y, 0 )
|
|
||||||
.color( r, g, b, 1.0f )
|
|
||||||
.uv( BACKGROUND_END, BACKGROUND_START )
|
|
||||||
.endVertex();
|
|
||||||
buffer.vertex( transform, x + width, y, 0 )
|
|
||||||
.color( r, g, b, 1.0f )
|
|
||||||
.uv( BACKGROUND_END, BACKGROUND_START )
|
|
||||||
.endVertex();
|
|
||||||
buffer.vertex( transform, x, y + height, 0 )
|
|
||||||
.color( r, g, b, 1.0f )
|
|
||||||
.uv( BACKGROUND_START, BACKGROUND_END )
|
|
||||||
.endVertex();
|
|
||||||
buffer.vertex( transform, x + width, y + height, 0 )
|
|
||||||
.color( r, g, b, 1.0f )
|
|
||||||
.uv( BACKGROUND_END, BACKGROUND_END )
|
|
||||||
.endVertex();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void drawTerminalWithoutCursor( @Nonnull Matrix4f transform, @Nonnull VertexConsumer buffer, float x, float y,
|
|
||||||
@Nonnull Terminal terminal, boolean greyscale, float topMarginSize, float bottomMarginSize,
|
|
||||||
float leftMarginSize, float rightMarginSize )
|
|
||||||
{
|
{
|
||||||
Palette palette = terminal.getPalette();
|
Palette palette = terminal.getPalette();
|
||||||
int height = terminal.getHeight();
|
int height = terminal.getHeight();
|
||||||
|
|
||||||
// Top and bottom margins
|
// Top and bottom margins
|
||||||
drawBackground( transform,
|
drawBackground(
|
||||||
buffer,
|
transform, buffer, x, y - topMarginSize,
|
||||||
x,
|
terminal.getBackgroundColourLine( 0 ), palette, greyscale,
|
||||||
y - topMarginSize,
|
leftMarginSize, rightMarginSize, topMarginSize
|
||||||
terminal.getBackgroundColourLine( 0 ),
|
);
|
||||||
palette,
|
|
||||||
greyscale,
|
|
||||||
leftMarginSize,
|
|
||||||
rightMarginSize,
|
|
||||||
topMarginSize );
|
|
||||||
|
|
||||||
drawBackground( transform,
|
drawBackground(
|
||||||
buffer,
|
transform, buffer, x, y + height * FONT_HEIGHT,
|
||||||
x,
|
terminal.getBackgroundColourLine( height - 1 ), palette, greyscale,
|
||||||
y + height * FONT_HEIGHT,
|
leftMarginSize, rightMarginSize, bottomMarginSize
|
||||||
terminal.getBackgroundColourLine( height - 1 ),
|
);
|
||||||
palette,
|
|
||||||
greyscale,
|
|
||||||
leftMarginSize,
|
|
||||||
rightMarginSize,
|
|
||||||
bottomMarginSize );
|
|
||||||
|
|
||||||
// The main text
|
// The main text
|
||||||
for( int i = 0; i < height; i++ )
|
for( int i = 0; i < height; i++ )
|
||||||
{
|
{
|
||||||
drawString( transform,
|
drawString(
|
||||||
buffer,
|
transform, buffer, x, y + FixedWidthFontRenderer.FONT_HEIGHT * i,
|
||||||
x,
|
terminal.getLine( i ), terminal.getTextColourLine( i ), terminal.getBackgroundColourLine( i ),
|
||||||
y + FixedWidthFontRenderer.FONT_HEIGHT * i,
|
palette, greyscale, leftMarginSize, rightMarginSize, FULL_BRIGHT_LIGHTMAP
|
||||||
terminal.getLine( i ),
|
);
|
||||||
terminal.getTextColourLine( i ),
|
|
||||||
terminal.getBackgroundColourLine( i ),
|
|
||||||
palette,
|
|
||||||
greyscale,
|
|
||||||
leftMarginSize,
|
|
||||||
rightMarginSize, FULL_BRIGHT_LIGHTMAP );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void drawCursor( @Nonnull Matrix4f transform, @Nonnull VertexConsumer buffer, float x, float y, @Nonnull Terminal terminal,
|
public static void drawCursor(
|
||||||
boolean greyscale )
|
@Nonnull Matrix4f transform, @Nonnull VertexConsumer buffer, float x, float y,
|
||||||
|
@Nonnull Terminal terminal, boolean greyscale
|
||||||
|
)
|
||||||
{
|
{
|
||||||
Palette palette = terminal.getPalette();
|
Palette palette = terminal.getPalette();
|
||||||
int width = terminal.getWidth();
|
int width = terminal.getWidth();
|
||||||
@@ -309,52 +246,40 @@ public final class FixedWidthFontRenderer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void drawTerminal( @Nonnull Matrix4f transform, @Nonnull VertexConsumer buffer, float x, float y, @Nonnull Terminal terminal,
|
public static void drawTerminal(
|
||||||
boolean greyscale, float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize )
|
@Nonnull Matrix4f transform, @Nonnull VertexConsumer buffer, float x, float y,
|
||||||
|
@Nonnull Terminal terminal, boolean greyscale,
|
||||||
|
float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize
|
||||||
|
)
|
||||||
{
|
{
|
||||||
drawTerminalWithoutCursor( transform, buffer, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize );
|
drawTerminalWithoutCursor( transform, buffer, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize );
|
||||||
drawCursor( transform, buffer, x, y, terminal, greyscale );
|
drawCursor( transform, buffer, x, y, terminal, greyscale );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void drawTerminal( @Nonnull Matrix4f transform, float x, float y, @Nonnull Terminal terminal, boolean greyscale, float topMarginSize,
|
public static void drawTerminal(
|
||||||
float bottomMarginSize, float leftMarginSize, float rightMarginSize )
|
@Nonnull Matrix4f transform, float x, float y, @Nonnull Terminal terminal, boolean greyscale,
|
||||||
|
float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize
|
||||||
|
)
|
||||||
{
|
{
|
||||||
MultiBufferSource.BufferSource renderer = Minecraft.getInstance()
|
MultiBufferSource.BufferSource renderer = MultiBufferSource.immediate( Tesselator.getInstance().getBuilder() );
|
||||||
.renderBuffers()
|
|
||||||
.bufferSource();
|
|
||||||
VertexConsumer buffer = renderer.getBuffer( RenderTypes.TERMINAL_WITH_DEPTH );
|
VertexConsumer buffer = renderer.getBuffer( RenderTypes.TERMINAL_WITH_DEPTH );
|
||||||
drawTerminal( transform, buffer, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize );
|
drawTerminal( transform, buffer, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize );
|
||||||
renderer.endBatch();
|
renderer.endBatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void drawTerminal( float x, float y, @Nonnull Terminal terminal, boolean greyscale, float topMarginSize, float bottomMarginSize,
|
public static void drawEmptyTerminal( @Nonnull Matrix4f transform, @Nonnull MultiBufferSource renderer, float x, float y, float width, float height )
|
||||||
float leftMarginSize, float rightMarginSize )
|
|
||||||
{
|
|
||||||
drawTerminal( IDENTITY, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize );
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void drawEmptyTerminal( float x, float y, float width, float height )
|
|
||||||
{
|
{
|
||||||
Colour colour = Colour.BLACK;
|
Colour colour = Colour.BLACK;
|
||||||
drawEmptyTerminal( IDENTITY, x, y, width, height );
|
drawQuad( transform, renderer.getBuffer( RenderTypes.TERMINAL_WITH_DEPTH ), x, y, width, height, colour.getR(), colour.getG(), colour.getB() );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void drawEmptyTerminal( @Nonnull Matrix4f transform, float x, float y, float width, float height )
|
public static void drawEmptyTerminal( @Nonnull Matrix4f transform, float x, float y, float width, float height )
|
||||||
{
|
{
|
||||||
MultiBufferSource.BufferSource renderer = Minecraft.getInstance()
|
MultiBufferSource.BufferSource renderer = MultiBufferSource.immediate( Tesselator.getInstance().getBuilder() );
|
||||||
.renderBuffers()
|
|
||||||
.bufferSource();
|
|
||||||
drawEmptyTerminal( transform, renderer, x, y, width, height );
|
drawEmptyTerminal( transform, renderer, x, y, width, height );
|
||||||
renderer.endBatch();
|
renderer.endBatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void drawEmptyTerminal( @Nonnull Matrix4f transform, @Nonnull MultiBufferSource renderer, float x, float y, float width,
|
|
||||||
float height )
|
|
||||||
{
|
|
||||||
Colour colour = Colour.BLACK;
|
|
||||||
drawQuad( transform, renderer.getBuffer( RenderTypes.TERMINAL_WITH_DEPTH ), x, y, width, height, colour.getR(), colour.getG(), colour.getB() );
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void drawBlocker( @Nonnull Matrix4f transform, @Nonnull MultiBufferSource renderer, float x, float y, float width, float height )
|
public static void drawBlocker( @Nonnull Matrix4f transform, @Nonnull MultiBufferSource renderer, float x, float y, float width, float height )
|
||||||
{
|
{
|
||||||
Colour colour = Colour.BLACK;
|
Colour colour = Colour.BLACK;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.client.gui;
|
package dan200.computercraft.client.gui;
|
||||||
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
@@ -20,14 +19,15 @@ import net.minecraft.world.entity.player.Inventory;
|
|||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
import static dan200.computercraft.client.render.ComputerBorderRenderer.BORDER;
|
import static dan200.computercraft.client.render.ComputerBorderRenderer.BORDER;
|
||||||
import static dan200.computercraft.client.render.ComputerBorderRenderer.getTexture;
|
|
||||||
|
|
||||||
public final class GuiComputer<T extends ContainerComputerBase> extends ComputerScreenBase<T>
|
public final class GuiComputer<T extends ContainerComputerBase> extends ComputerScreenBase<T>
|
||||||
{
|
{
|
||||||
private final int termWidth;
|
private final int termWidth;
|
||||||
private final int termHeight;
|
private final int termHeight;
|
||||||
|
|
||||||
private GuiComputer( T container, Inventory player, Component title, int termWidth, int termHeight )
|
private GuiComputer(
|
||||||
|
T container, Inventory player, Component title, int termWidth, int termHeight
|
||||||
|
)
|
||||||
{
|
{
|
||||||
super( container, player, title, BORDER );
|
super( container, player, title, BORDER );
|
||||||
this.termWidth = termWidth;
|
this.termWidth = termWidth;
|
||||||
@@ -37,19 +37,31 @@ public final class GuiComputer<T extends ContainerComputerBase> extends Computer
|
|||||||
imageHeight = WidgetTerminal.getHeight( termHeight ) + BORDER * 2;
|
imageHeight = WidgetTerminal.getHeight( termHeight ) + BORDER * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
public static GuiComputer<ContainerComputerBase> create( ContainerComputerBase container, Inventory inventory, Component component )
|
public static GuiComputer<ContainerComputerBase> create( ContainerComputerBase container, Inventory inventory, Component component )
|
||||||
{
|
{
|
||||||
return new GuiComputer<>( container, inventory, component, ComputerCraft.computerTermWidth, ComputerCraft.computerTermHeight );
|
return new GuiComputer<>(
|
||||||
|
container, inventory, component,
|
||||||
|
ComputerCraft.computerTermWidth, ComputerCraft.computerTermHeight
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
public static GuiComputer<ContainerComputerBase> createPocket( ContainerComputerBase container, Inventory inventory, Component component )
|
public static GuiComputer<ContainerComputerBase> createPocket( ContainerComputerBase container, Inventory inventory, Component component )
|
||||||
{
|
{
|
||||||
return new GuiComputer<>( container, inventory, component, ComputerCraft.pocketTermWidth, ComputerCraft.pocketTermHeight );
|
return new GuiComputer<>(
|
||||||
|
container, inventory, component,
|
||||||
|
ComputerCraft.pocketTermWidth, ComputerCraft.pocketTermHeight
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
public static GuiComputer<ContainerViewComputer> createView( ContainerViewComputer container, Inventory inventory, Component component )
|
public static GuiComputer<ContainerViewComputer> createView( ContainerViewComputer container, Inventory inventory, Component component )
|
||||||
{
|
{
|
||||||
return new GuiComputer<>( container, inventory, component, container.getWidth(), container.getHeight() );
|
return new GuiComputer<>(
|
||||||
|
container, inventory, component,
|
||||||
|
container.getWidth(), container.getHeight()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -63,9 +75,11 @@ public final class GuiComputer<T extends ContainerComputerBase> extends Computer
|
|||||||
@Override
|
@Override
|
||||||
public void renderBg( @Nonnull PoseStack stack, float partialTicks, int mouseX, int mouseY )
|
public void renderBg( @Nonnull PoseStack stack, float partialTicks, int mouseX, int mouseY )
|
||||||
{
|
{
|
||||||
|
// Draw a border around the terminal
|
||||||
ComputerBorderRenderer.render(
|
ComputerBorderRenderer.render(
|
||||||
getTexture( family ), terminal.x, terminal.y, getBlitOffset(),
|
ComputerBorderRenderer.getTexture( family ), terminal.x, terminal.y, getBlitOffset(),
|
||||||
RenderTypes.FULL_BRIGHT_LIGHTMAP, terminal.getWidth(), terminal.getHeight() );
|
RenderTypes.FULL_BRIGHT_LIGHTMAP, terminal.getWidth(), terminal.getHeight()
|
||||||
|
);
|
||||||
ComputerSidebar.renderBackground( stack, leftPos, topPos + sidebarYOffset );
|
ComputerSidebar.renderBackground( stack, leftPos, topPos + sidebarYOffset );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,12 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.client.gui;
|
package dan200.computercraft.client.gui;
|
||||||
|
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive;
|
import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive;
|
||||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
||||||
import net.minecraft.client.renderer.GameRenderer;
|
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.entity.player.Inventory;
|
import net.minecraft.world.entity.player.Inventory;
|
||||||
@@ -26,6 +24,14 @@ public class GuiDiskDrive extends AbstractContainerScreen<ContainerDiskDrive>
|
|||||||
super( container, player, title );
|
super( container, player, title );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void renderBg( @Nonnull PoseStack transform, float partialTicks, int mouseX, int mouseY )
|
||||||
|
{
|
||||||
|
RenderSystem.setShaderColor( 1.0F, 1.0F, 1.0F, 1.0F );
|
||||||
|
RenderSystem.setShaderTexture( 0, BACKGROUND );
|
||||||
|
blit( transform, leftPos, topPos, 0, 0, imageWidth, imageHeight );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render( @Nonnull PoseStack transform, int mouseX, int mouseY, float partialTicks )
|
public void render( @Nonnull PoseStack transform, int mouseX, int mouseY, float partialTicks )
|
||||||
{
|
{
|
||||||
@@ -33,13 +39,4 @@ public class GuiDiskDrive extends AbstractContainerScreen<ContainerDiskDrive>
|
|||||||
super.render( transform, mouseX, mouseY, partialTicks );
|
super.render( transform, mouseX, mouseY, partialTicks );
|
||||||
renderTooltip( transform, mouseX, mouseY );
|
renderTooltip( transform, mouseX, mouseY );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void renderBg( @Nonnull PoseStack transform, float partialTicks, int mouseX, int mouseY )
|
|
||||||
{
|
|
||||||
RenderSystem.setShader( GameRenderer::getPositionTexShader );
|
|
||||||
RenderSystem.setShaderColor( 1.0F, 1.0F, 1.0F, 1.0F );
|
|
||||||
RenderSystem.setShaderTexture( 0, BACKGROUND );
|
|
||||||
blit( transform, leftPos, topPos, 0, 0, imageWidth, imageHeight );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.client.gui;
|
package dan200.computercraft.client.gui;
|
||||||
|
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
@@ -25,14 +24,6 @@ public class GuiPrinter extends AbstractContainerScreen<ContainerPrinter>
|
|||||||
super( container, player, title );
|
super( container, player, title );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void render( @Nonnull PoseStack stack, int mouseX, int mouseY, float partialTicks )
|
|
||||||
{
|
|
||||||
renderBackground( stack );
|
|
||||||
super.render( stack, mouseX, mouseY, partialTicks );
|
|
||||||
renderTooltip( stack, mouseX, mouseY );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void renderBg( @Nonnull PoseStack transform, float partialTicks, int mouseX, int mouseY )
|
protected void renderBg( @Nonnull PoseStack transform, float partialTicks, int mouseX, int mouseY )
|
||||||
{
|
{
|
||||||
@@ -40,9 +31,14 @@ public class GuiPrinter extends AbstractContainerScreen<ContainerPrinter>
|
|||||||
RenderSystem.setShaderTexture( 0, BACKGROUND );
|
RenderSystem.setShaderTexture( 0, BACKGROUND );
|
||||||
blit( transform, leftPos, topPos, 0, 0, imageWidth, imageHeight );
|
blit( transform, leftPos, topPos, 0, 0, imageWidth, imageHeight );
|
||||||
|
|
||||||
if( getMenu().isPrinting() )
|
if( getMenu().isPrinting() ) blit( transform, leftPos + 34, topPos + 21, 176, 0, 25, 45 );
|
||||||
{
|
}
|
||||||
blit( transform, leftPos + 34, topPos + 21, 176, 0, 25, 45 );
|
|
||||||
}
|
@Override
|
||||||
|
public void render( @Nonnull PoseStack stack, int mouseX, int mouseY, float partialTicks )
|
||||||
|
{
|
||||||
|
renderBackground( stack );
|
||||||
|
super.render( stack, mouseX, mouseY, partialTicks );
|
||||||
|
renderTooltip( stack, mouseX, mouseY );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,16 +3,15 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.client.gui;
|
package dan200.computercraft.client.gui;
|
||||||
|
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import com.mojang.blaze3d.vertex.Tesselator;
|
||||||
import com.mojang.math.Matrix4f;
|
import com.mojang.math.Matrix4f;
|
||||||
import dan200.computercraft.core.terminal.TextBuffer;
|
import dan200.computercraft.core.terminal.TextBuffer;
|
||||||
import dan200.computercraft.shared.common.ContainerHeldItem;
|
import dan200.computercraft.shared.common.ContainerHeldItem;
|
||||||
import dan200.computercraft.shared.media.items.ItemPrintout;
|
import dan200.computercraft.shared.media.items.ItemPrintout;
|
||||||
import net.minecraft.client.Minecraft;
|
|
||||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
||||||
import net.minecraft.client.renderer.MultiBufferSource;
|
import net.minecraft.client.renderer.MultiBufferSource;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
@@ -40,54 +39,72 @@ public class GuiPrintout extends AbstractContainerScreen<ContainerHeldItem>
|
|||||||
|
|
||||||
String[] text = ItemPrintout.getText( container.getStack() );
|
String[] text = ItemPrintout.getText( container.getStack() );
|
||||||
this.text = new TextBuffer[text.length];
|
this.text = new TextBuffer[text.length];
|
||||||
for( int i = 0; i < this.text.length; i++ )
|
for( int i = 0; i < this.text.length; i++ ) this.text[i] = new TextBuffer( text[i] );
|
||||||
{
|
|
||||||
this.text[i] = new TextBuffer( text[i] );
|
|
||||||
}
|
|
||||||
|
|
||||||
String[] colours = ItemPrintout.getColours( container.getStack() );
|
String[] colours = ItemPrintout.getColours( container.getStack() );
|
||||||
this.colours = new TextBuffer[colours.length];
|
this.colours = new TextBuffer[colours.length];
|
||||||
for( int i = 0; i < this.colours.length; i++ )
|
for( int i = 0; i < this.colours.length; i++ ) this.colours[i] = new TextBuffer( colours[i] );
|
||||||
{
|
|
||||||
this.colours[i] = new TextBuffer( colours[i] );
|
|
||||||
}
|
|
||||||
|
|
||||||
page = 0;
|
page = 0;
|
||||||
pages = Math.max( this.text.length / ItemPrintout.LINES_PER_PAGE, 1 );
|
pages = Math.max( this.text.length / ItemPrintout.LINES_PER_PAGE, 1 );
|
||||||
book = ((ItemPrintout) container.getStack()
|
book = ((ItemPrintout) container.getStack().getItem()).getType() == ItemPrintout.Type.BOOK;
|
||||||
.getItem()).getType() == ItemPrintout.Type.BOOK;
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean keyPressed( int key, int scancode, int modifiers )
|
||||||
|
{
|
||||||
|
if( super.keyPressed( key, scancode, modifiers ) ) return true;
|
||||||
|
|
||||||
|
if( key == GLFW.GLFW_KEY_RIGHT )
|
||||||
|
{
|
||||||
|
if( page < pages - 1 ) page++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( key == GLFW.GLFW_KEY_LEFT )
|
||||||
|
{
|
||||||
|
if( page > 0 ) page--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean mouseScrolled( double x, double y, double delta )
|
public boolean mouseScrolled( double x, double y, double delta )
|
||||||
{
|
{
|
||||||
if( super.mouseScrolled( x, y, delta ) )
|
if( super.mouseScrolled( x, y, delta ) ) return true;
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if( delta < 0 )
|
if( delta < 0 )
|
||||||
{
|
{
|
||||||
// Scroll up goes to the next page
|
// Scroll up goes to the next page
|
||||||
if( page < pages - 1 )
|
if( page < pages - 1 ) page++;
|
||||||
{
|
|
||||||
page++;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( delta > 0 )
|
if( delta > 0 )
|
||||||
{
|
{
|
||||||
// Scroll down goes to the previous page
|
// Scroll down goes to the previous page
|
||||||
if( page > 0 )
|
if( page > 0 ) page--;
|
||||||
{
|
|
||||||
page--;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void renderBg( @Nonnull PoseStack transform, float partialTicks, int mouseX, int mouseY )
|
||||||
|
{
|
||||||
|
// Draw the printout
|
||||||
|
RenderSystem.setShaderColor( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||||
|
RenderSystem.enableDepthTest();
|
||||||
|
|
||||||
|
MultiBufferSource.BufferSource renderer = MultiBufferSource.immediate( Tesselator.getInstance().getBuilder() );
|
||||||
|
Matrix4f matrix = transform.last().pose();
|
||||||
|
drawBorder( matrix, renderer, leftPos, topPos, getBlitOffset(), page, pages, book, FULL_BRIGHT_LIGHTMAP );
|
||||||
|
drawText( matrix, renderer, leftPos + X_TEXT_MARGIN, topPos + Y_TEXT_MARGIN, ItemPrintout.LINES_PER_PAGE * page, FULL_BRIGHT_LIGHTMAP, text, colours );
|
||||||
|
renderer.endBatch();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render( @Nonnull PoseStack stack, int mouseX, int mouseY, float partialTicks )
|
public void render( @Nonnull PoseStack stack, int mouseX, int mouseY, float partialTicks )
|
||||||
{
|
{
|
||||||
@@ -104,50 +121,4 @@ public class GuiPrintout extends AbstractContainerScreen<ContainerHeldItem>
|
|||||||
{
|
{
|
||||||
// Skip rendering labels.
|
// Skip rendering labels.
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void renderBg( @Nonnull PoseStack transform, float partialTicks, int mouseX, int mouseY )
|
|
||||||
{
|
|
||||||
// Draw the printout
|
|
||||||
RenderSystem.setShaderColor( 1.0f, 1.0f, 1.0f, 1.0f );
|
|
||||||
RenderSystem.enableDepthTest();
|
|
||||||
|
|
||||||
MultiBufferSource.BufferSource renderer = Minecraft.getInstance()
|
|
||||||
.renderBuffers()
|
|
||||||
.bufferSource();
|
|
||||||
Matrix4f matrix = transform.last()
|
|
||||||
.pose();
|
|
||||||
drawBorder( matrix, renderer, leftPos, topPos, getBlitOffset(), page, pages, book, FULL_BRIGHT_LIGHTMAP );
|
|
||||||
drawText( matrix, renderer, leftPos + X_TEXT_MARGIN, topPos + Y_TEXT_MARGIN, ItemPrintout.LINES_PER_PAGE * page, FULL_BRIGHT_LIGHTMAP, text, colours );
|
|
||||||
renderer.endBatch();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean keyPressed( int key, int scancode, int modifiers )
|
|
||||||
{
|
|
||||||
if( super.keyPressed( key, scancode, modifiers ) )
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( key == GLFW.GLFW_KEY_RIGHT )
|
|
||||||
{
|
|
||||||
if( page < pages - 1 )
|
|
||||||
{
|
|
||||||
page++;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( key == GLFW.GLFW_KEY_LEFT )
|
|
||||||
{
|
|
||||||
if( page > 0 )
|
|
||||||
{
|
|
||||||
page--;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.client.gui;
|
package dan200.computercraft.client.gui;
|
||||||
|
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
@@ -20,12 +19,12 @@ import net.minecraft.world.entity.player.Inventory;
|
|||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
import static dan200.computercraft.shared.turtle.inventory.ContainerTurtle.BORDER;
|
import static dan200.computercraft.shared.turtle.inventory.ContainerTurtle.*;
|
||||||
|
|
||||||
public class GuiTurtle extends ComputerScreenBase<ContainerTurtle>
|
public class GuiTurtle extends ComputerScreenBase<ContainerTurtle>
|
||||||
{
|
{
|
||||||
private static final ResourceLocation BACKGROUND_NORMAL = new ResourceLocation( "computercraft", "textures/gui/turtle_normal.png" );
|
private static final ResourceLocation BACKGROUND_NORMAL = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/turtle_normal.png" );
|
||||||
private static final ResourceLocation BACKGROUND_ADVANCED = new ResourceLocation( "computercraft", "textures/gui/turtle_advanced.png" );
|
private static final ResourceLocation BACKGROUND_ADVANCED = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/turtle_advanced.png" );
|
||||||
|
|
||||||
private static final int TEX_WIDTH = 254;
|
private static final int TEX_WIDTH = 254;
|
||||||
private static final int TEX_HEIGHT = 217;
|
private static final int TEX_HEIGHT = 217;
|
||||||
@@ -35,11 +34,10 @@ public class GuiTurtle extends ComputerScreenBase<ContainerTurtle>
|
|||||||
public GuiTurtle( ContainerTurtle container, Inventory player, Component title )
|
public GuiTurtle( ContainerTurtle container, Inventory player, Component title )
|
||||||
{
|
{
|
||||||
super( container, player, title, BORDER );
|
super( container, player, title, BORDER );
|
||||||
|
|
||||||
family = container.getFamily();
|
family = container.getFamily();
|
||||||
|
|
||||||
imageWidth = TEX_WIDTH + ComputerSidebar.WIDTH;
|
imageWidth = TEX_WIDTH + ComputerSidebar.WIDTH;
|
||||||
imageHeight = TEX_HEIGHT;
|
imageHeight = TEX_HEIGHT;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -52,23 +50,22 @@ public class GuiTurtle extends ComputerScreenBase<ContainerTurtle>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void renderBg( @Nonnull PoseStack transform, float partialTicks, int mouseX, int mouseY )
|
protected void renderBg( @Nonnull PoseStack transform, float partialTicks, int mouseX, int mouseY )
|
||||||
{
|
{
|
||||||
boolean advanced = family == ComputerFamily.ADVANCED;
|
boolean advanced = family == ComputerFamily.ADVANCED;
|
||||||
RenderSystem.setShaderTexture( 0, advanced ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL );
|
RenderSystem.setShaderTexture( 0, advanced ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL );
|
||||||
blit( transform, leftPos + ComputerSidebar.WIDTH, topPos, 0, 0, TEX_WIDTH, TEX_HEIGHT );
|
blit( transform, leftPos + ComputerSidebar.WIDTH, topPos, 0, 0, TEX_WIDTH, TEX_HEIGHT );
|
||||||
|
|
||||||
// Draw selection slot
|
|
||||||
int slot = getMenu().getSelectedSlot();
|
int slot = getMenu().getSelectedSlot();
|
||||||
if( slot >= 0 )
|
if( slot >= 0 )
|
||||||
{
|
{
|
||||||
|
RenderSystem.setShaderColor( 1.0F, 1.0F, 1.0F, 1.0F );
|
||||||
int slotX = slot % 4;
|
int slotX = slot % 4;
|
||||||
int slotY = slot / 4;
|
int slotY = slot / 4;
|
||||||
blit( transform, leftPos + ContainerTurtle.TURTLE_START_X - 2 + slotX * 18, topPos + ContainerTurtle.PLAYER_START_Y - 2 + slotY * 18,
|
blit( transform,
|
||||||
0,
|
leftPos + TURTLE_START_X - 2 + slotX * 18, topPos + PLAYER_START_Y - 2 + slotY * 18,
|
||||||
217,
|
0, 217, 24, 24
|
||||||
24,
|
);
|
||||||
24 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderSystem.setShaderTexture( 0, advanced ? ComputerBorderRenderer.BACKGROUND_ADVANCED : ComputerBorderRenderer.BACKGROUND_NORMAL );
|
RenderSystem.setShaderTexture( 0, advanced ? ComputerBorderRenderer.BACKGROUND_ADVANCED : ComputerBorderRenderer.BACKGROUND_NORMAL );
|
||||||
|
|||||||
@@ -43,9 +43,10 @@ public class NoTermComputerScreen<T extends ContainerComputerBase> extends Scree
|
|||||||
@Override
|
@Override
|
||||||
protected void init()
|
protected void init()
|
||||||
{
|
{
|
||||||
this.passEvents = true;
|
passEvents = true; // Pass mouse vents through to the game's mouse handler.
|
||||||
minecraft.mouseHandler.grabMouse();
|
minecraft.mouseHandler.grabMouse();
|
||||||
minecraft.screen = this;
|
minecraft.screen = this;
|
||||||
|
|
||||||
super.init();
|
super.init();
|
||||||
minecraft.keyboardHandler.setSendRepeatsToGui( true );
|
minecraft.keyboardHandler.setSendRepeatsToGui( true );
|
||||||
|
|
||||||
@@ -102,7 +103,7 @@ public class NoTermComputerScreen<T extends ContainerComputerBase> extends Scree
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render( PoseStack transform, int mouseX, int mouseY, float partialTicks )
|
public void render( @Nonnull PoseStack transform, int mouseX, int mouseY, float partialTicks )
|
||||||
{
|
{
|
||||||
super.render( transform, mouseX, mouseY, partialTicks );
|
super.render( transform, mouseX, mouseY, partialTicks );
|
||||||
|
|
||||||
|
|||||||
@@ -49,9 +49,9 @@ public final class OptionScreen extends Screen
|
|||||||
this.originalScreen = originalScreen;
|
this.originalScreen = originalScreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void show( Minecraft client, Component title, Component message, List<AbstractWidget> buttons, Runnable exit )
|
public static void show( Minecraft minecraft, Component title, Component message, List<AbstractWidget> buttons, Runnable exit )
|
||||||
{
|
{
|
||||||
client.setScreen( new OptionScreen( title, message, buttons, exit, unwrap( client.screen ) ) );
|
minecraft.setScreen( new OptionScreen( title, message, buttons, exit, unwrap( minecraft.screen ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Screen unwrap( Screen screen )
|
public static Screen unwrap( Screen screen )
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ package dan200.computercraft.client.gui.widgets;
|
|||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.ComputerCraft;
|
||||||
import dan200.computercraft.client.render.ComputerBorderRenderer;
|
import dan200.computercraft.client.render.ComputerBorderRenderer;
|
||||||
import dan200.computercraft.shared.command.text.ChatHelpers;
|
|
||||||
import dan200.computercraft.shared.computer.core.ClientComputer;
|
import dan200.computercraft.shared.computer.core.ClientComputer;
|
||||||
import net.minecraft.ChatFormatting;
|
import net.minecraft.ChatFormatting;
|
||||||
import net.minecraft.client.gui.components.AbstractWidget;
|
import net.minecraft.client.gui.components.AbstractWidget;
|
||||||
@@ -55,10 +54,10 @@ public final class ComputerSidebar
|
|||||||
TEXTURE, TEX_SIZE, TEX_SIZE, b -> toggleComputer( computer ),
|
TEXTURE, TEX_SIZE, TEX_SIZE, b -> toggleComputer( computer ),
|
||||||
() -> computer.isOn() ? Arrays.asList(
|
() -> computer.isOn() ? Arrays.asList(
|
||||||
new TranslatableComponent( "gui.computercraft.tooltip.turn_off" ),
|
new TranslatableComponent( "gui.computercraft.tooltip.turn_off" ),
|
||||||
ChatHelpers.coloured( new TranslatableComponent( "gui.computercraft.tooltip.turn_off.key" ), ChatFormatting.GRAY )
|
new TranslatableComponent( "gui.computercraft.tooltip.turn_off.key" ).withStyle( ChatFormatting.GRAY )
|
||||||
) : Arrays.asList(
|
) : Arrays.asList(
|
||||||
new TranslatableComponent( "gui.computercraft.tooltip.turn_on" ),
|
new TranslatableComponent( "gui.computercraft.tooltip.turn_on" ),
|
||||||
ChatHelpers.coloured( new TranslatableComponent( "gui.computercraft.tooltip.turn_off.key" ), ChatFormatting.GRAY )
|
new TranslatableComponent( "gui.computercraft.tooltip.turn_off.key" ).withStyle( ChatFormatting.GRAY )
|
||||||
)
|
)
|
||||||
) );
|
) );
|
||||||
|
|
||||||
@@ -69,7 +68,7 @@ public final class ComputerSidebar
|
|||||||
TEXTURE, TEX_SIZE, TEX_SIZE, b -> computer.queueEvent( "terminate" ),
|
TEXTURE, TEX_SIZE, TEX_SIZE, b -> computer.queueEvent( "terminate" ),
|
||||||
Arrays.asList(
|
Arrays.asList(
|
||||||
new TranslatableComponent( "gui.computercraft.tooltip.terminate" ),
|
new TranslatableComponent( "gui.computercraft.tooltip.terminate" ),
|
||||||
ChatHelpers.coloured( new TranslatableComponent( "gui.computercraft.tooltip.terminate.key" ), ChatFormatting.GRAY )
|
new TranslatableComponent( "gui.computercraft.tooltip.terminate.key" ).withStyle( ChatFormatting.GRAY )
|
||||||
)
|
)
|
||||||
) );
|
) );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ package dan200.computercraft.client.gui.widgets;
|
|||||||
|
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import dan200.computercraft.shared.util.NonNullSupplier;
|
||||||
import net.minecraft.client.gui.components.Button;
|
import net.minecraft.client.gui.components.Button;
|
||||||
import net.minecraft.client.gui.screens.Screen;
|
import net.minecraft.client.gui.screens.Screen;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
@@ -16,7 +17,6 @@ import net.minecraft.resources.ResourceLocation;
|
|||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.IntSupplier;
|
import java.util.function.IntSupplier;
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Version of {@link net.minecraft.client.gui.components.ImageButton} which allows changing some properties
|
* Version of {@link net.minecraft.client.gui.components.ImageButton} which allows changing some properties
|
||||||
@@ -31,7 +31,7 @@ public class DynamicImageButton extends Button
|
|||||||
private final int yDiffTex;
|
private final int yDiffTex;
|
||||||
private final int textureWidth;
|
private final int textureWidth;
|
||||||
private final int textureHeight;
|
private final int textureHeight;
|
||||||
private final Supplier<List<Component>> tooltip;
|
private final NonNullSupplier<List<Component>> tooltip;
|
||||||
|
|
||||||
public DynamicImageButton(
|
public DynamicImageButton(
|
||||||
Screen screen, int x, int y, int width, int height, int xTexStart, int yTexStart, int yDiffTex,
|
Screen screen, int x, int y, int width, int height, int xTexStart, int yTexStart, int yDiffTex,
|
||||||
@@ -50,7 +50,7 @@ public class DynamicImageButton extends Button
|
|||||||
public DynamicImageButton(
|
public DynamicImageButton(
|
||||||
Screen screen, int x, int y, int width, int height, IntSupplier xTexStart, int yTexStart, int yDiffTex,
|
Screen screen, int x, int y, int width, int height, IntSupplier xTexStart, int yTexStart, int yDiffTex,
|
||||||
ResourceLocation texture, int textureWidth, int textureHeight,
|
ResourceLocation texture, int textureWidth, int textureHeight,
|
||||||
OnPress onPress, Supplier<List<Component>> tooltip
|
OnPress onPress, NonNullSupplier<List<Component>> tooltip
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
super( x, y, width, height, TextComponent.EMPTY, onPress );
|
super( x, y, width, height, TextComponent.EMPTY, onPress );
|
||||||
@@ -76,7 +76,7 @@ public class DynamicImageButton extends Button
|
|||||||
blit( stack, x, y, xTexStart.getAsInt(), yTex, width, height, textureWidth, textureHeight );
|
blit( stack, x, y, xTexStart.getAsInt(), yTex, width, height, textureWidth, textureHeight );
|
||||||
RenderSystem.enableDepthTest();
|
RenderSystem.enableDepthTest();
|
||||||
|
|
||||||
if( isHoveredOrFocused() ) renderToolTip( stack, mouseX, mouseY );
|
if( isHovered ) renderToolTip( stack, mouseX, mouseY );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@@ -87,11 +87,10 @@ public class DynamicImageButton extends Button
|
|||||||
return tooltip.isEmpty() ? TextComponent.EMPTY : tooltip.get( 0 );
|
return tooltip.isEmpty() ? TextComponent.EMPTY : tooltip.get( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Override
|
@Override
|
||||||
public void renderToolTip( @Nonnull PoseStack stack, int mouseX, int mouseY )
|
public void renderToolTip( @Nonnull PoseStack stack, int mouseX, int mouseY )
|
||||||
{
|
{
|
||||||
List<Component> tooltip = this.tooltip.get();
|
List<Component> tooltip = this.tooltip.get();
|
||||||
|
|
||||||
if( !tooltip.isEmpty() )
|
if( !tooltip.isEmpty() )
|
||||||
{
|
{
|
||||||
screen.renderComponentTooltip( stack, tooltip, mouseX, mouseY );
|
screen.renderComponentTooltip( stack, tooltip, mouseX, mouseY );
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.client.gui.widgets;
|
package dan200.computercraft.client.gui.widgets;
|
||||||
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
@@ -65,15 +64,104 @@ public class WidgetTerminal extends AbstractWidget
|
|||||||
if( ch >= 32 && ch <= 126 || ch >= 160 && ch <= 255 ) // printable chars in byte range
|
if( ch >= 32 && ch <= 126 || ch >= 160 && ch <= 255 ) // printable chars in byte range
|
||||||
{
|
{
|
||||||
// Queue the "char" event
|
// Queue the "char" event
|
||||||
queueEvent( "char", Character.toString( ch ) );
|
computer.queueEvent( "char", new Object[] { Character.toString( ch ) } );
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean inTermRegion( double mouseX, double mouseY )
|
@Override
|
||||||
|
public boolean keyPressed( int key, int scancode, int modifiers )
|
||||||
{
|
{
|
||||||
return active && visible && mouseX >= innerX && mouseY >= innerY && mouseX < innerX + innerWidth && mouseY < innerY + innerHeight;
|
if( key == GLFW.GLFW_KEY_ESCAPE ) return false;
|
||||||
|
if( (modifiers & GLFW.GLFW_MOD_CONTROL) != 0 )
|
||||||
|
{
|
||||||
|
switch( key )
|
||||||
|
{
|
||||||
|
case GLFW.GLFW_KEY_T:
|
||||||
|
if( terminateTimer < 0 ) terminateTimer = 0;
|
||||||
|
return true;
|
||||||
|
case GLFW.GLFW_KEY_S:
|
||||||
|
if( shutdownTimer < 0 ) shutdownTimer = 0;
|
||||||
|
return true;
|
||||||
|
case GLFW.GLFW_KEY_R:
|
||||||
|
if( rebootTimer < 0 ) rebootTimer = 0;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case GLFW.GLFW_KEY_V:
|
||||||
|
// Ctrl+V for paste
|
||||||
|
String clipboard = Minecraft.getInstance().keyboardHandler.getClipboard();
|
||||||
|
if( clipboard != null )
|
||||||
|
{
|
||||||
|
// Clip to the first occurrence of \r or \n
|
||||||
|
int newLineIndex1 = clipboard.indexOf( "\r" );
|
||||||
|
int newLineIndex2 = clipboard.indexOf( "\n" );
|
||||||
|
if( newLineIndex1 >= 0 && newLineIndex2 >= 0 )
|
||||||
|
{
|
||||||
|
clipboard = clipboard.substring( 0, Math.min( newLineIndex1, newLineIndex2 ) );
|
||||||
|
}
|
||||||
|
else if( newLineIndex1 >= 0 )
|
||||||
|
{
|
||||||
|
clipboard = clipboard.substring( 0, newLineIndex1 );
|
||||||
|
}
|
||||||
|
else if( newLineIndex2 >= 0 )
|
||||||
|
{
|
||||||
|
clipboard = clipboard.substring( 0, newLineIndex2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter the string
|
||||||
|
clipboard = SharedConstants.filterText( clipboard );
|
||||||
|
if( !clipboard.isEmpty() )
|
||||||
|
{
|
||||||
|
// Clip to 512 characters and queue the event
|
||||||
|
if( clipboard.length() > 512 ) clipboard = clipboard.substring( 0, 512 );
|
||||||
|
computer.queueEvent( "paste", new Object[] { clipboard } );
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( key >= 0 && terminateTimer < 0 && rebootTimer < 0 && shutdownTimer < 0 )
|
||||||
|
{
|
||||||
|
// Queue the "key" event and add to the down set
|
||||||
|
boolean repeat = keysDown.get( key );
|
||||||
|
keysDown.set( key );
|
||||||
|
computer.keyDown( key, repeat );
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean keyReleased( int key, int scancode, int modifiers )
|
||||||
|
{
|
||||||
|
// Queue the "key_up" event and remove from the down set
|
||||||
|
if( key >= 0 && keysDown.get( key ) )
|
||||||
|
{
|
||||||
|
keysDown.set( key, false );
|
||||||
|
computer.keyUp( key );
|
||||||
|
}
|
||||||
|
|
||||||
|
switch( key )
|
||||||
|
{
|
||||||
|
case GLFW.GLFW_KEY_T:
|
||||||
|
terminateTimer = -1;
|
||||||
|
break;
|
||||||
|
case GLFW.GLFW_KEY_R:
|
||||||
|
rebootTimer = -1;
|
||||||
|
break;
|
||||||
|
case GLFW.GLFW_KEY_S:
|
||||||
|
shutdownTimer = -1;
|
||||||
|
break;
|
||||||
|
case GLFW.GLFW_KEY_LEFT_CONTROL:
|
||||||
|
case GLFW.GLFW_KEY_RIGHT_CONTROL:
|
||||||
|
terminateTimer = rebootTimer = shutdownTimer = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -175,113 +263,27 @@ public class WidgetTerminal extends AbstractWidget
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private boolean inTermRegion( double mouseX, double mouseY )
|
||||||
public boolean keyPressed( int key, int scancode, int modifiers )
|
|
||||||
{
|
{
|
||||||
if( key == GLFW.GLFW_KEY_ESCAPE )
|
return active && visible && mouseX >= innerX && mouseY >= innerY && mouseX < innerX + innerWidth && mouseY < innerY + innerHeight;
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if( (modifiers & GLFW.GLFW_MOD_CONTROL) != 0 )
|
|
||||||
{
|
|
||||||
switch( key )
|
|
||||||
{
|
|
||||||
case GLFW.GLFW_KEY_T:
|
|
||||||
if( terminateTimer < 0 )
|
|
||||||
{
|
|
||||||
terminateTimer = 0;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
case GLFW.GLFW_KEY_S:
|
|
||||||
if( shutdownTimer < 0 )
|
|
||||||
{
|
|
||||||
shutdownTimer = 0;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
case GLFW.GLFW_KEY_R:
|
|
||||||
if( rebootTimer < 0 )
|
|
||||||
{
|
|
||||||
rebootTimer = 0;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case GLFW.GLFW_KEY_V:
|
|
||||||
// Ctrl+V for paste
|
|
||||||
String clipboard = Minecraft.getInstance().keyboardHandler.getClipboard();
|
|
||||||
if( clipboard != null )
|
|
||||||
{
|
|
||||||
// Clip to the first occurrence of \r or \n
|
|
||||||
int newLineIndex1 = clipboard.indexOf( "\r" );
|
|
||||||
int newLineIndex2 = clipboard.indexOf( "\n" );
|
|
||||||
if( newLineIndex1 >= 0 && newLineIndex2 >= 0 )
|
|
||||||
{
|
|
||||||
clipboard = clipboard.substring( 0, Math.min( newLineIndex1, newLineIndex2 ) );
|
|
||||||
}
|
|
||||||
else if( newLineIndex1 >= 0 )
|
|
||||||
{
|
|
||||||
clipboard = clipboard.substring( 0, newLineIndex1 );
|
|
||||||
}
|
|
||||||
else if( newLineIndex2 >= 0 )
|
|
||||||
{
|
|
||||||
clipboard = clipboard.substring( 0, newLineIndex2 );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter the string
|
|
||||||
clipboard = SharedConstants.filterText( clipboard );
|
|
||||||
if( !clipboard.isEmpty() )
|
|
||||||
{
|
|
||||||
// Clip to 512 characters and queue the event
|
|
||||||
if( clipboard.length() > 512 )
|
|
||||||
{
|
|
||||||
clipboard = clipboard.substring( 0, 512 );
|
|
||||||
}
|
|
||||||
queueEvent( "paste", clipboard );
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( key >= 0 && terminateTimer < 0 && rebootTimer < 0 && shutdownTimer < 0 )
|
|
||||||
{
|
|
||||||
// Queue the "key" event and add to the down set
|
|
||||||
boolean repeat = keysDown.get( key );
|
|
||||||
keysDown.set( key );
|
|
||||||
computer.keyDown( key, repeat );
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void update()
|
||||||
public boolean keyReleased( int key, int scancode, int modifiers )
|
|
||||||
{
|
{
|
||||||
// Queue the "key_up" event and remove from the down set
|
if( terminateTimer >= 0 && terminateTimer < TERMINATE_TIME && (terminateTimer += 0.05f) > TERMINATE_TIME )
|
||||||
if( key >= 0 && keysDown.get( key ) )
|
|
||||||
{
|
{
|
||||||
keysDown.set( key, false );
|
computer.queueEvent( "terminate" );
|
||||||
computer.keyUp( key );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch( key )
|
if( shutdownTimer >= 0 && shutdownTimer < TERMINATE_TIME && (shutdownTimer += 0.05f) > TERMINATE_TIME )
|
||||||
{
|
{
|
||||||
case GLFW.GLFW_KEY_T:
|
computer.shutdown();
|
||||||
terminateTimer = -1;
|
|
||||||
break;
|
|
||||||
case GLFW.GLFW_KEY_R:
|
|
||||||
rebootTimer = -1;
|
|
||||||
break;
|
|
||||||
case GLFW.GLFW_KEY_S:
|
|
||||||
shutdownTimer = -1;
|
|
||||||
break;
|
|
||||||
case GLFW.GLFW_KEY_LEFT_CONTROL:
|
|
||||||
case GLFW.GLFW_KEY_RIGHT_CONTROL:
|
|
||||||
terminateTimer = rebootTimer = shutdownTimer = -1;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
if( rebootTimer >= 0 && rebootTimer < TERMINATE_TIME && (rebootTimer += 0.05f) > TERMINATE_TIME )
|
||||||
|
{
|
||||||
|
computer.reboot();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -307,44 +309,6 @@ public class WidgetTerminal extends AbstractWidget
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isMouseOver( double x, double y )
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void queueEvent( String event, Object... args )
|
|
||||||
{
|
|
||||||
computer.queueEvent( event, args );
|
|
||||||
}
|
|
||||||
|
|
||||||
public void update()
|
|
||||||
{
|
|
||||||
if( terminateTimer >= 0 && terminateTimer < TERMINATE_TIME && (terminateTimer += 0.05f) > TERMINATE_TIME )
|
|
||||||
{
|
|
||||||
queueEvent( "terminate" );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( shutdownTimer >= 0 && shutdownTimer < TERMINATE_TIME && (shutdownTimer += 0.05f) > TERMINATE_TIME )
|
|
||||||
{
|
|
||||||
computer.shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
if( rebootTimer >= 0 && rebootTimer < TERMINATE_TIME && (rebootTimer += 0.05f) > TERMINATE_TIME )
|
|
||||||
{
|
|
||||||
computer.reboot();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void queueEvent( String event )
|
|
||||||
{
|
|
||||||
ClientComputer computer = this.computer;
|
|
||||||
if( computer != null )
|
|
||||||
{
|
|
||||||
computer.queueEvent( event );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render( @Nonnull PoseStack transform, int mouseX, int mouseY, float partialTicks )
|
public void render( @Nonnull PoseStack transform, int mouseX, int mouseY, float partialTicks )
|
||||||
{
|
{
|
||||||
@@ -362,9 +326,9 @@ public class WidgetTerminal extends AbstractWidget
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateNarration( NarrationElementOutput builder )
|
public void updateNarration( @Nonnull NarrationElementOutput output )
|
||||||
{
|
{
|
||||||
|
// I'm not sure what the right option is here.
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getWidth( int termWidth )
|
public static int getWidth( int termWidth )
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import dan200.computercraft.client.render.TileEntityTurtleRenderer;
|
|||||||
import dan200.computercraft.client.render.TurtleModelLoader;
|
import dan200.computercraft.client.render.TurtleModelLoader;
|
||||||
import dan200.computercraft.client.render.TurtlePlayerRenderer;
|
import dan200.computercraft.client.render.TurtlePlayerRenderer;
|
||||||
import dan200.computercraft.fabric.events.ClientUnloadWorldEvent;
|
import dan200.computercraft.fabric.events.ClientUnloadWorldEvent;
|
||||||
import dan200.computercraft.shared.ComputerCraftRegistry;
|
import dan200.computercraft.shared.Registry;
|
||||||
import dan200.computercraft.shared.common.ContainerHeldItem;
|
import dan200.computercraft.shared.common.ContainerHeldItem;
|
||||||
import dan200.computercraft.shared.common.IColouredItem;
|
import dan200.computercraft.shared.common.IColouredItem;
|
||||||
import dan200.computercraft.shared.common.TileGeneric;
|
import dan200.computercraft.shared.common.TileGeneric;
|
||||||
@@ -73,17 +73,17 @@ public final class ComputerCraftProxyClient implements ClientModInitializer
|
|||||||
registerContainers();
|
registerContainers();
|
||||||
|
|
||||||
// While turtles themselves are not transparent, their upgrades may be.
|
// While turtles themselves are not transparent, their upgrades may be.
|
||||||
BlockRenderLayerMap.INSTANCE.putBlock( ComputerCraftRegistry.ModBlocks.TURTLE_NORMAL, RenderType.translucent() );
|
BlockRenderLayerMap.INSTANCE.putBlock( Registry.ModBlocks.TURTLE_NORMAL, RenderType.translucent() );
|
||||||
BlockRenderLayerMap.INSTANCE.putBlock( ComputerCraftRegistry.ModBlocks.TURTLE_ADVANCED, RenderType.translucent() );
|
BlockRenderLayerMap.INSTANCE.putBlock( Registry.ModBlocks.TURTLE_ADVANCED, RenderType.translucent() );
|
||||||
// Monitors' textures have transparent fronts and so count as cutouts.
|
// Monitors' textures have transparent fronts and so count as cutouts.
|
||||||
BlockRenderLayerMap.INSTANCE.putBlock( ComputerCraftRegistry.ModBlocks.MONITOR_NORMAL, RenderType.cutout() );
|
BlockRenderLayerMap.INSTANCE.putBlock( Registry.ModBlocks.MONITOR_NORMAL, RenderType.cutout() );
|
||||||
BlockRenderLayerMap.INSTANCE.putBlock( ComputerCraftRegistry.ModBlocks.MONITOR_ADVANCED, RenderType.cutout() );
|
BlockRenderLayerMap.INSTANCE.putBlock( Registry.ModBlocks.MONITOR_ADVANCED, RenderType.cutout() );
|
||||||
|
|
||||||
// Setup TESRs
|
// Setup TESRs
|
||||||
BlockEntityRendererRegistry.register( ComputerCraftRegistry.ModTiles.MONITOR_NORMAL, TileEntityMonitorRenderer::new );
|
BlockEntityRendererRegistry.register( Registry.ModBlockEntities.MONITOR_NORMAL, TileEntityMonitorRenderer::new );
|
||||||
BlockEntityRendererRegistry.register( ComputerCraftRegistry.ModTiles.MONITOR_ADVANCED, TileEntityMonitorRenderer::new );
|
BlockEntityRendererRegistry.register( Registry.ModBlockEntities.MONITOR_ADVANCED, TileEntityMonitorRenderer::new );
|
||||||
BlockEntityRendererRegistry.register( ComputerCraftRegistry.ModTiles.TURTLE_NORMAL, TileEntityTurtleRenderer::new );
|
BlockEntityRendererRegistry.register( Registry.ModBlockEntities.TURTLE_NORMAL, TileEntityTurtleRenderer::new );
|
||||||
BlockEntityRendererRegistry.register( ComputerCraftRegistry.ModTiles.TURTLE_ADVANCED, TileEntityTurtleRenderer::new );
|
BlockEntityRendererRegistry.register( Registry.ModBlockEntities.TURTLE_ADVANCED, TileEntityTurtleRenderer::new );
|
||||||
|
|
||||||
ClientSpriteRegistryCallback.event( InventoryMenu.BLOCK_ATLAS )
|
ClientSpriteRegistryCallback.event( InventoryMenu.BLOCK_ATLAS )
|
||||||
.register( ClientRegistry::onTextureStitchEvent );
|
.register( ClientRegistry::onTextureStitchEvent );
|
||||||
@@ -92,17 +92,17 @@ public final class ComputerCraftProxyClient implements ClientModInitializer
|
|||||||
TurtleModelLoader.INSTANCE.loadModel(
|
TurtleModelLoader.INSTANCE.loadModel(
|
||||||
name ) : null );
|
name ) : null );
|
||||||
|
|
||||||
EntityRendererRegistry.register( ComputerCraftRegistry.ModEntities.TURTLE_PLAYER, TurtlePlayerRenderer::new );
|
EntityRendererRegistry.register( Registry.ModEntities.TURTLE_PLAYER, TurtlePlayerRenderer::new );
|
||||||
|
|
||||||
registerItemProperty( "state",
|
registerItemProperty( "state",
|
||||||
( stack, world, player, integer ) -> ItemPocketComputer.getState( stack )
|
( stack, world, player, integer ) -> ItemPocketComputer.getState( stack )
|
||||||
.ordinal(),
|
.ordinal(),
|
||||||
() -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_NORMAL,
|
() -> Registry.ModItems.POCKET_COMPUTER_NORMAL,
|
||||||
() -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_ADVANCED );
|
() -> Registry.ModItems.POCKET_COMPUTER_ADVANCED );
|
||||||
registerItemProperty( "state",
|
registerItemProperty( "state",
|
||||||
( stack, world, player, integer ) -> IColouredItem.getColourBasic( stack ) != -1 ? 1 : 0,
|
( stack, world, player, integer ) -> IColouredItem.getColourBasic( stack ) != -1 ? 1 : 0,
|
||||||
() -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_NORMAL,
|
() -> Registry.ModItems.POCKET_COMPUTER_NORMAL,
|
||||||
() -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_ADVANCED );
|
() -> Registry.ModItems.POCKET_COMPUTER_ADVANCED );
|
||||||
ClientRegistry.onItemColours();
|
ClientRegistry.onItemColours();
|
||||||
|
|
||||||
initEvents();
|
initEvents();
|
||||||
@@ -111,18 +111,18 @@ public final class ComputerCraftProxyClient implements ClientModInitializer
|
|||||||
// My IDE doesn't think so, but we do actually need these generics.
|
// My IDE doesn't think so, but we do actually need these generics.
|
||||||
private static void registerContainers()
|
private static void registerContainers()
|
||||||
{
|
{
|
||||||
ScreenRegistry.<ContainerComputerBase, GuiComputer<ContainerComputerBase>>register( ComputerCraftRegistry.ModContainers.COMPUTER, GuiComputer::create );
|
ScreenRegistry.<ContainerComputerBase, GuiComputer<ContainerComputerBase>>register( Registry.ModContainers.COMPUTER, GuiComputer::create );
|
||||||
ScreenRegistry.<ContainerComputerBase, GuiComputer<ContainerComputerBase>>register( ComputerCraftRegistry.ModContainers.POCKET_COMPUTER,
|
ScreenRegistry.<ContainerComputerBase, GuiComputer<ContainerComputerBase>>register( Registry.ModContainers.POCKET_COMPUTER,
|
||||||
GuiComputer::createPocket );
|
GuiComputer::createPocket );
|
||||||
ScreenRegistry.<ContainerComputerBase, NoTermComputerScreen<ContainerComputerBase>>register( ComputerCraftRegistry.ModContainers.POCKET_COMPUTER_NO_TERM,
|
ScreenRegistry.<ContainerComputerBase, NoTermComputerScreen<ContainerComputerBase>>register( Registry.ModContainers.POCKET_COMPUTER_NO_TERM,
|
||||||
NoTermComputerScreen::new );
|
NoTermComputerScreen::new );
|
||||||
ScreenRegistry.<ContainerTurtle, GuiTurtle>register( ComputerCraftRegistry.ModContainers.TURTLE, GuiTurtle::new );
|
ScreenRegistry.<ContainerTurtle, GuiTurtle>register( Registry.ModContainers.TURTLE, GuiTurtle::new );
|
||||||
|
|
||||||
ScreenRegistry.<ContainerPrinter, GuiPrinter>register( ComputerCraftRegistry.ModContainers.PRINTER, GuiPrinter::new );
|
ScreenRegistry.<ContainerPrinter, GuiPrinter>register( Registry.ModContainers.PRINTER, GuiPrinter::new );
|
||||||
ScreenRegistry.<ContainerDiskDrive, GuiDiskDrive>register( ComputerCraftRegistry.ModContainers.DISK_DRIVE, GuiDiskDrive::new );
|
ScreenRegistry.<ContainerDiskDrive, GuiDiskDrive>register( Registry.ModContainers.DISK_DRIVE, GuiDiskDrive::new );
|
||||||
ScreenRegistry.<ContainerHeldItem, GuiPrintout>register( ComputerCraftRegistry.ModContainers.PRINTOUT, GuiPrintout::new );
|
ScreenRegistry.<ContainerHeldItem, GuiPrintout>register( Registry.ModContainers.PRINTOUT, GuiPrintout::new );
|
||||||
|
|
||||||
ScreenRegistry.<ContainerViewComputer, GuiComputer<ContainerViewComputer>>register( ComputerCraftRegistry.ModContainers.VIEW_COMPUTER,
|
ScreenRegistry.<ContainerViewComputer, GuiComputer<ContainerViewComputer>>register( Registry.ModContainers.VIEW_COMPUTER,
|
||||||
GuiComputer::createView );
|
GuiComputer::createView );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,14 +3,13 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.client.render;
|
package dan200.computercraft.client.render;
|
||||||
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||||
import com.mojang.math.Matrix3f;
|
import com.mojang.math.Matrix3f;
|
||||||
import com.mojang.math.Matrix4f;
|
import com.mojang.math.Matrix4f;
|
||||||
import dan200.computercraft.shared.ComputerCraftRegistry;
|
import dan200.computercraft.shared.Registry;
|
||||||
import dan200.computercraft.shared.peripheral.modem.wired.BlockCable;
|
import dan200.computercraft.shared.peripheral.modem.wired.BlockCable;
|
||||||
import dan200.computercraft.shared.peripheral.modem.wired.CableShapes;
|
import dan200.computercraft.shared.peripheral.modem.wired.CableShapes;
|
||||||
import dan200.computercraft.shared.util.WorldUtil;
|
import dan200.computercraft.shared.util.WorldUtil;
|
||||||
@@ -33,35 +32,34 @@ public final class CableHighlightRenderer
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean drawHighlight( PoseStack stack, VertexConsumer consumer, Entity entity, double d, double e, double f, BlockPos pos,
|
/*
|
||||||
BlockState state )
|
* Draw an outline for a specific part of a cable "Multipart".
|
||||||
|
*
|
||||||
|
* @see net.minecraft.client.renderer.LevelRenderer#renderHitOutline
|
||||||
|
*/
|
||||||
|
public static boolean drawHighlight( PoseStack stack, VertexConsumer buffer, Entity entity, double d, double e, double f, BlockPos pos, BlockState state )
|
||||||
{
|
{
|
||||||
|
HitResult hitResult = Minecraft.getInstance().hitResult;
|
||||||
Camera info = Minecraft.getInstance().gameRenderer.getMainCamera();
|
Camera info = Minecraft.getInstance().gameRenderer.getMainCamera();
|
||||||
|
|
||||||
// We only care about instances with both cable and modem.
|
// We only care about instances with both cable and modem.
|
||||||
if( state.getBlock() != ComputerCraftRegistry.ModBlocks.CABLE || state.getValue( BlockCable.MODEM )
|
if( state.getBlock() != Registry.ModBlocks.CABLE || state.getValue( BlockCable.MODEM ).getFacing() == null || !state.getValue( BlockCable.CABLE ) )
|
||||||
.getFacing() == null || !state.getValue( BlockCable.CABLE ) )
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
HitResult hitResult = Minecraft.getInstance().hitResult;
|
|
||||||
|
|
||||||
Vec3 hitPos = hitResult != null ? hitResult.getLocation() : new Vec3( d, e, f );
|
Vec3 hitPos = hitResult != null ? hitResult.getLocation() : new Vec3( d, e, f );
|
||||||
|
|
||||||
VoxelShape shape = WorldUtil.isVecInside( CableShapes.getModemShape( state ),
|
VoxelShape shape = WorldUtil.isVecInside( CableShapes.getModemShape( state ), hitPos.subtract( pos.getX(), pos.getY(), pos.getZ() ) )
|
||||||
hitPos.subtract( pos.getX(),
|
? CableShapes.getModemShape( state )
|
||||||
pos.getY(),
|
: CableShapes.getCableShape( state );
|
||||||
pos.getZ() ) ) ? CableShapes.getModemShape( state ) : CableShapes.getCableShape(
|
|
||||||
state );
|
|
||||||
|
|
||||||
Vec3 cameraPos = info.getPosition();
|
Vec3 cameraPos = info.getPosition();
|
||||||
|
|
||||||
double xOffset = pos.getX() - cameraPos.x();
|
double xOffset = pos.getX() - cameraPos.x();
|
||||||
double yOffset = pos.getY() - cameraPos.y();
|
double yOffset = pos.getY() - cameraPos.y();
|
||||||
double zOffset = pos.getZ() - cameraPos.z();
|
double zOffset = pos.getZ() - cameraPos.z();
|
||||||
Matrix4f matrix4f = stack.last()
|
|
||||||
.pose();
|
Matrix4f matrix4f = stack.last().pose();
|
||||||
Matrix3f normal = stack.last().normal();
|
Matrix3f normal = stack.last().normal();
|
||||||
shape.forAllEdges( ( x1, y1, z1, x2, y2, z2 ) -> {
|
shape.forAllEdges( ( x1, y1, z1, x2, y2, z2 ) -> {
|
||||||
float xDelta = (float) (x2 - x1);
|
float xDelta = (float) (x2 - x1);
|
||||||
@@ -72,11 +70,13 @@ public final class CableHighlightRenderer
|
|||||||
yDelta = yDelta / len;
|
yDelta = yDelta / len;
|
||||||
zDelta = zDelta / len;
|
zDelta = zDelta / len;
|
||||||
|
|
||||||
consumer.vertex( matrix4f, (float) (x1 + xOffset), (float) (y1 + yOffset), (float) (z1 + zOffset) )
|
buffer
|
||||||
|
.vertex( matrix4f, (float) (x1 + xOffset), (float) (y1 + yOffset), (float) (z1 + zOffset) )
|
||||||
.color( 0, 0, 0, 0.4f )
|
.color( 0, 0, 0, 0.4f )
|
||||||
.normal( normal, xDelta, yDelta, zDelta )
|
.normal( normal, xDelta, yDelta, zDelta )
|
||||||
.endVertex();
|
.endVertex();
|
||||||
consumer.vertex( matrix4f, (float) (x2 + xOffset), (float) (y2 + yOffset), (float) (z2 + zOffset) )
|
buffer
|
||||||
|
.vertex( matrix4f, (float) (x2 + xOffset), (float) (y2 + yOffset), (float) (z2 + zOffset) )
|
||||||
.color( 0, 0, 0, 0.4f )
|
.color( 0, 0, 0, 0.4f )
|
||||||
.normal( normal, xDelta, yDelta, zDelta )
|
.normal( normal, xDelta, yDelta, zDelta )
|
||||||
.endVertex();
|
.endVertex();
|
||||||
|
|||||||
@@ -22,15 +22,24 @@ public class ComputerBorderRenderer
|
|||||||
public static final ResourceLocation BACKGROUND_ADVANCED = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/corners_advanced.png" );
|
public static final ResourceLocation BACKGROUND_ADVANCED = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/corners_advanced.png" );
|
||||||
public static final ResourceLocation BACKGROUND_COMMAND = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/corners_command.png" );
|
public static final ResourceLocation BACKGROUND_COMMAND = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/corners_command.png" );
|
||||||
public static final ResourceLocation BACKGROUND_COLOUR = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/corners_colour.png" );
|
public static final ResourceLocation BACKGROUND_COLOUR = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/corners_colour.png" );
|
||||||
|
|
||||||
|
private static final Matrix4f IDENTITY = new Matrix4f();
|
||||||
|
|
||||||
|
static
|
||||||
|
{
|
||||||
|
IDENTITY.setIdentity();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The margin between the terminal and its border.
|
* The margin between the terminal and its border.
|
||||||
*/
|
*/
|
||||||
public static final int MARGIN = 2;
|
public static final int MARGIN = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The width of the terminal border.
|
* The width of the terminal border.
|
||||||
*/
|
*/
|
||||||
public static final int BORDER = 12;
|
public static final int BORDER = 12;
|
||||||
private static final Matrix4f IDENTITY = new Matrix4f();
|
|
||||||
private static final int CORNER_TOP_Y = 28;
|
private static final int CORNER_TOP_Y = 28;
|
||||||
private static final int CORNER_BOTTOM_Y = CORNER_TOP_Y + BORDER;
|
private static final int CORNER_BOTTOM_Y = CORNER_TOP_Y + BORDER;
|
||||||
private static final int CORNER_LEFT_X = BORDER;
|
private static final int CORNER_LEFT_X = BORDER;
|
||||||
@@ -40,21 +49,16 @@ public class ComputerBorderRenderer
|
|||||||
private static final int LIGHT_CORNER_Y = 80;
|
private static final int LIGHT_CORNER_Y = 80;
|
||||||
|
|
||||||
public static final int LIGHT_HEIGHT = 8;
|
public static final int LIGHT_HEIGHT = 8;
|
||||||
|
|
||||||
public static final int TEX_SIZE = 256;
|
public static final int TEX_SIZE = 256;
|
||||||
private static final float TEX_SCALE = 1 / (float) TEX_SIZE;
|
private static final float TEX_SCALE = 1 / (float) TEX_SIZE;
|
||||||
|
|
||||||
static
|
|
||||||
{
|
|
||||||
IDENTITY.setIdentity();
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Matrix4f transform;
|
private final Matrix4f transform;
|
||||||
private final VertexConsumer builder;
|
private final VertexConsumer builder;
|
||||||
|
private final int light;
|
||||||
private final int z;
|
private final int z;
|
||||||
private final float r, g, b;
|
private final float r, g, b;
|
||||||
|
|
||||||
private final int light;
|
|
||||||
|
|
||||||
public ComputerBorderRenderer( Matrix4f transform, VertexConsumer builder, int z, int light, float r, float g, float b )
|
public ComputerBorderRenderer( Matrix4f transform, VertexConsumer builder, int z, int light, float r, float g, float b )
|
||||||
{
|
{
|
||||||
this.transform = transform;
|
this.transform = transform;
|
||||||
@@ -82,14 +86,19 @@ public class ComputerBorderRenderer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static RenderType getRenderType( ResourceLocation location )
|
||||||
|
{
|
||||||
|
// See note in RenderTypes about why we use text rather than anything intuitive.
|
||||||
|
return RenderType.text( location );
|
||||||
|
}
|
||||||
|
|
||||||
public static void render( ResourceLocation location, int x, int y, int z, int light, int width, int height )
|
public static void render( ResourceLocation location, int x, int y, int z, int light, int width, int height )
|
||||||
{
|
{
|
||||||
MultiBufferSource.BufferSource source = MultiBufferSource.immediate( Tesselator.getInstance().getBuilder() );
|
MultiBufferSource.BufferSource source = MultiBufferSource.immediate( Tesselator.getInstance().getBuilder() );
|
||||||
render( IDENTITY, source.getBuffer( RenderType.text( location ) ), x, y, z, light, width, height, false, 1, 1, 1 );
|
render( IDENTITY, source.getBuffer( getRenderType( location ) ), x, y, z, light, width, height, false, 1, 1, 1 );
|
||||||
source.endBatch();
|
source.endBatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void render( Matrix4f transform, VertexConsumer buffer, int x, int y, int z, int light, int width, int height, boolean withLight, float r, float g, float b )
|
public static void render( Matrix4f transform, VertexConsumer buffer, int x, int y, int z, int light, int width, int height, boolean withLight, float r, float g, float b )
|
||||||
{
|
{
|
||||||
new ComputerBorderRenderer( transform, buffer, z, light, r, g, b ).doRender( x, y, width, height, withLight );
|
new ComputerBorderRenderer( transform, buffer, z, light, r, g, b ).doRender( x, y, width, height, withLight );
|
||||||
@@ -125,16 +134,16 @@ public class ComputerBorderRenderer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderLine( int x, int y, int u, int v, int width, int height )
|
|
||||||
{
|
|
||||||
renderTexture( x, y, u, v, width, height, BORDER, BORDER );
|
|
||||||
}
|
|
||||||
|
|
||||||
private void renderCorner( int x, int y, int u, int v )
|
private void renderCorner( int x, int y, int u, int v )
|
||||||
{
|
{
|
||||||
renderTexture( x, y, u, v, BORDER, BORDER, BORDER, BORDER );
|
renderTexture( x, y, u, v, BORDER, BORDER, BORDER, BORDER );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void renderLine( int x, int y, int u, int v, int width, int height )
|
||||||
|
{
|
||||||
|
renderTexture( x, y, u, v, width, height, BORDER, BORDER );
|
||||||
|
}
|
||||||
|
|
||||||
private void renderTexture( int x, int y, int u, int v, int width, int height )
|
private void renderTexture( int x, int y, int u, int v, int width, int height )
|
||||||
{
|
{
|
||||||
renderTexture( x, y, u, v, width, height, width, height );
|
renderTexture( x, y, u, v, width, height, width, height );
|
||||||
@@ -142,25 +151,9 @@ public class ComputerBorderRenderer
|
|||||||
|
|
||||||
private void renderTexture( int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight )
|
private void renderTexture( int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight )
|
||||||
{
|
{
|
||||||
builder.vertex( transform, x, y + height, z )
|
builder.vertex( transform, x, y + height, z ).color( r, g, b, 1.0f ).uv( u * TEX_SCALE, (v + textureHeight) * TEX_SCALE ).uv2( light ).endVertex();
|
||||||
.color( r, g, b, 1.0f )
|
builder.vertex( transform, x + width, y + height, z ).color( r, g, b, 1.0f ).uv( (u + textureWidth) * TEX_SCALE, (v + textureHeight) * TEX_SCALE ).uv2( light ).endVertex();
|
||||||
.uv( u * TEX_SCALE, (v + textureHeight) * TEX_SCALE )
|
builder.vertex( transform, x + width, y, z ).color( r, g, b, 1.0f ).uv( (u + textureWidth) * TEX_SCALE, v * TEX_SCALE ).uv2( light ).endVertex();
|
||||||
.uv2( light )
|
builder.vertex( transform, x, y, z ).color( r, g, b, 1.0f ).uv( u * TEX_SCALE, v * TEX_SCALE ).uv2( light ).endVertex();
|
||||||
.endVertex();
|
|
||||||
builder.vertex( transform, x + width, y + height, z )
|
|
||||||
.color( r, g, b, 1.0f )
|
|
||||||
.uv( (u + textureWidth) * TEX_SCALE, (v + textureHeight) * TEX_SCALE )
|
|
||||||
.uv2( light )
|
|
||||||
.endVertex();
|
|
||||||
builder.vertex( transform, x + width, y, z )
|
|
||||||
.color( r, g, b, 1.0f )
|
|
||||||
.uv( (u + textureWidth) * TEX_SCALE, v * TEX_SCALE )
|
|
||||||
.uv2( light )
|
|
||||||
.endVertex();
|
|
||||||
builder.vertex( transform, x, y, z )
|
|
||||||
.color( r, g, b, 1.0f )
|
|
||||||
.uv( u * TEX_SCALE, v * TEX_SCALE )
|
|
||||||
.uv2( light )
|
|
||||||
.endVertex();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,30 +3,36 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.client.render;
|
package dan200.computercraft.client.render;
|
||||||
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import com.mojang.math.Vector3f;
|
import com.mojang.math.Vector3f;
|
||||||
import dan200.computercraft.fabric.mixin.ItemInHandRendererAccess;
|
import dan200.computercraft.fabric.mixin.ItemInHandRendererAccess;
|
||||||
import net.fabricmc.api.EnvType;
|
|
||||||
import net.fabricmc.api.Environment;
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.renderer.ItemInHandRenderer;
|
import net.minecraft.client.renderer.ItemInHandRenderer;
|
||||||
import net.minecraft.client.renderer.MultiBufferSource;
|
import net.minecraft.client.renderer.MultiBufferSource;
|
||||||
|
import net.minecraft.client.renderer.block.model.ItemTransforms;
|
||||||
import net.minecraft.util.Mth;
|
import net.minecraft.util.Mth;
|
||||||
import net.minecraft.world.InteractionHand;
|
import net.minecraft.world.InteractionHand;
|
||||||
import net.minecraft.world.entity.HumanoidArm;
|
import net.minecraft.world.entity.HumanoidArm;
|
||||||
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
|
||||||
@Environment( EnvType.CLIENT )
|
|
||||||
public abstract class ItemMapLikeRenderer
|
public abstract class ItemMapLikeRenderer
|
||||||
{
|
{
|
||||||
public void renderItemFirstPerson(
|
/**
|
||||||
PoseStack transform, MultiBufferSource render, int lightTexture, InteractionHand hand, float pitch, float equipProgress,
|
* The main rendering method for the item.
|
||||||
float swingProgress, ItemStack stack
|
*
|
||||||
)
|
* @param transform The matrix transformation stack
|
||||||
|
* @param render The buffer to render to
|
||||||
|
* @param stack The stack to render
|
||||||
|
* @param light The packed lightmap coordinates.
|
||||||
|
* @see ItemInHandRenderer#renderItem(LivingEntity, ItemStack, ItemTransforms.TransformType, boolean, PoseStack, MultiBufferSource, int)
|
||||||
|
*/
|
||||||
|
protected abstract void renderItem( PoseStack transform, MultiBufferSource render, ItemStack stack, int light );
|
||||||
|
|
||||||
|
public void renderItemFirstPerson( PoseStack transform, MultiBufferSource render, int lightTexture, InteractionHand hand, float pitch, float equipProgress, float swingProgress, ItemStack stack )
|
||||||
{
|
{
|
||||||
Player player = Minecraft.getInstance().player;
|
Player player = Minecraft.getInstance().player;
|
||||||
|
|
||||||
@@ -37,17 +43,60 @@ public abstract class ItemMapLikeRenderer
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
renderItemFirstPersonSide( transform,
|
renderItemFirstPersonSide(
|
||||||
render,
|
transform, render, lightTexture,
|
||||||
lightTexture,
|
|
||||||
hand == InteractionHand.MAIN_HAND ? player.getMainArm() : player.getMainArm().getOpposite(),
|
hand == InteractionHand.MAIN_HAND ? player.getMainArm() : player.getMainArm().getOpposite(),
|
||||||
equipProgress,
|
equipProgress, swingProgress, stack
|
||||||
swingProgress,
|
);
|
||||||
stack );
|
|
||||||
}
|
}
|
||||||
transform.popPose();
|
transform.popPose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the item to one side of the player.
|
||||||
|
*
|
||||||
|
* @param transform The matrix transformation stack
|
||||||
|
* @param render The buffer to render to
|
||||||
|
* @param combinedLight The current light level
|
||||||
|
* @param side The side to render on
|
||||||
|
* @param equipProgress The equip progress of this item
|
||||||
|
* @param swingProgress The swing progress of this item
|
||||||
|
* @param stack The stack to render
|
||||||
|
* @see ItemInHandRenderer#renderOneHandedMap(PoseStack, MultiBufferSource, int, float, HumanoidArm, float, ItemStack)
|
||||||
|
*/
|
||||||
|
private void renderItemFirstPersonSide( PoseStack transform, MultiBufferSource render, int combinedLight, HumanoidArm side, float equipProgress, float swingProgress, ItemStack stack )
|
||||||
|
{
|
||||||
|
Minecraft minecraft = Minecraft.getInstance();
|
||||||
|
float offset = side == HumanoidArm.RIGHT ? 1f : -1f;
|
||||||
|
transform.translate( offset * 0.125f, -0.125f, 0f );
|
||||||
|
|
||||||
|
// If the player is not invisible then render a single arm
|
||||||
|
if( !minecraft.player.isInvisible() )
|
||||||
|
{
|
||||||
|
transform.pushPose();
|
||||||
|
transform.mulPose( Vector3f.ZP.rotationDegrees( offset * 10f ) );
|
||||||
|
((ItemInHandRendererAccess) minecraft.getItemInHandRenderer()).callRenderPlayerArm( transform, render, combinedLight, equipProgress, swingProgress, side );
|
||||||
|
transform.popPose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup the appropriate transformations. This is just copied from the
|
||||||
|
// corresponding method in ItemRenderer.
|
||||||
|
transform.pushPose();
|
||||||
|
transform.translate( offset * 0.51f, -0.08f + equipProgress * -1.2f, -0.75f );
|
||||||
|
float f1 = Mth.sqrt( swingProgress );
|
||||||
|
float f2 = Mth.sin( f1 * (float) Math.PI );
|
||||||
|
float f3 = -0.5f * f2;
|
||||||
|
float f4 = 0.4f * Mth.sin( f1 * ((float) Math.PI * 2f) );
|
||||||
|
float f5 = -0.3f * Mth.sin( swingProgress * (float) Math.PI );
|
||||||
|
transform.translate( offset * f3, f4 - 0.3f * f2, f5 );
|
||||||
|
transform.mulPose( Vector3f.XP.rotationDegrees( f2 * -45f ) );
|
||||||
|
transform.mulPose( Vector3f.YP.rotationDegrees( offset * f2 * -30f ) );
|
||||||
|
|
||||||
|
renderItem( transform, render, stack, combinedLight );
|
||||||
|
|
||||||
|
transform.popPose();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render an item in the middle of the screen.
|
* Render an item in the middle of the screen.
|
||||||
*
|
*
|
||||||
@@ -58,9 +107,9 @@ public abstract class ItemMapLikeRenderer
|
|||||||
* @param equipProgress The equip progress of this item
|
* @param equipProgress The equip progress of this item
|
||||||
* @param swingProgress The swing progress of this item
|
* @param swingProgress The swing progress of this item
|
||||||
* @param stack The stack to render
|
* @param stack The stack to render
|
||||||
|
* @see ItemInHandRenderer#renderTwoHandedMap(PoseStack, MultiBufferSource, int, float, float, float)
|
||||||
*/
|
*/
|
||||||
private void renderItemFirstPersonCenter( PoseStack transform, MultiBufferSource render, int combinedLight, float pitch, float equipProgress,
|
private void renderItemFirstPersonCenter( PoseStack transform, MultiBufferSource render, int combinedLight, float pitch, float equipProgress, float swingProgress, ItemStack stack )
|
||||||
float swingProgress, ItemStack stack )
|
|
||||||
{
|
{
|
||||||
Minecraft minecraft = Minecraft.getInstance();
|
Minecraft minecraft = Minecraft.getInstance();
|
||||||
ItemInHandRenderer renderer = minecraft.getItemInHandRenderer();
|
ItemInHandRenderer renderer = minecraft.getItemInHandRenderer();
|
||||||
@@ -91,60 +140,4 @@ public abstract class ItemMapLikeRenderer
|
|||||||
|
|
||||||
renderItem( transform, render, stack, combinedLight );
|
renderItem( transform, render, stack, combinedLight );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders the item to one side of the player.
|
|
||||||
*
|
|
||||||
* @param transform The matrix transformation stack
|
|
||||||
* @param render The buffer to render to
|
|
||||||
* @param combinedLight The current light level
|
|
||||||
* @param side The side to render on
|
|
||||||
* @param equipProgress The equip progress of this item
|
|
||||||
* @param swingProgress The swing progress of this item
|
|
||||||
* @param stack The stack to render
|
|
||||||
*/
|
|
||||||
private void renderItemFirstPersonSide( PoseStack transform, MultiBufferSource render, int combinedLight, HumanoidArm side, float equipProgress,
|
|
||||||
float swingProgress, ItemStack stack )
|
|
||||||
{
|
|
||||||
Minecraft minecraft = Minecraft.getInstance();
|
|
||||||
float offset = side == HumanoidArm.RIGHT ? 1f : -1f;
|
|
||||||
transform.translate( offset * 0.125f, -0.125f, 0f );
|
|
||||||
|
|
||||||
// If the player is not invisible then render a single arm
|
|
||||||
if( !minecraft.player.isInvisible() )
|
|
||||||
{
|
|
||||||
transform.pushPose();
|
|
||||||
transform.mulPose( Vector3f.ZP.rotationDegrees( offset * 10f ) );
|
|
||||||
((ItemInHandRendererAccess) minecraft.getItemInHandRenderer())
|
|
||||||
.callRenderPlayerArm( transform, render, combinedLight, equipProgress, swingProgress, side );
|
|
||||||
transform.popPose();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup the appropriate transformations. This is just copied from the
|
|
||||||
// corresponding method in ItemRenderer.
|
|
||||||
transform.pushPose();
|
|
||||||
transform.translate( offset * 0.51f, -0.08f + equipProgress * -1.2f, -0.75f );
|
|
||||||
float f1 = Mth.sqrt( swingProgress );
|
|
||||||
float f2 = Mth.sin( f1 * (float) Math.PI );
|
|
||||||
float f3 = -0.5f * f2;
|
|
||||||
float f4 = 0.4f * Mth.sin( f1 * ((float) Math.PI * 2f) );
|
|
||||||
float f5 = -0.3f * Mth.sin( swingProgress * (float) Math.PI );
|
|
||||||
transform.translate( offset * f3, f4 - 0.3f * f2, f5 );
|
|
||||||
transform.mulPose( Vector3f.XP.rotationDegrees( f2 * -45f ) );
|
|
||||||
transform.mulPose( Vector3f.YP.rotationDegrees( offset * f2 * -30f ) );
|
|
||||||
|
|
||||||
renderItem( transform, render, stack, combinedLight );
|
|
||||||
|
|
||||||
transform.popPose();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The main rendering method for the item.
|
|
||||||
*
|
|
||||||
* @param transform The matrix transformation stack
|
|
||||||
* @param render The buffer to render to
|
|
||||||
* @param stack The stack to render
|
|
||||||
* @param light TODO rebase
|
|
||||||
*/
|
|
||||||
protected abstract void renderItem( PoseStack transform, MultiBufferSource render, ItemStack stack, int light );
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,8 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.client.render;
|
package dan200.computercraft.client.render;
|
||||||
|
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
|
||||||
import com.mojang.blaze3d.vertex.*;
|
import com.mojang.blaze3d.vertex.*;
|
||||||
import com.mojang.math.Matrix4f;
|
import com.mojang.math.Matrix4f;
|
||||||
import com.mojang.math.Vector3f;
|
import com.mojang.math.Vector3f;
|
||||||
@@ -17,9 +15,7 @@ import dan200.computercraft.shared.computer.core.ClientComputer;
|
|||||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||||
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
|
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
|
||||||
import dan200.computercraft.shared.util.Colour;
|
import dan200.computercraft.shared.util.Colour;
|
||||||
import net.minecraft.client.Minecraft;
|
|
||||||
import net.minecraft.client.renderer.MultiBufferSource;
|
import net.minecraft.client.renderer.MultiBufferSource;
|
||||||
import net.minecraft.client.renderer.RenderType;
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
|
||||||
@@ -39,7 +35,7 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void renderItem( PoseStack transform, MultiBufferSource render, ItemStack stack, int light )
|
protected void renderItem( PoseStack transform, MultiBufferSource renderer, ItemStack stack, int light )
|
||||||
{
|
{
|
||||||
ClientComputer computer = ItemPocketComputer.createClientComputer( stack );
|
ClientComputer computer = ItemPocketComputer.createClientComputer( stack );
|
||||||
Terminal terminal = computer == null ? null : computer.getTerminal();
|
Terminal terminal = computer == null ? null : computer.getTerminal();
|
||||||
@@ -67,7 +63,7 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
|
|||||||
transform.scale( 0.5f, 0.5f, 0.5f );
|
transform.scale( 0.5f, 0.5f, 0.5f );
|
||||||
|
|
||||||
float scale = 0.75f / Math.max( width + BORDER * 2, height + BORDER * 2 + LIGHT_HEIGHT );
|
float scale = 0.75f / Math.max( width + BORDER * 2, height + BORDER * 2 + LIGHT_HEIGHT );
|
||||||
transform.scale( scale, scale, 0 );
|
transform.scale( scale, scale, -1.0f );
|
||||||
transform.translate( -0.5 * width, -0.5 * height, 0 );
|
transform.translate( -0.5 * width, -0.5 * height, 0 );
|
||||||
|
|
||||||
// Render the main frame
|
// Render the main frame
|
||||||
@@ -75,26 +71,21 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
|
|||||||
ComputerFamily family = item.getFamily();
|
ComputerFamily family = item.getFamily();
|
||||||
int frameColour = item.getColour( stack );
|
int frameColour = item.getColour( stack );
|
||||||
|
|
||||||
Matrix4f matrix = transform.last()
|
Matrix4f matrix = transform.last().pose();
|
||||||
.pose();
|
renderFrame( matrix, renderer, family, frameColour, light, width, height );
|
||||||
renderFrame( matrix, render, family, frameColour, light, width, height );
|
|
||||||
|
|
||||||
// Render the light
|
// Render the light
|
||||||
int lightColour = ItemPocketComputer.getLightState( stack );
|
int lightColour = ItemPocketComputer.getLightState( stack );
|
||||||
if( lightColour == -1 )
|
if( lightColour == -1 ) lightColour = Colour.BLACK.getHex();
|
||||||
{
|
renderLight( matrix, renderer, lightColour, width, height );
|
||||||
lightColour = Colour.BLACK.getHex();
|
|
||||||
}
|
|
||||||
renderLight( matrix, lightColour, width, height );
|
|
||||||
|
|
||||||
if( computer != null && terminal != null )
|
if( computer != null && terminal != null )
|
||||||
{
|
{
|
||||||
FixedWidthFontRenderer.drawTerminal(
|
FixedWidthFontRenderer.drawTerminal(
|
||||||
matrix, render.getBuffer( RenderTypes.TERMINAL_WITHOUT_DEPTH ),
|
matrix, renderer.getBuffer( RenderTypes.TERMINAL_WITHOUT_DEPTH ),
|
||||||
MARGIN, MARGIN, terminal, !computer.isColour(), MARGIN, MARGIN, MARGIN, MARGIN
|
MARGIN, MARGIN, terminal, !computer.isColour(), MARGIN, MARGIN, MARGIN, MARGIN
|
||||||
);
|
);
|
||||||
FixedWidthFontRenderer.drawBlocker( transform.last().pose(), render, 0, 0, width, height );
|
FixedWidthFontRenderer.drawBlocker( transform.last().pose(), renderer, 0, 0, width, height );
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -106,45 +97,26 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
|
|||||||
|
|
||||||
private static void renderFrame( Matrix4f transform, MultiBufferSource render, ComputerFamily family, int colour, int light, int width, int height )
|
private static void renderFrame( Matrix4f transform, MultiBufferSource render, ComputerFamily family, int colour, int light, int width, int height )
|
||||||
{
|
{
|
||||||
RenderSystem.enableBlend();
|
|
||||||
Minecraft.getInstance()
|
|
||||||
.getTextureManager()
|
|
||||||
.bindForSetup( colour != -1 ? ComputerBorderRenderer.BACKGROUND_COLOUR : ComputerBorderRenderer.getTexture( family ) );
|
|
||||||
|
|
||||||
ResourceLocation texture = colour != -1 ? ComputerBorderRenderer.BACKGROUND_COLOUR : ComputerBorderRenderer.getTexture( family );
|
ResourceLocation texture = colour != -1 ? ComputerBorderRenderer.BACKGROUND_COLOUR : ComputerBorderRenderer.getTexture( family );
|
||||||
|
|
||||||
float r = ((colour >>> 16) & 0xFF) / 255.0f;
|
float r = ((colour >>> 16) & 0xFF) / 255.0f;
|
||||||
float g = ((colour >>> 8) & 0xFF) / 255.0f;
|
float g = ((colour >>> 8) & 0xFF) / 255.0f;
|
||||||
float b = (colour & 0xFF) / 255.0f;
|
float b = (colour & 0xFF) / 255.0f;
|
||||||
|
|
||||||
ComputerBorderRenderer.render( transform, render.getBuffer( RenderType.text( texture ) ), 0, 0, 0, light, width, height, true, r, g, b );
|
ComputerBorderRenderer.render( transform, render.getBuffer( ComputerBorderRenderer.getRenderType( texture ) ), 0, 0, 0, light, width, height, true, r, g, b );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void renderLight( Matrix4f transform, int colour, int width, int height )
|
private static void renderLight( Matrix4f transform, MultiBufferSource render, int colour, int width, int height )
|
||||||
{
|
{
|
||||||
RenderSystem.disableTexture();
|
|
||||||
|
|
||||||
float r = ((colour >>> 16) & 0xFF) / 255.0f;
|
float r = ((colour >>> 16) & 0xFF) / 255.0f;
|
||||||
float g = ((colour >>> 8) & 0xFF) / 255.0f;
|
float g = ((colour >>> 8) & 0xFF) / 255.0f;
|
||||||
float b = (colour & 0xFF) / 255.0f;
|
float b = (colour & 0xFF) / 255.0f;
|
||||||
|
float z = 0.001f;
|
||||||
|
|
||||||
Tesselator tessellator = Tesselator.getInstance();
|
VertexConsumer buffer = render.getBuffer( RenderTypes.POSITION_COLOR );
|
||||||
BufferBuilder buffer = tessellator.getBuilder();
|
buffer.vertex( transform, width - LIGHT_HEIGHT * 2, height + LIGHT_HEIGHT + BORDER / 2.0f, z ).color( r, g, b, 1.0f ).endVertex();
|
||||||
buffer.begin( VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR );
|
buffer.vertex( transform, width, height + LIGHT_HEIGHT + BORDER / 2.0f, z ).color( r, g, b, 1.0f ).endVertex();
|
||||||
buffer.vertex( transform, width - LIGHT_HEIGHT * 2, height + LIGHT_HEIGHT + BORDER / 2.0f, 0 )
|
buffer.vertex( transform, width, height + BORDER / 2.0f, z ).color( r, g, b, 1.0f ).endVertex();
|
||||||
.color( r, g, b, 1.0f )
|
buffer.vertex( transform, width - LIGHT_HEIGHT * 2, height + BORDER / 2.0f, z ).color( r, g, b, 1.0f ).endVertex();
|
||||||
.endVertex();
|
|
||||||
buffer.vertex( transform, width, height + LIGHT_HEIGHT + BORDER / 2.0f, 0 )
|
|
||||||
.color( r, g, b, 1.0f )
|
|
||||||
.endVertex();
|
|
||||||
buffer.vertex( transform, width, height + BORDER / 2.0f, 0 )
|
|
||||||
.color( r, g, b, 1.0f )
|
|
||||||
.endVertex();
|
|
||||||
buffer.vertex( transform, width - LIGHT_HEIGHT * 2, height + BORDER / 2.0f, 0 )
|
|
||||||
.color( r, g, b, 1.0f )
|
|
||||||
.endVertex();
|
|
||||||
|
|
||||||
tessellator.end();
|
|
||||||
RenderSystem.enableTexture();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.client.render;
|
package dan200.computercraft.client.render;
|
||||||
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
@@ -30,6 +29,21 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean renderInFrame( PoseStack matrixStack, MultiBufferSource consumerProvider, ItemStack stack, int light )
|
||||||
|
{
|
||||||
|
if( !(stack.getItem() instanceof ItemPrintout) ) return false;
|
||||||
|
|
||||||
|
// Move a little bit forward to ensure we're not clipping with the frame
|
||||||
|
matrixStack.translate( 0.0f, 0.0f, -0.001f );
|
||||||
|
matrixStack.mulPose( Vector3f.ZP.rotationDegrees( 180f ) );
|
||||||
|
matrixStack.scale( 0.95f, 0.95f, -0.95f );
|
||||||
|
matrixStack.translate( -0.5f, -0.5f, 0.0f );
|
||||||
|
|
||||||
|
drawPrintout( matrixStack, consumerProvider, stack, light );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void renderItem( PoseStack transform, MultiBufferSource render, ItemStack stack, int light )
|
protected void renderItem( PoseStack transform, MultiBufferSource render, ItemStack stack, int light )
|
||||||
{
|
{
|
||||||
@@ -49,10 +63,7 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer
|
|||||||
double height = LINES_PER_PAGE * FONT_HEIGHT + Y_TEXT_MARGIN * 2;
|
double height = LINES_PER_PAGE * FONT_HEIGHT + Y_TEXT_MARGIN * 2;
|
||||||
|
|
||||||
// Non-books will be left aligned
|
// Non-books will be left aligned
|
||||||
if( !book )
|
if( !book ) width += offsetAt( pages );
|
||||||
{
|
|
||||||
width += offsetAt( pages );
|
|
||||||
}
|
|
||||||
|
|
||||||
double visualWidth = width, visualHeight = height;
|
double visualWidth = width, visualHeight = height;
|
||||||
|
|
||||||
@@ -70,27 +81,11 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer
|
|||||||
transform.scale( scale, scale, scale );
|
transform.scale( scale, scale, scale );
|
||||||
transform.translate( (max - width) / 2.0, (max - height) / 2.0, 0.0 );
|
transform.translate( (max - width) / 2.0, (max - height) / 2.0, 0.0 );
|
||||||
|
|
||||||
Matrix4f matrix = transform.last()
|
Matrix4f matrix = transform.last().pose();
|
||||||
.pose();
|
|
||||||
drawBorder( matrix, render, 0, 0, -0.01f, 0, pages, book, light );
|
drawBorder( matrix, render, 0, 0, -0.01f, 0, pages, book, light );
|
||||||
drawText( matrix, render, X_TEXT_MARGIN, Y_TEXT_MARGIN, 0, light, ItemPrintout.getText( stack ), ItemPrintout.getColours( stack ) );
|
drawText(
|
||||||
}
|
matrix, render, X_TEXT_MARGIN, Y_TEXT_MARGIN, 0, light,
|
||||||
|
ItemPrintout.getText( stack ), ItemPrintout.getColours( stack )
|
||||||
public boolean renderInFrame( PoseStack matrixStack, MultiBufferSource consumerProvider, ItemStack stack, int light )
|
);
|
||||||
{
|
|
||||||
if( !(stack.getItem() instanceof ItemPrintout) )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move a little bit forward to ensure we're not clipping with the frame
|
|
||||||
matrixStack.translate( 0.0f, 0.0f, -0.001f );
|
|
||||||
matrixStack.mulPose( Vector3f.ZP.rotationDegrees( 180f ) );
|
|
||||||
matrixStack.scale( 0.95f, 0.95f, -0.95f );
|
|
||||||
matrixStack.translate( -0.5f, -0.5f, 0.0f );
|
|
||||||
|
|
||||||
drawPrintout( matrixStack, consumerProvider, stack, light );
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.client.render;
|
package dan200.computercraft.client.render;
|
||||||
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
@@ -27,8 +26,8 @@ import java.util.EnumSet;
|
|||||||
import static net.minecraft.core.Direction.*;
|
import static net.minecraft.core.Direction.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overrides monitor highlighting to only render the outline of the <em>whole</em> monitor, rather than the current block. This means you do not get an
|
* Overrides monitor highlighting to only render the outline of the <em>whole</em> monitor, rather than the current
|
||||||
* intrusive outline on top of the screen.
|
* block. This means you do not get an intrusive outline on top of the screen.
|
||||||
*/
|
*/
|
||||||
@Environment( EnvType.CLIENT )
|
@Environment( EnvType.CLIENT )
|
||||||
public final class MonitorHighlightRenderer
|
public final class MonitorHighlightRenderer
|
||||||
@@ -37,115 +36,62 @@ public final class MonitorHighlightRenderer
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean drawHighlight( PoseStack matrixStack, VertexConsumer vertexConsumer, Entity entity, double d, double e, double f, BlockPos pos, BlockState blockState )
|
public static boolean drawHighlight( PoseStack transformStack, VertexConsumer buffer, Entity entity, double d, double e, double f, BlockPos pos, BlockState blockState )
|
||||||
{
|
{
|
||||||
// Preserve normal behaviour when crouching.
|
// Preserve normal behaviour when crouching.
|
||||||
if( entity.isCrouching() )
|
if( entity.isCrouching() ) return false;
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Level world = entity.getCommandSenderWorld();
|
Level world = entity.getCommandSenderWorld();
|
||||||
|
|
||||||
BlockEntity tile = world.getBlockEntity( pos );
|
BlockEntity tile = world.getBlockEntity( pos );
|
||||||
if( !(tile instanceof TileMonitor monitor) )
|
if( !(tile instanceof TileMonitor monitor) ) return false;
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine which sides are part of the external faces of the monitor, and so which need to be rendered.
|
// Determine which sides are part of the external faces of the monitor, and so which need to be rendered.
|
||||||
EnumSet<Direction> faces = EnumSet.allOf( Direction.class );
|
EnumSet<Direction> faces = EnumSet.allOf( Direction.class );
|
||||||
Direction front = monitor.getFront();
|
Direction front = monitor.getFront();
|
||||||
faces.remove( front );
|
faces.remove( front );
|
||||||
if( monitor.getXIndex() != 0 )
|
if( monitor.getXIndex() != 0 ) faces.remove( monitor.getRight().getOpposite() );
|
||||||
{
|
if( monitor.getXIndex() != monitor.getWidth() - 1 ) faces.remove( monitor.getRight() );
|
||||||
faces.remove( monitor.getRight()
|
if( monitor.getYIndex() != 0 ) faces.remove( monitor.getDown().getOpposite() );
|
||||||
.getOpposite() );
|
if( monitor.getYIndex() != monitor.getHeight() - 1 ) faces.remove( monitor.getDown() );
|
||||||
}
|
|
||||||
if( monitor.getXIndex() != monitor.getWidth() - 1 )
|
|
||||||
{
|
|
||||||
faces.remove( monitor.getRight() );
|
|
||||||
}
|
|
||||||
if( monitor.getYIndex() != 0 )
|
|
||||||
{
|
|
||||||
faces.remove( monitor.getDown()
|
|
||||||
.getOpposite() );
|
|
||||||
}
|
|
||||||
if( monitor.getYIndex() != monitor.getHeight() - 1 )
|
|
||||||
{
|
|
||||||
faces.remove( monitor.getDown() );
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec3 cameraPos = Minecraft.getInstance().gameRenderer.getMainCamera()
|
Vec3 cameraPos = Minecraft.getInstance().gameRenderer.getMainCamera().getPosition();
|
||||||
.getPosition();
|
transformStack.pushPose();
|
||||||
matrixStack.pushPose();
|
transformStack.translate( pos.getX() - cameraPos.x(), pos.getY() - cameraPos.y(), pos.getZ() - cameraPos.z() );
|
||||||
matrixStack.translate( pos.getX() - cameraPos.x(), pos.getY() - cameraPos.y(), pos.getZ() - cameraPos.z() );
|
|
||||||
|
|
||||||
// I wish I could think of a better way to do this
|
// I wish I could think of a better way to do this
|
||||||
Matrix4f transform = matrixStack.last()
|
Matrix4f transform = transformStack.last().pose();
|
||||||
.pose();
|
Matrix3f normal = transformStack.last().normal();
|
||||||
Matrix3f normal = matrixStack.last().normal();
|
if( faces.contains( NORTH ) || faces.contains( WEST ) ) line( buffer, transform, normal, 0, 0, 0, UP );
|
||||||
if( faces.contains( NORTH ) || faces.contains( WEST ) )
|
if( faces.contains( SOUTH ) || faces.contains( WEST ) ) line( buffer, transform, normal, 0, 0, 1, UP );
|
||||||
{
|
if( faces.contains( NORTH ) || faces.contains( EAST ) ) line( buffer, transform, normal, 1, 0, 0, UP );
|
||||||
line( vertexConsumer, transform, normal, 0, 0, 0, UP );
|
if( faces.contains( SOUTH ) || faces.contains( EAST ) ) line( buffer, transform, normal, 1, 0, 1, UP );
|
||||||
}
|
if( faces.contains( NORTH ) || faces.contains( DOWN ) ) line( buffer, transform, normal, 0, 0, 0, EAST );
|
||||||
if( faces.contains( SOUTH ) || faces.contains( WEST ) )
|
if( faces.contains( SOUTH ) || faces.contains( DOWN ) ) line( buffer, transform, normal, 0, 0, 1, EAST );
|
||||||
{
|
if( faces.contains( NORTH ) || faces.contains( UP ) ) line( buffer, transform, normal, 0, 1, 0, EAST );
|
||||||
line( vertexConsumer, transform, normal, 0, 0, 1, UP );
|
if( faces.contains( SOUTH ) || faces.contains( UP ) ) line( buffer, transform, normal, 0, 1, 1, EAST );
|
||||||
}
|
if( faces.contains( WEST ) || faces.contains( DOWN ) ) line( buffer, transform, normal, 0, 0, 0, SOUTH );
|
||||||
if( faces.contains( NORTH ) || faces.contains( EAST ) )
|
if( faces.contains( EAST ) || faces.contains( DOWN ) ) line( buffer, transform, normal, 1, 0, 0, SOUTH );
|
||||||
{
|
if( faces.contains( WEST ) || faces.contains( UP ) ) line( buffer, transform, normal, 0, 1, 0, SOUTH );
|
||||||
line( vertexConsumer, transform, normal, 1, 0, 0, UP );
|
if( faces.contains( EAST ) || faces.contains( UP ) ) line( buffer, transform, normal, 1, 1, 0, SOUTH );
|
||||||
}
|
|
||||||
if( faces.contains( SOUTH ) || faces.contains( EAST ) )
|
|
||||||
{
|
|
||||||
line( vertexConsumer, transform, normal, 1, 0, 1, UP );
|
|
||||||
}
|
|
||||||
if( faces.contains( NORTH ) || faces.contains( DOWN ) )
|
|
||||||
{
|
|
||||||
line( vertexConsumer, transform, normal, 0, 0, 0, EAST );
|
|
||||||
}
|
|
||||||
if( faces.contains( SOUTH ) || faces.contains( DOWN ) )
|
|
||||||
{
|
|
||||||
line( vertexConsumer, transform, normal, 0, 0, 1, EAST );
|
|
||||||
}
|
|
||||||
if( faces.contains( NORTH ) || faces.contains( UP ) )
|
|
||||||
{
|
|
||||||
line( vertexConsumer, transform, normal, 0, 1, 0, EAST );
|
|
||||||
}
|
|
||||||
if( faces.contains( SOUTH ) || faces.contains( UP ) )
|
|
||||||
{
|
|
||||||
line( vertexConsumer, transform, normal, 0, 1, 1, EAST );
|
|
||||||
}
|
|
||||||
if( faces.contains( WEST ) || faces.contains( DOWN ) )
|
|
||||||
{
|
|
||||||
line( vertexConsumer, transform, normal, 0, 0, 0, SOUTH );
|
|
||||||
}
|
|
||||||
if( faces.contains( EAST ) || faces.contains( DOWN ) )
|
|
||||||
{
|
|
||||||
line( vertexConsumer, transform, normal, 1, 0, 0, SOUTH );
|
|
||||||
}
|
|
||||||
if( faces.contains( WEST ) || faces.contains( UP ) )
|
|
||||||
{
|
|
||||||
line( vertexConsumer, transform, normal, 0, 1, 0, SOUTH );
|
|
||||||
}
|
|
||||||
if( faces.contains( EAST ) || faces.contains( UP ) )
|
|
||||||
{
|
|
||||||
line( vertexConsumer, transform, normal, 1, 1, 0, SOUTH );
|
|
||||||
}
|
|
||||||
|
|
||||||
matrixStack.popPose();
|
|
||||||
|
|
||||||
|
transformStack.popPose();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void line( VertexConsumer buffer, Matrix4f transform, Matrix3f normal, float x, float y, float z, Direction direction )
|
private static void line( VertexConsumer buffer, Matrix4f transform, Matrix3f normal, float x, float y, float z, Direction direction )
|
||||||
{
|
{
|
||||||
buffer.vertex( transform, x, y, z )
|
buffer
|
||||||
|
.vertex( transform, x, y, z )
|
||||||
.color( 0, 0, 0, 0.4f )
|
.color( 0, 0, 0, 0.4f )
|
||||||
.normal( normal, direction.getStepX(), direction.getStepY(), direction.getStepZ() )
|
.normal( normal, direction.getStepX(), direction.getStepY(), direction.getStepZ() )
|
||||||
.endVertex();
|
.endVertex();
|
||||||
buffer.vertex( transform, x + direction.getStepX(), y + direction.getStepY(), z + direction.getStepZ() )
|
buffer
|
||||||
|
.vertex( transform,
|
||||||
|
x + direction.getStepX(),
|
||||||
|
y + direction.getStepY(),
|
||||||
|
z + direction.getStepZ()
|
||||||
|
)
|
||||||
.color( 0, 0, 0, 0.4f )
|
.color( 0, 0, 0, 0.4f )
|
||||||
.normal( normal, direction.getStepX(), direction.getStepY(), direction.getStepZ() )
|
.normal( normal, direction.getStepX(), direction.getStepY(), direction.getStepZ() )
|
||||||
.endVertex();
|
.endVertex();
|
||||||
|
|||||||
@@ -29,13 +29,13 @@ public class MonitorTextureBufferShader extends ShaderInstance
|
|||||||
private final Uniform width;
|
private final Uniform width;
|
||||||
private final Uniform height;
|
private final Uniform height;
|
||||||
|
|
||||||
public MonitorTextureBufferShader( ResourceProvider factory, String name, VertexFormat format ) throws IOException
|
public MonitorTextureBufferShader( ResourceProvider provider, String name, VertexFormat format ) throws IOException
|
||||||
{
|
{
|
||||||
super( factory, name, format );
|
super( provider, name, format );
|
||||||
|
|
||||||
width = getUniformChecked( "Width" );
|
width = getUniformChecked( "Width" );
|
||||||
height = getUniformChecked( "Height" );
|
height = getUniformChecked( "Height" );
|
||||||
palette = new Uniform( "Palette", Uniform.UT_FLOAT3 /* UT_FLOAT3 */, 16 * 3, this );
|
palette = new Uniform( "Palette", Uniform.UT_FLOAT3, 16 * 3, this );
|
||||||
updateUniformLocation( palette );
|
updateUniformLocation( palette );
|
||||||
|
|
||||||
Uniform tbo = getUniformChecked( "Tbo" );
|
Uniform tbo = getUniformChecked( "Tbo" );
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.client.render;
|
package dan200.computercraft.client.render;
|
||||||
|
|
||||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||||
@@ -18,31 +17,38 @@ import static dan200.computercraft.shared.media.items.ItemPrintout.LINES_PER_PAG
|
|||||||
|
|
||||||
public final class PrintoutRenderer
|
public final class PrintoutRenderer
|
||||||
{
|
{
|
||||||
|
private static final float BG_SIZE = 256.0f;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Width of a page.
|
* Width of a page.
|
||||||
*/
|
*/
|
||||||
public static final int X_SIZE = 172;
|
public static final int X_SIZE = 172;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Height of a page.
|
* Height of a page.
|
||||||
*/
|
*/
|
||||||
public static final int Y_SIZE = 209;
|
public static final int Y_SIZE = 209;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Padding between the left and right of a page and the text.
|
* Padding between the left and right of a page and the text.
|
||||||
*/
|
*/
|
||||||
public static final int X_TEXT_MARGIN = 13;
|
public static final int X_TEXT_MARGIN = 13;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Padding between the top and bottom of a page and the text.
|
* Padding between the top and bottom of a page and the text.
|
||||||
*/
|
*/
|
||||||
public static final int Y_TEXT_MARGIN = 11;
|
public static final int Y_TEXT_MARGIN = 11;
|
||||||
/**
|
|
||||||
* Size of the leather cover.
|
|
||||||
*/
|
|
||||||
public static final int COVER_SIZE = 12;
|
|
||||||
private static final float BG_SIZE = 256.0f;
|
|
||||||
/**
|
/**
|
||||||
* Width of the extra page texture.
|
* Width of the extra page texture.
|
||||||
*/
|
*/
|
||||||
private static final int X_FOLD_SIZE = 12;
|
private static final int X_FOLD_SIZE = 12;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of the leather cover.
|
||||||
|
*/
|
||||||
|
public static final int COVER_SIZE = 12;
|
||||||
|
|
||||||
private static final int COVER_Y = Y_SIZE;
|
private static final int COVER_Y = Y_SIZE;
|
||||||
private static final int COVER_X = X_SIZE + 4 * X_FOLD_SIZE;
|
private static final int COVER_X = X_SIZE + 4 * X_FOLD_SIZE;
|
||||||
|
|
||||||
@@ -53,18 +59,11 @@ public final class PrintoutRenderer
|
|||||||
VertexConsumer buffer = renderer.getBuffer( RenderTypes.PRINTOUT_TEXT );
|
VertexConsumer buffer = renderer.getBuffer( RenderTypes.PRINTOUT_TEXT );
|
||||||
for( int line = 0; line < LINES_PER_PAGE && line < text.length; line++ )
|
for( int line = 0; line < LINES_PER_PAGE && line < text.length; line++ )
|
||||||
{
|
{
|
||||||
FixedWidthFontRenderer.drawString( transform,
|
FixedWidthFontRenderer.drawString( transform, buffer,
|
||||||
buffer,
|
x, y + line * FONT_HEIGHT, text[start + line], colours[start + line], null, Palette.DEFAULT,
|
||||||
x,
|
false, 0, 0,
|
||||||
y + line * FONT_HEIGHT,
|
light
|
||||||
text[start + line],
|
);
|
||||||
colours[start + line],
|
|
||||||
null,
|
|
||||||
Palette.DEFAULT,
|
|
||||||
false,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
light );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,18 +72,12 @@ public final class PrintoutRenderer
|
|||||||
VertexConsumer buffer = renderer.getBuffer( RenderTypes.PRINTOUT_TEXT );
|
VertexConsumer buffer = renderer.getBuffer( RenderTypes.PRINTOUT_TEXT );
|
||||||
for( int line = 0; line < LINES_PER_PAGE && line < text.length; line++ )
|
for( int line = 0; line < LINES_PER_PAGE && line < text.length; line++ )
|
||||||
{
|
{
|
||||||
FixedWidthFontRenderer.drawString( transform,
|
FixedWidthFontRenderer.drawString( transform, buffer,
|
||||||
buffer,
|
x, y + line * FONT_HEIGHT,
|
||||||
x,
|
new TextBuffer( text[start + line] ), new TextBuffer( colours[start + line] ),
|
||||||
y + line * FONT_HEIGHT,
|
null, Palette.DEFAULT, false, 0, 0,
|
||||||
new TextBuffer( text[start + line] ),
|
light
|
||||||
new TextBuffer( colours[start + line] ),
|
);
|
||||||
null,
|
|
||||||
Palette.DEFAULT,
|
|
||||||
false,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
light );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,18 +100,11 @@ public final class PrintoutRenderer
|
|||||||
drawTexture( transform, buffer, right, y - 8, z - 0.02f, COVER_X + COVER_SIZE, 0, COVER_SIZE, Y_SIZE + COVER_SIZE * 2, light );
|
drawTexture( transform, buffer, right, y - 8, z - 0.02f, COVER_X + COVER_SIZE, 0, COVER_SIZE, Y_SIZE + COVER_SIZE * 2, light );
|
||||||
|
|
||||||
// Draw centre panel (just stretched texture, sorry).
|
// Draw centre panel (just stretched texture, sorry).
|
||||||
drawTexture( transform,
|
drawTexture( transform, buffer,
|
||||||
buffer,
|
x - offset, y, z - 0.02f, X_SIZE + offset * 2, Y_SIZE,
|
||||||
x - offset,
|
COVER_X + COVER_SIZE / 2.0f, COVER_SIZE, COVER_SIZE, Y_SIZE,
|
||||||
y,
|
light
|
||||||
z - 0.02f,
|
);
|
||||||
X_SIZE + offset * 2,
|
|
||||||
Y_SIZE,
|
|
||||||
COVER_X + COVER_SIZE / 2.0f,
|
|
||||||
COVER_SIZE,
|
|
||||||
COVER_SIZE,
|
|
||||||
Y_SIZE,
|
|
||||||
light );
|
|
||||||
|
|
||||||
float borderX = left;
|
float borderX = left;
|
||||||
while( borderX < right )
|
while( borderX < right )
|
||||||
@@ -134,26 +120,27 @@ public final class PrintoutRenderer
|
|||||||
drawTexture( transform, buffer, x, y, z, X_FOLD_SIZE * 2, 0, X_SIZE / 2.0f, Y_SIZE, light );
|
drawTexture( transform, buffer, x, y, z, X_FOLD_SIZE * 2, 0, X_SIZE / 2.0f, Y_SIZE, light );
|
||||||
for( int n = 0; n <= leftPages; n++ )
|
for( int n = 0; n <= leftPages; n++ )
|
||||||
{
|
{
|
||||||
drawTexture( transform, buffer, x - offsetAt( n ), y, z - 1e-3f * n,
|
drawTexture( transform, buffer,
|
||||||
|
x - offsetAt( n ), y, z - 1e-3f * n,
|
||||||
// Use the left "bold" fold for the outermost page
|
// Use the left "bold" fold for the outermost page
|
||||||
n == leftPages ? 0 : X_FOLD_SIZE, 0, X_FOLD_SIZE, Y_SIZE, light );
|
n == leftPages ? 0 : X_FOLD_SIZE, 0,
|
||||||
|
X_FOLD_SIZE, Y_SIZE, light
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Right half
|
// Right half
|
||||||
drawTexture( transform, buffer, x + X_SIZE / 2.0f, y, z, X_FOLD_SIZE * 2 + X_SIZE / 2.0f, 0, X_SIZE / 2.0f, Y_SIZE, light );
|
drawTexture( transform, buffer, x + X_SIZE / 2.0f, y, z, X_FOLD_SIZE * 2 + X_SIZE / 2.0f, 0, X_SIZE / 2.0f, Y_SIZE, light );
|
||||||
for( int n = 0; n <= rightPages; n++ )
|
for( int n = 0; n <= rightPages; n++ )
|
||||||
{
|
{
|
||||||
drawTexture( transform, buffer, x + (X_SIZE - X_FOLD_SIZE) + offsetAt( n ), y, z - 1e-3f * n,
|
drawTexture( transform, buffer,
|
||||||
|
x + (X_SIZE - X_FOLD_SIZE) + offsetAt( n ), y, z - 1e-3f * n,
|
||||||
// Two folds, then the main page. Use the right "bold" fold for the outermost page.
|
// Two folds, then the main page. Use the right "bold" fold for the outermost page.
|
||||||
X_FOLD_SIZE * 2 + X_SIZE + (n == rightPages ? X_FOLD_SIZE : 0), 0, X_FOLD_SIZE, Y_SIZE, light );
|
X_FOLD_SIZE * 2 + X_SIZE + (n == rightPages ? X_FOLD_SIZE : 0), 0,
|
||||||
|
X_FOLD_SIZE, Y_SIZE, light
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float offsetAt( int page )
|
|
||||||
{
|
|
||||||
return (float) (32 * (1 - Math.pow( 1.2, -page )));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void drawTexture( Matrix4f matrix, VertexConsumer buffer, float x, float y, float z, float u, float v, float width, float height, int light )
|
private static void drawTexture( Matrix4f matrix, VertexConsumer buffer, float x, float y, float z, float u, float v, float width, float height, int light )
|
||||||
{
|
{
|
||||||
vertex( buffer, matrix, x, y + height, z, u / BG_SIZE, (v + height) / BG_SIZE, light );
|
vertex( buffer, matrix, x, y + height, z, u / BG_SIZE, (v + height) / BG_SIZE, light );
|
||||||
@@ -162,8 +149,7 @@ public final class PrintoutRenderer
|
|||||||
vertex( buffer, matrix, x, y, z, u / BG_SIZE, v / BG_SIZE, light );
|
vertex( buffer, matrix, x, y, z, u / BG_SIZE, v / BG_SIZE, light );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void drawTexture( Matrix4f matrix, VertexConsumer buffer, float x, float y, float z, float width, float height, float u, float v,
|
private static void drawTexture( Matrix4f matrix, VertexConsumer buffer, float x, float y, float z, float width, float height, float u, float v, float tWidth, float tHeight, int light )
|
||||||
float tWidth, float tHeight, int light )
|
|
||||||
{
|
{
|
||||||
vertex( buffer, matrix, x, y + height, z, u / BG_SIZE, (v + tHeight) / BG_SIZE, light );
|
vertex( buffer, matrix, x, y + height, z, u / BG_SIZE, (v + tHeight) / BG_SIZE, light );
|
||||||
vertex( buffer, matrix, x + width, y + height, z, (u + tWidth) / BG_SIZE, (v + tHeight) / BG_SIZE, light );
|
vertex( buffer, matrix, x + width, y + height, z, (u + tWidth) / BG_SIZE, (v + tHeight) / BG_SIZE, light );
|
||||||
@@ -175,4 +161,9 @@ public final class PrintoutRenderer
|
|||||||
{
|
{
|
||||||
buffer.vertex( matrix, x, y, z ).color( 255, 255, 255, 255 ).uv( u, v ).uv2( light ).endVertex();
|
buffer.vertex( matrix, x, y, z ).color( 255, 255, 255, 255 ).uv( u, v ).uv2( light ).endVertex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static float offsetAt( int page )
|
||||||
|
{
|
||||||
|
return (float) (32 * (1 - Math.pow( 1.2, -page )));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,25 +14,26 @@ import net.minecraft.client.renderer.ShaderInstance;
|
|||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
public class RenderTypes
|
public class RenderTypes
|
||||||
{
|
{
|
||||||
|
|
||||||
public static final int FULL_BRIGHT_LIGHTMAP = (0xF << 4) | (0xF << 20);
|
public static final int FULL_BRIGHT_LIGHTMAP = (0xF << 4) | (0xF << 20);
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public static MonitorTextureBufferShader monitorTboShader;
|
public static MonitorTextureBufferShader monitorTboShader;
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public static ShaderInstance terminalShader;
|
public static ShaderInstance terminalShader;
|
||||||
|
|
||||||
public static final RenderType TERMINAL_WITHOUT_DEPTH = Types.TERMINAL_WITHOUT_DEPTH;
|
public static final RenderType TERMINAL_WITHOUT_DEPTH = Types.TERMINAL_WITHOUT_DEPTH;
|
||||||
public static final RenderType MONITOR_TBO = Types.MONITOR_TBO;
|
public static final RenderType TERMINAL_BLOCKER = Types.TERMINAL_BLOCKER;
|
||||||
public static final RenderType TERMINAL_BLOCKER = Types.BLOCKER;
|
|
||||||
public static final RenderType TERMINAL_WITH_DEPTH = Types.TERMINAL_WITH_DEPTH;
|
public static final RenderType TERMINAL_WITH_DEPTH = Types.TERMINAL_WITH_DEPTH;
|
||||||
|
public static final RenderType MONITOR_TBO = Types.MONITOR_TBO;
|
||||||
public static final RenderType PRINTOUT_TEXT = Types.PRINTOUT_TEXT;
|
public static final RenderType PRINTOUT_TEXT = Types.PRINTOUT_TEXT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This looks wrong (it should be POSITION_COLOR_TEX_LIGHTMAP surely!) but the fragment/vertex shader for that
|
||||||
|
* appear to entirely ignore the lightmap.
|
||||||
|
*
|
||||||
|
* Note that vanilla maps do the same, so this isn't unreasonable.
|
||||||
|
*/
|
||||||
public static final RenderType PRINTOUT_BACKGROUND = RenderType.text( new ResourceLocation( "computercraft", "textures/gui/printout.png" ) );
|
public static final RenderType PRINTOUT_BACKGROUND = RenderType.text( new ResourceLocation( "computercraft", "textures/gui/printout.png" ) );
|
||||||
|
|
||||||
public static final RenderType POSITION_COLOR = Types.POSITION_COLOR;
|
public static final RenderType POSITION_COLOR = Types.POSITION_COLOR;
|
||||||
@@ -53,24 +54,26 @@ public class RenderTypes
|
|||||||
|
|
||||||
private static final class Types extends RenderStateShard
|
private static final class Types extends RenderStateShard
|
||||||
{
|
{
|
||||||
private static final VertexFormat.Mode GL_MODE = VertexFormat.Mode.TRIANGLES;
|
private static final RenderStateShard.TextureStateShard TERM_FONT_TEXTURE = new TextureStateShard(
|
||||||
private static final VertexFormat FORMAT = DefaultVertexFormat.POSITION_COLOR_TEX;
|
|
||||||
private static final ShaderStateShard TERM_SHADER = new ShaderStateShard( RenderTypes::getTerminalShader );
|
|
||||||
|
|
||||||
private static final RenderStateShard.TextureStateShard TERM_FONT_TEXTURE = new RenderStateShard.TextureStateShard(
|
|
||||||
FixedWidthFontRenderer.FONT,
|
FixedWidthFontRenderer.FONT,
|
||||||
false, false // blur, minimap
|
false, false // blur, minimap
|
||||||
);
|
);
|
||||||
|
private static final VertexFormat TERM_FORMAT = DefaultVertexFormat.POSITION_COLOR_TEX;
|
||||||
|
private static final VertexFormat.Mode TERM_MODE = VertexFormat.Mode.TRIANGLES;
|
||||||
|
private static final ShaderStateShard TERM_SHADER = new ShaderStateShard( RenderTypes::getTerminalShader );
|
||||||
|
|
||||||
public static final RenderType MONITOR_TBO = RenderType.create( "monitor_tbo", DefaultVertexFormat.POSITION_TEX, VertexFormat.Mode.TRIANGLE_STRIP, 128, false, false, // useDelegate, needsSorting
|
static final RenderType MONITOR_TBO = RenderType.create(
|
||||||
|
"monitor_tbo", DefaultVertexFormat.POSITION_TEX, VertexFormat.Mode.TRIANGLE_STRIP, 128,
|
||||||
|
false, false, // useDelegate, needsSorting
|
||||||
RenderType.CompositeState.builder()
|
RenderType.CompositeState.builder()
|
||||||
.setTextureState( TERM_FONT_TEXTURE ) // blur, minimap
|
.setTextureState( TERM_FONT_TEXTURE )
|
||||||
.setShaderState( new RenderStateShard.ShaderStateShard( RenderTypes::getMonitorTextureBufferShader ) )
|
.setShaderState( new ShaderStateShard( RenderTypes::getMonitorTextureBufferShader ) )
|
||||||
.setWriteMaskState( RenderType.COLOR_DEPTH_WRITE )
|
.setWriteMaskState( COLOR_WRITE )
|
||||||
.createCompositeState( false ) );
|
.createCompositeState( false )
|
||||||
|
);
|
||||||
|
|
||||||
static final RenderType TERMINAL_WITHOUT_DEPTH = RenderType.create(
|
static final RenderType TERMINAL_WITHOUT_DEPTH = RenderType.create(
|
||||||
"terminal_without_depth", FORMAT, GL_MODE, 1024,
|
"terminal_without_depth", TERM_FORMAT, TERM_MODE, 1024,
|
||||||
false, false, // useDelegate, needsSorting
|
false, false, // useDelegate, needsSorting
|
||||||
RenderType.CompositeState.builder()
|
RenderType.CompositeState.builder()
|
||||||
.setTextureState( TERM_FONT_TEXTURE )
|
.setTextureState( TERM_FONT_TEXTURE )
|
||||||
@@ -79,15 +82,18 @@ public class RenderTypes
|
|||||||
.createCompositeState( false )
|
.createCompositeState( false )
|
||||||
);
|
);
|
||||||
|
|
||||||
static final RenderType BLOCKER = RenderType.create( "terminal_blocker", FORMAT, GL_MODE, 256, false, false, // useDelegate, needsSorting
|
static final RenderType TERMINAL_BLOCKER = RenderType.create(
|
||||||
|
"terminal_blocker", TERM_FORMAT, TERM_MODE, 256,
|
||||||
|
false, false, // useDelegate, needsSorting
|
||||||
RenderType.CompositeState.builder()
|
RenderType.CompositeState.builder()
|
||||||
.setTextureState( TERM_FONT_TEXTURE )
|
.setTextureState( TERM_FONT_TEXTURE )
|
||||||
.setShaderState( TERM_SHADER )
|
.setShaderState( TERM_SHADER )
|
||||||
.setWriteMaskState( DEPTH_WRITE )
|
.setWriteMaskState( DEPTH_WRITE )
|
||||||
.createCompositeState( false ) );
|
.createCompositeState( false )
|
||||||
|
);
|
||||||
|
|
||||||
static final RenderType TERMINAL_WITH_DEPTH = RenderType.create(
|
static final RenderType TERMINAL_WITH_DEPTH = RenderType.create(
|
||||||
"terminal_with_depth", FORMAT, GL_MODE, 1024,
|
"terminal_with_depth", TERM_FORMAT, TERM_MODE, 1024,
|
||||||
false, false, // useDelegate, needsSorting
|
false, false, // useDelegate, needsSorting
|
||||||
RenderType.CompositeState.builder()
|
RenderType.CompositeState.builder()
|
||||||
.setTextureState( TERM_FONT_TEXTURE )
|
.setTextureState( TERM_FONT_TEXTURE )
|
||||||
@@ -95,8 +101,11 @@ public class RenderTypes
|
|||||||
.createCompositeState( false )
|
.createCompositeState( false )
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A variant of {@link #TERMINAL_WITH_DEPTH} which uses the lightmap rather than rendering fullbright.
|
||||||
|
*/
|
||||||
static final RenderType PRINTOUT_TEXT = RenderType.create(
|
static final RenderType PRINTOUT_TEXT = RenderType.create(
|
||||||
"printout_text", DefaultVertexFormat.POSITION_COLOR_TEX_LIGHTMAP, GL_MODE, 1024,
|
"printout_text", DefaultVertexFormat.POSITION_COLOR_TEX_LIGHTMAP, TERM_MODE, 1024,
|
||||||
false, false, // useDelegate, needsSorting
|
false, false, // useDelegate, needsSorting
|
||||||
RenderType.CompositeState.builder()
|
RenderType.CompositeState.builder()
|
||||||
.setTextureState( TERM_FONT_TEXTURE )
|
.setTextureState( TERM_FONT_TEXTURE )
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.client.render;
|
package dan200.computercraft.client.render;
|
||||||
|
|
||||||
import com.mojang.blaze3d.platform.GlStateManager;
|
import com.mojang.blaze3d.platform.GlStateManager;
|
||||||
|
import com.mojang.blaze3d.platform.MemoryTracker;
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
import com.mojang.blaze3d.vertex.*;
|
import com.mojang.blaze3d.vertex.*;
|
||||||
import com.mojang.math.Matrix4f;
|
import com.mojang.math.Matrix4f;
|
||||||
@@ -35,27 +35,25 @@ import org.lwjgl.opengl.GL31;
|
|||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
import static com.mojang.blaze3d.platform.MemoryTracker.create;
|
|
||||||
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.*;
|
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.*;
|
||||||
|
|
||||||
public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonitor>
|
public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonitor>
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* {@link TileMonitor#RENDER_MARGIN}, but a tiny bit of additional padding to ensure that there is no space between the monitor frame and contents.
|
* {@link TileMonitor#RENDER_MARGIN}, but a tiny bit of additional padding to ensure that there is no space between
|
||||||
|
* the monitor frame and contents.
|
||||||
*/
|
*/
|
||||||
private static final float MARGIN = (float) (TileMonitor.RENDER_MARGIN * 1.1);
|
private static final float MARGIN = (float) (TileMonitor.RENDER_MARGIN * 1.1);
|
||||||
private static final Matrix4f IDENTITY = Transformation.identity()
|
|
||||||
.getMatrix();
|
|
||||||
private static ByteBuffer tboContents;
|
private static ByteBuffer tboContents;
|
||||||
|
|
||||||
|
private static final Matrix4f IDENTITY = Transformation.identity().getMatrix();
|
||||||
|
|
||||||
public TileEntityMonitorRenderer( BlockEntityRendererProvider.Context context )
|
public TileEntityMonitorRenderer( BlockEntityRendererProvider.Context context )
|
||||||
{
|
{
|
||||||
// super( context );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render( @Nonnull TileMonitor monitor, float partialTicks, @Nonnull PoseStack transform, @Nonnull MultiBufferSource renderer,
|
public void render( @Nonnull TileMonitor monitor, float partialTicks, @Nonnull PoseStack transform, @Nonnull MultiBufferSource renderer, int lightmapCoord, int overlayLight )
|
||||||
int lightmapCoord, int overlayLight )
|
|
||||||
{
|
{
|
||||||
// Render from the origin monitor
|
// Render from the origin monitor
|
||||||
ClientMonitor originTerminal = monitor.getClientMonitor();
|
ClientMonitor originTerminal = monitor.getClientMonitor();
|
||||||
@@ -86,15 +84,19 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito
|
|||||||
|
|
||||||
// Setup initial transform
|
// Setup initial transform
|
||||||
transform.pushPose();
|
transform.pushPose();
|
||||||
transform.translate( originPos.getX() - monitorPos.getX() + 0.5,
|
transform.translate(
|
||||||
|
originPos.getX() - monitorPos.getX() + 0.5,
|
||||||
originPos.getY() - monitorPos.getY() + 0.5,
|
originPos.getY() - monitorPos.getY() + 0.5,
|
||||||
originPos.getZ() - monitorPos.getZ() + 0.5 );
|
originPos.getZ() - monitorPos.getZ() + 0.5
|
||||||
|
);
|
||||||
|
|
||||||
transform.mulPose( Vector3f.YN.rotationDegrees( yaw ) );
|
transform.mulPose( Vector3f.YN.rotationDegrees( yaw ) );
|
||||||
transform.mulPose( Vector3f.XP.rotationDegrees( pitch ) );
|
transform.mulPose( Vector3f.XP.rotationDegrees( pitch ) );
|
||||||
transform.translate( -0.5 + TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN,
|
transform.translate(
|
||||||
|
-0.5 + TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN,
|
||||||
origin.getHeight() - 0.5 - (TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN) + 0,
|
origin.getHeight() - 0.5 - (TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN) + 0,
|
||||||
0.50 );
|
0.5
|
||||||
|
);
|
||||||
double xSize = origin.getWidth() - 2.0 * (TileMonitor.RENDER_MARGIN + TileMonitor.RENDER_BORDER);
|
double xSize = origin.getWidth() - 2.0 * (TileMonitor.RENDER_MARGIN + TileMonitor.RENDER_BORDER);
|
||||||
double ySize = origin.getHeight() - 2.0 * (TileMonitor.RENDER_MARGIN + TileMonitor.RENDER_BORDER);
|
double ySize = origin.getHeight() - 2.0 * (TileMonitor.RENDER_MARGIN + TileMonitor.RENDER_BORDER);
|
||||||
|
|
||||||
@@ -116,58 +118,56 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito
|
|||||||
|
|
||||||
// We don't draw the cursor with the VBO, as it's dynamic and so we'll end up refreshing far more than is
|
// We don't draw the cursor with the VBO, as it's dynamic and so we'll end up refreshing far more than is
|
||||||
// reasonable.
|
// reasonable.
|
||||||
FixedWidthFontRenderer.drawCursor( matrix, renderer.getBuffer( RenderTypes.TERMINAL_WITHOUT_DEPTH ), 0, 0, terminal, !originTerminal.isColour() );
|
FixedWidthFontRenderer.drawCursor(
|
||||||
|
matrix, renderer.getBuffer( RenderTypes.TERMINAL_WITHOUT_DEPTH ),
|
||||||
|
0, 0, terminal, !originTerminal.isColour()
|
||||||
|
);
|
||||||
|
|
||||||
transform.popPose();
|
transform.popPose();
|
||||||
|
|
||||||
// Draw the background blocker
|
|
||||||
FixedWidthFontRenderer.drawBlocker(
|
FixedWidthFontRenderer.drawBlocker(
|
||||||
transform.last().pose(), renderer,
|
transform.last().pose(), renderer,
|
||||||
-MARGIN, MARGIN,
|
-MARGIN, MARGIN,
|
||||||
(float) (xSize + 2 * MARGIN), (float) -(ySize + MARGIN * 2)
|
(float) (xSize + 2 * MARGIN), (float) -(ySize + MARGIN * 2)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Force a flush of the blocker. WorldRenderer.updateCameraAndRender will "finish" all the built-in
|
||||||
|
// buffers before calling renderer.finish, which means the blocker isn't actually rendered at that point!
|
||||||
renderer.getBuffer( RenderType.solid() );
|
renderer.getBuffer( RenderType.solid() );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FixedWidthFontRenderer.drawEmptyTerminal( transform.last()
|
FixedWidthFontRenderer.drawEmptyTerminal(
|
||||||
.pose(),
|
transform.last().pose(), renderer,
|
||||||
renderer,
|
-MARGIN, MARGIN,
|
||||||
-MARGIN,
|
(float) (xSize + 2 * MARGIN), (float) -(ySize + MARGIN * 2)
|
||||||
MARGIN,
|
);
|
||||||
(float) (xSize + 2 * MARGIN),
|
|
||||||
(float) -(ySize + MARGIN * 2) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
transform.popPose();
|
transform.popPose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void renderTerminal( MultiBufferSource renderer, Matrix4f matrix, ClientMonitor monitor, float xMargin, float yMargin )
|
private static void renderTerminal( @Nonnull MultiBufferSource renderer, Matrix4f matrix, ClientMonitor monitor, float xMargin, float yMargin )
|
||||||
{
|
{
|
||||||
Terminal terminal = monitor.getTerminal();
|
Terminal terminal = monitor.getTerminal();
|
||||||
|
|
||||||
MonitorRenderer renderType = MonitorRenderer.current();
|
MonitorRenderer renderType = MonitorRenderer.current();
|
||||||
boolean redraw = monitor.pollTerminalChanged();
|
boolean redraw = monitor.pollTerminalChanged();
|
||||||
if( monitor.createBuffer( renderType ) )
|
if( monitor.createBuffer( renderType ) ) redraw = true;
|
||||||
{
|
|
||||||
redraw = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch( renderType )
|
switch( renderType )
|
||||||
{
|
{
|
||||||
case TBO:
|
case TBO:
|
||||||
{
|
{
|
||||||
|
|
||||||
int width = terminal.getWidth(), height = terminal.getHeight();
|
int width = terminal.getWidth(), height = terminal.getHeight();
|
||||||
int pixelWidth = width * FONT_WIDTH, pixelHeight = height * FONT_HEIGHT;
|
|
||||||
|
|
||||||
|
int pixelWidth = width * FONT_WIDTH, pixelHeight = height * FONT_HEIGHT;
|
||||||
if( redraw )
|
if( redraw )
|
||||||
{
|
{
|
||||||
int size = width * height * 3;
|
int size = width * height * 3;
|
||||||
if( tboContents == null || tboContents.capacity() < size )
|
if( tboContents == null || tboContents.capacity() < size )
|
||||||
{
|
{
|
||||||
tboContents = create( size );
|
tboContents = MemoryTracker.create( size );
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteBuffer monitorBuffer = tboContents;
|
ByteBuffer monitorBuffer = tboContents;
|
||||||
@@ -204,37 +204,34 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito
|
|||||||
tboVertex( buffer, matrix, pixelWidth + xMargin, -yMargin );
|
tboVertex( buffer, matrix, pixelWidth + xMargin, -yMargin );
|
||||||
tboVertex( buffer, matrix, pixelWidth + xMargin, pixelHeight + yMargin );
|
tboVertex( buffer, matrix, pixelWidth + xMargin, pixelHeight + yMargin );
|
||||||
|
|
||||||
|
// And force things to flush. We strictly speaking do this later on anyway for the cursor, but nice to
|
||||||
|
// be consistent.
|
||||||
renderer.getBuffer( RenderTypes.TERMINAL_WITHOUT_DEPTH );
|
renderer.getBuffer( RenderTypes.TERMINAL_WITHOUT_DEPTH );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case VBO:
|
case VBO:
|
||||||
|
{
|
||||||
VertexBuffer vbo = monitor.buffer;
|
VertexBuffer vbo = monitor.buffer;
|
||||||
if( redraw )
|
if( redraw )
|
||||||
{
|
{
|
||||||
Tesselator tessellator = Tesselator.getInstance();
|
Tesselator tessellator = Tesselator.getInstance();
|
||||||
BufferBuilder builder = tessellator.getBuilder();
|
BufferBuilder builder = tessellator.getBuilder();
|
||||||
builder.begin( RenderTypes.TERMINAL_WITHOUT_DEPTH.mode(), RenderTypes.TERMINAL_WITHOUT_DEPTH.format() );
|
builder.begin( RenderTypes.TERMINAL_WITHOUT_DEPTH.mode(), RenderTypes.TERMINAL_WITHOUT_DEPTH.format() );
|
||||||
FixedWidthFontRenderer.drawTerminalWithoutCursor( IDENTITY,
|
FixedWidthFontRenderer.drawTerminalWithoutCursor(
|
||||||
builder,
|
IDENTITY, builder, 0, 0,
|
||||||
0,
|
terminal, !monitor.isColour(), yMargin, yMargin, xMargin, xMargin
|
||||||
0,
|
);
|
||||||
terminal,
|
|
||||||
!monitor.isColour(),
|
|
||||||
yMargin,
|
|
||||||
yMargin,
|
|
||||||
xMargin,
|
|
||||||
xMargin );
|
|
||||||
|
|
||||||
builder.end();
|
builder.end();
|
||||||
vbo.upload( builder );
|
vbo.upload( builder );
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer.getBuffer( RenderTypes.TERMINAL_WITHOUT_DEPTH );
|
renderer.getBuffer( RenderTypes.TERMINAL_WITHOUT_DEPTH );
|
||||||
|
|
||||||
RenderTypes.TERMINAL_WITHOUT_DEPTH.setupRenderState();
|
RenderTypes.TERMINAL_WITHOUT_DEPTH.setupRenderState();
|
||||||
vbo.drawWithShader( matrix, RenderSystem.getProjectionMatrix(), RenderTypes.getTerminalShader() );
|
vbo.drawWithShader( matrix, RenderSystem.getProjectionMatrix(), RenderTypes.getTerminalShader() );
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public class TileEntityTurtleRenderer implements BlockEntityRenderer<TileTurtle>
|
|||||||
|
|
||||||
private final Random random = new Random( 0 );
|
private final Random random = new Random( 0 );
|
||||||
|
|
||||||
BlockEntityRenderDispatcher renderer;
|
private final BlockEntityRenderDispatcher renderer;
|
||||||
|
|
||||||
public TileEntityTurtleRenderer( BlockEntityRendererProvider.Context context )
|
public TileEntityTurtleRenderer( BlockEntityRendererProvider.Context context )
|
||||||
{
|
{
|
||||||
@@ -68,39 +68,28 @@ public class TileEntityTurtleRenderer implements BlockEntityRenderer<TileTurtle>
|
|||||||
|
|
||||||
public static ModelResourceLocation getTurtleOverlayModel( ResourceLocation overlay, boolean christmas )
|
public static ModelResourceLocation getTurtleOverlayModel( ResourceLocation overlay, boolean christmas )
|
||||||
{
|
{
|
||||||
if( overlay != null )
|
if( overlay != null ) return new ModelResourceLocation( overlay, "inventory" );
|
||||||
{
|
if( christmas ) return ELF_OVERLAY_MODEL;
|
||||||
return new ModelResourceLocation( overlay, "inventory" );
|
|
||||||
}
|
|
||||||
if( christmas )
|
|
||||||
{
|
|
||||||
return ELF_OVERLAY_MODEL;
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render( @Nonnull TileTurtle turtle, float partialTicks, @Nonnull PoseStack transform, @Nonnull MultiBufferSource buffers,
|
public void render( @Nonnull TileTurtle turtle, float partialTicks, @Nonnull PoseStack transform, @Nonnull MultiBufferSource buffers, int lightmapCoord, int overlayLight )
|
||||||
int lightmapCoord, int overlayLight )
|
|
||||||
{
|
{
|
||||||
// Render the label
|
// Render the label
|
||||||
String label = turtle.createProxy()
|
String label = turtle.createProxy().getLabel();
|
||||||
.getLabel();
|
|
||||||
HitResult hit = renderer.cameraHitResult;
|
HitResult hit = renderer.cameraHitResult;
|
||||||
if( label != null && hit.getType() == HitResult.Type.BLOCK && turtle.getBlockPos()
|
if( label != null && hit.getType() == HitResult.Type.BLOCK && turtle.getBlockPos().equals( ((BlockHitResult) hit).getBlockPos() ) )
|
||||||
.equals( ((BlockHitResult) hit).getBlockPos() ) )
|
|
||||||
{
|
{
|
||||||
Minecraft mc = Minecraft.getInstance();
|
Minecraft mc = Minecraft.getInstance();
|
||||||
Font font = mc.font;
|
Font font = mc.font;
|
||||||
|
|
||||||
transform.pushPose();
|
transform.pushPose();
|
||||||
transform.translate( 0.5, 1.2, 0.5 );
|
transform.translate( 0.5, 1.2, 0.5 );
|
||||||
transform.mulPose( mc.getEntityRenderDispatcher()
|
transform.mulPose( mc.getEntityRenderDispatcher().cameraOrientation() );
|
||||||
.cameraOrientation() );
|
|
||||||
transform.scale( -0.025f, -0.025f, 0.025f );
|
transform.scale( -0.025f, -0.025f, 0.025f );
|
||||||
|
|
||||||
Matrix4f matrix = transform.last()
|
Matrix4f matrix = transform.last().pose();
|
||||||
.pose();
|
|
||||||
int opacity = (int) (mc.options.getBackgroundOpacity( 0.25f ) * 255) << 24;
|
int opacity = (int) (mc.options.getBackgroundOpacity( 0.25f ) * 255) << 24;
|
||||||
float width = -font.width( label ) / 2.0f;
|
float width = -font.width( label ) / 2.0f;
|
||||||
font.drawInBatch( label, width, (float) 0, 0x20ffffff, false, matrix, buffers, true, opacity, lightmapCoord );
|
font.drawInBatch( label, width, (float) 0, 0x20ffffff, false, matrix, buffers, true, opacity, lightmapCoord );
|
||||||
@@ -147,14 +136,10 @@ public class TileEntityTurtleRenderer implements BlockEntityRenderer<TileTurtle>
|
|||||||
transform.popPose();
|
transform.popPose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderUpgrade( @Nonnull PoseStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, TileTurtle turtle,
|
private void renderUpgrade( @Nonnull PoseStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, TileTurtle turtle, TurtleSide side, float f )
|
||||||
TurtleSide side, float f )
|
|
||||||
{
|
{
|
||||||
ITurtleUpgrade upgrade = turtle.getUpgrade( side );
|
ITurtleUpgrade upgrade = turtle.getUpgrade( side );
|
||||||
if( upgrade == null )
|
if( upgrade == null ) return;
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
transform.pushPose();
|
transform.pushPose();
|
||||||
|
|
||||||
float toolAngle = turtle.getToolRenderAngle( side, f );
|
float toolAngle = turtle.getToolRenderAngle( side, f );
|
||||||
@@ -170,18 +155,13 @@ public class TileEntityTurtleRenderer implements BlockEntityRenderer<TileTurtle>
|
|||||||
transform.popPose();
|
transform.popPose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderModel( @Nonnull PoseStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight,
|
private void renderModel( @Nonnull PoseStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, ModelResourceLocation modelLocation, int[] tints )
|
||||||
ModelResourceLocation modelLocation, int[] tints )
|
|
||||||
{
|
{
|
||||||
ModelManager modelManager = Minecraft.getInstance()
|
ModelManager modelManager = Minecraft.getInstance().getItemRenderer().getItemModelShaper().getModelManager();
|
||||||
.getItemRenderer()
|
|
||||||
.getItemModelShaper()
|
|
||||||
.getModelManager();
|
|
||||||
renderModel( transform, renderer, lightmapCoord, overlayLight, modelManager.getModel( modelLocation ), tints );
|
renderModel( transform, renderer, lightmapCoord, overlayLight, modelManager.getModel( modelLocation ), tints );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderModel( @Nonnull PoseStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, BakedModel model,
|
private void renderModel( @Nonnull PoseStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, BakedModel model, int[] tints )
|
||||||
int[] tints )
|
|
||||||
{
|
{
|
||||||
random.setSeed( 0 );
|
random.setSeed( 0 );
|
||||||
renderQuads( transform, renderer, lightmapCoord, overlayLight, model.getQuads( null, null, random ), tints );
|
renderQuads( transform, renderer, lightmapCoord, overlayLight, model.getQuads( null, null, random ), tints );
|
||||||
@@ -191,8 +171,7 @@ public class TileEntityTurtleRenderer implements BlockEntityRenderer<TileTurtle>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void renderQuads( @Nonnull PoseStack transform, @Nonnull VertexConsumer buffer, int lightmapCoord, int overlayLight,
|
private static void renderQuads( @Nonnull PoseStack transform, @Nonnull VertexConsumer buffer, int lightmapCoord, int overlayLight, List<BakedQuad> quads, int[] tints )
|
||||||
List<BakedQuad> quads, int[] tints )
|
|
||||||
{
|
{
|
||||||
PoseStack.Pose matrix = transform.last();
|
PoseStack.Pose matrix = transform.last();
|
||||||
|
|
||||||
@@ -202,10 +181,7 @@ public class TileEntityTurtleRenderer implements BlockEntityRenderer<TileTurtle>
|
|||||||
if( tints != null && bakedquad.isTinted() )
|
if( tints != null && bakedquad.isTinted() )
|
||||||
{
|
{
|
||||||
int idx = bakedquad.getTintIndex();
|
int idx = bakedquad.getTintIndex();
|
||||||
if( idx >= 0 && idx < tints.length )
|
if( idx >= 0 && idx < tints.length ) tint = tints[bakedquad.getTintIndex()];
|
||||||
{
|
|
||||||
tint = tints[bakedquad.getTintIndex()];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float f = (float) (tint >> 16 & 255) / 255.0F;
|
float f = (float) (tint >> 16 & 255) / 255.0F;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.client.render;
|
package dan200.computercraft.client.render;
|
||||||
|
|
||||||
import com.mojang.datafixers.util.Pair;
|
import com.mojang.datafixers.util.Pair;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.client.render;
|
package dan200.computercraft.client.render;
|
||||||
|
|
||||||
import com.mojang.math.Transformation;
|
import com.mojang.math.Transformation;
|
||||||
@@ -32,8 +31,7 @@ public class TurtleMultiModel implements BakedModel
|
|||||||
private List<BakedQuad> generalQuads = null;
|
private List<BakedQuad> generalQuads = null;
|
||||||
private final Map<Direction, List<BakedQuad>> faceQuads = new EnumMap<>( Direction.class );
|
private final Map<Direction, List<BakedQuad>> faceQuads = new EnumMap<>( Direction.class );
|
||||||
|
|
||||||
public TurtleMultiModel( BakedModel baseModel, BakedModel overlayModel, Transformation generalTransform, TransformedModel leftUpgradeModel,
|
public TurtleMultiModel( BakedModel baseModel, BakedModel overlayModel, Transformation generalTransform, TransformedModel leftUpgradeModel, TransformedModel rightUpgradeModel )
|
||||||
TransformedModel rightUpgradeModel )
|
|
||||||
{
|
{
|
||||||
// Get the models
|
// Get the models
|
||||||
this.baseModel = baseModel;
|
this.baseModel = baseModel;
|
||||||
@@ -45,22 +43,17 @@ public class TurtleMultiModel implements BakedModel
|
|||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public List<BakedQuad> getQuads( BlockState state, Direction side, @Nonnull Random rand )
|
public List<BakedQuad> getQuads( BlockState state, Direction side, @Nonnull Random rand )
|
||||||
{
|
{
|
||||||
if( side != null )
|
if( side != null )
|
||||||
{
|
{
|
||||||
if( !faceQuads.containsKey( side ) )
|
if( !faceQuads.containsKey( side ) ) faceQuads.put( side, buildQuads( state, side, rand ) );
|
||||||
{
|
|
||||||
faceQuads.put( side, buildQuads( state, side, rand ) );
|
|
||||||
}
|
|
||||||
return faceQuads.get( side );
|
return faceQuads.get( side );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if( generalQuads == null )
|
if( generalQuads == null ) generalQuads = buildQuads( state, side, rand );
|
||||||
{
|
|
||||||
generalQuads = buildQuads( state, side, rand );
|
|
||||||
}
|
|
||||||
return generalQuads;
|
return generalQuads;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -70,24 +63,20 @@ public class TurtleMultiModel implements BakedModel
|
|||||||
ArrayList<BakedQuad> quads = new ArrayList<>();
|
ArrayList<BakedQuad> quads = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
ModelTransformer.transformQuadsTo( quads, baseModel.getQuads( state, side, rand ), generalTransform.getMatrix() );
|
transformQuadsTo( quads, baseModel.getQuads( state, side, rand ), generalTransform );
|
||||||
if( overlayModel != null )
|
if( overlayModel != null )
|
||||||
{
|
{
|
||||||
ModelTransformer.transformQuadsTo( quads, overlayModel.getQuads( state, side, rand ), generalTransform.getMatrix() );
|
transformQuadsTo( quads, overlayModel.getQuads( state, side, rand ), generalTransform );
|
||||||
}
|
}
|
||||||
if( leftUpgradeModel != null )
|
if( leftUpgradeModel != null )
|
||||||
{
|
{
|
||||||
Transformation upgradeTransform = generalTransform.compose( leftUpgradeModel.getMatrix() );
|
Transformation upgradeTransform = generalTransform.compose( leftUpgradeModel.getMatrix() );
|
||||||
ModelTransformer.transformQuadsTo( quads, leftUpgradeModel.getModel()
|
transformQuadsTo( quads, leftUpgradeModel.getModel().getQuads( state, side, rand ), upgradeTransform );
|
||||||
.getQuads( state, side, rand ),
|
|
||||||
upgradeTransform.getMatrix() );
|
|
||||||
}
|
}
|
||||||
if( rightUpgradeModel != null )
|
if( rightUpgradeModel != null )
|
||||||
{
|
{
|
||||||
Transformation upgradeTransform = generalTransform.compose( rightUpgradeModel.getMatrix() );
|
Transformation upgradeTransform = generalTransform.compose( rightUpgradeModel.getMatrix() );
|
||||||
ModelTransformer.transformQuadsTo( quads, rightUpgradeModel.getModel()
|
transformQuadsTo( quads, rightUpgradeModel.getModel().getQuads( state, side, rand ), upgradeTransform );
|
||||||
.getQuads( state, side, rand ),
|
|
||||||
upgradeTransform.getMatrix() );
|
|
||||||
}
|
}
|
||||||
quads.trimToSize();
|
quads.trimToSize();
|
||||||
return quads;
|
return quads;
|
||||||
@@ -105,18 +94,18 @@ public class TurtleMultiModel implements BakedModel
|
|||||||
return baseModel.isGui3d();
|
return baseModel.isGui3d();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean usesBlockLight()
|
|
||||||
{
|
|
||||||
return baseModel.usesBlockLight();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCustomRenderer()
|
public boolean isCustomRenderer()
|
||||||
{
|
{
|
||||||
return baseModel.isCustomRenderer();
|
return baseModel.isCustomRenderer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean usesBlockLight()
|
||||||
|
{
|
||||||
|
return baseModel.usesBlockLight();
|
||||||
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@@ -139,4 +128,9 @@ public class TurtleMultiModel implements BakedModel
|
|||||||
{
|
{
|
||||||
return ItemOverrides.EMPTY;
|
return ItemOverrides.EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void transformQuadsTo( List<BakedQuad> output, List<BakedQuad> quads, Transformation transform )
|
||||||
|
{
|
||||||
|
ModelTransformer.transformQuadsTo( output, quads, transform.getMatrix() );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,16 +15,10 @@ import net.minecraft.resources.ResourceLocation;
|
|||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
public class TurtlePlayerRenderer extends EntityRenderer<TurtlePlayer>
|
public class TurtlePlayerRenderer extends EntityRenderer<TurtlePlayer>
|
||||||
{ //FIXME Make sure this isn't an issue. Context was EntityRenderDispatcher.
|
{
|
||||||
public TurtlePlayerRenderer( EntityRendererProvider.Context context )
|
public TurtlePlayerRenderer( EntityRendererProvider.Context renderManager )
|
||||||
{
|
|
||||||
super( context );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void render( @Nonnull TurtlePlayer entityIn, float entityYaw, float partialTicks, @Nonnull PoseStack transform,
|
|
||||||
@Nonnull MultiBufferSource buffer, int packedLightIn )
|
|
||||||
{
|
{
|
||||||
|
super( renderManager );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@@ -33,4 +27,9 @@ public class TurtlePlayerRenderer extends EntityRenderer<TurtlePlayer>
|
|||||||
{
|
{
|
||||||
return ComputerBorderRenderer.BACKGROUND_NORMAL;
|
return ComputerBorderRenderer.BACKGROUND_NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render( @Nonnull TurtlePlayer entityIn, float entityYaw, float partialTicks, @Nonnull PoseStack transform, @Nonnull MultiBufferSource buffer, int packedLightIn )
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
*/
|
*/
|
||||||
package dan200.computercraft.client.render;
|
package dan200.computercraft.client.render;
|
||||||
|
|
||||||
import com.google.common.base.Objects;
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import com.mojang.math.Transformation;
|
import com.mojang.math.Transformation;
|
||||||
import dan200.computercraft.api.client.TransformedModel;
|
import dan200.computercraft.api.client.TransformedModel;
|
||||||
@@ -50,59 +49,18 @@ public class TurtleSmartItemModel implements BakedModel
|
|||||||
stack.translate( 0, 0, 1 );
|
stack.translate( 0, 0, 1 );
|
||||||
|
|
||||||
identity = Transformation.identity();
|
identity = Transformation.identity();
|
||||||
flip = new Transformation( stack.last()
|
flip = new Transformation( stack.last().pose() );
|
||||||
.pose() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class TurtleModelCombination
|
private static record TurtleModelCombination(
|
||||||
|
boolean colour,
|
||||||
|
ITurtleUpgrade leftUpgrade,
|
||||||
|
ITurtleUpgrade rightUpgrade,
|
||||||
|
ResourceLocation overlay,
|
||||||
|
boolean christmas,
|
||||||
|
boolean flip
|
||||||
|
)
|
||||||
{
|
{
|
||||||
final boolean colour;
|
|
||||||
final ITurtleUpgrade leftUpgrade;
|
|
||||||
final ITurtleUpgrade rightUpgrade;
|
|
||||||
final ResourceLocation overlay;
|
|
||||||
final boolean christmas;
|
|
||||||
final boolean flip;
|
|
||||||
|
|
||||||
TurtleModelCombination( boolean colour, ITurtleUpgrade leftUpgrade, ITurtleUpgrade rightUpgrade, ResourceLocation overlay, boolean christmas,
|
|
||||||
boolean flip )
|
|
||||||
{
|
|
||||||
this.colour = colour;
|
|
||||||
this.leftUpgrade = leftUpgrade;
|
|
||||||
this.rightUpgrade = rightUpgrade;
|
|
||||||
this.overlay = overlay;
|
|
||||||
this.christmas = christmas;
|
|
||||||
this.flip = flip;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals( Object other )
|
|
||||||
{
|
|
||||||
if( other == this )
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if( !(other instanceof TurtleModelCombination otherCombo) )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return otherCombo.colour == colour && otherCombo.leftUpgrade == leftUpgrade && otherCombo.rightUpgrade == rightUpgrade && Objects.equal(
|
|
||||||
otherCombo.overlay, overlay ) && otherCombo.christmas == christmas && otherCombo.flip == flip;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode()
|
|
||||||
{
|
|
||||||
final int prime = 31;
|
|
||||||
int result = 0;
|
|
||||||
result = prime * result + (colour ? 1 : 0);
|
|
||||||
result = prime * result + (leftUpgrade != null ? leftUpgrade.hashCode() : 0);
|
|
||||||
result = prime * result + (rightUpgrade != null ? rightUpgrade.hashCode() : 0);
|
|
||||||
result = prime * result + (overlay != null ? overlay.hashCode() : 0);
|
|
||||||
result = prime * result + (christmas ? 1 : 0);
|
|
||||||
result = prime * result + (flip ? 1 : 0);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final BakedModel familyModel;
|
private final BakedModel familyModel;
|
||||||
@@ -121,7 +79,7 @@ public class TurtleSmartItemModel implements BakedModel
|
|||||||
{
|
{
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public BakedModel resolve( BakedModel originalModel, ItemStack stack, @Nullable ClientLevel world, @Nullable LivingEntity entity, int seed )
|
public BakedModel resolve( @Nonnull BakedModel originalModel, @Nonnull ItemStack stack, @Nullable ClientLevel world, @Nullable LivingEntity entity, int random )
|
||||||
{
|
{
|
||||||
ItemTurtle turtle = (ItemTurtle) stack.getItem();
|
ItemTurtle turtle = (ItemTurtle) stack.getItem();
|
||||||
int colour = turtle.getColour( stack );
|
int colour = turtle.getColour( stack );
|
||||||
@@ -134,21 +92,23 @@ public class TurtleSmartItemModel implements BakedModel
|
|||||||
TurtleModelCombination combo = new TurtleModelCombination( colour != -1, leftUpgrade, rightUpgrade, overlay, christmas, flip );
|
TurtleModelCombination combo = new TurtleModelCombination( colour != -1, leftUpgrade, rightUpgrade, overlay, christmas, flip );
|
||||||
|
|
||||||
BakedModel model = cachedModels.get( combo );
|
BakedModel model = cachedModels.get( combo );
|
||||||
if( model == null )
|
if( model == null ) cachedModels.put( combo, model = buildModel( combo ) );
|
||||||
{
|
|
||||||
cachedModels.put( combo, model = buildModel( combo ) );
|
|
||||||
}
|
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public ItemOverrides getOverrides()
|
||||||
|
{
|
||||||
|
return overrides;
|
||||||
|
}
|
||||||
|
|
||||||
private BakedModel buildModel( TurtleModelCombination combo )
|
private BakedModel buildModel( TurtleModelCombination combo )
|
||||||
{
|
{
|
||||||
Minecraft mc = Minecraft.getInstance();
|
Minecraft mc = Minecraft.getInstance();
|
||||||
ModelManager modelManager = mc.getItemRenderer()
|
ModelManager modelManager = mc.getItemRenderer().getItemModelShaper().getModelManager();
|
||||||
.getItemModelShaper()
|
|
||||||
.getModelManager();
|
|
||||||
ModelResourceLocation overlayModelLocation = TileEntityTurtleRenderer.getTurtleOverlayModel( combo.overlay, combo.christmas );
|
ModelResourceLocation overlayModelLocation = TileEntityTurtleRenderer.getTurtleOverlayModel( combo.overlay, combo.christmas );
|
||||||
|
|
||||||
BakedModel baseModel = combo.colour ? colourModel : familyModel;
|
BakedModel baseModel = combo.colour ? colourModel : familyModel;
|
||||||
@@ -179,12 +139,6 @@ public class TurtleSmartItemModel implements BakedModel
|
|||||||
return familyModel.isGui3d();
|
return familyModel.isGui3d();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean usesBlockLight()
|
|
||||||
{
|
|
||||||
return familyModel.usesBlockLight();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCustomRenderer()
|
public boolean isCustomRenderer()
|
||||||
{
|
{
|
||||||
@@ -192,17 +146,17 @@ public class TurtleSmartItemModel implements BakedModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Deprecated
|
public boolean usesBlockLight()
|
||||||
public TextureAtlasSprite getParticleIcon()
|
|
||||||
{
|
{
|
||||||
return familyModel.getParticleIcon();
|
return familyModel.usesBlockLight();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public ItemOverrides getOverrides()
|
@Deprecated
|
||||||
|
public TextureAtlasSprite getParticleIcon()
|
||||||
{
|
{
|
||||||
return overrides;
|
return familyModel.getParticleIcon();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
|
|||||||
@@ -484,7 +484,7 @@ public class FSAPI implements ILuaAPI
|
|||||||
*
|
*
|
||||||
* This string is formatted like a normal path string, but can include any
|
* This string is formatted like a normal path string, but can include any
|
||||||
* number of wildcards ({@code *}) to look for files matching anything.
|
* number of wildcards ({@code *}) to look for files matching anything.
|
||||||
* For example, {@code rom/* /command*} will look for any path starting with
|
* For example, <code>rom/*/command*</code> will look for any path starting with
|
||||||
* {@code command} inside any subdirectory of {@code /rom}.
|
* {@code command} inside any subdirectory of {@code /rom}.
|
||||||
*
|
*
|
||||||
* @param path The wildcard-qualified path to search for.
|
* @param path The wildcard-qualified path to search for.
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import dan200.computercraft.core.asm.NamedMethod;
|
|||||||
import dan200.computercraft.core.asm.PeripheralMethod;
|
import dan200.computercraft.core.asm.PeripheralMethod;
|
||||||
import dan200.computercraft.core.computer.ComputerSide;
|
import dan200.computercraft.core.computer.ComputerSide;
|
||||||
import dan200.computercraft.core.tracking.TrackingField;
|
import dan200.computercraft.core.tracking.TrackingField;
|
||||||
|
import dan200.computercraft.shared.util.LuaUtil;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@@ -36,6 +37,7 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
|
|||||||
private final IPeripheral peripheral;
|
private final IPeripheral peripheral;
|
||||||
|
|
||||||
private final String type;
|
private final String type;
|
||||||
|
private final Set<String> additionalTypes;
|
||||||
private final Map<String, PeripheralMethod> methodMap;
|
private final Map<String, PeripheralMethod> methodMap;
|
||||||
private boolean attached;
|
private boolean attached;
|
||||||
|
|
||||||
@@ -47,6 +49,7 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
|
|||||||
attached = false;
|
attached = false;
|
||||||
|
|
||||||
type = Objects.requireNonNull( peripheral.getType(), "Peripheral type cannot be null" );
|
type = Objects.requireNonNull( peripheral.getType(), "Peripheral type cannot be null" );
|
||||||
|
additionalTypes = peripheral.getAdditionalTypes();
|
||||||
|
|
||||||
methodMap = PeripheralAPI.getMethods( peripheral );
|
methodMap = PeripheralAPI.getMethods( peripheral );
|
||||||
}
|
}
|
||||||
@@ -61,6 +64,11 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Set<String> getAdditionalTypes()
|
||||||
|
{
|
||||||
|
return additionalTypes;
|
||||||
|
}
|
||||||
|
|
||||||
public Collection<String> getMethods()
|
public Collection<String> getMethods()
|
||||||
{
|
{
|
||||||
return methodMap.keySet();
|
return methodMap.keySet();
|
||||||
@@ -298,7 +306,23 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
|
|||||||
synchronized( peripherals )
|
synchronized( peripherals )
|
||||||
{
|
{
|
||||||
PeripheralWrapper p = peripherals[side.ordinal()];
|
PeripheralWrapper p = peripherals[side.ordinal()];
|
||||||
if( p != null ) return new Object[] { p.getType() };
|
return p == null ? null : LuaUtil.consArray( p.getType(), p.getAdditionalTypes() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction
|
||||||
|
public final Object[] hasType( String sideName, String type )
|
||||||
|
{
|
||||||
|
ComputerSide side = ComputerSide.valueOfInsensitive( sideName );
|
||||||
|
if( side == null ) return null;
|
||||||
|
|
||||||
|
synchronized( peripherals )
|
||||||
|
{
|
||||||
|
PeripheralWrapper p = peripherals[side.ordinal()];
|
||||||
|
if( p != null )
|
||||||
|
{
|
||||||
|
return new Object[] { p.getType().equals( type ) || p.getAdditionalTypes().contains( type ) };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ public class BinaryWritableHandle extends HandleGeneric
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Technically this is not needed
|
// Technically this is not needed
|
||||||
if( writer instanceof FileChannel ) ((FileChannel) writer).force( false );
|
if( writer instanceof FileChannel channel ) channel.force( false );
|
||||||
}
|
}
|
||||||
catch( IOException ignored )
|
catch( IOException ignored )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ public class WebsocketHandle implements Closeable
|
|||||||
return MethodResult.of();
|
return MethodResult.of();
|
||||||
}
|
}
|
||||||
else if( event.length >= 2 && timeoutId != -1 && Objects.equal( event[0], TIMER_EVENT )
|
else if( event.length >= 2 && timeoutId != -1 && Objects.equal( event[0], TIMER_EVENT )
|
||||||
&& event[1] instanceof Number && ((Number) event[1]).intValue() == timeoutId )
|
&& event[1] instanceof Number id && id.intValue() == timeoutId )
|
||||||
{
|
{
|
||||||
// If we received a matching timer event then abort.
|
// If we received a matching timer event then abort.
|
||||||
return MethodResult.of();
|
return MethodResult.of();
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
package dan200.computercraft.fabric.mixin;
|
package dan200.computercraft.fabric.mixin;
|
||||||
|
|
||||||
import dan200.computercraft.shared.ComputerCraftRegistry;
|
import dan200.computercraft.shared.Registry;
|
||||||
import net.minecraft.advancements.CriteriaTriggers;
|
import net.minecraft.advancements.CriteriaTriggers;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
@@ -33,7 +33,7 @@ public class MixinServerPlayerGameMode
|
|||||||
{
|
{
|
||||||
BlockPos pos = hitResult.getBlockPos();
|
BlockPos pos = hitResult.getBlockPos();
|
||||||
BlockState state = world.getBlockState( pos );
|
BlockState state = world.getBlockState( pos );
|
||||||
if( player.getMainHandItem().getItem() == ComputerCraftRegistry.ModItems.DISK && state.getBlock() == ComputerCraftRegistry.ModBlocks.DISK_DRIVE )
|
if( player.getMainHandItem().getItem() == Registry.ModItems.DISK && state.getBlock() == Registry.ModBlocks.DISK_DRIVE )
|
||||||
{
|
{
|
||||||
InteractionResult actionResult = state.use( world, player, hand, hitResult );
|
InteractionResult actionResult = state.use( world, player, hand, hitResult );
|
||||||
if( actionResult.consumesAction() )
|
if( actionResult.consumesAction() )
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared;
|
package dan200.computercraft.shared;
|
||||||
|
|
||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.ComputerCraft;
|
||||||
@@ -34,18 +33,9 @@ public final class BundledRedstone
|
|||||||
return world.isInWorldBounds( pos ) ? DefaultBundledRedstoneProvider.getDefaultBundledRedstoneOutput( world, pos, side ) : -1;
|
return world.isInWorldBounds( pos ) ? DefaultBundledRedstoneProvider.getDefaultBundledRedstoneOutput( world, pos, side ) : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getOutput( Level world, BlockPos pos, Direction side )
|
|
||||||
{
|
|
||||||
int signal = getUnmaskedOutput( world, pos, side );
|
|
||||||
return signal >= 0 ? signal : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int getUnmaskedOutput( Level world, BlockPos pos, Direction side )
|
private static int getUnmaskedOutput( Level world, BlockPos pos, Direction side )
|
||||||
{
|
{
|
||||||
if( !world.isInWorldBounds( pos ) )
|
if( !world.isInWorldBounds( pos ) ) return -1;
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try the providers in order:
|
// Try the providers in order:
|
||||||
int combinedSignal = -1;
|
int combinedSignal = -1;
|
||||||
@@ -67,4 +57,10 @@ public final class BundledRedstone
|
|||||||
|
|
||||||
return combinedSignal;
|
return combinedSignal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int getOutput( Level world, BlockPos pos, Direction side )
|
||||||
|
{
|
||||||
|
int signal = getUnmaskedOutput( world, pos, side );
|
||||||
|
return signal >= 0 ? signal : 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,330 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
|
||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
|
||||||
*/
|
|
||||||
|
|
||||||
package dan200.computercraft.shared;
|
|
||||||
|
|
||||||
import dan200.computercraft.ComputerCraft;
|
|
||||||
import dan200.computercraft.api.ComputerCraftAPI;
|
|
||||||
import dan200.computercraft.shared.common.ContainerHeldItem;
|
|
||||||
import dan200.computercraft.shared.computer.blocks.BlockComputer;
|
|
||||||
import dan200.computercraft.shared.computer.blocks.TileCommandComputer;
|
|
||||||
import dan200.computercraft.shared.computer.blocks.TileComputer;
|
|
||||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
|
||||||
import dan200.computercraft.shared.computer.inventory.ComputerMenuWithoutInventory;
|
|
||||||
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
|
|
||||||
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
|
|
||||||
import dan200.computercraft.shared.computer.items.ItemComputer;
|
|
||||||
import dan200.computercraft.shared.media.items.ItemDisk;
|
|
||||||
import dan200.computercraft.shared.media.items.ItemPrintout;
|
|
||||||
import dan200.computercraft.shared.media.items.ItemTreasureDisk;
|
|
||||||
import dan200.computercraft.shared.network.container.ComputerContainerData;
|
|
||||||
import dan200.computercraft.shared.network.container.ContainerData;
|
|
||||||
import dan200.computercraft.shared.network.container.HeldItemContainerData;
|
|
||||||
import dan200.computercraft.shared.network.container.ViewComputerContainerData;
|
|
||||||
import dan200.computercraft.shared.peripheral.diskdrive.BlockDiskDrive;
|
|
||||||
import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive;
|
|
||||||
import dan200.computercraft.shared.peripheral.diskdrive.TileDiskDrive;
|
|
||||||
import dan200.computercraft.shared.peripheral.modem.wired.*;
|
|
||||||
import dan200.computercraft.shared.peripheral.modem.wireless.BlockWirelessModem;
|
|
||||||
import dan200.computercraft.shared.peripheral.modem.wireless.TileWirelessModem;
|
|
||||||
import dan200.computercraft.shared.peripheral.monitor.BlockMonitor;
|
|
||||||
import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
|
|
||||||
import dan200.computercraft.shared.peripheral.printer.BlockPrinter;
|
|
||||||
import dan200.computercraft.shared.peripheral.printer.ContainerPrinter;
|
|
||||||
import dan200.computercraft.shared.peripheral.printer.TilePrinter;
|
|
||||||
import dan200.computercraft.shared.peripheral.speaker.BlockSpeaker;
|
|
||||||
import dan200.computercraft.shared.peripheral.speaker.TileSpeaker;
|
|
||||||
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
|
|
||||||
import dan200.computercraft.shared.pocket.peripherals.PocketModem;
|
|
||||||
import dan200.computercraft.shared.pocket.peripherals.PocketSpeaker;
|
|
||||||
import dan200.computercraft.shared.turtle.blocks.BlockTurtle;
|
|
||||||
import dan200.computercraft.shared.turtle.blocks.TileTurtle;
|
|
||||||
import dan200.computercraft.shared.turtle.core.TurtlePlayer;
|
|
||||||
import dan200.computercraft.shared.turtle.inventory.ContainerTurtle;
|
|
||||||
import dan200.computercraft.shared.turtle.items.ItemTurtle;
|
|
||||||
import dan200.computercraft.shared.turtle.upgrades.*;
|
|
||||||
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
|
||||||
import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder;
|
|
||||||
import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry;
|
|
||||||
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
|
|
||||||
import net.minecraft.core.BlockPos;
|
|
||||||
import net.minecraft.core.Registry;
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import net.minecraft.world.entity.EntityType;
|
|
||||||
import net.minecraft.world.entity.MobCategory;
|
|
||||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
|
||||||
import net.minecraft.world.inventory.MenuType;
|
|
||||||
import net.minecraft.world.item.BlockItem;
|
|
||||||
import net.minecraft.world.item.CreativeModeTab;
|
|
||||||
import net.minecraft.world.item.Item;
|
|
||||||
import net.minecraft.world.item.Items;
|
|
||||||
import net.minecraft.world.level.block.Block;
|
|
||||||
import net.minecraft.world.level.block.Blocks;
|
|
||||||
import net.minecraft.world.level.block.SoundType;
|
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
|
||||||
import net.minecraft.world.level.block.state.BlockBehaviour;
|
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
|
||||||
import net.minecraft.world.level.material.Material;
|
|
||||||
|
|
||||||
import java.util.function.BiFunction;
|
|
||||||
|
|
||||||
import static net.minecraft.core.Registry.BLOCK_ENTITY_TYPE;
|
|
||||||
|
|
||||||
public final class ComputerCraftRegistry
|
|
||||||
{
|
|
||||||
public static final String MOD_ID = ComputerCraft.MOD_ID;
|
|
||||||
|
|
||||||
public static void init()
|
|
||||||
{
|
|
||||||
Object[] o = {
|
|
||||||
ModTiles.CABLE,
|
|
||||||
ModBlocks.CABLE,
|
|
||||||
ModItems.CABLE,
|
|
||||||
ModEntities.TURTLE_PLAYER,
|
|
||||||
ModContainers.COMPUTER,
|
|
||||||
};
|
|
||||||
|
|
||||||
TurtleUpgrades.registerTurtleUpgrades();
|
|
||||||
PocketUpgrades.registerPocketUpgrades();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class ModBlocks
|
|
||||||
{
|
|
||||||
public static final BlockComputer COMPUTER_NORMAL = register( "computer_normal",
|
|
||||||
new BlockComputer( properties(), ComputerFamily.NORMAL, ComputerCraftRegistry.ModTiles.COMPUTER_NORMAL ) );
|
|
||||||
public static final BlockComputer COMPUTER_ADVANCED = register( "computer_advanced",
|
|
||||||
new BlockComputer( properties(),
|
|
||||||
ComputerFamily.ADVANCED,
|
|
||||||
ComputerCraftRegistry.ModTiles.COMPUTER_ADVANCED ) );
|
|
||||||
public static final BlockComputer COMPUTER_COMMAND = register( "computer_command",
|
|
||||||
new BlockComputer( FabricBlockSettings.copyOf( Blocks.STONE )
|
|
||||||
.strength( -1, 6000000.0F ),
|
|
||||||
ComputerFamily.COMMAND,
|
|
||||||
ComputerCraftRegistry.ModTiles.COMPUTER_COMMAND ) );
|
|
||||||
public static final BlockTurtle TURTLE_NORMAL = register( "turtle_normal",
|
|
||||||
new BlockTurtle( turtleProperties(), ComputerFamily.NORMAL, ComputerCraftRegistry.ModTiles.TURTLE_NORMAL ) );
|
|
||||||
public static final BlockTurtle TURTLE_ADVANCED = register( "turtle_advanced",
|
|
||||||
new BlockTurtle( turtleProperties(), ComputerFamily.ADVANCED, ComputerCraftRegistry.ModTiles.TURTLE_ADVANCED ) );
|
|
||||||
public static final BlockSpeaker SPEAKER = register( "speaker", new BlockSpeaker( properties() ) );
|
|
||||||
public static final BlockDiskDrive DISK_DRIVE = register( "disk_drive", new BlockDiskDrive( properties() ) );
|
|
||||||
public static final BlockPrinter PRINTER = register( "printer", new BlockPrinter( properties() ) );
|
|
||||||
public static final BlockMonitor MONITOR_NORMAL = register( "monitor_normal", new BlockMonitor( properties(), ModTiles.MONITOR_NORMAL, false ) );
|
|
||||||
public static final BlockMonitor MONITOR_ADVANCED = register( "monitor_advanced", new BlockMonitor( properties(), ModTiles.MONITOR_ADVANCED, true ) );
|
|
||||||
public static final BlockWirelessModem WIRELESS_MODEM_NORMAL = register( "wireless_modem_normal",
|
|
||||||
new BlockWirelessModem( properties(), ComputerCraftRegistry.ModTiles.WIRELESS_MODEM_NORMAL, ComputerFamily.NORMAL ) );
|
|
||||||
public static final BlockWirelessModem WIRELESS_MODEM_ADVANCED = register( "wireless_modem_advanced",
|
|
||||||
new BlockWirelessModem( properties(), ComputerCraftRegistry.ModTiles.WIRELESS_MODEM_ADVANCED, ComputerFamily.ADVANCED ) );
|
|
||||||
public static final BlockWiredModemFull WIRED_MODEM_FULL = register( "wired_modem_full",
|
|
||||||
new BlockWiredModemFull( modemProperties(), ComputerCraftRegistry.ModTiles.WIRED_MODEM_FULL ) );
|
|
||||||
public static final BlockCable CABLE = register( "cable", new BlockCable( modemProperties() ) );
|
|
||||||
|
|
||||||
private static BlockBehaviour.Properties properties()
|
|
||||||
{
|
|
||||||
//return FabricBlockSettings.copyOf(Blocks.GLASS)
|
|
||||||
// .strength(2);
|
|
||||||
return BlockBehaviour.Properties.of( Material.GLASS )
|
|
||||||
.strength( 2F )
|
|
||||||
.sound( SoundType.STONE )
|
|
||||||
.noOcclusion();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static BlockBehaviour.Properties turtleProperties()
|
|
||||||
{
|
|
||||||
return FabricBlockSettings.copyOf( Blocks.STONE )
|
|
||||||
.strength( 2.5f );
|
|
||||||
}
|
|
||||||
|
|
||||||
private static BlockBehaviour.Properties modemProperties()
|
|
||||||
{
|
|
||||||
return FabricBlockSettings.copyOf( Blocks.STONE )
|
|
||||||
.breakByHand( true )
|
|
||||||
.breakByTool( FabricToolTags.PICKAXES )
|
|
||||||
.strength( 1.5f );
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T extends Block> T register( String id, T value )
|
|
||||||
{
|
|
||||||
return Registry.register( Registry.BLOCK, new ResourceLocation( MOD_ID, id ), value );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ModTiles
|
|
||||||
{
|
|
||||||
|
|
||||||
public static final BlockEntityType<TileMonitor> MONITOR_NORMAL = ofBlock( ModBlocks.MONITOR_NORMAL,
|
|
||||||
"monitor_normal",
|
|
||||||
( blockPos, blockState ) -> new TileMonitor( ModTiles.MONITOR_NORMAL, false, blockPos, blockState ) );
|
|
||||||
public static final BlockEntityType<TileMonitor> MONITOR_ADVANCED = ofBlock( ModBlocks.MONITOR_ADVANCED,
|
|
||||||
"monitor_advanced",
|
|
||||||
( blockPos, blockState ) -> new TileMonitor( ModTiles.MONITOR_ADVANCED, true, blockPos, blockState ) );
|
|
||||||
public static final BlockEntityType<TileComputer> COMPUTER_NORMAL = ofBlock( ModBlocks.COMPUTER_NORMAL,
|
|
||||||
"computer_normal",
|
|
||||||
( blockPos, blockState ) -> new TileComputer( ComputerFamily.NORMAL, ModTiles.COMPUTER_NORMAL, blockPos, blockState ) );
|
|
||||||
public static final BlockEntityType<TileComputer> COMPUTER_ADVANCED = ofBlock( ModBlocks.COMPUTER_ADVANCED,
|
|
||||||
"computer_advanced",
|
|
||||||
( blockPos, blockState ) -> new TileComputer( ComputerFamily.ADVANCED, ModTiles.COMPUTER_ADVANCED, blockPos, blockState ) );
|
|
||||||
public static final BlockEntityType<TileCommandComputer> COMPUTER_COMMAND = ofBlock( ModBlocks.COMPUTER_COMMAND,
|
|
||||||
"computer_command",
|
|
||||||
( blockPos, blockState ) -> new TileCommandComputer( ComputerFamily.COMMAND, ModTiles.COMPUTER_COMMAND, blockPos, blockState ) );
|
|
||||||
public static final BlockEntityType<TileTurtle> TURTLE_NORMAL = ofBlock( ModBlocks.TURTLE_NORMAL,
|
|
||||||
"turtle_normal",
|
|
||||||
( blockPos, blockState ) -> new TileTurtle( ModTiles.TURTLE_NORMAL, blockPos, blockState, ComputerFamily.NORMAL ) );
|
|
||||||
public static final BlockEntityType<TileTurtle> TURTLE_ADVANCED = ofBlock( ModBlocks.TURTLE_ADVANCED,
|
|
||||||
"turtle_advanced",
|
|
||||||
( blockPos, blockState ) -> new TileTurtle( ModTiles.TURTLE_ADVANCED, blockPos, blockState, ComputerFamily.ADVANCED ) );
|
|
||||||
public static final BlockEntityType<TileSpeaker> SPEAKER = ofBlock( ModBlocks.SPEAKER, "speaker",
|
|
||||||
( blockPos, blockState ) -> new TileSpeaker( ModTiles.SPEAKER, blockPos, blockState ) );
|
|
||||||
public static final BlockEntityType<TileDiskDrive> DISK_DRIVE = ofBlock( ModBlocks.DISK_DRIVE, "disk_drive",
|
|
||||||
( blockPos, blockState ) -> new TileDiskDrive( ModTiles.DISK_DRIVE, blockPos, blockState ) );
|
|
||||||
public static final BlockEntityType<TilePrinter> PRINTER = ofBlock( ModBlocks.PRINTER, "printer",
|
|
||||||
( blockPos, blockState ) -> new TilePrinter( ModTiles.PRINTER, blockPos, blockState ) );
|
|
||||||
public static final BlockEntityType<TileWiredModemFull> WIRED_MODEM_FULL = ofBlock( ModBlocks.WIRED_MODEM_FULL,
|
|
||||||
"wired_modem_full",
|
|
||||||
( blockPos, blockState ) -> new TileWiredModemFull( ModTiles.WIRED_MODEM_FULL, blockPos, blockState ) );
|
|
||||||
public static final BlockEntityType<TileCable> CABLE = ofBlock( ModBlocks.CABLE, "cable",
|
|
||||||
( blockPos, blockState ) -> new TileCable( ModTiles.CABLE, blockPos, blockState ) );
|
|
||||||
public static final BlockEntityType<TileWirelessModem> WIRELESS_MODEM_NORMAL = ofBlock( ModBlocks.WIRELESS_MODEM_NORMAL,
|
|
||||||
"wireless_modem_normal",
|
|
||||||
( blockPos, blockState ) -> new TileWirelessModem( ModTiles.WIRELESS_MODEM_NORMAL, false, blockPos, blockState ) );
|
|
||||||
public static final BlockEntityType<TileWirelessModem> WIRELESS_MODEM_ADVANCED = ofBlock( ModBlocks.WIRELESS_MODEM_ADVANCED,
|
|
||||||
"wireless_modem_advanced",
|
|
||||||
( blockPos, blockState ) -> new TileWirelessModem( ModTiles.WIRELESS_MODEM_ADVANCED, true, blockPos, blockState ) );
|
|
||||||
|
|
||||||
private static <T extends BlockEntity> BlockEntityType<T> ofBlock( Block block, String id, BiFunction<BlockPos, BlockState, T> factory )
|
|
||||||
{
|
|
||||||
BlockEntityType<T> blockEntityType = FabricBlockEntityTypeBuilder.create( factory::apply, block ).build();
|
|
||||||
return Registry.register( BLOCK_ENTITY_TYPE,
|
|
||||||
new ResourceLocation( MOD_ID, id ),
|
|
||||||
blockEntityType
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class ModItems
|
|
||||||
{
|
|
||||||
private static final CreativeModeTab mainItemGroup = ComputerCraft.MAIN_GROUP;
|
|
||||||
public static final ItemComputer COMPUTER_NORMAL = ofBlock( ModBlocks.COMPUTER_NORMAL, ItemComputer::new );
|
|
||||||
public static final ItemComputer COMPUTER_ADVANCED = ofBlock( ModBlocks.COMPUTER_ADVANCED, ItemComputer::new );
|
|
||||||
public static final ItemComputer COMPUTER_COMMAND = ofBlock( ModBlocks.COMPUTER_COMMAND, ItemComputer::new );
|
|
||||||
public static final ItemPocketComputer POCKET_COMPUTER_NORMAL = register( "pocket_computer_normal",
|
|
||||||
new ItemPocketComputer( properties().stacksTo( 1 ), ComputerFamily.NORMAL ) );
|
|
||||||
public static final ItemPocketComputer POCKET_COMPUTER_ADVANCED = register( "pocket_computer_advanced",
|
|
||||||
new ItemPocketComputer( properties().stacksTo( 1 ),
|
|
||||||
ComputerFamily.ADVANCED ) );
|
|
||||||
public static final ItemTurtle TURTLE_NORMAL = ofBlock( ModBlocks.TURTLE_NORMAL, ItemTurtle::new );
|
|
||||||
public static final ItemTurtle TURTLE_ADVANCED = ofBlock( ModBlocks.TURTLE_ADVANCED, ItemTurtle::new );
|
|
||||||
public static final ItemDisk DISK = register( "disk", new ItemDisk( properties().stacksTo( 1 ) ) );
|
|
||||||
public static final ItemTreasureDisk TREASURE_DISK = register( "treasure_disk", new ItemTreasureDisk( properties().stacksTo( 1 ) ) );
|
|
||||||
public static final ItemPrintout PRINTED_PAGE = register( "printed_page", new ItemPrintout( properties().stacksTo( 1 ), ItemPrintout.Type.PAGE ) );
|
|
||||||
public static final ItemPrintout PRINTED_PAGES = register( "printed_pages", new ItemPrintout( properties().stacksTo( 1 ), ItemPrintout.Type.PAGES ) );
|
|
||||||
public static final ItemPrintout PRINTED_BOOK = register( "printed_book", new ItemPrintout( properties().stacksTo( 1 ), ItemPrintout.Type.BOOK ) );
|
|
||||||
public static final BlockItem SPEAKER = ofBlock( ModBlocks.SPEAKER, BlockItem::new );
|
|
||||||
public static final BlockItem DISK_DRIVE = ofBlock( ModBlocks.DISK_DRIVE, BlockItem::new );
|
|
||||||
public static final BlockItem PRINTER = ofBlock( ModBlocks.PRINTER, BlockItem::new );
|
|
||||||
public static final BlockItem MONITOR_NORMAL = ofBlock( ModBlocks.MONITOR_NORMAL, BlockItem::new );
|
|
||||||
public static final BlockItem MONITOR_ADVANCED = ofBlock( ModBlocks.MONITOR_ADVANCED, BlockItem::new );
|
|
||||||
public static final BlockItem WIRELESS_MODEM_NORMAL = ofBlock( ModBlocks.WIRELESS_MODEM_NORMAL, BlockItem::new );
|
|
||||||
public static final BlockItem WIRELESS_MODEM_ADVANCED = ofBlock( ModBlocks.WIRELESS_MODEM_ADVANCED, BlockItem::new );
|
|
||||||
public static final BlockItem WIRED_MODEM_FULL = ofBlock( ModBlocks.WIRED_MODEM_FULL, BlockItem::new );
|
|
||||||
public static final ItemBlockCable.Cable CABLE = register( "cable", new ItemBlockCable.Cable( ModBlocks.CABLE, properties() ) );
|
|
||||||
public static final ItemBlockCable.WiredModem WIRED_MODEM = register( "wired_modem", new ItemBlockCable.WiredModem( ModBlocks.CABLE, properties() ) );
|
|
||||||
|
|
||||||
private static <B extends Block, I extends Item> I ofBlock( B parent, BiFunction<B, Item.Properties, I> supplier )
|
|
||||||
{
|
|
||||||
return Registry.register( Registry.ITEM, Registry.BLOCK.getKey( parent ), supplier.apply( parent, properties() ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Item.Properties properties()
|
|
||||||
{
|
|
||||||
return new Item.Properties().tab( mainItemGroup );
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <T extends Item> T register( String id, T item )
|
|
||||||
{
|
|
||||||
return Registry.register( Registry.ITEM, new ResourceLocation( MOD_ID, id ), item );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ModEntities
|
|
||||||
{
|
|
||||||
public static final EntityType<TurtlePlayer> TURTLE_PLAYER = Registry.register( Registry.ENTITY_TYPE,
|
|
||||||
new ResourceLocation( MOD_ID, "turtle_player" ),
|
|
||||||
EntityType.Builder.<TurtlePlayer>createNothing( MobCategory.MISC ).noSave()
|
|
||||||
.noSummon()
|
|
||||||
.sized(
|
|
||||||
0,
|
|
||||||
0 )
|
|
||||||
.build(
|
|
||||||
ComputerCraft.MOD_ID + ":turtle_player" ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ModContainers
|
|
||||||
{
|
|
||||||
public static final MenuType<ContainerComputerBase> COMPUTER = ContainerData.toType( new ResourceLocation( MOD_ID, "computer" ), ModContainers.COMPUTER, ComputerContainerData::new, ComputerMenuWithoutInventory::new );
|
|
||||||
public static final MenuType<ContainerComputerBase> POCKET_COMPUTER = ContainerData.toType( new ResourceLocation( MOD_ID, "pocket_computer" ), ModContainers.POCKET_COMPUTER, ComputerContainerData::new, ComputerMenuWithoutInventory::new );
|
|
||||||
public static final MenuType<ContainerComputerBase> POCKET_COMPUTER_NO_TERM = ContainerData.toType( new ResourceLocation( MOD_ID, "pocket_computer_no_term" ), ModContainers.POCKET_COMPUTER_NO_TERM, ComputerContainerData::new, ComputerMenuWithoutInventory::new );
|
|
||||||
public static final MenuType<ContainerTurtle> TURTLE = ContainerData.toType( new ResourceLocation( MOD_ID, "turtle" ), ComputerContainerData::new, ContainerTurtle::new );
|
|
||||||
public static final MenuType<ContainerDiskDrive> DISK_DRIVE = registerSimple( "disk_drive", ContainerDiskDrive::new );
|
|
||||||
public static final MenuType<ContainerPrinter> PRINTER = registerSimple( "printer", ContainerPrinter::new );
|
|
||||||
public static final MenuType<ContainerHeldItem> PRINTOUT = ContainerData.toType( new ResourceLocation( MOD_ID, "printout" ), HeldItemContainerData::new, ContainerHeldItem::createPrintout );
|
|
||||||
public static final MenuType<ContainerViewComputer> VIEW_COMPUTER = ContainerData.toType( new ResourceLocation( MOD_ID, "view_computer" ), ViewComputerContainerData::new, ContainerViewComputer::new );
|
|
||||||
|
|
||||||
private static <T extends AbstractContainerMenu> MenuType<T> registerSimple( String id,
|
|
||||||
ScreenHandlerRegistry.SimpleClientHandlerFactory<T> function )
|
|
||||||
{
|
|
||||||
return ScreenHandlerRegistry.registerSimple( new ResourceLocation( MOD_ID, id ), function );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class TurtleUpgrades
|
|
||||||
{
|
|
||||||
public static TurtleModem wirelessModemNormal = new TurtleModem( false, new ResourceLocation( ComputerCraft.MOD_ID, "wireless_modem_normal" ) );
|
|
||||||
public static TurtleModem wirelessModemAdvanced = new TurtleModem( true, new ResourceLocation( ComputerCraft.MOD_ID, "wireless_modem_advanced" ) );
|
|
||||||
public static TurtleSpeaker speaker = new TurtleSpeaker( new ResourceLocation( ComputerCraft.MOD_ID, "speaker" ) );
|
|
||||||
|
|
||||||
public static TurtleCraftingTable craftingTable = new TurtleCraftingTable( new ResourceLocation( "minecraft", "crafting_table" ) );
|
|
||||||
public static TurtleSword diamondSword = new TurtleSword( new ResourceLocation( "minecraft", "diamond_sword" ), Items.DIAMOND_SWORD );
|
|
||||||
public static TurtleShovel diamondShovel = new TurtleShovel( new ResourceLocation( "minecraft", "diamond_shovel" ), Items.DIAMOND_SHOVEL );
|
|
||||||
public static TurtleTool diamondPickaxe = new TurtleTool( new ResourceLocation( "minecraft", "diamond_pickaxe" ), Items.DIAMOND_PICKAXE );
|
|
||||||
public static TurtleAxe diamondAxe = new TurtleAxe( new ResourceLocation( "minecraft", "diamond_axe" ), Items.DIAMOND_AXE );
|
|
||||||
public static TurtleHoe diamondHoe = new TurtleHoe( new ResourceLocation( "minecraft", "diamond_hoe" ), Items.DIAMOND_HOE );
|
|
||||||
|
|
||||||
public static TurtleTool netheritePickaxe = new TurtleTool( new ResourceLocation( "minecraft", "netherite_pickaxe" ), Items.NETHERITE_PICKAXE );
|
|
||||||
|
|
||||||
public static void registerTurtleUpgrades()
|
|
||||||
{
|
|
||||||
ComputerCraftAPI.registerTurtleUpgrade( wirelessModemNormal );
|
|
||||||
ComputerCraftAPI.registerTurtleUpgrade( wirelessModemAdvanced );
|
|
||||||
ComputerCraftAPI.registerTurtleUpgrade( speaker );
|
|
||||||
|
|
||||||
ComputerCraftAPI.registerTurtleUpgrade( craftingTable );
|
|
||||||
ComputerCraftAPI.registerTurtleUpgrade( diamondSword );
|
|
||||||
ComputerCraftAPI.registerTurtleUpgrade( diamondShovel );
|
|
||||||
ComputerCraftAPI.registerTurtleUpgrade( diamondPickaxe );
|
|
||||||
ComputerCraftAPI.registerTurtleUpgrade( diamondAxe );
|
|
||||||
ComputerCraftAPI.registerTurtleUpgrade( diamondHoe );
|
|
||||||
|
|
||||||
ComputerCraftAPI.registerTurtleUpgrade( netheritePickaxe );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class PocketUpgrades
|
|
||||||
{
|
|
||||||
public static PocketModem wirelessModemNormal = new PocketModem( false );
|
|
||||||
public static PocketModem wirelessModemAdvanced = new PocketModem( true );
|
|
||||||
public static PocketSpeaker speaker = new PocketSpeaker();
|
|
||||||
|
|
||||||
public static void registerPocketUpgrades()
|
|
||||||
{
|
|
||||||
ComputerCraftAPI.registerPocketUpgrade( wirelessModemNormal );
|
|
||||||
ComputerCraftAPI.registerPocketUpgrade( wirelessModemAdvanced );
|
|
||||||
ComputerCraftAPI.registerPocketUpgrade( speaker );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared;
|
package dan200.computercraft.shared;
|
||||||
|
|
||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.ComputerCraft;
|
||||||
@@ -30,10 +29,7 @@ public final class MediaProviders
|
|||||||
|
|
||||||
public static IMedia get( @Nonnull ItemStack stack )
|
public static IMedia get( @Nonnull ItemStack stack )
|
||||||
{
|
{
|
||||||
if( stack.isEmpty() )
|
if( stack.isEmpty() ) return null;
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try the handlers in order:
|
// Try the handlers in order:
|
||||||
for( IMediaProvider mediaProvider : providers )
|
for( IMediaProvider mediaProvider : providers )
|
||||||
@@ -41,10 +37,7 @@ public final class MediaProviders
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
IMedia media = mediaProvider.getMedia( stack );
|
IMedia media = mediaProvider.getMedia( stack );
|
||||||
if( media != null )
|
if( media != null ) return media;
|
||||||
{
|
|
||||||
return media;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch( Exception e )
|
catch( Exception e )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared;
|
package dan200.computercraft.shared;
|
||||||
|
|
||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.ComputerCraft;
|
||||||
@@ -47,10 +46,7 @@ public final class Peripherals
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
IPeripheral peripheral = peripheralProvider.getPeripheral( world, pos, side );
|
IPeripheral peripheral = peripheralProvider.getPeripheral( world, pos, side );
|
||||||
if( peripheral != null )
|
if( peripheral != null ) return peripheral;
|
||||||
{
|
|
||||||
return peripheral;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch( Exception e )
|
catch( Exception e )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import net.minecraft.world.item.ItemStack;
|
|||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
public final class PocketUpgrades
|
public final class PocketUpgrades
|
||||||
{
|
{
|
||||||
@@ -72,17 +73,18 @@ public final class PocketUpgrades
|
|||||||
return upgradeOwners.get( upgrade );
|
return upgradeOwners.get( upgrade );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Iterable<IPocketUpgrade> getVanillaUpgrades()
|
|
||||||
{
|
|
||||||
List<IPocketUpgrade> vanilla = new ArrayList<>();
|
|
||||||
vanilla.add( ComputerCraftRegistry.PocketUpgrades.wirelessModemNormal );
|
|
||||||
vanilla.add( ComputerCraftRegistry.PocketUpgrades.wirelessModemAdvanced );
|
|
||||||
vanilla.add( ComputerCraftRegistry.PocketUpgrades.speaker );
|
|
||||||
return vanilla;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Iterable<IPocketUpgrade> getUpgrades()
|
public static Iterable<IPocketUpgrade> getUpgrades()
|
||||||
{
|
{
|
||||||
return Collections.unmodifiableCollection( upgrades.values() );
|
return Collections.unmodifiableCollection( upgrades.values() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Stream<IPocketUpgrade> getVanillaUpgrades()
|
||||||
|
{
|
||||||
|
List<IPocketUpgrade> vanilla = Arrays.asList(
|
||||||
|
Registry.PocketUpgrades.wirelessModemNormal,
|
||||||
|
Registry.PocketUpgrades.wirelessModemAdvanced,
|
||||||
|
Registry.PocketUpgrades.speaker
|
||||||
|
);
|
||||||
|
return vanilla.stream();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
393
src/main/java/dan200/computercraft/shared/Registry.java
Normal file
393
src/main/java/dan200/computercraft/shared/Registry.java
Normal file
@@ -0,0 +1,393 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||||
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
|
*/
|
||||||
|
package dan200.computercraft.shared;
|
||||||
|
|
||||||
|
import dan200.computercraft.ComputerCraft;
|
||||||
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
|
import dan200.computercraft.shared.common.ContainerHeldItem;
|
||||||
|
import dan200.computercraft.shared.computer.blocks.BlockComputer;
|
||||||
|
import dan200.computercraft.shared.computer.blocks.TileCommandComputer;
|
||||||
|
import dan200.computercraft.shared.computer.blocks.TileComputer;
|
||||||
|
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||||
|
import dan200.computercraft.shared.computer.inventory.ComputerMenuWithoutInventory;
|
||||||
|
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
|
||||||
|
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
|
||||||
|
import dan200.computercraft.shared.computer.items.ItemComputer;
|
||||||
|
import dan200.computercraft.shared.media.items.ItemDisk;
|
||||||
|
import dan200.computercraft.shared.media.items.ItemPrintout;
|
||||||
|
import dan200.computercraft.shared.media.items.ItemTreasureDisk;
|
||||||
|
import dan200.computercraft.shared.network.container.ComputerContainerData;
|
||||||
|
import dan200.computercraft.shared.network.container.ContainerData;
|
||||||
|
import dan200.computercraft.shared.network.container.HeldItemContainerData;
|
||||||
|
import dan200.computercraft.shared.network.container.ViewComputerContainerData;
|
||||||
|
import dan200.computercraft.shared.peripheral.diskdrive.BlockDiskDrive;
|
||||||
|
import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive;
|
||||||
|
import dan200.computercraft.shared.peripheral.diskdrive.TileDiskDrive;
|
||||||
|
import dan200.computercraft.shared.peripheral.modem.wired.*;
|
||||||
|
import dan200.computercraft.shared.peripheral.modem.wireless.BlockWirelessModem;
|
||||||
|
import dan200.computercraft.shared.peripheral.modem.wireless.TileWirelessModem;
|
||||||
|
import dan200.computercraft.shared.peripheral.monitor.BlockMonitor;
|
||||||
|
import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
|
||||||
|
import dan200.computercraft.shared.peripheral.printer.BlockPrinter;
|
||||||
|
import dan200.computercraft.shared.peripheral.printer.ContainerPrinter;
|
||||||
|
import dan200.computercraft.shared.peripheral.printer.TilePrinter;
|
||||||
|
import dan200.computercraft.shared.peripheral.speaker.BlockSpeaker;
|
||||||
|
import dan200.computercraft.shared.peripheral.speaker.TileSpeaker;
|
||||||
|
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
|
||||||
|
import dan200.computercraft.shared.pocket.peripherals.PocketModem;
|
||||||
|
import dan200.computercraft.shared.pocket.peripherals.PocketSpeaker;
|
||||||
|
import dan200.computercraft.shared.turtle.blocks.BlockTurtle;
|
||||||
|
import dan200.computercraft.shared.turtle.blocks.TileTurtle;
|
||||||
|
import dan200.computercraft.shared.turtle.core.TurtlePlayer;
|
||||||
|
import dan200.computercraft.shared.turtle.inventory.ContainerTurtle;
|
||||||
|
import dan200.computercraft.shared.turtle.items.ItemTurtle;
|
||||||
|
import dan200.computercraft.shared.turtle.upgrades.*;
|
||||||
|
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
||||||
|
import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder;
|
||||||
|
import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry;
|
||||||
|
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.cauldron.CauldronInteraction;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.entity.EntityType;
|
||||||
|
import net.minecraft.world.entity.MobCategory;
|
||||||
|
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||||
|
import net.minecraft.world.inventory.MenuType;
|
||||||
|
import net.minecraft.world.item.*;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.Blocks;
|
||||||
|
import net.minecraft.world.level.block.SoundType;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
|
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.level.material.Material;
|
||||||
|
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
|
import static net.minecraft.core.Registry.BLOCK_ENTITY_TYPE;
|
||||||
|
|
||||||
|
public final class Registry
|
||||||
|
{
|
||||||
|
public static final String MOD_ID = ComputerCraft.MOD_ID;
|
||||||
|
|
||||||
|
public static void init()
|
||||||
|
{
|
||||||
|
TurtleUpgrades.registerTurtleUpgrades();
|
||||||
|
PocketUpgrades.registerPocketUpgrades();
|
||||||
|
|
||||||
|
CauldronInteraction.WATER.put( ModItems.TURTLE_NORMAL, ItemTurtle.CAULDRON_INTERACTION );
|
||||||
|
CauldronInteraction.WATER.put( ModItems.TURTLE_ADVANCED, ItemTurtle.CAULDRON_INTERACTION );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class ModBlocks
|
||||||
|
{
|
||||||
|
public static <T extends Block> T register( String id, T value )
|
||||||
|
{
|
||||||
|
return net.minecraft.core.Registry.register( net.minecraft.core.Registry.BLOCK, new ResourceLocation( MOD_ID, id ), value );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final BlockMonitor MONITOR_NORMAL =
|
||||||
|
register( "monitor_normal", new BlockMonitor( properties(), () -> ModBlockEntities.MONITOR_NORMAL ) );
|
||||||
|
|
||||||
|
public static final BlockMonitor MONITOR_ADVANCED =
|
||||||
|
register( "monitor_advanced", new BlockMonitor( properties(), () -> ModBlockEntities.MONITOR_ADVANCED ) );
|
||||||
|
|
||||||
|
public static final BlockComputer COMPUTER_NORMAL =
|
||||||
|
register( "computer_normal", new BlockComputer( properties(), ComputerFamily.NORMAL, () -> ModBlockEntities.COMPUTER_NORMAL ) );
|
||||||
|
|
||||||
|
public static final BlockComputer COMPUTER_ADVANCED =
|
||||||
|
register( "computer_advanced", new BlockComputer( properties(), ComputerFamily.ADVANCED, () -> ModBlockEntities.COMPUTER_ADVANCED ) );
|
||||||
|
|
||||||
|
public static final BlockComputer COMPUTER_COMMAND =
|
||||||
|
register( "computer_command", new BlockComputer( FabricBlockSettings.copyOf( Blocks.STONE ).strength( -1, 6000000.0F ), ComputerFamily.COMMAND, () -> ModBlockEntities.COMPUTER_COMMAND ) );
|
||||||
|
|
||||||
|
public static final BlockTurtle TURTLE_NORMAL =
|
||||||
|
register( "turtle_normal", new BlockTurtle( turtleProperties(), ComputerFamily.NORMAL, () -> ModBlockEntities.TURTLE_NORMAL ) );
|
||||||
|
|
||||||
|
public static final BlockTurtle TURTLE_ADVANCED =
|
||||||
|
register( "turtle_advanced", new BlockTurtle( turtleProperties(), ComputerFamily.ADVANCED, () -> ModBlockEntities.TURTLE_ADVANCED ) );
|
||||||
|
|
||||||
|
public static final BlockSpeaker SPEAKER =
|
||||||
|
register( "speaker", new BlockSpeaker( properties() ) );
|
||||||
|
|
||||||
|
public static final BlockDiskDrive DISK_DRIVE =
|
||||||
|
register( "disk_drive", new BlockDiskDrive( properties() ) );
|
||||||
|
|
||||||
|
public static final BlockPrinter PRINTER =
|
||||||
|
register( "printer", new BlockPrinter( properties() ) );
|
||||||
|
|
||||||
|
public static final BlockWirelessModem WIRELESS_MODEM_NORMAL =
|
||||||
|
register( "wireless_modem_normal", new BlockWirelessModem( properties(), () -> ModBlockEntities.WIRELESS_MODEM_NORMAL ) );
|
||||||
|
|
||||||
|
public static final BlockWirelessModem WIRELESS_MODEM_ADVANCED =
|
||||||
|
register( "wireless_modem_advanced", new BlockWirelessModem( properties(), () -> ModBlockEntities.WIRELESS_MODEM_ADVANCED ) );
|
||||||
|
|
||||||
|
public static final BlockWiredModemFull WIRED_MODEM_FULL =
|
||||||
|
register( "wired_modem_full", new BlockWiredModemFull( modemProperties() ) );
|
||||||
|
|
||||||
|
public static final BlockCable CABLE =
|
||||||
|
register( "cable", new BlockCable( modemProperties() ) );
|
||||||
|
|
||||||
|
private static BlockBehaviour.Properties properties()
|
||||||
|
{
|
||||||
|
return BlockBehaviour.Properties.of( Material.GLASS ).strength( 2F ).sound( SoundType.STONE ).noOcclusion();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BlockBehaviour.Properties turtleProperties()
|
||||||
|
{
|
||||||
|
return FabricBlockSettings.copyOf( Blocks.STONE ).strength( 2.5f );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BlockBehaviour.Properties modemProperties()
|
||||||
|
{
|
||||||
|
return FabricBlockSettings.copyOf( Blocks.STONE ).breakByHand( true ).breakByTool( FabricToolTags.PICKAXES ).strength( 1.5f );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ModBlockEntities
|
||||||
|
{
|
||||||
|
private static <T extends BlockEntity> BlockEntityType<T> ofBlock( Block block, String id, BiFunction<BlockPos, BlockState, T> factory )
|
||||||
|
{
|
||||||
|
BlockEntityType<T> blockEntityType = FabricBlockEntityTypeBuilder.create( factory::apply, block ).build();
|
||||||
|
return net.minecraft.core.Registry.register( BLOCK_ENTITY_TYPE, new ResourceLocation( MOD_ID, id ), blockEntityType );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final BlockEntityType<TileMonitor> MONITOR_NORMAL =
|
||||||
|
ofBlock( ModBlocks.MONITOR_NORMAL, "monitor_normal", ( blockPos, blockState ) -> new TileMonitor( ModBlockEntities.MONITOR_NORMAL, blockPos, blockState, false ) );
|
||||||
|
|
||||||
|
public static final BlockEntityType<TileMonitor> MONITOR_ADVANCED =
|
||||||
|
ofBlock( ModBlocks.MONITOR_ADVANCED, "monitor_advanced", ( blockPos, blockState ) -> new TileMonitor( ModBlockEntities.MONITOR_ADVANCED, blockPos, blockState, true ) );
|
||||||
|
|
||||||
|
public static final BlockEntityType<TileComputer> COMPUTER_NORMAL =
|
||||||
|
ofBlock( ModBlocks.COMPUTER_NORMAL, "computer_normal", ( blockPos, blockState ) -> new TileComputer( ModBlockEntities.COMPUTER_NORMAL, blockPos, blockState, ComputerFamily.NORMAL ) );
|
||||||
|
|
||||||
|
public static final BlockEntityType<TileComputer> COMPUTER_ADVANCED =
|
||||||
|
ofBlock( ModBlocks.COMPUTER_ADVANCED, "computer_advanced", ( blockPos, blockState ) -> new TileComputer( ModBlockEntities.COMPUTER_ADVANCED, blockPos, blockState, ComputerFamily.ADVANCED ) );
|
||||||
|
|
||||||
|
public static final BlockEntityType<TileCommandComputer> COMPUTER_COMMAND =
|
||||||
|
ofBlock( ModBlocks.COMPUTER_COMMAND, "computer_command", ( blockPos, blockState ) -> new TileCommandComputer( ModBlockEntities.COMPUTER_COMMAND, blockPos, blockState ) );
|
||||||
|
|
||||||
|
public static final BlockEntityType<TileTurtle> TURTLE_NORMAL =
|
||||||
|
ofBlock( ModBlocks.TURTLE_NORMAL, "turtle_normal", ( blockPos, blockState ) -> new TileTurtle( ModBlockEntities.TURTLE_NORMAL, blockPos, blockState, ComputerFamily.NORMAL ) );
|
||||||
|
|
||||||
|
public static final BlockEntityType<TileTurtle> TURTLE_ADVANCED =
|
||||||
|
ofBlock( ModBlocks.TURTLE_ADVANCED, "turtle_advanced", ( blockPos, blockState ) -> new TileTurtle( ModBlockEntities.TURTLE_ADVANCED, blockPos, blockState, ComputerFamily.ADVANCED ) );
|
||||||
|
|
||||||
|
public static final BlockEntityType<TileSpeaker> SPEAKER =
|
||||||
|
ofBlock( ModBlocks.SPEAKER, "speaker", ( blockPos, blockState ) -> new TileSpeaker( ModBlockEntities.SPEAKER, blockPos, blockState ) );
|
||||||
|
|
||||||
|
public static final BlockEntityType<TileDiskDrive> DISK_DRIVE =
|
||||||
|
ofBlock( ModBlocks.DISK_DRIVE, "disk_drive", ( blockPos, blockState ) -> new TileDiskDrive( ModBlockEntities.DISK_DRIVE, blockPos, blockState ) );
|
||||||
|
|
||||||
|
public static final BlockEntityType<TilePrinter> PRINTER =
|
||||||
|
ofBlock( ModBlocks.PRINTER, "printer", ( blockPos, blockState ) -> new TilePrinter( ModBlockEntities.PRINTER, blockPos, blockState ) );
|
||||||
|
|
||||||
|
public static final BlockEntityType<TileWiredModemFull> WIRED_MODEM_FULL =
|
||||||
|
ofBlock( ModBlocks.WIRED_MODEM_FULL, "wired_modem_full", ( blockPos, blockState ) -> new TileWiredModemFull( ModBlockEntities.WIRED_MODEM_FULL, blockPos, blockState ) );
|
||||||
|
|
||||||
|
public static final BlockEntityType<TileCable> CABLE =
|
||||||
|
ofBlock( ModBlocks.CABLE, "cable", ( blockPos, blockState ) -> new TileCable( ModBlockEntities.CABLE, blockPos, blockState ) );
|
||||||
|
|
||||||
|
public static final BlockEntityType<TileWirelessModem> WIRELESS_MODEM_NORMAL =
|
||||||
|
ofBlock( ModBlocks.WIRELESS_MODEM_NORMAL, "wireless_modem_normal", ( blockPos, blockState ) -> new TileWirelessModem( ModBlockEntities.WIRELESS_MODEM_NORMAL, blockPos, blockState, false ) );
|
||||||
|
|
||||||
|
public static final BlockEntityType<TileWirelessModem> WIRELESS_MODEM_ADVANCED =
|
||||||
|
ofBlock( ModBlocks.WIRELESS_MODEM_ADVANCED, "wireless_modem_advanced", ( blockPos, blockState ) -> new TileWirelessModem( ModBlockEntities.WIRELESS_MODEM_ADVANCED, blockPos, blockState, true ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class ModItems
|
||||||
|
{
|
||||||
|
private static final CreativeModeTab mainItemGroup = ComputerCraft.MAIN_GROUP;
|
||||||
|
|
||||||
|
public static final ItemComputer COMPUTER_NORMAL =
|
||||||
|
ofBlock( ModBlocks.COMPUTER_NORMAL, ItemComputer::new );
|
||||||
|
|
||||||
|
public static final ItemComputer COMPUTER_ADVANCED =
|
||||||
|
ofBlock( ModBlocks.COMPUTER_ADVANCED, ItemComputer::new );
|
||||||
|
|
||||||
|
public static final ItemComputer COMPUTER_COMMAND =
|
||||||
|
ofBlock( ModBlocks.COMPUTER_COMMAND, ItemComputer::new );
|
||||||
|
|
||||||
|
public static final ItemPocketComputer POCKET_COMPUTER_NORMAL =
|
||||||
|
register( "pocket_computer_normal", new ItemPocketComputer( properties().stacksTo( 1 ), ComputerFamily.NORMAL ) );
|
||||||
|
|
||||||
|
public static final ItemPocketComputer POCKET_COMPUTER_ADVANCED =
|
||||||
|
register( "pocket_computer_advanced", new ItemPocketComputer( properties().stacksTo( 1 ), ComputerFamily.ADVANCED ) );
|
||||||
|
|
||||||
|
public static final ItemTurtle TURTLE_NORMAL =
|
||||||
|
ofBlock( ModBlocks.TURTLE_NORMAL, ItemTurtle::new );
|
||||||
|
|
||||||
|
public static final ItemTurtle TURTLE_ADVANCED =
|
||||||
|
ofBlock( ModBlocks.TURTLE_ADVANCED, ItemTurtle::new );
|
||||||
|
|
||||||
|
public static final ItemDisk DISK =
|
||||||
|
register( "disk", new ItemDisk( properties().stacksTo( 1 ) ) );
|
||||||
|
|
||||||
|
public static final ItemTreasureDisk TREASURE_DISK =
|
||||||
|
register( "treasure_disk", new ItemTreasureDisk( properties().stacksTo( 1 ) ) );
|
||||||
|
|
||||||
|
public static final ItemPrintout PRINTED_PAGE =
|
||||||
|
register( "printed_page", new ItemPrintout( properties().stacksTo( 1 ), ItemPrintout.Type.PAGE ) );
|
||||||
|
|
||||||
|
public static final ItemPrintout PRINTED_PAGES =
|
||||||
|
register( "printed_pages", new ItemPrintout( properties().stacksTo( 1 ), ItemPrintout.Type.PAGES ) );
|
||||||
|
|
||||||
|
public static final ItemPrintout PRINTED_BOOK =
|
||||||
|
register( "printed_book", new ItemPrintout( properties().stacksTo( 1 ), ItemPrintout.Type.BOOK ) );
|
||||||
|
|
||||||
|
public static final BlockItem SPEAKER =
|
||||||
|
ofBlock( ModBlocks.SPEAKER, BlockItem::new );
|
||||||
|
|
||||||
|
public static final BlockItem DISK_DRIVE =
|
||||||
|
ofBlock( ModBlocks.DISK_DRIVE, BlockItem::new );
|
||||||
|
|
||||||
|
public static final BlockItem PRINTER =
|
||||||
|
ofBlock( ModBlocks.PRINTER, BlockItem::new );
|
||||||
|
|
||||||
|
public static final BlockItem MONITOR_NORMAL =
|
||||||
|
ofBlock( ModBlocks.MONITOR_NORMAL, BlockItem::new );
|
||||||
|
|
||||||
|
public static final BlockItem MONITOR_ADVANCED =
|
||||||
|
ofBlock( ModBlocks.MONITOR_ADVANCED, BlockItem::new );
|
||||||
|
|
||||||
|
public static final BlockItem WIRELESS_MODEM_NORMAL =
|
||||||
|
ofBlock( ModBlocks.WIRELESS_MODEM_NORMAL, BlockItem::new );
|
||||||
|
|
||||||
|
public static final BlockItem WIRELESS_MODEM_ADVANCED =
|
||||||
|
ofBlock( ModBlocks.WIRELESS_MODEM_ADVANCED, BlockItem::new );
|
||||||
|
|
||||||
|
public static final BlockItem WIRED_MODEM_FULL =
|
||||||
|
ofBlock( ModBlocks.WIRED_MODEM_FULL, BlockItem::new );
|
||||||
|
|
||||||
|
public static final ItemBlockCable.Cable CABLE =
|
||||||
|
register( "cable", new ItemBlockCable.Cable( ModBlocks.CABLE, properties() ) );
|
||||||
|
|
||||||
|
public static final ItemBlockCable.WiredModem WIRED_MODEM =
|
||||||
|
register( "wired_modem", new ItemBlockCable.WiredModem( ModBlocks.CABLE, properties() ) );
|
||||||
|
|
||||||
|
|
||||||
|
private static <B extends Block, I extends Item> I ofBlock( B parent, BiFunction<B, Item.Properties, I> supplier )
|
||||||
|
{
|
||||||
|
return net.minecraft.core.Registry.register( net.minecraft.core.Registry.ITEM, net.minecraft.core.Registry.BLOCK.getKey( parent ), supplier.apply( parent, properties() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Item.Properties properties()
|
||||||
|
{
|
||||||
|
return new Item.Properties().tab( mainItemGroup );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T extends Item> T register( String id, T item )
|
||||||
|
{
|
||||||
|
return net.minecraft.core.Registry.register( net.minecraft.core.Registry.ITEM, new ResourceLocation( MOD_ID, id ), item );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ModEntities
|
||||||
|
{
|
||||||
|
public static final EntityType<TurtlePlayer> TURTLE_PLAYER =
|
||||||
|
net.minecraft.core.Registry.register( net.minecraft.core.Registry.ENTITY_TYPE, new ResourceLocation( MOD_ID, "turtle_player" ),
|
||||||
|
EntityType.Builder.<TurtlePlayer>createNothing( MobCategory.MISC ).noSave().noSummon().sized( 0, 0 ).build( ComputerCraft.MOD_ID + ":turtle_player" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ModContainers
|
||||||
|
{
|
||||||
|
public static final MenuType<ContainerComputerBase> COMPUTER =
|
||||||
|
ContainerData.toType( new ResourceLocation( MOD_ID, "computer" ), ModContainers.COMPUTER, ComputerContainerData::new, ComputerMenuWithoutInventory::new );
|
||||||
|
|
||||||
|
public static final MenuType<ContainerComputerBase> POCKET_COMPUTER =
|
||||||
|
ContainerData.toType( new ResourceLocation( MOD_ID, "pocket_computer" ), ModContainers.POCKET_COMPUTER, ComputerContainerData::new, ComputerMenuWithoutInventory::new );
|
||||||
|
|
||||||
|
public static final MenuType<ContainerComputerBase> POCKET_COMPUTER_NO_TERM =
|
||||||
|
ContainerData.toType( new ResourceLocation( MOD_ID, "pocket_computer_no_term" ), ModContainers.POCKET_COMPUTER_NO_TERM, ComputerContainerData::new, ComputerMenuWithoutInventory::new );
|
||||||
|
|
||||||
|
public static final MenuType<ContainerTurtle> TURTLE =
|
||||||
|
ContainerData.toType( new ResourceLocation( MOD_ID, "turtle" ), ComputerContainerData::new, ContainerTurtle::new );
|
||||||
|
|
||||||
|
public static final MenuType<ContainerDiskDrive> DISK_DRIVE =
|
||||||
|
registerSimple( "disk_drive", ContainerDiskDrive::new );
|
||||||
|
|
||||||
|
public static final MenuType<ContainerPrinter> PRINTER =
|
||||||
|
registerSimple( "printer", ContainerPrinter::new );
|
||||||
|
|
||||||
|
public static final MenuType<ContainerHeldItem> PRINTOUT =
|
||||||
|
ContainerData.toType( new ResourceLocation( MOD_ID, "printout" ), HeldItemContainerData::new, ContainerHeldItem::createPrintout );
|
||||||
|
|
||||||
|
public static final MenuType<ContainerViewComputer> VIEW_COMPUTER =
|
||||||
|
ContainerData.toType( new ResourceLocation( MOD_ID, "view_computer" ), ViewComputerContainerData::new, ContainerViewComputer::new );
|
||||||
|
|
||||||
|
private static <T extends AbstractContainerMenu> MenuType<T> registerSimple( String id, ScreenHandlerRegistry.SimpleClientHandlerFactory<T> function )
|
||||||
|
{
|
||||||
|
return ScreenHandlerRegistry.registerSimple( new ResourceLocation( MOD_ID, id ), function );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class TurtleUpgrades
|
||||||
|
{
|
||||||
|
public static TurtleModem wirelessModemNormal =
|
||||||
|
new TurtleModem( new ResourceLocation( ComputerCraft.MOD_ID, "wireless_modem_normal" ), new ItemStack( ModItems.WIRELESS_MODEM_NORMAL ), false );
|
||||||
|
|
||||||
|
public static TurtleModem wirelessModemAdvanced =
|
||||||
|
new TurtleModem( new ResourceLocation( ComputerCraft.MOD_ID, "wireless_modem_advanced" ), new ItemStack( ModItems.WIRELESS_MODEM_ADVANCED ), true );
|
||||||
|
|
||||||
|
public static TurtleSpeaker speaker =
|
||||||
|
new TurtleSpeaker( new ResourceLocation( ComputerCraft.MOD_ID, "speaker" ), new ItemStack( ModItems.SPEAKER ) );
|
||||||
|
|
||||||
|
public static TurtleCraftingTable craftingTable =
|
||||||
|
new TurtleCraftingTable( new ResourceLocation( "minecraft", "crafting_table" ), new ItemStack( Items.CRAFTING_TABLE ) );
|
||||||
|
|
||||||
|
public static TurtleSword diamondSword =
|
||||||
|
new TurtleSword( new ResourceLocation( "minecraft", "diamond_sword" ), Items.DIAMOND_SWORD, 9.0f );
|
||||||
|
|
||||||
|
public static TurtleShovel diamondShovel =
|
||||||
|
new TurtleShovel( new ResourceLocation( "minecraft", "diamond_shovel" ), Items.DIAMOND_SHOVEL, 1.0f );
|
||||||
|
|
||||||
|
public static TurtleTool diamondPickaxe =
|
||||||
|
new TurtleTool( new ResourceLocation( "minecraft", "diamond_pickaxe" ), Items.DIAMOND_PICKAXE, 1.0f );
|
||||||
|
|
||||||
|
public static TurtleAxe diamondAxe =
|
||||||
|
new TurtleAxe( new ResourceLocation( "minecraft", "diamond_axe" ), Items.DIAMOND_AXE, 6.0f );
|
||||||
|
|
||||||
|
public static TurtleHoe diamondHoe =
|
||||||
|
new TurtleHoe( new ResourceLocation( "minecraft", "diamond_hoe" ), Items.DIAMOND_HOE, 1.0f );
|
||||||
|
|
||||||
|
public static TurtleTool netheritePickaxe =
|
||||||
|
new TurtleTool( new ResourceLocation( "minecraft", "netherite_pickaxe" ), Items.NETHERITE_PICKAXE, 1.0f );
|
||||||
|
|
||||||
|
public static void registerTurtleUpgrades()
|
||||||
|
{
|
||||||
|
ComputerCraftAPI.registerTurtleUpgrade( wirelessModemNormal );
|
||||||
|
ComputerCraftAPI.registerTurtleUpgrade( wirelessModemAdvanced );
|
||||||
|
ComputerCraftAPI.registerTurtleUpgrade( speaker );
|
||||||
|
ComputerCraftAPI.registerTurtleUpgrade( craftingTable );
|
||||||
|
|
||||||
|
ComputerCraftAPI.registerTurtleUpgrade( diamondSword );
|
||||||
|
ComputerCraftAPI.registerTurtleUpgrade( diamondShovel );
|
||||||
|
ComputerCraftAPI.registerTurtleUpgrade( diamondPickaxe );
|
||||||
|
ComputerCraftAPI.registerTurtleUpgrade( diamondAxe );
|
||||||
|
ComputerCraftAPI.registerTurtleUpgrade( diamondHoe );
|
||||||
|
ComputerCraftAPI.registerTurtleUpgrade( netheritePickaxe );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class PocketUpgrades
|
||||||
|
{
|
||||||
|
public static PocketModem wirelessModemNormal = new PocketModem( new ResourceLocation( ComputerCraft.MOD_ID, "wireless_modem_normal" ), new ItemStack( ModItems.WIRELESS_MODEM_NORMAL ), false );
|
||||||
|
|
||||||
|
public static PocketModem wirelessModemAdvanced = new PocketModem( new ResourceLocation( ComputerCraft.MOD_ID, "wireless_modem_advanced" ), new ItemStack( ModItems.WIRELESS_MODEM_ADVANCED ), true );
|
||||||
|
|
||||||
|
public static PocketSpeaker speaker = new PocketSpeaker( new ResourceLocation( ComputerCraft.MOD_ID, "speaker" ), new ItemStack( ModItems.SPEAKER ) );
|
||||||
|
|
||||||
|
public static void registerPocketUpgrades()
|
||||||
|
{
|
||||||
|
ComputerCraftAPI.registerPocketUpgrade( wirelessModemNormal );
|
||||||
|
ComputerCraftAPI.registerPocketUpgrade( wirelessModemAdvanced );
|
||||||
|
ComputerCraftAPI.registerPocketUpgrade( speaker );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -98,17 +98,17 @@ public final class TurtleUpgrades
|
|||||||
{
|
{
|
||||||
vanilla = new ITurtleUpgrade[] {
|
vanilla = new ITurtleUpgrade[] {
|
||||||
// ComputerCraft upgrades
|
// ComputerCraft upgrades
|
||||||
ComputerCraftRegistry.TurtleUpgrades.wirelessModemNormal,
|
Registry.TurtleUpgrades.wirelessModemNormal,
|
||||||
ComputerCraftRegistry.TurtleUpgrades.wirelessModemAdvanced,
|
Registry.TurtleUpgrades.wirelessModemAdvanced,
|
||||||
ComputerCraftRegistry.TurtleUpgrades.speaker,
|
Registry.TurtleUpgrades.speaker,
|
||||||
|
|
||||||
// Vanilla Minecraft upgrades
|
// Vanilla Minecraft upgrades
|
||||||
ComputerCraftRegistry.TurtleUpgrades.diamondPickaxe,
|
Registry.TurtleUpgrades.diamondPickaxe,
|
||||||
ComputerCraftRegistry.TurtleUpgrades.diamondAxe,
|
Registry.TurtleUpgrades.diamondAxe,
|
||||||
ComputerCraftRegistry.TurtleUpgrades.diamondSword,
|
Registry.TurtleUpgrades.diamondSword,
|
||||||
ComputerCraftRegistry.TurtleUpgrades.diamondShovel,
|
Registry.TurtleUpgrades.diamondShovel,
|
||||||
ComputerCraftRegistry.TurtleUpgrades.diamondHoe,
|
Registry.TurtleUpgrades.diamondHoe,
|
||||||
ComputerCraftRegistry.TurtleUpgrades.craftingTable,
|
Registry.TurtleUpgrades.craftingTable,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,9 @@
|
|||||||
package dan200.computercraft.shared.command;
|
package dan200.computercraft.shared.command;
|
||||||
|
|
||||||
import dan200.computercraft.shared.util.IDAssigner;
|
import dan200.computercraft.shared.util.IDAssigner;
|
||||||
|
import me.shedaniel.cloth.api.utils.v1.GameInstanceUtils;
|
||||||
import net.minecraft.Util;
|
import net.minecraft.Util;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
@@ -28,6 +30,9 @@ public final class ClientCommands
|
|||||||
// Emulate the command on the client side
|
// Emulate the command on the client side
|
||||||
if( message.startsWith( OPEN_COMPUTER ) )
|
if( message.startsWith( OPEN_COMPUTER ) )
|
||||||
{
|
{
|
||||||
|
MinecraftServer server = GameInstanceUtils.getServer();
|
||||||
|
if( server == null || server.isDedicatedServer() ) return false;
|
||||||
|
|
||||||
String idStr = message.substring( OPEN_COMPUTER.length() ).trim();
|
String idStr = message.substring( OPEN_COMPUTER.length() ).trim();
|
||||||
int id;
|
int id;
|
||||||
try
|
try
|
||||||
@@ -36,7 +41,7 @@ public final class ClientCommands
|
|||||||
}
|
}
|
||||||
catch( NumberFormatException ignore )
|
catch( NumberFormatException ignore )
|
||||||
{
|
{
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
File file = new File( IDAssigner.getDir(), "computer/" + id );
|
File file = new File( IDAssigner.getDir(), "computer/" + id );
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory;
|
|||||||
import net.minecraft.commands.CommandSourceStack;
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.network.chat.MutableComponent;
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
import net.minecraft.network.chat.TextComponent;
|
import net.minecraft.network.chat.TextComponent;
|
||||||
import net.minecraft.network.chat.TranslatableComponent;
|
import net.minecraft.network.chat.TranslatableComponent;
|
||||||
@@ -82,15 +83,15 @@ public final class CommandComputerCraft
|
|||||||
BlockPos pos = new BlockPos( source.getPosition() );
|
BlockPos pos = new BlockPos( source.getPosition() );
|
||||||
|
|
||||||
computers.sort( ( a, b ) -> {
|
computers.sort( ( a, b ) -> {
|
||||||
if( a.getWorld() == b.getWorld() && a.getWorld() == world )
|
if( a.getLevel() == b.getLevel() && a.getLevel() == world )
|
||||||
{
|
{
|
||||||
return Double.compare( a.getPosition().distSqr( pos ), b.getPosition().distSqr( pos ) );
|
return Double.compare( a.getPosition().distSqr( pos ), b.getPosition().distSqr( pos ) );
|
||||||
}
|
}
|
||||||
else if( a.getWorld() == world )
|
else if( a.getLevel() == world )
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else if( b.getWorld() == world )
|
else if( b.getLevel() == world )
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -171,15 +172,14 @@ public final class CommandComputerCraft
|
|||||||
.arg( "computer", oneComputer() )
|
.arg( "computer", oneComputer() )
|
||||||
.executes( context -> {
|
.executes( context -> {
|
||||||
ServerComputer computer = getComputerArgument( context, "computer" );
|
ServerComputer computer = getComputerArgument( context, "computer" );
|
||||||
Level world = computer.getWorld();
|
Level world = computer.getLevel();
|
||||||
BlockPos pos = computer.getPosition();
|
BlockPos pos = computer.getPosition();
|
||||||
|
|
||||||
if( world == null || pos == null ) throw TP_NOT_THERE.create();
|
if( world == null || pos == null ) throw TP_NOT_THERE.create();
|
||||||
|
|
||||||
Entity entity = context.getSource().getEntityOrException();
|
Entity entity = context.getSource().getEntityOrException();
|
||||||
if( !(entity instanceof ServerPlayer) ) throw TP_NOT_PLAYER.create();
|
if( !(entity instanceof ServerPlayer player) ) throw TP_NOT_PLAYER.create();
|
||||||
|
|
||||||
ServerPlayer player = (ServerPlayer) entity;
|
|
||||||
if( player.getCommandSenderWorld() == world )
|
if( player.getCommandSenderWorld() == world )
|
||||||
{
|
{
|
||||||
player.connection.teleport(
|
player.connection.teleport(
|
||||||
@@ -236,7 +236,7 @@ public final class CommandComputerCraft
|
|||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public MutableComponent getDisplayName()
|
public Component getDisplayName()
|
||||||
{
|
{
|
||||||
return new TranslatableComponent( "gui.computercraft.view_computer" );
|
return new TranslatableComponent( "gui.computercraft.view_computer" );
|
||||||
}
|
}
|
||||||
@@ -292,7 +292,7 @@ public final class CommandComputerCraft
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MutableComponent linkComputer( CommandSourceStack source, ServerComputer serverComputer, int computerId )
|
private static Component linkComputer( CommandSourceStack source, ServerComputer serverComputer, int computerId )
|
||||||
{
|
{
|
||||||
MutableComponent out = new TextComponent( "" );
|
MutableComponent out = new TextComponent( "" );
|
||||||
|
|
||||||
@@ -333,14 +333,14 @@ public final class CommandComputerCraft
|
|||||||
|
|
||||||
if( UserLevel.OWNER.test( source ) && isPlayer( source ) )
|
if( UserLevel.OWNER.test( source ) && isPlayer( source ) )
|
||||||
{
|
{
|
||||||
MutableComponent linkPath = linkStorage( computerId );
|
Component linkPath = linkStorage( computerId );
|
||||||
if( linkPath != null ) out.append( " " ).append( linkPath );
|
if( linkPath != null ) out.append( " " ).append( linkPath );
|
||||||
}
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MutableComponent linkPosition( CommandSourceStack context, ServerComputer computer )
|
private static Component linkPosition( CommandSourceStack context, ServerComputer computer )
|
||||||
{
|
{
|
||||||
if( UserLevel.OP.test( context ) )
|
if( UserLevel.OP.test( context ) )
|
||||||
{
|
{
|
||||||
@@ -356,7 +356,7 @@ public final class CommandComputerCraft
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MutableComponent linkStorage( int id )
|
private static Component linkStorage( int id )
|
||||||
{
|
{
|
||||||
File file = new File( IDAssigner.getDir(), "computer/" + id );
|
File file = new File( IDAssigner.getDir(), "computer/" + id );
|
||||||
if( !file.isDirectory() ) return null;
|
if( !file.isDirectory() ) return null;
|
||||||
@@ -398,7 +398,7 @@ public final class CommandComputerCraft
|
|||||||
|
|
||||||
timings.sort( Comparator.<ComputerTracker, Long>comparing( x -> x.get( sortField ) ).reversed() );
|
timings.sort( Comparator.<ComputerTracker, Long>comparing( x -> x.get( sortField ) ).reversed() );
|
||||||
|
|
||||||
MutableComponent[] headers = new MutableComponent[1 + fields.size()];
|
Component[] headers = new Component[1 + fields.size()];
|
||||||
headers[0] = translate( "commands.computercraft.track.dump.computer" );
|
headers[0] = translate( "commands.computercraft.track.dump.computer" );
|
||||||
for( int i = 0; i < fields.size(); i++ ) headers[i + 1] = translate( fields.get( i ).translationKey() );
|
for( int i = 0; i < fields.size(); i++ ) headers[i + 1] = translate( fields.get( i ).translationKey() );
|
||||||
TableBuilder table = new TableBuilder( TRACK_ID, headers );
|
TableBuilder table = new TableBuilder( TRACK_ID, headers );
|
||||||
@@ -408,9 +408,9 @@ public final class CommandComputerCraft
|
|||||||
Computer computer = entry.getComputer();
|
Computer computer = entry.getComputer();
|
||||||
ServerComputer serverComputer = computer == null ? null : lookup.get( computer );
|
ServerComputer serverComputer = computer == null ? null : lookup.get( computer );
|
||||||
|
|
||||||
MutableComponent computerComponent = linkComputer( source, serverComputer, entry.getComputerId() );
|
Component computerComponent = linkComputer( source, serverComputer, entry.getComputerId() );
|
||||||
|
|
||||||
MutableComponent[] row = new MutableComponent[1 + fields.size()];
|
Component[] row = new Component[1 + fields.size()];
|
||||||
row[0] = computerComponent;
|
row[0] = computerComponent;
|
||||||
for( int i = 0; i < fields.size(); i++ ) row[i + 1] = text( entry.getFormatted( fields.get( i ) ) );
|
for( int i = 0; i < fields.size(); i++ ) row[i + 1] = text( entry.getFormatted( fields.get( i ) ) );
|
||||||
table.row( row );
|
table.row( row );
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.command;
|
package dan200.computercraft.shared.command;
|
||||||
|
|
||||||
import com.mojang.brigadier.context.CommandContext;
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
@@ -27,12 +26,13 @@ public final class CommandUtils
|
|||||||
public static boolean isPlayer( CommandSourceStack output )
|
public static boolean isPlayer( CommandSourceStack output )
|
||||||
{
|
{
|
||||||
Entity sender = output.getEntity();
|
Entity sender = output.getEntity();
|
||||||
return sender instanceof ServerPlayer && !(sender instanceof FakePlayer) && ((ServerPlayer) sender).connection != null;
|
return sender instanceof ServerPlayer
|
||||||
|
&& !(sender instanceof FakePlayer)
|
||||||
|
&& ((ServerPlayer) sender).connection != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings( "unchecked" )
|
@SuppressWarnings( "unchecked" )
|
||||||
public static CompletableFuture<Suggestions> suggestOnServer( CommandContext<?> context, SuggestionsBuilder builder,
|
public static CompletableFuture<Suggestions> suggestOnServer( CommandContext<?> context, SuggestionsBuilder builder, Function<CommandContext<CommandSourceStack>, CompletableFuture<Suggestions>> supplier )
|
||||||
Function<CommandContext<CommandSourceStack>, CompletableFuture<Suggestions>> supplier )
|
|
||||||
{
|
{
|
||||||
Object source = context.getSource();
|
Object source = context.getSource();
|
||||||
if( !(source instanceof SharedSuggestionProvider) )
|
if( !(source instanceof SharedSuggestionProvider) )
|
||||||
@@ -49,26 +49,21 @@ public final class CommandUtils
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> CompletableFuture<Suggestions> suggest( SuggestionsBuilder builder, T[] candidates, Function<T, String> toString )
|
|
||||||
{
|
|
||||||
return suggest( builder, Arrays.asList( candidates ), toString );
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> CompletableFuture<Suggestions> suggest( SuggestionsBuilder builder, Iterable<T> candidates, Function<T, String> toString )
|
public static <T> CompletableFuture<Suggestions> suggest( SuggestionsBuilder builder, Iterable<T> candidates, Function<T, String> toString )
|
||||||
{
|
{
|
||||||
String remaining = builder.getRemaining()
|
String remaining = builder.getRemaining().toLowerCase( Locale.ROOT );
|
||||||
.toLowerCase( Locale.ROOT );
|
|
||||||
for( T choice : candidates )
|
for( T choice : candidates )
|
||||||
{
|
{
|
||||||
String name = toString.apply( choice );
|
String name = toString.apply( choice );
|
||||||
if( !name.toLowerCase( Locale.ROOT )
|
if( !name.toLowerCase( Locale.ROOT ).startsWith( remaining ) ) continue;
|
||||||
.startsWith( remaining ) )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
builder.suggest( name );
|
builder.suggest( name );
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.buildFuture();
|
return builder.buildFuture();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <T> CompletableFuture<Suggestions> suggest( SuggestionsBuilder builder, T[] candidates, Function<T, String> toString )
|
||||||
|
{
|
||||||
|
return suggest( builder, Arrays.asList( candidates ), toString );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.command;
|
package dan200.computercraft.shared.command;
|
||||||
|
|
||||||
import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType;
|
import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType;
|
||||||
@@ -17,12 +16,15 @@ public final class Exceptions
|
|||||||
public static final Dynamic2CommandExceptionType COMPUTER_ARG_MANY = translated2( "argument.computercraft.computer.many_matching" );
|
public static final Dynamic2CommandExceptionType COMPUTER_ARG_MANY = translated2( "argument.computercraft.computer.many_matching" );
|
||||||
|
|
||||||
public static final DynamicCommandExceptionType TRACKING_FIELD_ARG_NONE = translated1( "argument.computercraft.tracking_field.no_field" );
|
public static final DynamicCommandExceptionType TRACKING_FIELD_ARG_NONE = translated1( "argument.computercraft.tracking_field.no_field" );
|
||||||
public static final SimpleCommandExceptionType ARGUMENT_EXPECTED = translated( "argument.computercraft.argument_expected" );
|
|
||||||
static final SimpleCommandExceptionType NOT_TRACKING_EXCEPTION = translated( "commands.computercraft.track.stop.not_enabled" );
|
static final SimpleCommandExceptionType NOT_TRACKING_EXCEPTION = translated( "commands.computercraft.track.stop.not_enabled" );
|
||||||
static final SimpleCommandExceptionType NO_TIMINGS_EXCEPTION = translated( "commands.computercraft.track.dump.no_timings" );
|
static final SimpleCommandExceptionType NO_TIMINGS_EXCEPTION = translated( "commands.computercraft.track.dump.no_timings" );
|
||||||
|
|
||||||
static final SimpleCommandExceptionType TP_NOT_THERE = translated( "commands.computercraft.tp.not_there" );
|
static final SimpleCommandExceptionType TP_NOT_THERE = translated( "commands.computercraft.tp.not_there" );
|
||||||
static final SimpleCommandExceptionType TP_NOT_PLAYER = translated( "commands.computercraft.tp.not_player" );
|
static final SimpleCommandExceptionType TP_NOT_PLAYER = translated( "commands.computercraft.tp.not_player" );
|
||||||
|
|
||||||
|
public static final SimpleCommandExceptionType ARGUMENT_EXPECTED = translated( "argument.computercraft.argument_expected" );
|
||||||
|
|
||||||
private static SimpleCommandExceptionType translated( String key )
|
private static SimpleCommandExceptionType translated( String key )
|
||||||
{
|
{
|
||||||
return new SimpleCommandExceptionType( new TranslatableComponent( key ) );
|
return new SimpleCommandExceptionType( new TranslatableComponent( key ) );
|
||||||
|
|||||||
@@ -67,6 +67,6 @@ public enum UserLevel implements Predicate<CommandSourceStack>
|
|||||||
Entity sender = source.getEntity();
|
Entity sender = source.getEntity();
|
||||||
return server.isDedicatedServer()
|
return server.isDedicatedServer()
|
||||||
? source.getEntity() == null && source.hasPermission( 4 ) && source.getTextName().equals( "Server" )
|
? source.getEntity() == null && source.hasPermission( 4 ) && source.getTextName().equals( "Server" )
|
||||||
: sender instanceof Player && ((Player) sender).getGameProfile().getName().equalsIgnoreCase( server.getServerModName() );
|
: sender instanceof Player player && player.getGameProfile().getName().equalsIgnoreCase( server.getServerModName() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.command.arguments;
|
package dan200.computercraft.shared.command.arguments;
|
||||||
|
|
||||||
import com.mojang.brigadier.arguments.ArgumentType;
|
import com.mojang.brigadier.arguments.ArgumentType;
|
||||||
@@ -15,17 +14,10 @@ import net.minecraft.resources.ResourceLocation;
|
|||||||
|
|
||||||
public final class ArgumentSerializers
|
public final class ArgumentSerializers
|
||||||
{
|
{
|
||||||
public static void register()
|
@SuppressWarnings( "unchecked" )
|
||||||
|
private static <T extends ArgumentType<?>> void registerUnsafe( ResourceLocation id, Class<T> type, ArgumentSerializer<?> serializer )
|
||||||
{
|
{
|
||||||
register( new ResourceLocation( ComputerCraft.MOD_ID, "tracking_field" ), TrackingFieldArgumentType.trackingField() );
|
ArgumentTypes.register( id.toString(), type, (ArgumentSerializer<T>) serializer );
|
||||||
register( new ResourceLocation( ComputerCraft.MOD_ID, "computer" ), ComputerArgumentType.oneComputer() );
|
|
||||||
register( new ResourceLocation( ComputerCraft.MOD_ID, "computers" ), ComputersArgumentType.class, new ComputersArgumentType.Serializer() );
|
|
||||||
registerUnsafe( new ResourceLocation( ComputerCraft.MOD_ID, "repeat" ), RepeatArgumentType.class, new RepeatArgumentType.Serializer() );
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <T extends ArgumentType<?>> void register( ResourceLocation id, T instance )
|
|
||||||
{
|
|
||||||
registerUnsafe( id, instance.getClass(), new EmptyArgumentSerializer<>( () -> instance ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <T extends ArgumentType<?>> void register( ResourceLocation id, Class<T> type, ArgumentSerializer<T> serializer )
|
private static <T extends ArgumentType<?>> void register( ResourceLocation id, Class<T> type, ArgumentSerializer<T> serializer )
|
||||||
@@ -33,9 +25,16 @@ public final class ArgumentSerializers
|
|||||||
ArgumentTypes.register( id.toString(), type, serializer );
|
ArgumentTypes.register( id.toString(), type, serializer );
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings( "unchecked" )
|
private static <T extends ArgumentType<?>> void register( ResourceLocation id, T instance )
|
||||||
private static <T extends ArgumentType<?>> void registerUnsafe( ResourceLocation id, Class<T> type, ArgumentSerializer<?> serializer )
|
|
||||||
{
|
{
|
||||||
ArgumentTypes.register( id.toString(), type, (ArgumentSerializer<T>) serializer );
|
registerUnsafe( id, instance.getClass(), new EmptyArgumentSerializer<>( () -> instance ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void register()
|
||||||
|
{
|
||||||
|
register( new ResourceLocation( ComputerCraft.MOD_ID, "tracking_field" ), TrackingFieldArgumentType.trackingField() );
|
||||||
|
register( new ResourceLocation( ComputerCraft.MOD_ID, "computer" ), ComputerArgumentType.oneComputer() );
|
||||||
|
register( new ResourceLocation( ComputerCraft.MOD_ID, "computers" ), ComputersArgumentType.class, new ComputersArgumentType.Serializer() );
|
||||||
|
registerUnsafe( new ResourceLocation( ComputerCraft.MOD_ID, "repeat" ), RepeatArgumentType.class, new RepeatArgumentType.Serializer() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.command.arguments;
|
package dan200.computercraft.shared.command.arguments;
|
||||||
|
|
||||||
import com.mojang.brigadier.Message;
|
import com.mojang.brigadier.Message;
|
||||||
@@ -43,10 +42,7 @@ public abstract class ChoiceArgumentType<T> implements ArgumentType<T>
|
|||||||
for( T choice : choices )
|
for( T choice : choices )
|
||||||
{
|
{
|
||||||
String choiceName = this.name.apply( choice );
|
String choiceName = this.name.apply( choice );
|
||||||
if( name.equals( choiceName ) )
|
if( name.equals( choiceName ) ) return choice;
|
||||||
{
|
|
||||||
return choice;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
reader.setCursor( start );
|
reader.setCursor( start );
|
||||||
@@ -56,16 +52,11 @@ public abstract class ChoiceArgumentType<T> implements ArgumentType<T>
|
|||||||
@Override
|
@Override
|
||||||
public <S> CompletableFuture<Suggestions> listSuggestions( CommandContext<S> context, SuggestionsBuilder builder )
|
public <S> CompletableFuture<Suggestions> listSuggestions( CommandContext<S> context, SuggestionsBuilder builder )
|
||||||
{
|
{
|
||||||
String remaining = builder.getRemaining()
|
String remaining = builder.getRemaining().toLowerCase( Locale.ROOT );
|
||||||
.toLowerCase( Locale.ROOT );
|
|
||||||
for( T choice : choices )
|
for( T choice : choices )
|
||||||
{
|
{
|
||||||
String name = this.name.apply( choice );
|
String name = this.name.apply( choice );
|
||||||
if( !name.toLowerCase( Locale.ROOT )
|
if( !name.toLowerCase( Locale.ROOT ).startsWith( remaining ) ) continue;
|
||||||
.startsWith( remaining ) )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
builder.suggest( name, tooltip.apply( choice ) );
|
builder.suggest( name, tooltip.apply( choice ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,10 +67,7 @@ public abstract class ChoiceArgumentType<T> implements ArgumentType<T>
|
|||||||
public Collection<String> getExamples()
|
public Collection<String> getExamples()
|
||||||
{
|
{
|
||||||
List<String> items = choices instanceof Collection<?> ? new ArrayList<>( ((Collection<T>) choices).size() ) : new ArrayList<>();
|
List<String> items = choices instanceof Collection<?> ? new ArrayList<>( ((Collection<T>) choices).size() ) : new ArrayList<>();
|
||||||
for( T choice : choices )
|
for( T choice : choices ) items.add( name.apply( choice ) );
|
||||||
{
|
|
||||||
items.add( name.apply( choice ) );
|
|
||||||
}
|
|
||||||
items.sort( Comparator.naturalOrder() );
|
items.sort( Comparator.naturalOrder() );
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.command.arguments;
|
package dan200.computercraft.shared.command.arguments;
|
||||||
|
|
||||||
import com.mojang.brigadier.StringReader;
|
import com.mojang.brigadier.StringReader;
|
||||||
@@ -25,10 +24,6 @@ public final class ComputerArgumentType implements ArgumentType<ComputerArgument
|
|||||||
{
|
{
|
||||||
private static final ComputerArgumentType INSTANCE = new ComputerArgumentType();
|
private static final ComputerArgumentType INSTANCE = new ComputerArgumentType();
|
||||||
|
|
||||||
private ComputerArgumentType()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ComputerArgumentType oneComputer()
|
public static ComputerArgumentType oneComputer()
|
||||||
{
|
{
|
||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
@@ -36,27 +31,24 @@ public final class ComputerArgumentType implements ArgumentType<ComputerArgument
|
|||||||
|
|
||||||
public static ServerComputer getComputerArgument( CommandContext<CommandSourceStack> context, String name ) throws CommandSyntaxException
|
public static ServerComputer getComputerArgument( CommandContext<CommandSourceStack> context, String name ) throws CommandSyntaxException
|
||||||
{
|
{
|
||||||
return context.getArgument( name, ComputerSupplier.class )
|
return context.getArgument( name, ComputerSupplier.class ).unwrap( context.getSource() );
|
||||||
.unwrap( context.getSource() );
|
}
|
||||||
|
|
||||||
|
private ComputerArgumentType()
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ComputerSupplier parse( StringReader reader ) throws CommandSyntaxException
|
public ComputerSupplier parse( StringReader reader ) throws CommandSyntaxException
|
||||||
{
|
{
|
||||||
int start = reader.getCursor();
|
int start = reader.getCursor();
|
||||||
ComputersSupplier supplier = ComputersArgumentType.someComputers()
|
ComputersSupplier supplier = ComputersArgumentType.someComputers().parse( reader );
|
||||||
.parse( reader );
|
String selector = reader.getString().substring( start, reader.getCursor() );
|
||||||
String selector = reader.getString()
|
|
||||||
.substring( start, reader.getCursor() );
|
|
||||||
|
|
||||||
return s -> {
|
return s -> {
|
||||||
Collection<ServerComputer> computers = supplier.unwrap( s );
|
Collection<ServerComputer> computers = supplier.unwrap( s );
|
||||||
|
|
||||||
if( computers.size() == 1 )
|
if( computers.size() == 1 ) return computers.iterator().next();
|
||||||
{
|
|
||||||
return computers.iterator()
|
|
||||||
.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
@@ -84,15 +76,13 @@ public final class ComputerArgumentType implements ArgumentType<ComputerArgument
|
|||||||
@Override
|
@Override
|
||||||
public <S> CompletableFuture<Suggestions> listSuggestions( CommandContext<S> context, SuggestionsBuilder builder )
|
public <S> CompletableFuture<Suggestions> listSuggestions( CommandContext<S> context, SuggestionsBuilder builder )
|
||||||
{
|
{
|
||||||
return ComputersArgumentType.someComputers()
|
return ComputersArgumentType.someComputers().listSuggestions( context, builder );
|
||||||
.listSuggestions( context, builder );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<String> getExamples()
|
public Collection<String> getExamples()
|
||||||
{
|
{
|
||||||
return ComputersArgumentType.someComputers()
|
return ComputersArgumentType.someComputers().getExamples();
|
||||||
.getExamples();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.command.arguments;
|
package dan200.computercraft.shared.command.arguments;
|
||||||
|
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
@@ -36,13 +35,9 @@ public final class ComputersArgumentType implements ArgumentType<ComputersArgume
|
|||||||
private static final ComputersArgumentType MANY = new ComputersArgumentType( false );
|
private static final ComputersArgumentType MANY = new ComputersArgumentType( false );
|
||||||
private static final ComputersArgumentType SOME = new ComputersArgumentType( true );
|
private static final ComputersArgumentType SOME = new ComputersArgumentType( true );
|
||||||
|
|
||||||
private static final List<String> EXAMPLES = Arrays.asList( "0", "#0", "@Label", "~Advanced" );
|
private static final List<String> EXAMPLES = Arrays.asList(
|
||||||
private final boolean requireSome;
|
"0", "#0", "@Label", "~Advanced"
|
||||||
|
);
|
||||||
private ComputersArgumentType( boolean requireSome )
|
|
||||||
{
|
|
||||||
this.requireSome = requireSome;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ComputersArgumentType manyComputers()
|
public static ComputersArgumentType manyComputers()
|
||||||
{
|
{
|
||||||
@@ -56,18 +51,14 @@ public final class ComputersArgumentType implements ArgumentType<ComputersArgume
|
|||||||
|
|
||||||
public static Collection<ServerComputer> getComputersArgument( CommandContext<CommandSourceStack> context, String name ) throws CommandSyntaxException
|
public static Collection<ServerComputer> getComputersArgument( CommandContext<CommandSourceStack> context, String name ) throws CommandSyntaxException
|
||||||
{
|
{
|
||||||
return context.getArgument( name, ComputersSupplier.class )
|
return context.getArgument( name, ComputersSupplier.class ).unwrap( context.getSource() );
|
||||||
.unwrap( context.getSource() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Set<ServerComputer> unwrap( CommandSourceStack source, Collection<ComputersSupplier> suppliers ) throws CommandSyntaxException
|
private final boolean requireSome;
|
||||||
|
|
||||||
|
private ComputersArgumentType( boolean requireSome )
|
||||||
{
|
{
|
||||||
Set<ServerComputer> computers = new HashSet<>();
|
this.requireSome = requireSome;
|
||||||
for( ComputersSupplier supplier : suppliers )
|
|
||||||
{
|
|
||||||
computers.addAll( supplier.unwrap( source ) );
|
|
||||||
}
|
|
||||||
return computers;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -86,9 +77,7 @@ public final class ComputersArgumentType implements ArgumentType<ComputersArgume
|
|||||||
{
|
{
|
||||||
reader.skip();
|
reader.skip();
|
||||||
String family = reader.readUnquotedString();
|
String family = reader.readUnquotedString();
|
||||||
computers = getComputers( x -> x.getFamily()
|
computers = getComputers( x -> x.getFamily().name().equalsIgnoreCase( family ) );
|
||||||
.name()
|
|
||||||
.equalsIgnoreCase( family ) );
|
|
||||||
}
|
}
|
||||||
else if( kind == '#' )
|
else if( kind == '#' )
|
||||||
{
|
{
|
||||||
@@ -107,14 +96,10 @@ public final class ComputersArgumentType implements ArgumentType<ComputersArgume
|
|||||||
|
|
||||||
if( requireSome )
|
if( requireSome )
|
||||||
{
|
{
|
||||||
String selector = reader.getString()
|
String selector = reader.getString().substring( start, reader.getCursor() );
|
||||||
.substring( start, reader.getCursor() );
|
|
||||||
return source -> {
|
return source -> {
|
||||||
Collection<ServerComputer> matched = computers.unwrap( source );
|
Collection<ServerComputer> matched = computers.unwrap( source );
|
||||||
if( matched.isEmpty() )
|
if( matched.isEmpty() ) throw COMPUTER_ARG_NONE.create( selector );
|
||||||
{
|
|
||||||
throw COMPUTER_ARG_NONE.create( selector );
|
|
||||||
}
|
|
||||||
return matched;
|
return matched;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -169,8 +154,7 @@ public final class ComputersArgumentType implements ArgumentType<ComputersArgume
|
|||||||
for( ServerComputer computer : ComputerCraft.serverComputerRegistry.getComputers() )
|
for( ServerComputer computer : ComputerCraft.serverComputerRegistry.getComputers() )
|
||||||
{
|
{
|
||||||
String converted = renderer.apply( computer );
|
String converted = renderer.apply( computer );
|
||||||
if( converted != null && converted.toLowerCase( Locale.ROOT )
|
if( converted != null && converted.toLowerCase( Locale.ROOT ).startsWith( remaining ) )
|
||||||
.startsWith( remaining ) )
|
|
||||||
{
|
{
|
||||||
builder.suggest( converted );
|
builder.suggest( converted );
|
||||||
}
|
}
|
||||||
@@ -179,16 +163,12 @@ 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( ComputerCraft.serverComputerRegistry.getComputers()
|
return s -> Collections.unmodifiableList( ComputerCraft.serverComputerRegistry
|
||||||
|
.getComputers()
|
||||||
.stream()
|
.stream()
|
||||||
.filter( predicate )
|
.filter( predicate )
|
||||||
.collect( Collectors.toList() ) );
|
.collect( Collectors.toList() )
|
||||||
}
|
);
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface ComputersSupplier
|
|
||||||
{
|
|
||||||
Collection<ServerComputer> unwrap( CommandSourceStack source ) throws CommandSyntaxException;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Serializer implements ArgumentSerializer<ComputersArgumentType>
|
public static class Serializer implements ArgumentSerializer<ComputersArgumentType>
|
||||||
@@ -213,4 +193,17 @@ public final class ComputersArgumentType implements ArgumentType<ComputersArgume
|
|||||||
json.addProperty( "requireSome", arg.requireSome );
|
json.addProperty( "requireSome", arg.requireSome );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface ComputersSupplier
|
||||||
|
{
|
||||||
|
Collection<ServerComputer> unwrap( CommandSourceStack source ) throws CommandSyntaxException;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Set<ServerComputer> unwrap( CommandSourceStack source, Collection<ComputersSupplier> suppliers ) throws CommandSyntaxException
|
||||||
|
{
|
||||||
|
Set<ServerComputer> computers = new HashSet<>();
|
||||||
|
for( ComputersSupplier supplier : suppliers ) computers.addAll( supplier.unwrap( source ) );
|
||||||
|
return computers;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.command.arguments;
|
package dan200.computercraft.shared.command.arguments;
|
||||||
|
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
@@ -32,8 +31,8 @@ import java.util.function.BiConsumer;
|
|||||||
/**
|
/**
|
||||||
* Reads one argument multiple times.
|
* Reads one argument multiple times.
|
||||||
*
|
*
|
||||||
* Note that this must be the last element in an argument chain: in order to improve the quality of error messages, we will always try to consume another
|
* Note that this must be the last element in an argument chain: in order to improve the quality of error messages,
|
||||||
* argument while there is input remaining.
|
* we will always try to consume another argument while there is input remaining.
|
||||||
*
|
*
|
||||||
* One problem with how parsers function, is that they must consume some input: and thus we
|
* One problem with how parsers function, is that they must consume some input: and thus we
|
||||||
*
|
*
|
||||||
@@ -73,10 +72,7 @@ public final class RepeatArgumentType<T, U> implements ArgumentType<List<T>>
|
|||||||
while( true )
|
while( true )
|
||||||
{
|
{
|
||||||
reader.skipWhitespace();
|
reader.skipWhitespace();
|
||||||
if( !reader.canRead() )
|
if( !reader.canRead() ) break;
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
int startParse = reader.getCursor();
|
int startParse = reader.getCursor();
|
||||||
appender.accept( out, child.parse( reader ) );
|
appender.accept( out, child.parse( reader ) );
|
||||||
@@ -91,10 +87,7 @@ public final class RepeatArgumentType<T, U> implements ArgumentType<List<T>>
|
|||||||
// Note that each child may return an empty list, we just require that some actual input
|
// Note that each child may return an empty list, we just require that some actual input
|
||||||
// was consumed.
|
// was consumed.
|
||||||
// We should probably review that this is sensible in the future.
|
// We should probably review that this is sensible in the future.
|
||||||
if( !hadSome )
|
if( !hadSome ) throw some.createWithContext( reader );
|
||||||
{
|
|
||||||
throw some.createWithContext( reader );
|
|
||||||
}
|
|
||||||
|
|
||||||
return Collections.unmodifiableList( out );
|
return Collections.unmodifiableList( out );
|
||||||
}
|
}
|
||||||
@@ -118,10 +111,7 @@ public final class RepeatArgumentType<T, U> implements ArgumentType<List<T>>
|
|||||||
|
|
||||||
int cursor = reader.getCursor();
|
int cursor = reader.getCursor();
|
||||||
reader.skipWhitespace();
|
reader.skipWhitespace();
|
||||||
if( cursor == reader.getCursor() )
|
if( cursor == reader.getCursor() ) break;
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
previous = reader.getCursor();
|
previous = reader.getCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,10 +137,7 @@ public final class RepeatArgumentType<T, U> implements ArgumentType<List<T>>
|
|||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings( {
|
@SuppressWarnings( { "unchecked", "rawtypes" } )
|
||||||
"unchecked",
|
|
||||||
"rawtypes"
|
|
||||||
} )
|
|
||||||
public RepeatArgumentType<?, ?> deserializeFromNetwork( @Nonnull FriendlyByteBuf buf )
|
public RepeatArgumentType<?, ?> deserializeFromNetwork( @Nonnull FriendlyByteBuf buf )
|
||||||
{
|
{
|
||||||
boolean isList = buf.readBoolean();
|
boolean isList = buf.readBoolean();
|
||||||
@@ -170,12 +157,8 @@ public final class RepeatArgumentType<T, U> implements ArgumentType<List<T>>
|
|||||||
|
|
||||||
private static Component getMessage( RepeatArgumentType<?, ?> arg )
|
private static Component getMessage( RepeatArgumentType<?, ?> arg )
|
||||||
{
|
{
|
||||||
Message message = arg.some.create()
|
Message message = arg.some.create().getRawMessage();
|
||||||
.getRawMessage();
|
if( message instanceof Component ) return (Component) message;
|
||||||
if( message instanceof Component )
|
|
||||||
{
|
|
||||||
return (Component) message;
|
|
||||||
}
|
|
||||||
return new TextComponent( message.getString() );
|
return new TextComponent( message.getString() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.command.arguments;
|
package dan200.computercraft.shared.command.arguments;
|
||||||
|
|
||||||
import dan200.computercraft.core.tracking.TrackingField;
|
import dan200.computercraft.core.tracking.TrackingField;
|
||||||
@@ -17,8 +16,7 @@ public final class TrackingFieldArgumentType extends ChoiceArgumentType<Tracking
|
|||||||
|
|
||||||
private TrackingFieldArgumentType()
|
private TrackingFieldArgumentType()
|
||||||
{
|
{
|
||||||
super( TrackingField.fields()
|
super( TrackingField.fields().values(), TrackingField::id, x -> translate( x.translationKey() ), Exceptions.TRACKING_FIELD_ARG_NONE );
|
||||||
.values(), TrackingField::id, x -> translate( x.translationKey() ), Exceptions.TRACKING_FIELD_ARG_NONE );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TrackingFieldArgumentType trackingField()
|
public static TrackingFieldArgumentType trackingField()
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.command.builder;
|
package dan200.computercraft.shared.command.builder;
|
||||||
|
|
||||||
import com.mojang.brigadier.Command;
|
import com.mojang.brigadier.Command;
|
||||||
@@ -25,13 +24,14 @@ import static dan200.computercraft.shared.command.Exceptions.ARGUMENT_EXPECTED;
|
|||||||
import static dan200.computercraft.shared.command.builder.HelpingArgumentBuilder.literal;
|
import static dan200.computercraft.shared.command.builder.HelpingArgumentBuilder.literal;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An alternative way of building command nodes, so one does not have to nest. {@link ArgumentBuilder#then(CommandNode)}s.
|
* An alternative way of building command nodes, so one does not have to nest.
|
||||||
|
* {@link ArgumentBuilder#then(CommandNode)}s.
|
||||||
*
|
*
|
||||||
* @param <S> The command source we consume.
|
* @param <S> The command source we consume.
|
||||||
*/
|
*/
|
||||||
public class CommandBuilder<S> implements CommandNodeBuilder<S, Command<S>>
|
public class CommandBuilder<S> implements CommandNodeBuilder<S, Command<S>>
|
||||||
{
|
{
|
||||||
private List<ArgumentBuilder<S, ?>> args = new ArrayList<>();
|
private final List<ArgumentBuilder<S, ?>> args = new ArrayList<>();
|
||||||
private Predicate<S> requires;
|
private Predicate<S> requires;
|
||||||
|
|
||||||
public static CommandBuilder<CommandSourceStack> args()
|
public static CommandBuilder<CommandSourceStack> args()
|
||||||
@@ -58,34 +58,38 @@ public class CommandBuilder<S> implements CommandNodeBuilder<S, Command<S>>
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> CommandNodeBuilder<S, ArgCommand<S, List<T>>> argManyValue( String name, ArgumentType<T> type, T defaultValue )
|
|
||||||
{
|
|
||||||
return argManyValue( name, type, Collections.singletonList( defaultValue ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> CommandNodeBuilder<S, ArgCommand<S, List<T>>> argManyValue( String name, ArgumentType<T> type, List<T> empty )
|
public <T> CommandNodeBuilder<S, ArgCommand<S, List<T>>> argManyValue( String name, ArgumentType<T> type, List<T> empty )
|
||||||
{
|
{
|
||||||
return argMany( name, type, () -> empty );
|
return argMany( name, type, () -> empty );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public <T> CommandNodeBuilder<S, ArgCommand<S, List<T>>> argManyValue( String name, ArgumentType<T> type, T defaultValue )
|
||||||
|
{
|
||||||
|
return argManyValue( name, type, Collections.singletonList( defaultValue ) );
|
||||||
|
}
|
||||||
|
|
||||||
public <T> CommandNodeBuilder<S, ArgCommand<S, List<T>>> argMany( String name, ArgumentType<T> type, Supplier<List<T>> empty )
|
public <T> CommandNodeBuilder<S, ArgCommand<S, List<T>>> argMany( String name, ArgumentType<T> type, Supplier<List<T>> empty )
|
||||||
{
|
{
|
||||||
return argMany( name, RepeatArgumentType.some( type, ARGUMENT_EXPECTED ), empty );
|
return argMany( name, RepeatArgumentType.some( type, ARGUMENT_EXPECTED ), empty );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public <T> CommandNodeBuilder<S, ArgCommand<S, List<T>>> argManyFlatten( String name, ArgumentType<List<T>> type, Supplier<List<T>> empty )
|
||||||
|
{
|
||||||
|
return argMany( name, RepeatArgumentType.someFlat( type, ARGUMENT_EXPECTED ), empty );
|
||||||
|
}
|
||||||
|
|
||||||
private <T, U> CommandNodeBuilder<S, ArgCommand<S, List<T>>> argMany( String name, RepeatArgumentType<T, ?> type, Supplier<List<T>> empty )
|
private <T, U> CommandNodeBuilder<S, ArgCommand<S, List<T>>> argMany( String name, RepeatArgumentType<T, ?> type, Supplier<List<T>> empty )
|
||||||
{
|
{
|
||||||
if( args.isEmpty() )
|
if( args.isEmpty() ) throw new IllegalStateException( "Cannot have empty arg chain builder" );
|
||||||
{
|
|
||||||
throw new IllegalStateException( "Cannot have empty arg chain builder" );
|
|
||||||
}
|
|
||||||
|
|
||||||
return command -> {
|
return command -> {
|
||||||
// The node for no arguments
|
// The node for no arguments
|
||||||
ArgumentBuilder<S, ?> tail = tail( ctx -> command.run( ctx, empty.get() ) );
|
ArgumentBuilder<S, ?> tail = tail( ctx -> command.run( ctx, empty.get() ) );
|
||||||
|
|
||||||
// The node for one or more arguments
|
// The node for one or more arguments
|
||||||
ArgumentBuilder<S, ?> moreArg = RequiredArgumentBuilder.<S, List<T>>argument( name, type ).executes( ctx -> command.run( ctx, getList( ctx, name ) ) );
|
ArgumentBuilder<S, ?> moreArg = RequiredArgumentBuilder
|
||||||
|
.<S, List<T>>argument( name, type )
|
||||||
|
.executes( ctx -> command.run( ctx, getList( ctx, name ) ) );
|
||||||
|
|
||||||
// Chain all of them together!
|
// Chain all of them together!
|
||||||
tail.then( moreArg );
|
tail.then( moreArg );
|
||||||
@@ -93,46 +97,31 @@ public class CommandBuilder<S> implements CommandNodeBuilder<S, Command<S>>
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArgumentBuilder<S, ?> tail( Command<S> command )
|
|
||||||
{
|
|
||||||
ArgumentBuilder<S, ?> defaultTail = args.get( args.size() - 1 );
|
|
||||||
defaultTail.executes( command );
|
|
||||||
if( requires != null )
|
|
||||||
{
|
|
||||||
defaultTail.requires( requires );
|
|
||||||
}
|
|
||||||
return defaultTail;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings( "unchecked" )
|
@SuppressWarnings( "unchecked" )
|
||||||
private static <T> List<T> getList( CommandContext<?> context, String name )
|
private static <T> List<T> getList( CommandContext<?> context, String name )
|
||||||
{
|
{
|
||||||
return (List<T>) context.getArgument( name, List.class );
|
return (List<T>) context.getArgument( name, List.class );
|
||||||
}
|
}
|
||||||
|
|
||||||
private CommandNode<S> link( ArgumentBuilder<S, ?> tail )
|
|
||||||
{
|
|
||||||
for( int i = args.size() - 2; i >= 0; i-- )
|
|
||||||
{
|
|
||||||
tail = args.get( i )
|
|
||||||
.then( tail );
|
|
||||||
}
|
|
||||||
return tail.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> CommandNodeBuilder<S, ArgCommand<S, List<T>>> argManyFlatten( String name, ArgumentType<List<T>> type, Supplier<List<T>> empty )
|
|
||||||
{
|
|
||||||
return argMany( name, RepeatArgumentType.someFlat( type, ARGUMENT_EXPECTED ), empty );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandNode<S> executes( Command<S> command )
|
public CommandNode<S> executes( Command<S> command )
|
||||||
{
|
{
|
||||||
if( args.isEmpty() )
|
if( args.isEmpty() ) throw new IllegalStateException( "Cannot have empty arg chain builder" );
|
||||||
{
|
|
||||||
throw new IllegalStateException( "Cannot have empty arg chain builder" );
|
|
||||||
}
|
|
||||||
|
|
||||||
return link( tail( command ) );
|
return link( tail( command ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ArgumentBuilder<S, ?> tail( Command<S> command )
|
||||||
|
{
|
||||||
|
ArgumentBuilder<S, ?> defaultTail = args.get( args.size() - 1 );
|
||||||
|
defaultTail.executes( command );
|
||||||
|
if( requires != null ) defaultTail.requires( requires );
|
||||||
|
return defaultTail;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CommandNode<S> link( ArgumentBuilder<S, ?> tail )
|
||||||
|
{
|
||||||
|
for( int i = args.size() - 2; i >= 0; i-- ) tail = args.get( i ).then( tail );
|
||||||
|
return tail.build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.command.builder;
|
package dan200.computercraft.shared.command.builder;
|
||||||
|
|
||||||
import com.mojang.brigadier.Command;
|
import com.mojang.brigadier.Command;
|
||||||
@@ -28,14 +27,11 @@ import static dan200.computercraft.shared.command.text.ChatHelpers.coloured;
|
|||||||
import static dan200.computercraft.shared.command.text.ChatHelpers.translate;
|
import static dan200.computercraft.shared.command.text.ChatHelpers.translate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An alternative to {@link LiteralArgumentBuilder} which also provides a {@code /... help} command, and defaults to that command when no arguments are
|
* An alternative to {@link LiteralArgumentBuilder} which also provides a {@code /... help} command, and defaults
|
||||||
* given.
|
* to that command when no arguments are given.
|
||||||
*/
|
*/
|
||||||
public final class HelpingArgumentBuilder extends LiteralArgumentBuilder<CommandSourceStack>
|
public final class HelpingArgumentBuilder extends LiteralArgumentBuilder<CommandSourceStack>
|
||||||
{
|
{
|
||||||
private static final ChatFormatting HEADER = ChatFormatting.LIGHT_PURPLE;
|
|
||||||
private static final ChatFormatting SYNOPSIS = ChatFormatting.AQUA;
|
|
||||||
private static final ChatFormatting NAME = ChatFormatting.GREEN;
|
|
||||||
private final Collection<HelpingArgumentBuilder> children = new ArrayList<>();
|
private final Collection<HelpingArgumentBuilder> children = new ArrayList<>();
|
||||||
|
|
||||||
private HelpingArgumentBuilder( String literal )
|
private HelpingArgumentBuilder( String literal )
|
||||||
@@ -48,69 +44,16 @@ public final class HelpingArgumentBuilder extends LiteralArgumentBuilder<Command
|
|||||||
return new HelpingArgumentBuilder( literal );
|
return new HelpingArgumentBuilder( literal );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Command<CommandSourceStack> helpForChild( CommandNode<CommandSourceStack> node, String id, String command )
|
@Override
|
||||||
|
public LiteralArgumentBuilder<CommandSourceStack> executes( final Command<CommandSourceStack> command )
|
||||||
{
|
{
|
||||||
return context -> {
|
throw new IllegalStateException( "Cannot use executes on a HelpingArgumentBuilder" );
|
||||||
context.getSource()
|
|
||||||
.sendSuccess( getHelp( context,
|
|
||||||
node,
|
|
||||||
id + "." + node.getName()
|
|
||||||
.replace( '-', '_' ),
|
|
||||||
command + " " + node.getName() ), false );
|
|
||||||
return 0;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Component getHelp( CommandContext<CommandSourceStack> context, CommandNode<CommandSourceStack> node, String id, String command )
|
|
||||||
{
|
|
||||||
// An ugly hack to extract usage information from the dispatcher. We generate a temporary node, generate
|
|
||||||
// the shorthand usage, and emit that.
|
|
||||||
CommandDispatcher<CommandSourceStack> dispatcher = context.getSource()
|
|
||||||
.getServer()
|
|
||||||
.getCommands()
|
|
||||||
.getDispatcher();
|
|
||||||
CommandNode<CommandSourceStack> temp = new LiteralCommandNode<>( "_", null, x -> true, null, null, false );
|
|
||||||
temp.addChild( node );
|
|
||||||
String usage = dispatcher.getSmartUsage( temp, context.getSource() )
|
|
||||||
.get( node )
|
|
||||||
.substring( node.getName()
|
|
||||||
.length() );
|
|
||||||
|
|
||||||
MutableComponent output = new TextComponent( "" ).append( coloured( "/" + command + usage, HEADER ) )
|
|
||||||
.append( " " )
|
|
||||||
.append( coloured( translate( "commands." + id + ".synopsis" ), SYNOPSIS ) )
|
|
||||||
.append( "\n" )
|
|
||||||
.append( translate( "commands." + id + ".desc" ) );
|
|
||||||
|
|
||||||
for( CommandNode<CommandSourceStack> child : node.getChildren() )
|
|
||||||
{
|
|
||||||
if( !child.getRequirement()
|
|
||||||
.test( context.getSource() ) || !(child instanceof LiteralCommandNode) )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
output.append( "\n" );
|
|
||||||
|
|
||||||
MutableComponent component = coloured( child.getName(), NAME );
|
|
||||||
component.getStyle()
|
|
||||||
.withClickEvent( new ClickEvent( ClickEvent.Action.SUGGEST_COMMAND, "/" + command + " " + child.getName() ) );
|
|
||||||
output.append( component );
|
|
||||||
|
|
||||||
output.append( " - " )
|
|
||||||
.append( translate( "commands." + id + "." + child.getName() + ".synopsis" ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LiteralArgumentBuilder<CommandSourceStack> then( final ArgumentBuilder<CommandSourceStack, ?> argument )
|
public LiteralArgumentBuilder<CommandSourceStack> then( final ArgumentBuilder<CommandSourceStack, ?> argument )
|
||||||
{
|
{
|
||||||
if( getRedirect() != null )
|
if( getRedirect() != null ) throw new IllegalStateException( "Cannot add children to a redirected node" );
|
||||||
{
|
|
||||||
throw new IllegalStateException( "Cannot add children to a redirected node" );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( argument instanceof HelpingArgumentBuilder )
|
if( argument instanceof HelpingArgumentBuilder )
|
||||||
{
|
{
|
||||||
@@ -138,12 +81,6 @@ public final class HelpingArgumentBuilder extends LiteralArgumentBuilder<Command
|
|||||||
return super.then( argument );
|
return super.then( argument );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public LiteralArgumentBuilder<CommandSourceStack> executes( final Command<CommandSourceStack> command )
|
|
||||||
{
|
|
||||||
throw new IllegalStateException( "Cannot use executes on a HelpingArgumentBuilder" );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LiteralCommandNode<CommandSourceStack> build()
|
public LiteralCommandNode<CommandSourceStack> build()
|
||||||
{
|
{
|
||||||
@@ -158,28 +95,24 @@ public final class HelpingArgumentBuilder extends LiteralArgumentBuilder<Command
|
|||||||
private LiteralCommandNode<CommandSourceStack> buildImpl( String id, String command )
|
private LiteralCommandNode<CommandSourceStack> buildImpl( String id, String command )
|
||||||
{
|
{
|
||||||
HelpCommand helpCommand = new HelpCommand( id, command );
|
HelpCommand helpCommand = new HelpCommand( id, command );
|
||||||
LiteralCommandNode<CommandSourceStack> node = new LiteralCommandNode<>( getLiteral(),
|
LiteralCommandNode<CommandSourceStack> node = new LiteralCommandNode<>( getLiteral(), helpCommand, getRequirement(), getRedirect(), getRedirectModifier(), isFork() );
|
||||||
helpCommand, getRequirement(),
|
|
||||||
getRedirect(), getRedirectModifier(), isFork() );
|
|
||||||
helpCommand.node = node;
|
helpCommand.node = node;
|
||||||
|
|
||||||
// Set up a /... help command
|
// Set up a /... help command
|
||||||
LiteralArgumentBuilder<CommandSourceStack> helpNode =
|
LiteralArgumentBuilder<CommandSourceStack> helpNode = LiteralArgumentBuilder.<CommandSourceStack>literal( "help" )
|
||||||
LiteralArgumentBuilder.<CommandSourceStack>literal( "help" ).requires( x -> getArguments().stream()
|
.requires( x -> getArguments().stream().anyMatch( y -> y.getRequirement().test( x ) ) )
|
||||||
.anyMatch(
|
.executes( helpCommand );
|
||||||
y -> y.getRequirement()
|
|
||||||
.test(
|
|
||||||
x ) ) )
|
|
||||||
.executes( helpCommand );
|
|
||||||
|
|
||||||
// Add all normal command children to this and the help node
|
// Add all normal command children to this and the help node
|
||||||
for( CommandNode<CommandSourceStack> child : getArguments() )
|
for( CommandNode<CommandSourceStack> child : getArguments() )
|
||||||
{
|
{
|
||||||
node.addChild( child );
|
node.addChild( child );
|
||||||
|
|
||||||
helpNode.then( LiteralArgumentBuilder.<CommandSourceStack>literal( child.getName() ).requires( child.getRequirement() )
|
helpNode.then( LiteralArgumentBuilder.<CommandSourceStack>literal( child.getName() )
|
||||||
|
.requires( child.getRequirement() )
|
||||||
.executes( helpForChild( child, id, command ) )
|
.executes( helpForChild( child, id, command ) )
|
||||||
.build() );
|
.build()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// And add alternative versions of which forward instead
|
// And add alternative versions of which forward instead
|
||||||
@@ -187,10 +120,12 @@ public final class HelpingArgumentBuilder extends LiteralArgumentBuilder<Command
|
|||||||
{
|
{
|
||||||
LiteralCommandNode<CommandSourceStack> child = childBuilder.build( id, command );
|
LiteralCommandNode<CommandSourceStack> child = childBuilder.build( id, command );
|
||||||
node.addChild( child );
|
node.addChild( child );
|
||||||
helpNode.then( LiteralArgumentBuilder.<CommandSourceStack>literal( child.getName() ).requires( child.getRequirement() )
|
helpNode.then( LiteralArgumentBuilder.<CommandSourceStack>literal( child.getName() )
|
||||||
|
.requires( child.getRequirement() )
|
||||||
.executes( helpForChild( child, id, command ) )
|
.executes( helpForChild( child, id, command ) )
|
||||||
.redirect( child.getChild( "help" ) )
|
.redirect( child.getChild( "help" ) )
|
||||||
.build() );
|
.build()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
node.addChild( helpNode.build() );
|
node.addChild( helpNode.build() );
|
||||||
@@ -198,6 +133,10 @@ public final class HelpingArgumentBuilder extends LiteralArgumentBuilder<Command
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final ChatFormatting HEADER = ChatFormatting.LIGHT_PURPLE;
|
||||||
|
private static final ChatFormatting SYNOPSIS = ChatFormatting.AQUA;
|
||||||
|
private static final ChatFormatting NAME = ChatFormatting.GREEN;
|
||||||
|
|
||||||
private static final class HelpCommand implements Command<CommandSourceStack>
|
private static final class HelpCommand implements Command<CommandSourceStack>
|
||||||
{
|
{
|
||||||
private final String id;
|
private final String id;
|
||||||
@@ -213,9 +152,54 @@ public final class HelpingArgumentBuilder extends LiteralArgumentBuilder<Command
|
|||||||
@Override
|
@Override
|
||||||
public int run( CommandContext<CommandSourceStack> context )
|
public int run( CommandContext<CommandSourceStack> context )
|
||||||
{
|
{
|
||||||
context.getSource()
|
context.getSource().sendSuccess( getHelp( context, node, id, command ), false );
|
||||||
.sendSuccess( getHelp( context, node, id, command ), false );
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Command<CommandSourceStack> helpForChild( CommandNode<CommandSourceStack> node, String id, String command )
|
||||||
|
{
|
||||||
|
return context -> {
|
||||||
|
context.getSource().sendSuccess( getHelp( context, node, id + "." + node.getName().replace( '-', '_' ), command + " " + node.getName() ), false );
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Component getHelp( CommandContext<CommandSourceStack> context, CommandNode<CommandSourceStack> node, String id, String command )
|
||||||
|
{
|
||||||
|
// An ugly hack to extract usage information from the dispatcher. We generate a temporary node, generate
|
||||||
|
// the shorthand usage, and emit that.
|
||||||
|
CommandDispatcher<CommandSourceStack> dispatcher = context.getSource().getServer().getCommands().getDispatcher();
|
||||||
|
CommandNode<CommandSourceStack> temp = new LiteralCommandNode<>( "_", null, x -> true, null, null, false );
|
||||||
|
temp.addChild( node );
|
||||||
|
String usage = dispatcher.getSmartUsage( temp, context.getSource() ).get( node ).substring( node.getName().length() );
|
||||||
|
|
||||||
|
MutableComponent output = new TextComponent( "" )
|
||||||
|
.append( coloured( "/" + command + usage, HEADER ) )
|
||||||
|
.append( " " )
|
||||||
|
.append( coloured( translate( "commands." + id + ".synopsis" ), SYNOPSIS ) )
|
||||||
|
.append( "\n" )
|
||||||
|
.append( translate( "commands." + id + ".desc" ) );
|
||||||
|
|
||||||
|
for( CommandNode<CommandSourceStack> child : node.getChildren() )
|
||||||
|
{
|
||||||
|
if( !child.getRequirement().test( context.getSource() ) || !(child instanceof LiteralCommandNode) )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
output.append( "\n" );
|
||||||
|
|
||||||
|
MutableComponent component = coloured( child.getName(), NAME );
|
||||||
|
component.getStyle().withClickEvent( new ClickEvent(
|
||||||
|
ClickEvent.Action.SUGGEST_COMMAND,
|
||||||
|
"/" + command + " " + child.getName()
|
||||||
|
) );
|
||||||
|
output.append( component );
|
||||||
|
|
||||||
|
output.append( " - " ).append( translate( "commands." + id + "." + child.getName() + ".synopsis" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,14 +20,12 @@ public final class ChatHelpers
|
|||||||
|
|
||||||
public static MutableComponent coloured( String text, ChatFormatting colour )
|
public static MutableComponent coloured( String text, ChatFormatting colour )
|
||||||
{
|
{
|
||||||
MutableComponent component = new TextComponent( text == null ? "" : text );
|
return new TextComponent( text == null ? "" : text ).withStyle( colour );
|
||||||
component.setStyle( component.getStyle().withColor( colour ) );
|
|
||||||
return component;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends MutableComponent> T coloured( T component, ChatFormatting colour )
|
public static <T extends MutableComponent> T coloured( T component, ChatFormatting colour )
|
||||||
{
|
{
|
||||||
component.setStyle( component.getStyle().withColor( colour ) );
|
component.withStyle( colour );
|
||||||
return component;
|
return component;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,10 +44,10 @@ public final class ChatHelpers
|
|||||||
return new TranslatableComponent( text == null ? "" : text, args );
|
return new TranslatableComponent( text == null ? "" : text, args );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MutableComponent list( MutableComponent... children )
|
public static MutableComponent list( Component... children )
|
||||||
{
|
{
|
||||||
MutableComponent component = new TextComponent( "" );
|
MutableComponent component = new TextComponent( "" );
|
||||||
for( MutableComponent child : children )
|
for( Component child : children )
|
||||||
{
|
{
|
||||||
component.append( child );
|
component.append( child );
|
||||||
}
|
}
|
||||||
@@ -69,12 +67,12 @@ public final class ChatHelpers
|
|||||||
: coloured( translate( "commands.computercraft.generic.no" ), ChatFormatting.RED );
|
: coloured( translate( "commands.computercraft.generic.no" ), ChatFormatting.RED );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MutableComponent link( MutableComponent component, String command, MutableComponent toolTip )
|
public static Component link( MutableComponent component, String command, Component toolTip )
|
||||||
{
|
{
|
||||||
return link( component, new ClickEvent( ClickEvent.Action.RUN_COMMAND, command ), toolTip );
|
return link( component, new ClickEvent( ClickEvent.Action.RUN_COMMAND, command ), toolTip );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MutableComponent link( MutableComponent component, ClickEvent click, MutableComponent toolTip )
|
public static Component link( Component component, ClickEvent click, Component toolTip )
|
||||||
{
|
{
|
||||||
Style style = component.getStyle();
|
Style style = component.getStyle();
|
||||||
|
|
||||||
@@ -82,9 +80,7 @@ public final class ChatHelpers
|
|||||||
style = style.withClickEvent( click );
|
style = style.withClickEvent( click );
|
||||||
style = style.withHoverEvent( new HoverEvent( HoverEvent.Action.SHOW_TEXT, toolTip ) );
|
style = style.withHoverEvent( new HoverEvent( HoverEvent.Action.SHOW_TEXT, toolTip ) );
|
||||||
|
|
||||||
component.setStyle( style );
|
return component.copy().withStyle( style );
|
||||||
|
|
||||||
return component;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MutableComponent header( String text )
|
public static MutableComponent header( String text )
|
||||||
@@ -95,9 +91,9 @@ public final class ChatHelpers
|
|||||||
public static MutableComponent copy( String text )
|
public static MutableComponent copy( String text )
|
||||||
{
|
{
|
||||||
TextComponent name = new TextComponent( text );
|
TextComponent name = new TextComponent( text );
|
||||||
name.setStyle( name.getStyle()
|
Style style = name.getStyle()
|
||||||
.withClickEvent( new ClickEvent( ClickEvent.Action.COPY_TO_CLIPBOARD, text ) )
|
.withClickEvent( new ClickEvent( ClickEvent.Action.COPY_TO_CLIPBOARD, text ) )
|
||||||
.withHoverEvent( new HoverEvent( HoverEvent.Action.SHOW_TEXT, new TranslatableComponent( "gui.computercraft.tooltip.copy" ) ) ) );
|
.withHoverEvent( new HoverEvent( HoverEvent.Action.SHOW_TEXT, new TranslatableComponent( "gui.computercraft.tooltip.copy" ) ) );
|
||||||
return name;
|
return name.withStyle( style );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.command.text;
|
package dan200.computercraft.shared.command.text;
|
||||||
|
|
||||||
import net.minecraft.commands.CommandSourceStack;
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
@@ -27,10 +26,7 @@ public class ServerTableFormatter implements TableFormatter
|
|||||||
public Component getPadding( Component component, int width )
|
public Component getPadding( Component component, int width )
|
||||||
{
|
{
|
||||||
int extraWidth = width - getWidth( component );
|
int extraWidth = width - getWidth( component );
|
||||||
if( extraWidth <= 0 )
|
if( extraWidth <= 0 ) return null;
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return new TextComponent( StringUtils.repeat( ' ', extraWidth ) );
|
return new TextComponent( StringUtils.repeat( ' ', extraWidth ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,8 +39,7 @@ public class ServerTableFormatter implements TableFormatter
|
|||||||
@Override
|
@Override
|
||||||
public int getWidth( Component component )
|
public int getWidth( Component component )
|
||||||
{
|
{
|
||||||
return component.getString()
|
return component.getString().length();
|
||||||
.length();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.command.text;
|
package dan200.computercraft.shared.command.text;
|
||||||
|
|
||||||
import dan200.computercraft.shared.command.CommandUtils;
|
import dan200.computercraft.shared.command.CommandUtils;
|
||||||
@@ -21,17 +20,14 @@ import java.util.List;
|
|||||||
public class TableBuilder
|
public class TableBuilder
|
||||||
{
|
{
|
||||||
private final int id;
|
private final int id;
|
||||||
|
private int columns = -1;
|
||||||
private final Component[] headers;
|
private final Component[] headers;
|
||||||
private final ArrayList<Component[]> rows = new ArrayList<>();
|
private final ArrayList<Component[]> rows = new ArrayList<>();
|
||||||
private int columns = -1;
|
|
||||||
private int additional;
|
private int additional;
|
||||||
|
|
||||||
public TableBuilder( int id, @Nonnull Component... headers )
|
public TableBuilder( int id, @Nonnull Component... headers )
|
||||||
{
|
{
|
||||||
if( id < 0 )
|
if( id < 0 ) throw new IllegalArgumentException( "ID must be positive" );
|
||||||
{
|
|
||||||
throw new IllegalArgumentException( "ID must be positive" );
|
|
||||||
}
|
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.headers = headers;
|
this.headers = headers;
|
||||||
columns = headers.length;
|
columns = headers.length;
|
||||||
@@ -39,47 +35,33 @@ public class TableBuilder
|
|||||||
|
|
||||||
public TableBuilder( int id )
|
public TableBuilder( int id )
|
||||||
{
|
{
|
||||||
if( id < 0 )
|
if( id < 0 ) throw new IllegalArgumentException( "ID must be positive" );
|
||||||
{
|
|
||||||
throw new IllegalArgumentException( "ID must be positive" );
|
|
||||||
}
|
|
||||||
this.id = id;
|
this.id = id;
|
||||||
headers = null;
|
headers = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TableBuilder( int id, @Nonnull String... headers )
|
public TableBuilder( int id, @Nonnull String... headers )
|
||||||
{
|
{
|
||||||
if( id < 0 )
|
if( id < 0 ) throw new IllegalArgumentException( "ID must be positive" );
|
||||||
{
|
|
||||||
throw new IllegalArgumentException( "ID must be positive" );
|
|
||||||
}
|
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.headers = new Component[headers.length];
|
this.headers = new Component[headers.length];
|
||||||
columns = headers.length;
|
columns = headers.length;
|
||||||
|
|
||||||
for( int i = 0; i < headers.length; i++ )
|
for( int i = 0; i < headers.length; i++ ) this.headers[i] = ChatHelpers.header( headers[i] );
|
||||||
{
|
|
||||||
this.headers[i] = ChatHelpers.header( headers[i] );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void row( @Nonnull Component... row )
|
public void row( @Nonnull Component... row )
|
||||||
{
|
{
|
||||||
if( columns == -1 )
|
if( columns == -1 ) columns = row.length;
|
||||||
{
|
if( row.length != columns ) throw new IllegalArgumentException( "Row is the incorrect length" );
|
||||||
columns = row.length;
|
|
||||||
}
|
|
||||||
if( row.length != columns )
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException( "Row is the incorrect length" );
|
|
||||||
}
|
|
||||||
rows.add( row );
|
rows.add( row );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the unique identifier for this table type.
|
* Get the unique identifier for this table type.
|
||||||
*
|
*
|
||||||
* When showing a table within Minecraft, previous instances of this table with the same ID will be removed from chat.
|
* When showing a table within Minecraft, previous instances of this table with
|
||||||
|
* the same ID will be removed from chat.
|
||||||
*
|
*
|
||||||
* @return This table's type.
|
* @return This table's type.
|
||||||
*/
|
*/
|
||||||
@@ -91,7 +73,8 @@ public class TableBuilder
|
|||||||
/**
|
/**
|
||||||
* Get the number of columns for this table.
|
* Get the number of columns for this table.
|
||||||
*
|
*
|
||||||
* This will be the same as {@link #getHeaders()}'s length if it is is non-{@code null}, otherwise the length of the first column.
|
* This will be the same as {@link #getHeaders()}'s length if it is is non-{@code null},
|
||||||
|
* otherwise the length of the first column.
|
||||||
*
|
*
|
||||||
* @return The number of columns.
|
* @return The number of columns.
|
||||||
*/
|
*/
|
||||||
@@ -122,6 +105,20 @@ public class TableBuilder
|
|||||||
this.additional = additional;
|
this.additional = additional;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trim this table to a given height.
|
||||||
|
*
|
||||||
|
* @param height The desired height.
|
||||||
|
*/
|
||||||
|
public void trim( int height )
|
||||||
|
{
|
||||||
|
if( rows.size() > height )
|
||||||
|
{
|
||||||
|
additional += rows.size() - height - 1;
|
||||||
|
rows.subList( height - 1, rows.size() ).clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void display( CommandSourceStack source )
|
public void display( CommandSourceStack source )
|
||||||
{
|
{
|
||||||
if( CommandUtils.isPlayer( source ) )
|
if( CommandUtils.isPlayer( source ) )
|
||||||
@@ -135,19 +132,4 @@ public class TableBuilder
|
|||||||
new ServerTableFormatter( source ).display( this );
|
new ServerTableFormatter( source ).display( this );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Trim this table to a given height.
|
|
||||||
*
|
|
||||||
* @param height The desired height.
|
|
||||||
*/
|
|
||||||
public void trim( int height )
|
|
||||||
{
|
|
||||||
if( rows.size() > height )
|
|
||||||
{
|
|
||||||
additional += rows.size() - height - 1;
|
|
||||||
rows.subList( height - 1, rows.size() )
|
|
||||||
.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.command.text;
|
package dan200.computercraft.shared.command.text;
|
||||||
|
|
||||||
import net.minecraft.ChatFormatting;
|
import net.minecraft.ChatFormatting;
|
||||||
@@ -21,12 +20,30 @@ public interface TableFormatter
|
|||||||
Component SEPARATOR = coloured( "| ", ChatFormatting.GRAY );
|
Component SEPARATOR = coloured( "| ", ChatFormatting.GRAY );
|
||||||
Component HEADER = coloured( "=", ChatFormatting.GRAY );
|
Component HEADER = coloured( "=", ChatFormatting.GRAY );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get additional padding for the component.
|
||||||
|
*
|
||||||
|
* @param component The component to pad
|
||||||
|
* @param width The desired width for the component
|
||||||
|
* @return The padding for this component, or {@code null} if none is needed.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
Component getPadding( Component component, int width );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the minimum padding between each column.
|
||||||
|
*
|
||||||
|
* @return The minimum padding.
|
||||||
|
*/
|
||||||
|
int getColumnPadding();
|
||||||
|
|
||||||
|
int getWidth( Component component );
|
||||||
|
|
||||||
|
void writeLine( int id, Component component );
|
||||||
|
|
||||||
default int display( TableBuilder table )
|
default int display( TableBuilder table )
|
||||||
{
|
{
|
||||||
if( table.getColumns() <= 0 )
|
if( table.getColumns() <= 0 ) return 0;
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int rowId = table.getId();
|
int rowId = table.getId();
|
||||||
int columns = table.getColumns();
|
int columns = table.getColumns();
|
||||||
@@ -35,10 +52,7 @@ public interface TableFormatter
|
|||||||
Component[] headers = table.getHeaders();
|
Component[] headers = table.getHeaders();
|
||||||
if( headers != null )
|
if( headers != null )
|
||||||
{
|
{
|
||||||
for( int i = 0; i < columns; i++ )
|
for( int i = 0; i < columns; i++ ) maxWidths[i] = getWidth( headers[i] );
|
||||||
{
|
|
||||||
maxWidths[i] = getWidth( headers[i] );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for( Component[] row : table.getRows() )
|
for( Component[] row : table.getRows() )
|
||||||
@@ -46,28 +60,19 @@ public interface TableFormatter
|
|||||||
for( int i = 0; i < row.length; i++ )
|
for( int i = 0; i < row.length; i++ )
|
||||||
{
|
{
|
||||||
int width = getWidth( row[i] );
|
int width = getWidth( row[i] );
|
||||||
if( width > maxWidths[i] )
|
if( width > maxWidths[i] ) maxWidths[i] = width;
|
||||||
{
|
|
||||||
maxWidths[i] = width;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a small amount of padding after each column
|
// Add a small amount of padding after each column
|
||||||
{
|
{
|
||||||
int padding = getColumnPadding();
|
int padding = getColumnPadding();
|
||||||
for( int i = 0; i < maxWidths.length - 1; i++ )
|
for( int i = 0; i < maxWidths.length - 1; i++ ) maxWidths[i] += padding;
|
||||||
{
|
|
||||||
maxWidths[i] += padding;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// And compute the total width
|
// And compute the total width
|
||||||
int totalWidth = (columns - 1) * getWidth( SEPARATOR );
|
int totalWidth = (columns - 1) * getWidth( SEPARATOR );
|
||||||
for( int x : maxWidths )
|
for( int x : maxWidths ) totalWidth += x;
|
||||||
{
|
|
||||||
totalWidth += x;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( headers != null )
|
if( headers != null )
|
||||||
{
|
{
|
||||||
@@ -76,10 +81,7 @@ public interface TableFormatter
|
|||||||
{
|
{
|
||||||
line.append( headers[i] );
|
line.append( headers[i] );
|
||||||
Component padding = getPadding( headers[i], maxWidths[i] );
|
Component padding = getPadding( headers[i], maxWidths[i] );
|
||||||
if( padding != null )
|
if( padding != null ) line.append( padding );
|
||||||
{
|
|
||||||
line.append( padding );
|
|
||||||
}
|
|
||||||
line.append( SEPARATOR );
|
line.append( SEPARATOR );
|
||||||
}
|
}
|
||||||
line.append( headers[columns - 1] );
|
line.append( headers[columns - 1] );
|
||||||
@@ -100,10 +102,7 @@ public interface TableFormatter
|
|||||||
{
|
{
|
||||||
line.append( row[i] );
|
line.append( row[i] );
|
||||||
Component padding = getPadding( row[i], maxWidths[i] );
|
Component padding = getPadding( row[i], maxWidths[i] );
|
||||||
if( padding != null )
|
if( padding != null ) line.append( padding );
|
||||||
{
|
|
||||||
line.append( padding );
|
|
||||||
}
|
|
||||||
line.append( SEPARATOR );
|
line.append( SEPARATOR );
|
||||||
}
|
}
|
||||||
line.append( row[columns - 1] );
|
line.append( row[columns - 1] );
|
||||||
@@ -117,25 +116,4 @@ public interface TableFormatter
|
|||||||
|
|
||||||
return rowId - table.getId();
|
return rowId - table.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
int getWidth( Component component );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the minimum padding between each column.
|
|
||||||
*
|
|
||||||
* @return The minimum padding.
|
|
||||||
*/
|
|
||||||
int getColumnPadding();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get additional padding for the component.
|
|
||||||
*
|
|
||||||
* @param component The component to pad
|
|
||||||
* @param width The desired width for the component
|
|
||||||
* @return The padding for this component, or {@code null} if none is needed.
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
Component getPadding( Component component, int width );
|
|
||||||
|
|
||||||
void writeLine( int id, Component component );
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.common;
|
package dan200.computercraft.shared.common;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
@@ -23,66 +22,45 @@ import net.minecraft.world.phys.BlockHitResult;
|
|||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public abstract class BlockGeneric extends BaseEntityBlock
|
public abstract class BlockGeneric extends BaseEntityBlock
|
||||||
{
|
{
|
||||||
private final BlockEntityType<? extends TileGeneric> type;
|
private final Supplier<? extends BlockEntityType<? extends TileGeneric>> type;
|
||||||
|
|
||||||
public BlockGeneric( Properties settings, BlockEntityType<? extends TileGeneric> type )
|
public BlockGeneric( Properties settings, Supplier<? extends BlockEntityType<? extends TileGeneric>> type )
|
||||||
{
|
{
|
||||||
super( settings );
|
super( settings );
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockEntityType<? extends TileGeneric> getType()
|
|
||||||
{
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RenderShape getRenderShape( BlockState state )
|
|
||||||
{
|
|
||||||
return RenderShape.MODEL;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Deprecated
|
|
||||||
public final void neighborChanged( @Nonnull BlockState state, Level world, @Nonnull BlockPos pos, @Nonnull Block neighbourBlock,
|
|
||||||
@Nonnull BlockPos neighbourPos, boolean isMoving )
|
|
||||||
{
|
|
||||||
BlockEntity tile = world.getBlockEntity( pos );
|
|
||||||
if( tile instanceof TileGeneric )
|
|
||||||
{
|
|
||||||
((TileGeneric) tile).onNeighbourChange( neighbourPos );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public final void onRemove( @Nonnull BlockState block, @Nonnull Level world, @Nonnull BlockPos pos, BlockState replace, boolean bool )
|
public final void onRemove( @Nonnull BlockState block, @Nonnull Level world, @Nonnull BlockPos pos, BlockState replace, boolean bool )
|
||||||
{
|
{
|
||||||
if( block.getBlock() == replace.getBlock() )
|
if( block.getBlock() == replace.getBlock() ) return;
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockEntity tile = world.getBlockEntity( pos );
|
BlockEntity tile = world.getBlockEntity( pos );
|
||||||
super.onRemove( block, world, pos, replace, bool );
|
super.onRemove( block, world, pos, replace, bool );
|
||||||
world.removeBlockEntity( pos );
|
world.removeBlockEntity( pos );
|
||||||
if( tile instanceof TileGeneric )
|
if( tile instanceof TileGeneric generic ) generic.destroy();
|
||||||
{
|
|
||||||
((TileGeneric) tile).destroy();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public final InteractionResult use( @Nonnull BlockState state, Level world, @Nonnull BlockPos pos, @Nonnull Player player, @Nonnull InteractionHand hand,
|
public final InteractionResult use( @Nonnull BlockState state, Level world, @Nonnull BlockPos pos, @Nonnull Player player, @Nonnull InteractionHand hand, @Nonnull BlockHitResult hit )
|
||||||
@Nonnull BlockHitResult hit )
|
|
||||||
{
|
{
|
||||||
BlockEntity tile = world.getBlockEntity( pos );
|
BlockEntity tile = world.getBlockEntity( pos );
|
||||||
return tile instanceof TileGeneric ? ((TileGeneric) tile).onActivate( player, hand, hit ) : InteractionResult.PASS;
|
return tile instanceof TileGeneric generic ? generic.onActivate( player, hand, hit ) : InteractionResult.PASS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Deprecated
|
||||||
|
public final void neighborChanged( @Nonnull BlockState state, Level world, @Nonnull BlockPos pos, @Nonnull Block neighbourBlock, @Nonnull BlockPos neighbourPos, boolean isMoving )
|
||||||
|
{
|
||||||
|
BlockEntity tile = world.getBlockEntity( pos );
|
||||||
|
if( tile instanceof TileGeneric generic ) generic.onNeighbourChange( neighbourPos );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -90,20 +68,21 @@ public abstract class BlockGeneric extends BaseEntityBlock
|
|||||||
public void tick( @Nonnull BlockState state, ServerLevel world, @Nonnull BlockPos pos, @Nonnull Random rand )
|
public void tick( @Nonnull BlockState state, ServerLevel world, @Nonnull BlockPos pos, @Nonnull Random rand )
|
||||||
{
|
{
|
||||||
BlockEntity te = world.getBlockEntity( pos );
|
BlockEntity te = world.getBlockEntity( pos );
|
||||||
if( te instanceof TileGeneric )
|
if( te instanceof TileGeneric generic ) generic.blockTick();
|
||||||
{
|
|
||||||
((TileGeneric) te).blockTick();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public BlockEntity newBlockEntity( BlockPos pos, BlockState state )
|
public BlockEntity newBlockEntity( @Nonnull BlockPos pos, @Nonnull BlockState state )
|
||||||
{
|
{
|
||||||
if( this.type != null )
|
return type.get().create( pos, state );
|
||||||
{
|
}
|
||||||
return type.create( pos, state );
|
|
||||||
}
|
@Nonnull
|
||||||
return null;
|
@Override
|
||||||
|
@Deprecated
|
||||||
|
public RenderShape getRenderShape( @Nonnull BlockState state )
|
||||||
|
{
|
||||||
|
return RenderShape.MODEL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,12 +3,10 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.common;
|
package dan200.computercraft.shared.common;
|
||||||
|
|
||||||
import dan200.computercraft.core.terminal.Terminal;
|
import dan200.computercraft.core.terminal.Terminal;
|
||||||
import dan200.computercraft.shared.network.client.TerminalState;
|
import dan200.computercraft.shared.network.client.TerminalState;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
|
||||||
|
|
||||||
public class ClientTerminal implements ITerminal
|
public class ClientTerminal implements ITerminal
|
||||||
{
|
{
|
||||||
@@ -79,19 +77,4 @@ public class ClientTerminal implements ITerminal
|
|||||||
terminalChanged = true;
|
terminalChanged = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void readDescription( CompoundTag nbt )
|
|
||||||
{
|
|
||||||
colour = nbt.getBoolean( "colour" );
|
|
||||||
if( nbt.contains( "terminal" ) )
|
|
||||||
{
|
|
||||||
CompoundTag terminal = nbt.getCompound( "terminal" );
|
|
||||||
resizeTerminal( terminal.getInt( "term_width" ), terminal.getInt( "term_height" ) );
|
|
||||||
this.terminal.readFromNBT( terminal );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
deleteTerminal();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.common;
|
package dan200.computercraft.shared.common;
|
||||||
|
|
||||||
import dan200.computercraft.shared.util.ColourTracker;
|
import dan200.computercraft.shared.util.ColourTracker;
|
||||||
@@ -21,8 +20,6 @@ import javax.annotation.Nonnull;
|
|||||||
|
|
||||||
public final class ColourableRecipe extends CustomRecipe
|
public final class ColourableRecipe extends CustomRecipe
|
||||||
{
|
{
|
||||||
public static final RecipeSerializer<?> SERIALIZER = new SimpleRecipeSerializer<>( ColourableRecipe::new );
|
|
||||||
|
|
||||||
private ColourableRecipe( ResourceLocation id )
|
private ColourableRecipe( ResourceLocation id )
|
||||||
{
|
{
|
||||||
super( id );
|
super( id );
|
||||||
@@ -36,17 +33,11 @@ public final class ColourableRecipe extends CustomRecipe
|
|||||||
for( int i = 0; i < inv.getContainerSize(); i++ )
|
for( int i = 0; i < inv.getContainerSize(); i++ )
|
||||||
{
|
{
|
||||||
ItemStack stack = inv.getItem( i );
|
ItemStack stack = inv.getItem( i );
|
||||||
if( stack.isEmpty() )
|
if( stack.isEmpty() ) continue;
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( stack.getItem() instanceof IColouredItem )
|
if( stack.getItem() instanceof IColouredItem )
|
||||||
{
|
{
|
||||||
if( hasColourable )
|
if( hasColourable ) return false;
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
hasColourable = true;
|
hasColourable = true;
|
||||||
}
|
}
|
||||||
else if( ColourUtils.getStackColour( stack ) != null )
|
else if( ColourUtils.getStackColour( stack ) != null )
|
||||||
@@ -74,9 +65,11 @@ public final class ColourableRecipe extends CustomRecipe
|
|||||||
{
|
{
|
||||||
ItemStack stack = inv.getItem( i );
|
ItemStack stack = inv.getItem( i );
|
||||||
|
|
||||||
if( stack.isEmpty() )
|
if( stack.isEmpty() ) continue;
|
||||||
|
|
||||||
|
if( stack.getItem() instanceof IColouredItem )
|
||||||
{
|
{
|
||||||
continue;
|
colourable = stack;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -104,4 +97,6 @@ public final class ColourableRecipe extends CustomRecipe
|
|||||||
{
|
{
|
||||||
return SERIALIZER;
|
return SERIALIZER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final SimpleRecipeSerializer<?> SERIALIZER = new SimpleRecipeSerializer<>( ColourableRecipe::new );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,9 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.common;
|
package dan200.computercraft.shared.common;
|
||||||
|
|
||||||
import dan200.computercraft.shared.ComputerCraftRegistry;
|
import dan200.computercraft.shared.Registry;
|
||||||
import dan200.computercraft.shared.network.container.HeldItemContainerData;
|
import dan200.computercraft.shared.network.container.HeldItemContainerData;
|
||||||
import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory;
|
import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
@@ -32,13 +31,12 @@ public class ContainerHeldItem extends AbstractContainerMenu
|
|||||||
super( type, id );
|
super( type, id );
|
||||||
|
|
||||||
this.hand = hand;
|
this.hand = hand;
|
||||||
stack = player.getItemInHand( hand )
|
stack = player.getItemInHand( hand ).copy();
|
||||||
.copy();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ContainerHeldItem createPrintout( int id, Inventory inventory, HeldItemContainerData data )
|
public static ContainerHeldItem createPrintout( int id, Inventory inventory, HeldItemContainerData data )
|
||||||
{
|
{
|
||||||
return new ContainerHeldItem( ComputerCraftRegistry.ModContainers.PRINTOUT, id, inventory.player, data.getHand() );
|
return new ContainerHeldItem( Registry.ModContainers.PRINTOUT, id, inventory.player, data.getHand() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@@ -50,10 +48,7 @@ public class ContainerHeldItem extends AbstractContainerMenu
|
|||||||
@Override
|
@Override
|
||||||
public boolean stillValid( @Nonnull Player player )
|
public boolean stillValid( @Nonnull Player player )
|
||||||
{
|
{
|
||||||
if( !player.isAlive() )
|
if( !player.isAlive() ) return false;
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ItemStack stack = player.getItemInHand( hand );
|
ItemStack stack = player.getItemInHand( hand );
|
||||||
return stack == this.stack || !stack.isEmpty() && !this.stack.isEmpty() && stack.getItem() == this.stack.getItem();
|
return stack == this.stack || !stack.isEmpty() && !this.stack.isEmpty() && stack.getItem() == this.stack.getItem();
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.common;
|
package dan200.computercraft.shared.common;
|
||||||
|
|
||||||
import dan200.computercraft.api.redstone.IBundledRedstoneProvider;
|
import dan200.computercraft.api.redstone.IBundledRedstoneProvider;
|
||||||
@@ -24,11 +23,9 @@ public class DefaultBundledRedstoneProvider implements IBundledRedstoneProvider
|
|||||||
|
|
||||||
public static int getDefaultBundledRedstoneOutput( Level world, BlockPos pos, Direction side )
|
public static int getDefaultBundledRedstoneOutput( Level world, BlockPos pos, Direction side )
|
||||||
{
|
{
|
||||||
Block block = world.getBlockState( pos )
|
Block block = world.getBlockState( pos ).getBlock();
|
||||||
.getBlock();
|
if( block instanceof IBundledRedstoneBlock generic )
|
||||||
if( block instanceof IBundledRedstoneBlock )
|
|
||||||
{
|
{
|
||||||
IBundledRedstoneBlock generic = (IBundledRedstoneBlock) block;
|
|
||||||
if( generic.getBundledRedstoneConnectivity( world, pos, side ) )
|
if( generic.getBundledRedstoneConnectivity( world, pos, side ) )
|
||||||
{
|
{
|
||||||
return generic.getBundledRedstoneOutput( world, pos, side );
|
return generic.getBundledRedstoneOutput( world, pos, side );
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.common;
|
package dan200.computercraft.shared.common;
|
||||||
|
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
@@ -18,12 +17,6 @@ public interface IColouredItem
|
|||||||
return getColourBasic( stack );
|
return getColourBasic( stack );
|
||||||
}
|
}
|
||||||
|
|
||||||
static int getColourBasic( ItemStack stack )
|
|
||||||
{
|
|
||||||
CompoundTag tag = stack.getTag();
|
|
||||||
return tag != null && tag.contains( NBT_COLOUR ) ? tag.getInt( NBT_COLOUR ) : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
default ItemStack withColour( ItemStack stack, int colour )
|
default ItemStack withColour( ItemStack stack, int colour )
|
||||||
{
|
{
|
||||||
ItemStack copy = stack.copy();
|
ItemStack copy = stack.copy();
|
||||||
@@ -31,20 +24,22 @@ public interface IColouredItem
|
|||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int getColourBasic( ItemStack stack )
|
||||||
|
{
|
||||||
|
CompoundTag tag = stack.getTag();
|
||||||
|
return tag != null && tag.contains( NBT_COLOUR ) ? tag.getInt( NBT_COLOUR ) : -1;
|
||||||
|
}
|
||||||
|
|
||||||
static void setColourBasic( ItemStack stack, int colour )
|
static void setColourBasic( ItemStack stack, int colour )
|
||||||
{
|
{
|
||||||
if( colour == -1 )
|
if( colour == -1 )
|
||||||
{
|
{
|
||||||
CompoundTag tag = stack.getTag();
|
CompoundTag tag = stack.getTag();
|
||||||
if( tag != null )
|
if( tag != null ) tag.remove( NBT_COLOUR );
|
||||||
{
|
|
||||||
tag.remove( NBT_COLOUR );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
stack.getOrCreateTag()
|
stack.getOrCreateTag().putInt( NBT_COLOUR, colour );
|
||||||
.putInt( NBT_COLOUR, colour );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,20 +3,18 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.common;
|
package dan200.computercraft.shared.common;
|
||||||
|
|
||||||
import dan200.computercraft.core.terminal.Terminal;
|
import dan200.computercraft.core.terminal.Terminal;
|
||||||
import dan200.computercraft.shared.network.client.TerminalState;
|
import dan200.computercraft.shared.network.client.TerminalState;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
public class ServerTerminal implements ITerminal
|
public class ServerTerminal implements ITerminal
|
||||||
{
|
{
|
||||||
private final boolean colour;
|
private final boolean colour;
|
||||||
private final AtomicBoolean terminalChanged = new AtomicBoolean( false );
|
|
||||||
private Terminal terminal;
|
private Terminal terminal;
|
||||||
|
private final AtomicBoolean terminalChanged = new AtomicBoolean( false );
|
||||||
private boolean terminalChangedLastFrame = false;
|
private boolean terminalChangedLastFrame = false;
|
||||||
|
|
||||||
public ServerTerminal( boolean colour )
|
public ServerTerminal( boolean colour )
|
||||||
@@ -31,11 +29,6 @@ public class ServerTerminal implements ITerminal
|
|||||||
terminal = new Terminal( terminalWidth, terminalHeight, this::markTerminalChanged );
|
terminal = new Terminal( terminalWidth, terminalHeight, this::markTerminalChanged );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void markTerminalChanged()
|
|
||||||
{
|
|
||||||
terminalChanged.set( true );
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void resize( int width, int height )
|
protected void resize( int width, int height )
|
||||||
{
|
{
|
||||||
if( terminal == null )
|
if( terminal == null )
|
||||||
@@ -58,6 +51,11 @@ public class ServerTerminal implements ITerminal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void markTerminalChanged()
|
||||||
|
{
|
||||||
|
terminalChanged.set( true );
|
||||||
|
}
|
||||||
|
|
||||||
public void update()
|
public void update()
|
||||||
{
|
{
|
||||||
terminalChangedLastFrame = terminalChanged.getAndSet( false );
|
terminalChangedLastFrame = terminalChanged.getAndSet( false );
|
||||||
@@ -84,17 +82,4 @@ public class ServerTerminal implements ITerminal
|
|||||||
{
|
{
|
||||||
return new TerminalState( colour, terminal );
|
return new TerminalState( colour, terminal );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeDescription( CompoundTag nbt )
|
|
||||||
{
|
|
||||||
nbt.putBoolean( "colour", colour );
|
|
||||||
if( terminal != null )
|
|
||||||
{
|
|
||||||
CompoundTag terminal = new CompoundTag();
|
|
||||||
terminal.putInt( "term_width", this.terminal.getWidth() );
|
|
||||||
terminal.putInt( "term_height", this.terminal.getHeight() );
|
|
||||||
this.terminal.writeToNBT( terminal );
|
|
||||||
nbt.put( "terminal", terminal );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.common;
|
package dan200.computercraft.shared.common;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
@@ -14,6 +13,7 @@ import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
|||||||
import net.minecraft.world.InteractionHand;
|
import net.minecraft.world.InteractionHand;
|
||||||
import net.minecraft.world.InteractionResult;
|
import net.minecraft.world.InteractionResult;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
@@ -33,6 +33,7 @@ public abstract class TileGeneric extends BlockEntity
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is called by fabric event hook in ComputerCraftProxyCommon
|
||||||
public void onChunkUnloaded()
|
public void onChunkUnloaded()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -42,7 +43,7 @@ public abstract class TileGeneric extends BlockEntity
|
|||||||
setChanged();
|
setChanged();
|
||||||
BlockPos pos = getBlockPos();
|
BlockPos pos = getBlockPos();
|
||||||
BlockState state = getBlockState();
|
BlockState state = getBlockState();
|
||||||
getLevel().sendBlockUpdated( pos, state, state, 3 );
|
getLevel().sendBlockUpdated( pos, state, state, Block.UPDATE_ALL );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@@ -70,26 +71,19 @@ public abstract class TileGeneric extends BlockEntity
|
|||||||
|
|
||||||
public boolean isUsable( Player player, boolean ignoreRange )
|
public boolean isUsable( Player player, boolean ignoreRange )
|
||||||
{
|
{
|
||||||
if( player == null || !player.isAlive() || getLevel().getBlockEntity( getBlockPos() ) != this )
|
if( player == null || !player.isAlive() || getLevel().getBlockEntity( getBlockPos() ) != this ) return false;
|
||||||
{
|
if( ignoreRange ) return true;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if( ignoreRange )
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
double range = getInteractRange( player );
|
double range = getInteractRange( player );
|
||||||
BlockPos pos = getBlockPos();
|
BlockPos pos = getBlockPos();
|
||||||
return player.getCommandSenderWorld() == getLevel() && player.distanceToSqr( pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5 ) <= range * range;
|
return player.getCommandSenderWorld() == getLevel() &&
|
||||||
|
player.distanceToSqr( pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5 ) <= range * range;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundTag getUpdateTag()
|
public CompoundTag getUpdateTag()
|
||||||
{
|
{
|
||||||
CompoundTag nbt = new CompoundTag();
|
return this.saveWithoutMetadata();
|
||||||
writeDescription( nbt );
|
|
||||||
return nbt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|||||||
@@ -3,31 +3,32 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.computer.apis;
|
package dan200.computercraft.shared.computer.apis;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.mojang.brigadier.tree.CommandNode;
|
import com.mojang.brigadier.tree.CommandNode;
|
||||||
import com.mojang.brigadier.tree.LiteralCommandNode;
|
import com.mojang.brigadier.tree.LiteralCommandNode;
|
||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.ComputerCraft;
|
||||||
import dan200.computercraft.api.lua.*;
|
import dan200.computercraft.api.lua.*;
|
||||||
import dan200.computercraft.shared.computer.blocks.TileCommandComputer;
|
import dan200.computercraft.shared.computer.blocks.TileCommandComputer;
|
||||||
|
import dan200.computercraft.shared.peripheral.generic.data.BlockData;
|
||||||
import dan200.computercraft.shared.util.NBTUtil;
|
import dan200.computercraft.shared.util.NBTUtil;
|
||||||
import net.minecraft.commands.CommandSourceStack;
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
import net.minecraft.commands.Commands;
|
import net.minecraft.commands.Commands;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Registry;
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.resources.ResourceKey;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.block.Block;
|
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.level.block.state.properties.Property;
|
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @cc.module commands
|
* @cc.module commands
|
||||||
|
* @cc.since 1.7
|
||||||
*/
|
*/
|
||||||
public class CommandAPI implements ILuaAPI
|
public class CommandAPI implements ILuaAPI
|
||||||
{
|
{
|
||||||
@@ -44,29 +45,14 @@ public class CommandAPI implements ILuaAPI
|
|||||||
return new String[] { "commands" };
|
return new String[] { "commands" };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private static Object createOutput( String output )
|
||||||
* Execute a specific command.
|
|
||||||
*
|
|
||||||
* @param command The command to execute.
|
|
||||||
* @return See {@code cc.treturn}.
|
|
||||||
* @cc.treturn boolean Whether the command executed successfully.
|
|
||||||
* @cc.treturn { string... } The output of this command, as a list of lines.
|
|
||||||
* @cc.treturn number|nil The number of "affected" objects, or `nil` if the command failed. The definition of this varies from command to command.
|
|
||||||
* @cc.usage Set the block above the command computer to stone.
|
|
||||||
* <pre>
|
|
||||||
* commands.exec("setblock ~ ~1 ~ minecraft:stone")
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
@LuaFunction( mainThread = true )
|
|
||||||
public final Object[] exec( String command )
|
|
||||||
{
|
{
|
||||||
return doCommand( command );
|
return new Object[] { output };
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object[] doCommand( String command )
|
private Object[] doCommand( String command )
|
||||||
{
|
{
|
||||||
MinecraftServer server = computer.getLevel()
|
MinecraftServer server = computer.getLevel().getServer();
|
||||||
.getServer();
|
|
||||||
if( server == null || !server.isCommandBlockEnabled() )
|
if( server == null || !server.isCommandBlockEnabled() )
|
||||||
{
|
{
|
||||||
return new Object[] { false, createOutput( "Command blocks disabled by server" ) };
|
return new Object[] { false, createOutput( "Command blocks disabled by server" ) };
|
||||||
@@ -82,36 +68,64 @@ public class CommandAPI implements ILuaAPI
|
|||||||
}
|
}
|
||||||
catch( Throwable t )
|
catch( Throwable t )
|
||||||
{
|
{
|
||||||
if( ComputerCraft.logComputerErrors )
|
if( ComputerCraft.logComputerErrors ) ComputerCraft.log.error( "Error running command.", t );
|
||||||
{
|
|
||||||
ComputerCraft.log.error( "Error running command.", t );
|
|
||||||
}
|
|
||||||
return new Object[] { false, createOutput( "Java Exception Thrown: " + t ) };
|
return new Object[] { false, createOutput( "Java Exception Thrown: " + t ) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object createOutput( String output )
|
private static Map<?, ?> getBlockInfo( Level world, BlockPos pos )
|
||||||
{
|
{
|
||||||
return new Object[] { output };
|
// Get the details of the block
|
||||||
|
BlockState state = world.getBlockState( pos );
|
||||||
|
Map<String, Object> table = BlockData.fill( new HashMap<>(), state );
|
||||||
|
|
||||||
|
BlockEntity tile = world.getBlockEntity( pos );
|
||||||
|
if( tile != null ) table.put( "nbt", NBTUtil.toLua( tile.saveWithFullMetadata() ) );
|
||||||
|
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute a specific command.
|
||||||
|
*
|
||||||
|
* @param command The command to execute.
|
||||||
|
* @return See {@code cc.treturn}.
|
||||||
|
* @cc.treturn boolean Whether the command executed successfully.
|
||||||
|
* @cc.treturn { string... } The output of this command, as a list of lines.
|
||||||
|
* @cc.treturn number|nil The number of "affected" objects, or `nil` if the command failed. The definition of this
|
||||||
|
* varies from command to command.
|
||||||
|
* @cc.changed 1.71 Added return value with command output.
|
||||||
|
* @cc.changed 1.85.0 Added return value with the number of affected objects.
|
||||||
|
* @cc.usage Set the block above the command computer to stone.
|
||||||
|
* <pre>{@code
|
||||||
|
* commands.exec("setblock ~ ~1 ~ minecraft:stone")
|
||||||
|
* }</pre>
|
||||||
|
*/
|
||||||
|
@LuaFunction( mainThread = true )
|
||||||
|
public final Object[] exec( String command )
|
||||||
|
{
|
||||||
|
return doCommand( command );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asynchronously execute a command.
|
* Asynchronously execute a command.
|
||||||
*
|
*
|
||||||
* Unlike {@link #exec}, this will immediately return, instead of waiting for the command to execute. This allows you to run multiple commands at the
|
* Unlike {@link #exec}, this will immediately return, instead of waiting for the
|
||||||
* same time.
|
* command to execute. This allows you to run multiple commands at the same
|
||||||
|
* time.
|
||||||
*
|
*
|
||||||
* When this command has finished executing, it will queue a `task_complete` event containing the result of executing this command (what {@link #exec}
|
* When this command has finished executing, it will queue a `task_complete`
|
||||||
* would return).
|
* event containing the result of executing this command (what {@link #exec} would
|
||||||
|
* return).
|
||||||
*
|
*
|
||||||
* @param context The context this command executes under.
|
* @param context The context this command executes under.
|
||||||
* @param command The command to execute.
|
* @param command The command to execute.
|
||||||
* @return The "task id". When this command has been executed, it will queue a `task_complete` event with a matching id.
|
* @return The "task id". When this command has been executed, it will queue a `task_complete` event with a matching id.
|
||||||
* @throws LuaException (hidden) If the task cannot be created.
|
* @throws LuaException (hidden) If the task cannot be created.
|
||||||
* @cc.usage Asynchronously sets the block above the computer to stone.
|
* @cc.usage Asynchronously sets the block above the computer to stone.
|
||||||
* <pre>
|
* <pre>{@code
|
||||||
* commands.execAsync("~ ~1 ~ minecraft:stone")
|
* commands.execAsync("setblock ~ ~1 ~ minecraft:stone")
|
||||||
* </pre>
|
* }</pre>
|
||||||
* @cc.see parallel One may also use the parallel API to run multiple commands at once.
|
* @cc.see parallel One may also use the parallel API to run multiple commands at once.
|
||||||
*/
|
*/
|
||||||
@LuaFunction
|
@LuaFunction
|
||||||
@@ -131,33 +145,21 @@ public class CommandAPI implements ILuaAPI
|
|||||||
@LuaFunction( mainThread = true )
|
@LuaFunction( mainThread = true )
|
||||||
public final List<String> list( IArguments args ) throws LuaException
|
public final List<String> list( IArguments args ) throws LuaException
|
||||||
{
|
{
|
||||||
MinecraftServer server = computer.getLevel()
|
MinecraftServer server = computer.getLevel().getServer();
|
||||||
.getServer();
|
|
||||||
|
|
||||||
if( server == null )
|
if( server == null ) return Collections.emptyList();
|
||||||
{
|
CommandNode<CommandSourceStack> node = server.getCommands().getDispatcher().getRoot();
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
CommandNode<CommandSourceStack> node = server.getCommands()
|
|
||||||
.getDispatcher()
|
|
||||||
.getRoot();
|
|
||||||
for( int j = 0; j < args.count(); j++ )
|
for( int j = 0; j < args.count(); j++ )
|
||||||
{
|
{
|
||||||
String name = args.getString( j );
|
String name = args.getString( j );
|
||||||
node = node.getChild( name );
|
node = node.getChild( name );
|
||||||
if( !(node instanceof LiteralCommandNode) )
|
if( !(node instanceof LiteralCommandNode) ) return Collections.emptyList();
|
||||||
{
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> result = new ArrayList<>();
|
List<String> result = new ArrayList<>();
|
||||||
for( CommandNode<?> child : node.getChildren() )
|
for( CommandNode<?> child : node.getChildren() )
|
||||||
{
|
{
|
||||||
if( child instanceof LiteralCommandNode<?> )
|
if( child instanceof LiteralCommandNode<?> ) result.add( child.getName() );
|
||||||
{
|
|
||||||
result.add( child.getName() );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -182,37 +184,47 @@ public class CommandAPI implements ILuaAPI
|
|||||||
/**
|
/**
|
||||||
* Get information about a range of blocks.
|
* Get information about a range of blocks.
|
||||||
*
|
*
|
||||||
* This returns the same information as @{getBlockInfo}, just for multiple blocks at once.
|
* This returns the same information as @{getBlockInfo}, just for multiple
|
||||||
|
* blocks at once.
|
||||||
*
|
*
|
||||||
* Blocks are traversed by ascending y level, followed by z and x - the returned table may be indexed using `x + z*width + y*depth*depth`.
|
* Blocks are traversed by ascending y level, followed by z and x - the returned
|
||||||
|
* table may be indexed using `x + z*width + y*depth*depth`.
|
||||||
*
|
*
|
||||||
* @param minX The start x coordinate of the range to query.
|
* @param minX The start x coordinate of the range to query.
|
||||||
* @param minY The start y coordinate of the range to query.
|
* @param minY The start y coordinate of the range to query.
|
||||||
* @param minZ The start z coordinate of the range to query.
|
* @param minZ The start z coordinate of the range to query.
|
||||||
* @param maxX The end x coordinate of the range to query.
|
* @param maxX The end x coordinate of the range to query.
|
||||||
* @param maxY The end y coordinate of the range to query.
|
* @param maxY The end y coordinate of the range to query.
|
||||||
* @param maxZ The end z coordinate of the range to query.
|
* @param maxZ The end z coordinate of the range to query.
|
||||||
|
* @param dimension The dimension to query (e.g. "minecraft:overworld"). Defaults to the current dimension.
|
||||||
* @return A list of information about each block.
|
* @return A list of information about each block.
|
||||||
* @throws LuaException If the coordinates are not within the world.
|
* @throws LuaException If the coordinates are not within the world.
|
||||||
* @throws LuaException If trying to get information about more than 4096 blocks.
|
* @throws LuaException If trying to get information about more than 4096 blocks.
|
||||||
|
* @cc.since 1.76
|
||||||
|
* @cc.changed 1.99 Added {@code dimension} argument.
|
||||||
*/
|
*/
|
||||||
@LuaFunction( mainThread = true )
|
@LuaFunction( mainThread = true )
|
||||||
public final List<Map<?, ?>> getBlockInfos( int minX, int minY, int minZ, int maxX, int maxY, int maxZ ) throws LuaException
|
public final List<Map<?, ?>> getBlockInfos( int minX, int minY, int minZ, int maxX, int maxY, int maxZ, Optional<String> dimension ) throws LuaException
|
||||||
{
|
{
|
||||||
// Get the details of the block
|
// Get the details of the block
|
||||||
Level world = computer.getLevel();
|
Level world = getLevel( dimension );
|
||||||
BlockPos min = new BlockPos( Math.min( minX, maxX ), Math.min( minY, maxY ), Math.min( minZ, maxZ ) );
|
BlockPos min = new BlockPos(
|
||||||
BlockPos max = new BlockPos( Math.max( minX, maxX ), Math.max( minY, maxY ), Math.max( minZ, maxZ ) );
|
Math.min( minX, maxX ),
|
||||||
if( !world.isInWorldBounds( min ) || !world.isInWorldBounds( max ) )
|
Math.min( minY, maxY ),
|
||||||
|
Math.min( minZ, maxZ )
|
||||||
|
);
|
||||||
|
BlockPos max = new BlockPos(
|
||||||
|
Math.max( minX, maxX ),
|
||||||
|
Math.max( minY, maxY ),
|
||||||
|
Math.max( minZ, maxZ )
|
||||||
|
);
|
||||||
|
if( world == null || !world.isInWorldBounds( min ) || !world.isInWorldBounds( max ) )
|
||||||
{
|
{
|
||||||
throw new LuaException( "Co-ordinates out of range" );
|
throw new LuaException( "Co-ordinates out of range" );
|
||||||
}
|
}
|
||||||
|
|
||||||
int blocks = (max.getX() - min.getX() + 1) * (max.getY() - min.getY() + 1) * (max.getZ() - min.getZ() + 1);
|
int blocks = (max.getX() - min.getX() + 1) * (max.getY() - min.getY() + 1) * (max.getZ() - min.getZ() + 1);
|
||||||
if( blocks > 4096 )
|
if( blocks > 4096 ) throw new LuaException( "Too many blocks" );
|
||||||
{
|
|
||||||
throw new LuaException( "Too many blocks" );
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Map<?, ?>> results = new ArrayList<>( blocks );
|
List<Map<?, ?>> results = new ArrayList<>( blocks );
|
||||||
for( int y = min.getY(); y <= max.getY(); y++ )
|
for( int y = min.getY(); y <= max.getY(); y++ )
|
||||||
@@ -230,71 +242,45 @@ public class CommandAPI implements ILuaAPI
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Map<?, ?> getBlockInfo( Level world, BlockPos pos )
|
|
||||||
{
|
|
||||||
// Get the details of the block
|
|
||||||
BlockState state = world.getBlockState( pos );
|
|
||||||
Block block = state.getBlock();
|
|
||||||
|
|
||||||
Map<Object, Object> table = new HashMap<>();
|
|
||||||
table.put( "name", Registry.BLOCK.getKey( block ).toString() );
|
|
||||||
table.put( "world", world.dimension() );
|
|
||||||
|
|
||||||
Map<Object, Object> stateTable = new HashMap<>();
|
|
||||||
for( ImmutableMap.Entry<Property<?>, Comparable<?>> entry : state.getValues().entrySet() )
|
|
||||||
{
|
|
||||||
Property<?> property = entry.getKey();
|
|
||||||
stateTable.put( property.getName(), getPropertyValue( property, entry.getValue() ) );
|
|
||||||
}
|
|
||||||
table.put( "state", stateTable );
|
|
||||||
|
|
||||||
BlockEntity tile = world.getBlockEntity( pos );
|
|
||||||
if( tile != null )
|
|
||||||
{
|
|
||||||
table.put( "nbt", NBTUtil.toLua( tile.saveWithFullMetadata() ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
return table;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings( {
|
|
||||||
"unchecked",
|
|
||||||
"rawtypes"
|
|
||||||
} )
|
|
||||||
private static Object getPropertyValue( Property property, Comparable value )
|
|
||||||
{
|
|
||||||
if( value instanceof String || value instanceof Number || value instanceof Boolean )
|
|
||||||
{
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
return property.getName( value );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get some basic information about a block.
|
* Get some basic information about a block.
|
||||||
*
|
*
|
||||||
* The returned table contains the current name, metadata and block state (as with @{turtle.inspect}). If there is a tile entity for that block, its NBT
|
* The returned table contains the current name, metadata and block state (as
|
||||||
|
* with @{turtle.inspect}). If there is a tile entity for that block, its NBT
|
||||||
* will also be returned.
|
* will also be returned.
|
||||||
*
|
*
|
||||||
* @param x The x position of the block to query.
|
* @param x The x position of the block to query.
|
||||||
* @param y The y position of the block to query.
|
* @param y The y position of the block to query.
|
||||||
* @param z The z position of the block to query.
|
* @param z The z position of the block to query.
|
||||||
|
* @param dimension The dimension to query (e.g. "minecraft:overworld"). Defaults to the current dimension.
|
||||||
* @return The given block's information.
|
* @return The given block's information.
|
||||||
* @throws LuaException If the coordinates are not within the world, or are not currently loaded.
|
* @throws LuaException If the coordinates are not within the world, or are not currently loaded.
|
||||||
|
* @cc.changed 1.76 Added block state info to return value
|
||||||
|
* @cc.changed 1.99 Added {@code dimension} argument.
|
||||||
*/
|
*/
|
||||||
@LuaFunction( mainThread = true )
|
@LuaFunction( mainThread = true )
|
||||||
public final Map<?, ?> getBlockInfo( int x, int y, int z ) throws LuaException
|
public final Map<?, ?> getBlockInfo( int x, int y, int z, Optional<String> dimension ) throws LuaException
|
||||||
{
|
{
|
||||||
// Get the details of the block
|
Level level = getLevel( dimension );
|
||||||
Level world = computer.getLevel();
|
|
||||||
BlockPos position = new BlockPos( x, y, z );
|
BlockPos position = new BlockPos( x, y, z );
|
||||||
if( world.isInWorldBounds( position ) )
|
if( !level.isInWorldBounds( position ) ) throw new LuaException( "Co-ordinates out of range" );
|
||||||
{
|
return getBlockInfo( level, position );
|
||||||
return getBlockInfo( world, position );
|
}
|
||||||
}
|
|
||||||
else
|
@Nonnull
|
||||||
{
|
private Level getLevel( @Nonnull Optional<String> id ) throws LuaException
|
||||||
throw new LuaException( "Co-ordinates out of range" );
|
{
|
||||||
}
|
Level currentLevel = computer.getLevel();
|
||||||
|
if( currentLevel == null ) throw new LuaException( "No world exists" );
|
||||||
|
|
||||||
|
if( !id.isPresent() ) return currentLevel;
|
||||||
|
|
||||||
|
ResourceLocation dimensionId = ResourceLocation.tryParse( id.get() );
|
||||||
|
if( dimensionId == null ) throw new LuaException( "Invalid dimension name" );
|
||||||
|
|
||||||
|
Level level = currentLevel.getServer().getLevel( ResourceKey.create( Registry.DIMENSION_REGISTRY, dimensionId ) );
|
||||||
|
if( level == null ) throw new LuaException( "Unknown dimension" );
|
||||||
|
|
||||||
|
return level;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,19 +3,15 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.computer.blocks;
|
package dan200.computercraft.shared.computer.blocks;
|
||||||
|
|
||||||
import dan200.computercraft.shared.ComputerCraftRegistry;
|
|
||||||
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.items.ComputerItemFactory;
|
import dan200.computercraft.shared.computer.items.ComputerItemFactory;
|
||||||
import net.minecraft.core.BlockPos;
|
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.level.block.state.StateDefinition;
|
import net.minecraft.world.level.block.state.StateDefinition;
|
||||||
@@ -25,26 +21,20 @@ import net.minecraft.world.level.block.state.properties.EnumProperty;
|
|||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class BlockComputer extends BlockComputerBase<TileComputer>
|
public class BlockComputer<T extends TileComputer> extends BlockComputerBase<T>
|
||||||
{
|
{
|
||||||
public static final EnumProperty<ComputerState> STATE = EnumProperty.create( "state", ComputerState.class );
|
public static final EnumProperty<ComputerState> STATE = EnumProperty.create( "state", ComputerState.class );
|
||||||
public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING;
|
public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING;
|
||||||
|
|
||||||
public BlockComputer( Properties settings, ComputerFamily family, BlockEntityType<? extends TileComputer> type )
|
public BlockComputer( Properties settings, ComputerFamily family, Supplier<BlockEntityType<T>> type )
|
||||||
{
|
{
|
||||||
super( settings, family, type );
|
super( settings, family, type );
|
||||||
registerDefaultState( defaultBlockState().setValue( FACING, Direction.NORTH )
|
registerDefaultState( defaultBlockState()
|
||||||
.setValue( STATE, ComputerState.OFF ) );
|
.setValue( FACING, Direction.NORTH )
|
||||||
}
|
.setValue( STATE, ComputerState.OFF )
|
||||||
|
);
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public BlockState getStateForPlacement( BlockPlaceContext placement )
|
|
||||||
{
|
|
||||||
return defaultBlockState().setValue( FACING,
|
|
||||||
placement.getHorizontalDirection()
|
|
||||||
.getOpposite() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -53,27 +43,17 @@ public class BlockComputer extends BlockComputerBase<TileComputer>
|
|||||||
builder.add( FACING, STATE );
|
builder.add( FACING, STATE );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public BlockState getStateForPlacement( BlockPlaceContext placement )
|
||||||
|
{
|
||||||
|
return defaultBlockState().setValue( FACING, placement.getHorizontalDirection().getOpposite() );
|
||||||
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
protected ItemStack getItem( TileComputerBase tile )
|
protected ItemStack getItem( TileComputerBase tile )
|
||||||
{
|
{
|
||||||
return tile instanceof TileComputer ? ComputerItemFactory.create( (TileComputer) tile ) : ItemStack.EMPTY;
|
return tile instanceof TileComputer ? ComputerItemFactory.create( (TileComputer) tile ) : ItemStack.EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockEntityType<? extends TileComputer> getTypeByFamily( ComputerFamily family )
|
|
||||||
{
|
|
||||||
return switch( family )
|
|
||||||
{
|
|
||||||
case COMMAND -> ComputerCraftRegistry.ModTiles.COMPUTER_COMMAND;
|
|
||||||
case ADVANCED -> ComputerCraftRegistry.ModTiles.COMPUTER_ADVANCED;
|
|
||||||
default -> ComputerCraftRegistry.ModTiles.COMPUTER_NORMAL;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public BlockEntity newBlockEntity( BlockPos pos, BlockState state )
|
|
||||||
{
|
|
||||||
return new TileComputer( getFamily(), getTypeByFamily( getFamily() ), pos, state );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.computer.blocks;
|
package dan200.computercraft.shared.computer.blocks;
|
||||||
|
|
||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.ComputerCraft;
|
||||||
@@ -23,6 +22,7 @@ import net.minecraft.world.entity.player.Player;
|
|||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.level.BlockGetter;
|
import net.minecraft.world.level.BlockGetter;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.level.block.BaseEntityBlock;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityTicker;
|
import net.minecraft.world.level.block.entity.BlockEntityTicker;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
@@ -33,17 +33,21 @@ import net.minecraft.world.phys.Vec3;
|
|||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public abstract class BlockComputerBase<T extends TileComputerBase> extends BlockGeneric implements IBundledRedstoneBlock
|
public abstract class BlockComputerBase<T extends TileComputerBase> extends BlockGeneric implements IBundledRedstoneBlock
|
||||||
{
|
{
|
||||||
private static final ResourceLocation DROP = new ResourceLocation( ComputerCraft.MOD_ID, "computer" );
|
private static final ResourceLocation DROP = new ResourceLocation( ComputerCraft.MOD_ID, "computer" );
|
||||||
|
|
||||||
private final ComputerFamily family;
|
private final ComputerFamily family;
|
||||||
|
protected final Supplier<BlockEntityType<T>> type;
|
||||||
|
private final BlockEntityTicker<T> serverTicker = ( level, pos, state, computer ) -> computer.serverTick();
|
||||||
|
|
||||||
protected BlockComputerBase( Properties settings, ComputerFamily family, BlockEntityType<? extends T> type )
|
protected BlockComputerBase( Properties settings, ComputerFamily family, Supplier<BlockEntityType<T>> type )
|
||||||
{
|
{
|
||||||
super( settings, type );
|
super( settings, type );
|
||||||
this.family = family;
|
this.family = family;
|
||||||
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -53,10 +57,7 @@ public abstract class BlockComputerBase<T extends TileComputerBase> extends Bloc
|
|||||||
super.onPlace( state, world, pos, oldState, isMoving );
|
super.onPlace( state, world, pos, oldState, isMoving );
|
||||||
|
|
||||||
BlockEntity tile = world.getBlockEntity( pos );
|
BlockEntity tile = world.getBlockEntity( pos );
|
||||||
if( tile instanceof TileComputerBase )
|
if( tile instanceof TileComputerBase computer ) computer.updateInputsImmediately();
|
||||||
{
|
|
||||||
((TileComputerBase) tile).updateInput();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -66,39 +67,35 @@ public abstract class BlockComputerBase<T extends TileComputerBase> extends Bloc
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
@Deprecated
|
|
||||||
public int getSignal( @Nonnull BlockState state, @Nonnull BlockGetter world, @Nonnull BlockPos pos, @Nonnull Direction incomingSide )
|
|
||||||
{
|
|
||||||
return getDirectSignal( state, world, pos, incomingSide );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public int getDirectSignal( @Nonnull BlockState state, BlockGetter world, @Nonnull BlockPos pos, @Nonnull Direction incomingSide )
|
public int getDirectSignal( @Nonnull BlockState state, BlockGetter world, @Nonnull BlockPos pos, @Nonnull Direction incomingSide )
|
||||||
{
|
{
|
||||||
BlockEntity entity = world.getBlockEntity( pos );
|
BlockEntity entity = world.getBlockEntity( pos );
|
||||||
if( !(entity instanceof TileComputerBase) )
|
if( !(entity instanceof TileComputerBase computerEntity) ) return 0;
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
TileComputerBase computerEntity = (TileComputerBase) entity;
|
|
||||||
ServerComputer computer = computerEntity.getServerComputer();
|
ServerComputer computer = computerEntity.getServerComputer();
|
||||||
if( computer == null )
|
if( computer == null ) return 0;
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ComputerSide localSide = computerEntity.remapToLocalSide( incomingSide.getOpposite() );
|
ComputerSide localSide = computerEntity.remapToLocalSide( incomingSide.getOpposite() );
|
||||||
return computer.getRedstoneOutput( localSide );
|
return computer.getRedstoneOutput( localSide );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
protected abstract ItemStack getItem( TileComputerBase tile );
|
||||||
|
|
||||||
public ComputerFamily getFamily()
|
public ComputerFamily getFamily()
|
||||||
{
|
{
|
||||||
return family;
|
return family;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Deprecated
|
||||||
|
public int getSignal( @Nonnull BlockState state, @Nonnull BlockGetter world, @Nonnull BlockPos pos, @Nonnull Direction incomingSide )
|
||||||
|
{
|
||||||
|
return getDirectSignal( state, world, pos, incomingSide );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean getBundledRedstoneConnectivity( Level world, BlockPos pos, Direction side )
|
public boolean getBundledRedstoneConnectivity( Level world, BlockPos pos, Direction side )
|
||||||
{
|
{
|
||||||
@@ -109,56 +106,15 @@ public abstract class BlockComputerBase<T extends TileComputerBase> extends Bloc
|
|||||||
public int getBundledRedstoneOutput( Level world, BlockPos pos, Direction side )
|
public int getBundledRedstoneOutput( Level world, BlockPos pos, Direction side )
|
||||||
{
|
{
|
||||||
BlockEntity entity = world.getBlockEntity( pos );
|
BlockEntity entity = world.getBlockEntity( pos );
|
||||||
if( !(entity instanceof TileComputerBase) )
|
if( !(entity instanceof TileComputerBase computerEntity) ) return 0;
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
TileComputerBase computerEntity = (TileComputerBase) entity;
|
|
||||||
ServerComputer computer = computerEntity.getServerComputer();
|
ServerComputer computer = computerEntity.getServerComputer();
|
||||||
if( computer == null )
|
if( computer == null ) return 0;
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ComputerSide localSide = computerEntity.remapToLocalSide( side );
|
ComputerSide localSide = computerEntity.remapToLocalSide( side );
|
||||||
return computer.getBundledRedstoneOutput( localSide );
|
return computer.getBundledRedstoneOutput( localSide );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void playerDestroy( @Nonnull Level world, Player player, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nullable BlockEntity tile,
|
|
||||||
@Nonnull ItemStack tool )
|
|
||||||
{
|
|
||||||
// Don't drop blocks here - see onBlockHarvested.
|
|
||||||
player.awardStat( Stats.BLOCK_MINED.get( this ) );
|
|
||||||
player.causeFoodExhaustion( 0.005F );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setPlacedBy( @Nonnull Level world, @Nonnull BlockPos pos, @Nonnull BlockState state, LivingEntity placer, @Nonnull ItemStack stack )
|
|
||||||
{
|
|
||||||
super.setPlacedBy( world, pos, state, placer, stack );
|
|
||||||
|
|
||||||
BlockEntity tile = world.getBlockEntity( pos );
|
|
||||||
if( !world.isClientSide && tile instanceof IComputerTile && stack.getItem() instanceof IComputerItem )
|
|
||||||
{
|
|
||||||
IComputerTile computer = (IComputerTile) tile;
|
|
||||||
IComputerItem item = (IComputerItem) stack.getItem();
|
|
||||||
|
|
||||||
int id = item.getComputerID( stack );
|
|
||||||
if( id != -1 )
|
|
||||||
{
|
|
||||||
computer.setComputerID( id );
|
|
||||||
}
|
|
||||||
|
|
||||||
String label = item.getLabel( stack );
|
|
||||||
if( label != null )
|
|
||||||
{
|
|
||||||
computer.setLabel( label );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public ItemStack getCloneItemStack( BlockGetter world, BlockPos pos, BlockState state )
|
public ItemStack getCloneItemStack( BlockGetter world, BlockPos pos, BlockState state )
|
||||||
@@ -167,38 +123,33 @@ public abstract class BlockComputerBase<T extends TileComputerBase> extends Bloc
|
|||||||
if( tile instanceof TileComputerBase )
|
if( tile instanceof TileComputerBase )
|
||||||
{
|
{
|
||||||
ItemStack result = getItem( (TileComputerBase) tile );
|
ItemStack result = getItem( (TileComputerBase) tile );
|
||||||
if( !result.isEmpty() )
|
if( !result.isEmpty() ) return result;
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.getCloneItemStack( world, pos, state );
|
return super.getCloneItemStack( world, pos, state );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Override
|
||||||
protected abstract ItemStack getItem( TileComputerBase tile );
|
public void playerDestroy( @Nonnull Level world, Player player, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nullable BlockEntity tile, @Nonnull ItemStack tool )
|
||||||
|
{
|
||||||
|
// Don't drop blocks here - see onBlockHarvested.
|
||||||
|
player.awardStat( Stats.BLOCK_MINED.get( this ) );
|
||||||
|
player.causeFoodExhaustion( 0.005F );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void playerWillDestroy( @Nonnull Level world, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nonnull Player player )
|
public void playerWillDestroy( @Nonnull Level world, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nonnull Player player )
|
||||||
{
|
{
|
||||||
// Call super as it is what provides sound and block break particles. Does not do anything else.
|
if( !(world instanceof ServerLevel serverWorld) ) return;
|
||||||
super.playerWillDestroy( world, pos, state, player );
|
|
||||||
|
|
||||||
if( !(world instanceof ServerLevel) )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ServerLevel serverWorld = (ServerLevel) world;
|
|
||||||
|
|
||||||
// We drop the item here instead of doing it in the harvest method, as we should
|
// We drop the item here instead of doing it in the harvest method, as we should
|
||||||
// drop computers for creative players too.
|
// drop computers for creative players too.
|
||||||
|
|
||||||
BlockEntity tile = world.getBlockEntity( pos );
|
BlockEntity tile = world.getBlockEntity( pos );
|
||||||
if( tile instanceof TileComputerBase )
|
if( tile instanceof TileComputerBase computer )
|
||||||
{
|
{
|
||||||
TileComputerBase computer = (TileComputerBase) tile;
|
LootContext.Builder context = new LootContext.Builder( serverWorld )
|
||||||
LootContext.Builder context = new LootContext.Builder( serverWorld ).withRandom( world.random )
|
.withRandom( world.random )
|
||||||
.withParameter( LootContextParams.ORIGIN, Vec3.atCenterOf( pos ) )
|
.withParameter( LootContextParams.ORIGIN, Vec3.atCenterOf( pos ) )
|
||||||
.withParameter( LootContextParams.TOOL, player.getMainHandItem() )
|
.withParameter( LootContextParams.TOOL, player.getMainHandItem() )
|
||||||
.withParameter( LootContextParams.THIS_ENTITY, player )
|
.withParameter( LootContextParams.THIS_ENTITY, player )
|
||||||
@@ -213,15 +164,27 @@ public abstract class BlockComputerBase<T extends TileComputerBase> extends Bloc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends BlockEntity> BlockEntityTicker<T> getTicker( Level world, BlockState state, BlockEntityType<T> type )
|
public void setPlacedBy( @Nonnull Level world, @Nonnull BlockPos pos, @Nonnull BlockState state, LivingEntity placer, @Nonnull ItemStack stack )
|
||||||
{
|
{
|
||||||
return world.isClientSide ? null : ( world1, pos, state1, tile ) -> {
|
super.setPlacedBy( world, pos, state, placer, stack );
|
||||||
if( tile instanceof TileComputerBase computer )
|
|
||||||
{
|
BlockEntity tile = world.getBlockEntity( pos );
|
||||||
computer.serverTick();
|
if( !world.isClientSide && tile instanceof IComputerTile computer && stack.getItem() instanceof IComputerItem item )
|
||||||
}
|
{
|
||||||
};
|
|
||||||
|
int id = item.getComputerID( stack );
|
||||||
|
if( id != -1 ) computer.setComputerID( id );
|
||||||
|
|
||||||
|
String label = item.getLabel( stack );
|
||||||
|
if( label != null ) computer.setLabel( label );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public <U extends BlockEntity> BlockEntityTicker<U> getTicker( @Nonnull Level level, @Nonnull BlockState state, @Nonnull BlockEntityType<U> type )
|
||||||
|
{
|
||||||
|
return level.isClientSide ? null : BaseEntityBlock.createTickerHelper( type, this.type.get(), serverTicker );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.computer.blocks;
|
package dan200.computercraft.shared.computer.blocks;
|
||||||
|
|
||||||
import dan200.computercraft.api.lua.LuaFunction;
|
import dan200.computercraft.api.lua.LuaFunction;
|
||||||
@@ -16,8 +15,8 @@ import javax.annotation.Nullable;
|
|||||||
/**
|
/**
|
||||||
* A computer or turtle wrapped as a peripheral.
|
* A computer or turtle wrapped as a peripheral.
|
||||||
*
|
*
|
||||||
* This allows for basic interaction with adjacent computers. Computers wrapped as peripherals will have the type {@code computer} while turtles will be
|
* This allows for basic interaction with adjacent computers. Computers wrapped as peripherals will have the type
|
||||||
* {@code turtle}.
|
* {@code computer} while turtles will be {@code turtle}.
|
||||||
*
|
*
|
||||||
* @cc.module computer
|
* @cc.module computer
|
||||||
*/
|
*/
|
||||||
@@ -39,19 +38,6 @@ public class ComputerPeripheral implements IPeripheral
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public Object getTarget()
|
|
||||||
{
|
|
||||||
return computer.getTile();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals( IPeripheral other )
|
|
||||||
{
|
|
||||||
return other instanceof ComputerPeripheral && computer == ((ComputerPeripheral) other).computer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Turn the other computer on.
|
* Turn the other computer on.
|
||||||
*/
|
*/
|
||||||
@@ -114,4 +100,17 @@ public class ComputerPeripheral implements IPeripheral
|
|||||||
{
|
{
|
||||||
return computer.getLabel();
|
return computer.getLabel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals( IPeripheral other )
|
||||||
|
{
|
||||||
|
return other instanceof ComputerPeripheral && computer == ((ComputerPeripheral) other).computer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public Object getTarget()
|
||||||
|
{
|
||||||
|
return computer.getTile();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.computer.blocks;
|
package dan200.computercraft.shared.computer.blocks;
|
||||||
|
|
||||||
import dan200.computercraft.shared.computer.core.IComputer;
|
import dan200.computercraft.shared.computer.core.IComputer;
|
||||||
@@ -14,7 +13,7 @@ import java.util.function.Supplier;
|
|||||||
/**
|
/**
|
||||||
* A proxy object for computer objects, delegating to {@link IComputer} or {@link TileComputer} where appropriate.
|
* A proxy object for computer objects, delegating to {@link IComputer} or {@link TileComputer} where appropriate.
|
||||||
*/
|
*/
|
||||||
public class ComputerProxy
|
public final class ComputerProxy
|
||||||
{
|
{
|
||||||
private final Supplier<TileComputerBase> get;
|
private final Supplier<TileComputerBase> get;
|
||||||
|
|
||||||
@@ -23,6 +22,11 @@ public class ComputerProxy
|
|||||||
this.get = get;
|
this.get = get;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TileComputerBase getTile()
|
||||||
|
{
|
||||||
|
return get.get();
|
||||||
|
}
|
||||||
|
|
||||||
public void turnOn()
|
public void turnOn()
|
||||||
{
|
{
|
||||||
TileComputerBase tile = getTile();
|
TileComputerBase tile = getTile();
|
||||||
@@ -37,11 +41,6 @@ public class ComputerProxy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected TileComputerBase getTile()
|
|
||||||
{
|
|
||||||
return get.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void shutdown()
|
public void shutdown()
|
||||||
{
|
{
|
||||||
TileComputerBase tile = getTile();
|
TileComputerBase tile = getTile();
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.computer.blocks;
|
package dan200.computercraft.shared.computer.blocks;
|
||||||
|
|
||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.ComputerCraft;
|
||||||
@@ -32,75 +31,6 @@ import java.util.UUID;
|
|||||||
|
|
||||||
public class TileCommandComputer extends TileComputer
|
public class TileCommandComputer extends TileComputer
|
||||||
{
|
{
|
||||||
private final CommandReceiver receiver;
|
|
||||||
|
|
||||||
public TileCommandComputer( ComputerFamily family, BlockEntityType<? extends TileCommandComputer> type, BlockPos pos, BlockState state )
|
|
||||||
{
|
|
||||||
super( family, type, pos, state );
|
|
||||||
receiver = new CommandReceiver();
|
|
||||||
}
|
|
||||||
|
|
||||||
public CommandReceiver getReceiver()
|
|
||||||
{
|
|
||||||
return receiver;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CommandSourceStack getSource()
|
|
||||||
{
|
|
||||||
ServerComputer computer = getServerComputer();
|
|
||||||
String name = "@";
|
|
||||||
if( computer != null )
|
|
||||||
{
|
|
||||||
String label = computer.getLabel();
|
|
||||||
if( label != null )
|
|
||||||
{
|
|
||||||
name = label;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new CommandSourceStack( receiver,
|
|
||||||
new Vec3( worldPosition.getX() + 0.5, worldPosition.getY() + 0.5, worldPosition.getZ() + 0.5 ),
|
|
||||||
Vec2.ZERO,
|
|
||||||
(ServerLevel) getLevel(),
|
|
||||||
2,
|
|
||||||
name,
|
|
||||||
new TextComponent( name ),
|
|
||||||
getLevel().getServer(),
|
|
||||||
null );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ServerComputer createComputer( int instanceID, int id )
|
|
||||||
{
|
|
||||||
ServerComputer computer = super.createComputer( instanceID, id );
|
|
||||||
computer.addAPI( new CommandAPI( this ) );
|
|
||||||
return computer;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isUsable( Player player, boolean ignoreRange )
|
|
||||||
{
|
|
||||||
return isUsable( player ) && super.isUsable( player, ignoreRange );
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isUsable( Player player )
|
|
||||||
{
|
|
||||||
MinecraftServer server = player.getServer();
|
|
||||||
if( server == null || !server.isCommandBlockEnabled() )
|
|
||||||
{
|
|
||||||
player.displayClientMessage( new TranslatableComponent( "advMode.notEnabled" ), true );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if( ComputerCraft.commandRequireCreative ? !player.canUseGameMasterBlocks() : !server.getPlayerList()
|
|
||||||
.isOp( player.getGameProfile() ) )
|
|
||||||
{
|
|
||||||
player.displayClientMessage( new TranslatableComponent( "advMode.notAllowed" ), true );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CommandReceiver implements CommandSource
|
public class CommandReceiver implements CommandSource
|
||||||
{
|
{
|
||||||
private final Map<Integer, String> output = new HashMap<>();
|
private final Map<Integer, String> output = new HashMap<>();
|
||||||
@@ -129,8 +59,7 @@ public class TileCommandComputer extends TileComputer
|
|||||||
@Override
|
@Override
|
||||||
public boolean acceptsSuccess()
|
public boolean acceptsSuccess()
|
||||||
{
|
{
|
||||||
return getLevel().getGameRules()
|
return true;
|
||||||
.getBoolean( GameRules.RULE_SENDCOMMANDFEEDBACK );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -142,8 +71,69 @@ public class TileCommandComputer extends TileComputer
|
|||||||
@Override
|
@Override
|
||||||
public boolean shouldInformAdmins()
|
public boolean shouldInformAdmins()
|
||||||
{
|
{
|
||||||
return getLevel().getGameRules()
|
return getLevel().getGameRules().getBoolean( GameRules.RULE_COMMANDBLOCKOUTPUT );
|
||||||
.getBoolean( GameRules.RULE_COMMANDBLOCKOUTPUT );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final CommandReceiver receiver;
|
||||||
|
|
||||||
|
public TileCommandComputer( BlockEntityType<? extends TileComputer> type, BlockPos pos, BlockState state )
|
||||||
|
{
|
||||||
|
super( type, pos, state, ComputerFamily.COMMAND );
|
||||||
|
receiver = new CommandReceiver();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandReceiver getReceiver()
|
||||||
|
{
|
||||||
|
return receiver;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandSourceStack getSource()
|
||||||
|
{
|
||||||
|
ServerComputer computer = getServerComputer();
|
||||||
|
String name = "@";
|
||||||
|
if( computer != null )
|
||||||
|
{
|
||||||
|
String label = computer.getLabel();
|
||||||
|
if( label != null ) name = label;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CommandSourceStack( receiver,
|
||||||
|
new Vec3( worldPosition.getX() + 0.5, worldPosition.getY() + 0.5, worldPosition.getZ() + 0.5 ), Vec2.ZERO,
|
||||||
|
(ServerLevel) getLevel(), 2,
|
||||||
|
name, new TextComponent( name ),
|
||||||
|
getLevel().getServer(), null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ServerComputer createComputer( int instanceID, int id )
|
||||||
|
{
|
||||||
|
ServerComputer computer = super.createComputer( instanceID, id );
|
||||||
|
computer.addAPI( new CommandAPI( this ) );
|
||||||
|
return computer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isUsable( Player player, boolean ignoreRange )
|
||||||
|
{
|
||||||
|
return isUsable( player ) && super.isUsable( player, ignoreRange );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isUsable( Player player )
|
||||||
|
{
|
||||||
|
MinecraftServer server = player.getServer();
|
||||||
|
if( server == null || !server.isCommandBlockEnabled() )
|
||||||
|
{
|
||||||
|
player.displayClientMessage( new TranslatableComponent( "advMode.notEnabled" ), true );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if( ComputerCraft.commandRequireCreative ? !player.canUseGameMasterBlocks() : !server.getPlayerList().isOp( player.getGameProfile() ) )
|
||||||
|
{
|
||||||
|
player.displayClientMessage( new TranslatableComponent( "advMode.notAllowed" ), true );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,12 +3,11 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.computer.blocks;
|
package dan200.computercraft.shared.computer.blocks;
|
||||||
|
|
||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.ComputerCraft;
|
||||||
import dan200.computercraft.core.computer.ComputerSide;
|
import dan200.computercraft.core.computer.ComputerSide;
|
||||||
import dan200.computercraft.shared.ComputerCraftRegistry;
|
import dan200.computercraft.shared.Registry;
|
||||||
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;
|
||||||
@@ -28,16 +27,35 @@ public class TileComputer extends TileComputerBase
|
|||||||
{
|
{
|
||||||
private ComputerProxy proxy;
|
private ComputerProxy proxy;
|
||||||
|
|
||||||
public TileComputer( ComputerFamily family, BlockEntityType<? extends TileComputer> type, BlockPos pos, BlockState state )
|
public TileComputer( BlockEntityType<? extends TileComputer> type, BlockPos pos, BlockState state, ComputerFamily family )
|
||||||
{
|
{
|
||||||
super( type, family, pos, state );
|
super( type, pos, state, family );
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isUsableByPlayer( Player player )
|
@Override
|
||||||
|
protected ServerComputer createComputer( int instanceID, int id )
|
||||||
|
{
|
||||||
|
ComputerFamily family = getFamily();
|
||||||
|
ServerComputer computer = new ServerComputer(
|
||||||
|
getLevel(), id, label, instanceID, family,
|
||||||
|
ComputerCraft.computerTermWidth,
|
||||||
|
ComputerCraft.computerTermHeight
|
||||||
|
);
|
||||||
|
computer.setPosition( getBlockPos() );
|
||||||
|
return computer;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isUsableByPlayer( Player player )
|
||||||
{
|
{
|
||||||
return isUsable( player, false );
|
return isUsable( player, false );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Direction getDirection()
|
||||||
|
{
|
||||||
|
return getBlockState().getValue( BlockComputer.FACING );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void updateBlockState( ComputerState newState )
|
protected void updateBlockState( ComputerState newState )
|
||||||
{
|
{
|
||||||
@@ -48,64 +66,21 @@ public class TileComputer extends TileComputerBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Direction getDirection()
|
|
||||||
{
|
|
||||||
return getBlockState().getValue( BlockComputer.FACING );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ComputerSide remapLocalSide( ComputerSide localSide )
|
protected ComputerSide remapLocalSide( ComputerSide localSide )
|
||||||
{
|
{
|
||||||
// For legacy reasons, computers invert the meaning of "left" and "right". A computer's front is facing
|
// For legacy reasons, computers invert the meaning of "left" and "right". A computer's front is facing
|
||||||
// towards you, but a turtle's front is facing the other way.
|
// towards you, but a turtle's front is facing the other way.
|
||||||
if( localSide == ComputerSide.RIGHT )
|
if( localSide == ComputerSide.RIGHT ) return ComputerSide.LEFT;
|
||||||
{
|
if( localSide == ComputerSide.LEFT ) return ComputerSide.RIGHT;
|
||||||
return ComputerSide.LEFT;
|
|
||||||
}
|
|
||||||
if( localSide == ComputerSide.LEFT )
|
|
||||||
{
|
|
||||||
return ComputerSide.RIGHT;
|
|
||||||
}
|
|
||||||
return localSide;
|
return localSide;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ServerComputer createComputer( int instanceID, int id )
|
|
||||||
{
|
|
||||||
ComputerFamily family = getFamily();
|
|
||||||
ServerComputer computer = new ServerComputer( getLevel(),
|
|
||||||
id, label,
|
|
||||||
instanceID,
|
|
||||||
family,
|
|
||||||
ComputerCraft.computerTermWidth,
|
|
||||||
ComputerCraft.computerTermHeight );
|
|
||||||
computer.setPosition( getBlockPos() );
|
|
||||||
return computer;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ComputerProxy createProxy()
|
|
||||||
{
|
|
||||||
if( proxy == null )
|
|
||||||
{
|
|
||||||
proxy = new ComputerProxy( () -> this )
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
protected TileComputerBase getTile()
|
|
||||||
{
|
|
||||||
return TileComputer.this;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return proxy;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public AbstractContainerMenu createMenu( int id, @Nonnull Inventory inventory, @Nonnull Player player )
|
public AbstractContainerMenu createMenu( int id, @Nonnull Inventory inventory, @Nonnull Player player )
|
||||||
{
|
{
|
||||||
return new ComputerMenuWithoutInventory( ComputerCraftRegistry.ModContainers.COMPUTER, id, inventory, this::isUsableByPlayer, createServerComputer(), getFamily() );
|
return new ComputerMenuWithoutInventory( Registry.ModContainers.COMPUTER, id, inventory, this::isUsableByPlayer, createServerComputer(), getFamily() );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.computer.blocks;
|
package dan200.computercraft.shared.computer.blocks;
|
||||||
|
|
||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.ComputerCraft;
|
||||||
@@ -28,6 +27,7 @@ import net.minecraft.network.FriendlyByteBuf;
|
|||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.network.chat.TextComponent;
|
import net.minecraft.network.chat.TextComponent;
|
||||||
import net.minecraft.network.chat.TranslatableComponent;
|
import net.minecraft.network.chat.TranslatableComponent;
|
||||||
|
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.world.InteractionHand;
|
import net.minecraft.world.InteractionHand;
|
||||||
import net.minecraft.world.InteractionResult;
|
import net.minecraft.world.InteractionResult;
|
||||||
@@ -35,9 +35,6 @@ import net.minecraft.world.Nameable;
|
|||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.Items;
|
import net.minecraft.world.item.Items;
|
||||||
import net.minecraft.world.level.Level;
|
|
||||||
import net.minecraft.world.level.block.Blocks;
|
|
||||||
import net.minecraft.world.level.block.RedStoneWireBlock;
|
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.phys.BlockHitResult;
|
import net.minecraft.world.phys.BlockHitResult;
|
||||||
@@ -46,26 +43,40 @@ import javax.annotation.Nonnull;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public abstract class TileComputerBase extends TileGeneric implements IComputerTile, IPeripheralTile, Nameable,
|
public abstract class TileComputerBase extends TileGeneric implements IComputerTile, IPeripheralTile, Nameable, ExtendedScreenHandlerFactory
|
||||||
ExtendedScreenHandlerFactory
|
|
||||||
{
|
{
|
||||||
private static final String NBT_ID = "ComputerId";
|
private static final String NBT_ID = "ComputerId";
|
||||||
private static final String NBT_LABEL = "Label";
|
private static final String NBT_LABEL = "Label";
|
||||||
private static final String NBT_ON = "On";
|
private static final String NBT_ON = "On";
|
||||||
private final ComputerFamily family;
|
|
||||||
protected String label = null;
|
|
||||||
boolean startOn = false;
|
|
||||||
private int instanceID = -1;
|
private int instanceID = -1;
|
||||||
private int computerID = -1;
|
private int computerID = -1;
|
||||||
|
protected String label = null;
|
||||||
private boolean on = false;
|
private boolean on = false;
|
||||||
|
boolean startOn = false;
|
||||||
private boolean fresh = false;
|
private boolean fresh = false;
|
||||||
|
|
||||||
public TileComputerBase( BlockEntityType<? extends TileGeneric> type, ComputerFamily family, BlockPos pos, BlockState state )
|
private int invalidSides = 0;
|
||||||
|
|
||||||
|
private final ComputerFamily family;
|
||||||
|
|
||||||
|
private ComputerProxy proxy;
|
||||||
|
|
||||||
|
public TileComputerBase( BlockEntityType<? extends TileGeneric> type, BlockPos pos, BlockState state, ComputerFamily family )
|
||||||
{
|
{
|
||||||
super( type, pos, state );
|
super( type, pos, state );
|
||||||
this.family = family;
|
this.family = family;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void unload()
|
||||||
|
{
|
||||||
|
if( instanceID >= 0 )
|
||||||
|
{
|
||||||
|
if( !getLevel().isClientSide ) ComputerCraft.serverComputerRegistry.remove( instanceID );
|
||||||
|
instanceID = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void destroy()
|
public void destroy()
|
||||||
{
|
{
|
||||||
@@ -82,16 +93,16 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
|||||||
unload();
|
unload();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void unload()
|
@Override
|
||||||
|
public void setRemoved()
|
||||||
{
|
{
|
||||||
if( instanceID >= 0 )
|
unload();
|
||||||
{
|
super.setRemoved();
|
||||||
if( !getLevel().isClientSide )
|
}
|
||||||
{
|
|
||||||
ComputerCraft.serverComputerRegistry.remove( instanceID );
|
protected boolean canNameWithTag( Player player )
|
||||||
}
|
{
|
||||||
instanceID = -1;
|
return false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@@ -104,8 +115,7 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
|||||||
// Label to rename computer
|
// Label to rename computer
|
||||||
if( !getLevel().isClientSide )
|
if( !getLevel().isClientSide )
|
||||||
{
|
{
|
||||||
setLabel( currentItem.getHoverName()
|
setLabel( currentItem.getHoverName().getString() );
|
||||||
.getString() );
|
|
||||||
currentItem.shrink( 1 );
|
currentItem.shrink( 1 );
|
||||||
}
|
}
|
||||||
return InteractionResult.SUCCESS;
|
return InteractionResult.SUCCESS;
|
||||||
@@ -124,162 +134,32 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
|||||||
return InteractionResult.PASS;
|
return InteractionResult.PASS;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean canNameWithTag( Player player )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ServerComputer createServerComputer()
|
|
||||||
{
|
|
||||||
if( getLevel().isClientSide )
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean changed = false;
|
|
||||||
if( instanceID < 0 )
|
|
||||||
{
|
|
||||||
instanceID = ComputerCraft.serverComputerRegistry.getUnusedInstanceID();
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
if( !ComputerCraft.serverComputerRegistry.contains( instanceID ) )
|
|
||||||
{
|
|
||||||
ServerComputer computer = createComputer( instanceID, computerID );
|
|
||||||
ComputerCraft.serverComputerRegistry.add( instanceID, computer );
|
|
||||||
fresh = true;
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
if( changed )
|
|
||||||
{
|
|
||||||
updateBlock();
|
|
||||||
updateInput();
|
|
||||||
}
|
|
||||||
return ComputerCraft.serverComputerRegistry.get( instanceID );
|
|
||||||
}
|
|
||||||
|
|
||||||
public ServerComputer getServerComputer()
|
|
||||||
{
|
|
||||||
return getLevel().isClientSide ? null : ComputerCraft.serverComputerRegistry.get( instanceID );
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract ServerComputer createComputer( int instanceID, int id );
|
|
||||||
|
|
||||||
public void updateInput()
|
|
||||||
{
|
|
||||||
if( getLevel() == null || getLevel().isClientSide )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update all sides
|
|
||||||
ServerComputer computer = getServerComputer();
|
|
||||||
if( computer == null )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockPos pos = computer.getPosition();
|
|
||||||
for( Direction dir : DirectionUtil.FACINGS )
|
|
||||||
{
|
|
||||||
updateSideInput( computer, dir, pos.relative( dir ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateSideInput( ServerComputer computer, Direction dir, BlockPos offset )
|
|
||||||
{
|
|
||||||
Direction offsetSide = dir.getOpposite();
|
|
||||||
ComputerSide localDir = remapToLocalSide( dir );
|
|
||||||
|
|
||||||
computer.setRedstoneInput( localDir, getRedstoneInput( level, offset, dir ) );
|
|
||||||
computer.setBundledRedstoneInput( localDir, BundledRedstone.getOutput( getLevel(), offset, offsetSide ) );
|
|
||||||
if( !isPeripheralBlockedOnSide( localDir ) )
|
|
||||||
{
|
|
||||||
IPeripheral peripheral = Peripherals.getPeripheral( getLevel(), offset, offsetSide );
|
|
||||||
computer.setPeripheral( localDir, peripheral );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ComputerSide remapToLocalSide( Direction globalSide )
|
|
||||||
{
|
|
||||||
return remapLocalSide( DirectionUtil.toLocal( getDirection(), globalSide ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the redstone input for an adjacent block.
|
|
||||||
*
|
|
||||||
* @param world The world we exist in
|
|
||||||
* @param pos The position of the neighbour
|
|
||||||
* @param side The side we are reading from
|
|
||||||
* @return The effective redstone power
|
|
||||||
*/
|
|
||||||
protected static int getRedstoneInput( Level world, BlockPos pos, Direction side )
|
|
||||||
{
|
|
||||||
int power = world.getSignal( pos, side );
|
|
||||||
if( power >= 15 )
|
|
||||||
{
|
|
||||||
return power;
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockState neighbour = world.getBlockState( pos );
|
|
||||||
return neighbour.getBlock() == Blocks.REDSTONE_WIRE ? Math.max( power, neighbour.getValue( RedStoneWireBlock.POWER ) ) : power;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean isPeripheralBlockedOnSide( ComputerSide localSide )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ComputerSide remapLocalSide( ComputerSide localSide )
|
|
||||||
{
|
|
||||||
return localSide;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract Direction getDirection();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNeighbourChange( @Nonnull BlockPos neighbour )
|
public void onNeighbourChange( @Nonnull BlockPos neighbour )
|
||||||
{
|
{
|
||||||
updateInput( neighbour );
|
updateInputAt( neighbour );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNeighbourTileEntityChange( @Nonnull BlockPos neighbour )
|
public void onNeighbourTileEntityChange( @Nonnull BlockPos neighbour )
|
||||||
{
|
{
|
||||||
updateInput( neighbour );
|
updateInputAt( neighbour );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
protected void serverTick()
|
||||||
protected void readDescription( @Nonnull CompoundTag nbt )
|
|
||||||
{
|
|
||||||
super.readDescription( nbt );
|
|
||||||
label = nbt.contains( NBT_LABEL ) ? nbt.getString( NBT_LABEL ) : null;
|
|
||||||
computerID = nbt.contains( NBT_ID ) ? nbt.getInt( NBT_ID ) : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void writeDescription( @Nonnull CompoundTag nbt )
|
|
||||||
{
|
|
||||||
super.writeDescription( nbt );
|
|
||||||
if( label != null )
|
|
||||||
{
|
|
||||||
nbt.putString( NBT_LABEL, label );
|
|
||||||
}
|
|
||||||
if( computerID >= 0 )
|
|
||||||
{
|
|
||||||
nbt.putInt( NBT_ID, computerID );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void serverTick()
|
|
||||||
{
|
{
|
||||||
ServerComputer computer = createServerComputer();
|
ServerComputer computer = createServerComputer();
|
||||||
if( computer == null )
|
|
||||||
|
if( invalidSides != 0 )
|
||||||
{
|
{
|
||||||
return;
|
for( Direction direction : DirectionUtil.FACINGS )
|
||||||
|
{
|
||||||
|
if( (invalidSides & (1 << direction.ordinal())) != 0 ) refreshPeripheral( computer, direction );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the computer isn't on and should be, then turn it on
|
// If the computer isn't on and should be, then turn it on
|
||||||
if( startOn || fresh && on )
|
if( startOn || (fresh && on) )
|
||||||
{
|
{
|
||||||
computer.turnOn();
|
computer.turnOn();
|
||||||
startOn = false;
|
startOn = false;
|
||||||
@@ -292,33 +172,28 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
|||||||
label = computer.getLabel();
|
label = computer.getLabel();
|
||||||
on = computer.isOn();
|
on = computer.isOn();
|
||||||
|
|
||||||
if( computer.hasOutputChanged() )
|
|
||||||
{
|
|
||||||
updateOutput();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the block state if needed. We don't fire a block update intentionally,
|
// Update the block state if needed. We don't fire a block update intentionally,
|
||||||
// as this only really is needed on the client side.
|
// as this only really is needed on the client side.
|
||||||
updateBlockState( computer.getState() );
|
updateBlockState( computer.getState() );
|
||||||
|
|
||||||
if( computer.hasOutputChanged() )
|
// TODO: This should ideally be split up into label/id/on (which should save NBT and sync to client) and
|
||||||
{
|
// redstone (which should update outputs)
|
||||||
updateOutput();
|
if( computer.hasOutputChanged() ) updateOutput();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateOutput()
|
|
||||||
{
|
|
||||||
// Update redstone
|
|
||||||
updateBlock();
|
|
||||||
for( Direction dir : DirectionUtil.FACINGS )
|
|
||||||
{
|
|
||||||
RedstoneUtil.propagateRedstoneOutput( getLevel(), getBlockPos(), dir );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void updateBlockState( ComputerState newState );
|
protected abstract void updateBlockState( ComputerState newState );
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveAdditional( @Nonnull CompoundTag nbt )
|
||||||
|
{
|
||||||
|
// Save ID, label and power state
|
||||||
|
if( computerID >= 0 ) nbt.putInt( NBT_ID, computerID );
|
||||||
|
if( label != null ) nbt.putString( NBT_LABEL, label );
|
||||||
|
nbt.putBoolean( NBT_ON, on );
|
||||||
|
|
||||||
|
super.saveAdditional( nbt );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load( @Nonnull CompoundTag nbt )
|
public void load( @Nonnull CompoundTag nbt )
|
||||||
{
|
{
|
||||||
@@ -330,116 +205,137 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
|||||||
on = startOn = nbt.getBoolean( NBT_ON );
|
on = startOn = nbt.getBoolean( NBT_ON );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
protected boolean isPeripheralBlockedOnSide( ComputerSide localSide )
|
||||||
public void saveAdditional( @Nonnull CompoundTag nbt )
|
|
||||||
{
|
{
|
||||||
// Save ID, label and power state
|
return false;
|
||||||
if( computerID >= 0 )
|
|
||||||
{
|
|
||||||
nbt.putInt( NBT_ID, computerID );
|
|
||||||
}
|
|
||||||
if( label != null )
|
|
||||||
{
|
|
||||||
nbt.putString( NBT_LABEL, label );
|
|
||||||
}
|
|
||||||
nbt.putBoolean( NBT_ON, on );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
protected abstract Direction getDirection();
|
||||||
public void setRemoved()
|
|
||||||
|
protected ComputerSide remapToLocalSide( Direction globalSide )
|
||||||
{
|
{
|
||||||
unload();
|
return remapLocalSide( DirectionUtil.toLocal( getDirection(), globalSide ) );
|
||||||
super.setRemoved();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateInput( BlockPos neighbour )
|
protected ComputerSide remapLocalSide( ComputerSide localSide )
|
||||||
{
|
{
|
||||||
if( getLevel() == null || this.level.isClientSide )
|
return localSide;
|
||||||
{
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
private void updateRedstoneInput( @Nonnull ServerComputer computer, Direction dir, BlockPos targetPos )
|
||||||
|
{
|
||||||
|
Direction offsetSide = dir.getOpposite();
|
||||||
|
ComputerSide localDir = remapToLocalSide( dir );
|
||||||
|
|
||||||
|
computer.setRedstoneInput( localDir, RedstoneUtil.getRedstoneInput( level, targetPos, dir ) );
|
||||||
|
computer.setBundledRedstoneInput( localDir, BundledRedstone.getOutput( getLevel(), targetPos, offsetSide ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refreshPeripheral( @Nonnull ServerComputer computer, Direction dir )
|
||||||
|
{
|
||||||
|
invalidSides &= ~(1 << dir.ordinal());
|
||||||
|
|
||||||
|
ComputerSide localDir = remapToLocalSide( dir );
|
||||||
|
if( isPeripheralBlockedOnSide( localDir ) ) return;
|
||||||
|
|
||||||
|
Direction offsetSide = dir.getOpposite();
|
||||||
|
IPeripheral peripheral = Peripherals.getPeripheral( getLevel(), getBlockPos().relative( dir ), offsetSide );
|
||||||
|
computer.setPeripheral( localDir, peripheral );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateInputsImmediately()
|
||||||
|
{
|
||||||
ServerComputer computer = getServerComputer();
|
ServerComputer computer = getServerComputer();
|
||||||
if( computer == null )
|
if( computer != null ) updateInputsImmediately( computer );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update all redstone and peripherals.
|
||||||
|
*
|
||||||
|
* This should only be really be called when the computer is being ticked (though there are some cases where it
|
||||||
|
* won't be), as peripheral scanning requires adjacent tiles to be in a "correct" state - which may not be the case
|
||||||
|
* if they're still updating!
|
||||||
|
*
|
||||||
|
* @param computer The current computer instance.
|
||||||
|
*/
|
||||||
|
private void updateInputsImmediately( @Nonnull ServerComputer computer )
|
||||||
|
{
|
||||||
|
BlockPos pos = getBlockPos();
|
||||||
|
for( Direction dir : DirectionUtil.FACINGS )
|
||||||
{
|
{
|
||||||
return;
|
updateRedstoneInput( computer, dir, pos.relative( dir ) );
|
||||||
|
refreshPeripheral( computer, dir );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateInputAt( @Nonnull BlockPos neighbour )
|
||||||
|
{
|
||||||
|
ServerComputer computer = getServerComputer();
|
||||||
|
if( computer == null ) return;
|
||||||
|
|
||||||
for( Direction dir : DirectionUtil.FACINGS )
|
for( Direction dir : DirectionUtil.FACINGS )
|
||||||
{
|
{
|
||||||
BlockPos offset = worldPosition.relative( dir );
|
BlockPos offset = getBlockPos().relative( dir );
|
||||||
if( offset.equals( neighbour ) )
|
if( offset.equals( neighbour ) )
|
||||||
{
|
{
|
||||||
updateSideInput( computer, dir, offset );
|
updateRedstoneInput( computer, dir, offset );
|
||||||
|
invalidSides |= 1 << dir.ordinal();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the position is not any adjacent one, update all inputs.
|
// If the position is not any adjacent one, update all inputs. This is pretty terrible, but some redstone mods
|
||||||
this.updateInput();
|
// handle this incorrectly.
|
||||||
|
BlockPos pos = getBlockPos();
|
||||||
|
for( Direction dir : DirectionUtil.FACINGS ) updateRedstoneInput( computer, dir, pos.relative( dir ) );
|
||||||
|
invalidSides = (1 << 6) - 1; // Mark all peripherals as dirty.
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateInput( Direction dir )
|
/**
|
||||||
|
* Update the block's state and propagate redstone output.
|
||||||
|
*/
|
||||||
|
public void updateOutput()
|
||||||
{
|
{
|
||||||
if( getLevel() == null || this.level.isClientSide )
|
updateBlock();
|
||||||
|
for( Direction dir : DirectionUtil.FACINGS )
|
||||||
{
|
{
|
||||||
return;
|
RedstoneUtil.propagateRedstoneOutput( getLevel(), getBlockPos(), dir );
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerComputer computer = getServerComputer();
|
|
||||||
if( computer == null )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
updateSideInput( computer, dir, worldPosition.relative( dir ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract ServerComputer createComputer( int instanceID, int id );
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final int getComputerID()
|
public final int getComputerID()
|
||||||
{
|
{
|
||||||
return computerID;
|
return computerID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void setComputerID( int id )
|
|
||||||
{
|
|
||||||
if( this.level.isClientSide || computerID == id )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
computerID = id;
|
|
||||||
ServerComputer computer = getServerComputer();
|
|
||||||
if( computer != null )
|
|
||||||
{
|
|
||||||
computer.setID( computerID );
|
|
||||||
}
|
|
||||||
setChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final String getLabel()
|
public final String getLabel()
|
||||||
{
|
{
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Networking stuff
|
@Override
|
||||||
|
public final void setComputerID( int id )
|
||||||
|
{
|
||||||
|
if( getLevel().isClientSide || computerID == id ) return;
|
||||||
|
|
||||||
|
computerID = id;
|
||||||
|
ServerComputer computer = getServerComputer();
|
||||||
|
if( computer != null ) computer.setID( computerID );
|
||||||
|
setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void setLabel( String label )
|
public final void setLabel( String label )
|
||||||
{
|
{
|
||||||
if( this.level.isClientSide || Objects.equals( this.label, label ) )
|
if( getLevel().isClientSide || Objects.equals( this.label, label ) ) return;
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.label = label;
|
this.label = label;
|
||||||
ServerComputer computer = getServerComputer();
|
ServerComputer computer = getServerComputer();
|
||||||
if( computer != null )
|
if( computer != null ) computer.setLabel( label );
|
||||||
{
|
|
||||||
computer.setLabel( label );
|
|
||||||
}
|
|
||||||
setChanged();
|
setChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -449,6 +345,64 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
|||||||
return family;
|
return family;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
public ServerComputer createServerComputer()
|
||||||
|
{
|
||||||
|
if( getLevel().isClientSide ) throw new IllegalStateException( "Cannot access server computer on the client." );
|
||||||
|
|
||||||
|
boolean changed = false;
|
||||||
|
if( instanceID < 0 )
|
||||||
|
{
|
||||||
|
instanceID = ComputerCraft.serverComputerRegistry.getUnusedInstanceID();
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerComputer computer = ComputerCraft.serverComputerRegistry.get( instanceID );
|
||||||
|
if( computer == null )
|
||||||
|
{
|
||||||
|
computer = createComputer( instanceID, computerID );
|
||||||
|
ComputerCraft.serverComputerRegistry.add( instanceID, computer );
|
||||||
|
fresh = true;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( changed ) updateInputsImmediately( computer );
|
||||||
|
return computer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public ServerComputer getServerComputer()
|
||||||
|
{
|
||||||
|
return getLevel().isClientSide ? null : ComputerCraft.serverComputerRegistry.get( instanceID );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Networking stuff
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public final ClientboundBlockEntityDataPacket getUpdatePacket()
|
||||||
|
{
|
||||||
|
return ClientboundBlockEntityDataPacket.create( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public CompoundTag getUpdateTag()
|
||||||
|
{
|
||||||
|
// We need this for pick block on the client side.
|
||||||
|
CompoundTag nbt = super.getUpdateTag();
|
||||||
|
if( label != null ) nbt.putString( NBT_LABEL, label );
|
||||||
|
if( computerID >= 0 ) nbt.putInt( NBT_ID, computerID );
|
||||||
|
return nbt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Override
|
||||||
|
// public void handleUpdateTag( @Nonnull CompoundTag nbt )
|
||||||
|
// {
|
||||||
|
// label = nbt.contains( NBT_LABEL ) ? nbt.getString( NBT_LABEL ) : null;
|
||||||
|
// computerID = nbt.contains( NBT_ID ) ? nbt.getInt( NBT_ID ) : -1;
|
||||||
|
// }
|
||||||
|
|
||||||
protected void transferStateFrom( TileComputerBase copy )
|
protected void transferStateFrom( TileComputerBase copy )
|
||||||
{
|
{
|
||||||
if( copy.computerID != computerID || copy.instanceID != instanceID )
|
if( copy.computerID != computerID || copy.instanceID != instanceID )
|
||||||
@@ -468,17 +422,17 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
|||||||
@Override
|
@Override
|
||||||
public IPeripheral getPeripheral( Direction side )
|
public IPeripheral getPeripheral( Direction side )
|
||||||
{
|
{
|
||||||
return new ComputerPeripheral( "computer", createProxy() );
|
if( proxy == null ) proxy = new ComputerProxy( () -> this );
|
||||||
|
return new ComputerPeripheral( "computer", proxy );
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract ComputerProxy createProxy();
|
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public Component getName()
|
public Component getName()
|
||||||
{
|
{
|
||||||
return hasCustomName() ? new TextComponent( label ) : new TranslatableComponent( getBlockState().getBlock()
|
return hasCustomName()
|
||||||
.getDescriptionId() );
|
? new TextComponent( label )
|
||||||
|
: new TranslatableComponent( getBlockState().getBlock().getDescriptionId() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -487,13 +441,6 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
|||||||
return !Strings.isNullOrEmpty( label );
|
return !Strings.isNullOrEmpty( label );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public Component getDisplayName()
|
|
||||||
{
|
|
||||||
return Nameable.super.getDisplayName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public Component getCustomName()
|
public Component getCustomName()
|
||||||
@@ -501,6 +448,13 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
|||||||
return hasCustomName() ? new TextComponent( label ) : null;
|
return hasCustomName() ? new TextComponent( label ) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public Component getDisplayName()
|
||||||
|
{
|
||||||
|
return Nameable.super.getDisplayName();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeScreenOpeningData( ServerPlayer serverPlayerEntity, FriendlyByteBuf packetByteBuf )
|
public void writeScreenOpeningData( ServerPlayer serverPlayerEntity, FriendlyByteBuf packetByteBuf )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.computer.core;
|
package dan200.computercraft.shared.computer.core;
|
||||||
|
|
||||||
import dan200.computercraft.shared.common.ClientTerminal;
|
import dan200.computercraft.shared.common.ClientTerminal;
|
||||||
@@ -19,7 +18,6 @@ public class ClientComputer extends ClientTerminal implements IComputer
|
|||||||
private boolean blinking = false;
|
private boolean blinking = false;
|
||||||
private CompoundTag userData = null;
|
private CompoundTag userData = null;
|
||||||
|
|
||||||
|
|
||||||
public ClientComputer( int instanceID )
|
public ClientComputer( int instanceID )
|
||||||
{
|
{
|
||||||
super( false );
|
super( false );
|
||||||
@@ -45,6 +43,18 @@ public class ClientComputer extends ClientTerminal implements IComputer
|
|||||||
return instanceID;
|
return instanceID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOn()
|
||||||
|
{
|
||||||
|
return on;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCursorDisplayed()
|
||||||
|
{
|
||||||
|
return on && blinking;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void turnOn()
|
public void turnOn()
|
||||||
{
|
{
|
||||||
@@ -73,24 +83,10 @@ public class ClientComputer extends ClientTerminal implements IComputer
|
|||||||
NetworkHandler.sendToServer( new QueueEventServerMessage( instanceID, event, arguments ) );
|
NetworkHandler.sendToServer( new QueueEventServerMessage( instanceID, event, arguments ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isOn()
|
|
||||||
{
|
|
||||||
return on;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCursorDisplayed()
|
|
||||||
{
|
|
||||||
return on && blinking;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void keyDown( int key, boolean repeat )
|
public void keyDown( int key, boolean repeat )
|
||||||
{
|
{
|
||||||
NetworkHandler.sendToServer( new KeyEventServerMessage( instanceID,
|
NetworkHandler.sendToServer( new KeyEventServerMessage( instanceID, repeat ? KeyEventServerMessage.TYPE_REPEAT : KeyEventServerMessage.TYPE_DOWN, key ) );
|
||||||
repeat ? KeyEventServerMessage.TYPE_REPEAT : KeyEventServerMessage.TYPE_DOWN,
|
|
||||||
key ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -3,10 +3,11 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.computer.core;
|
package dan200.computercraft.shared.computer.core;
|
||||||
|
|
||||||
public enum ComputerFamily
|
public enum ComputerFamily
|
||||||
{
|
{
|
||||||
NORMAL, ADVANCED, COMMAND
|
NORMAL,
|
||||||
|
ADVANCED,
|
||||||
|
COMMAND
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.computer.core;
|
package dan200.computercraft.shared.computer.core;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -13,23 +12,15 @@ import java.util.Random;
|
|||||||
|
|
||||||
public class ComputerRegistry<T extends IComputer>
|
public class ComputerRegistry<T extends IComputer>
|
||||||
{
|
{
|
||||||
private final Map<Integer, T> computers;
|
private final Map<Integer, T> computers = new HashMap<>();
|
||||||
private int nextUnusedInstanceID;
|
private int nextUnusedInstanceID;
|
||||||
private int sessionID;
|
private int sessionID;
|
||||||
|
|
||||||
protected ComputerRegistry()
|
protected ComputerRegistry()
|
||||||
{
|
{
|
||||||
computers = new HashMap<>();
|
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reset()
|
|
||||||
{
|
|
||||||
computers.clear();
|
|
||||||
nextUnusedInstanceID = 0;
|
|
||||||
sessionID = new Random().nextInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSessionID()
|
public int getSessionID()
|
||||||
{
|
{
|
||||||
return sessionID;
|
return sessionID;
|
||||||
@@ -76,4 +67,11 @@ public class ComputerRegistry<T extends IComputer>
|
|||||||
{
|
{
|
||||||
computers.remove( instanceID );
|
computers.remove( instanceID );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void reset()
|
||||||
|
{
|
||||||
|
computers.clear();
|
||||||
|
nextUnusedInstanceID = 0;
|
||||||
|
sessionID = new Random().nextInt();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.computer.core;
|
package dan200.computercraft.shared.computer.core;
|
||||||
|
|
||||||
import net.minecraft.util.StringRepresentable;
|
import net.minecraft.util.StringRepresentable;
|
||||||
@@ -12,7 +11,9 @@ import javax.annotation.Nonnull;
|
|||||||
|
|
||||||
public enum ComputerState implements StringRepresentable
|
public enum ComputerState implements StringRepresentable
|
||||||
{
|
{
|
||||||
OFF( "off", "" ), ON( "on", "_on" ), BLINKING( "blinking", "_blink" );
|
OFF( "off", "" ),
|
||||||
|
ON( "on", "_on" ),
|
||||||
|
BLINKING( "blinking", "_blink" );
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
private final String texture;
|
private final String texture;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.computer.core;
|
package dan200.computercraft.shared.computer.core;
|
||||||
|
|
||||||
import dan200.computercraft.shared.common.ITerminal;
|
import dan200.computercraft.shared.common.ITerminal;
|
||||||
@@ -12,30 +11,27 @@ public interface IComputer extends ITerminal, InputHandler
|
|||||||
{
|
{
|
||||||
int getInstanceID();
|
int getInstanceID();
|
||||||
|
|
||||||
|
boolean isOn();
|
||||||
|
|
||||||
|
boolean isCursorDisplayed();
|
||||||
|
|
||||||
void turnOn();
|
void turnOn();
|
||||||
|
|
||||||
void shutdown();
|
void shutdown();
|
||||||
|
|
||||||
void reboot();
|
void reboot();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void queueEvent( String event, Object[] arguments );
|
||||||
|
|
||||||
default void queueEvent( String event )
|
default void queueEvent( String event )
|
||||||
{
|
{
|
||||||
queueEvent( event, null );
|
queueEvent( event, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
void queueEvent( String event, Object[] arguments );
|
|
||||||
|
|
||||||
default ComputerState getState()
|
default ComputerState getState()
|
||||||
{
|
{
|
||||||
if( !isOn() )
|
if( !isOn() ) return ComputerState.OFF;
|
||||||
{
|
|
||||||
return ComputerState.OFF;
|
|
||||||
}
|
|
||||||
return isCursorDisplayed() ? ComputerState.BLINKING : ComputerState.ON;
|
return isCursorDisplayed() ? ComputerState.BLINKING : ComputerState.ON;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isOn();
|
|
||||||
|
|
||||||
boolean isCursorDisplayed();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,12 +3,12 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.computer.core;
|
package dan200.computercraft.shared.computer.core;
|
||||||
|
|
||||||
import dan200.computercraft.shared.computer.upload.FileSlice;
|
import dan200.computercraft.shared.computer.upload.FileSlice;
|
||||||
import dan200.computercraft.shared.computer.upload.FileUpload;
|
import dan200.computercraft.shared.computer.upload.FileUpload;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@@ -16,9 +16,9 @@ import java.util.List;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An instance of {@link Container} which provides a computer. You should implement this if you provide custom computers/GUIs to interact with them.
|
* An instance of {@link AbstractContainerMenu} which provides a computer. You should implement this
|
||||||
|
* if you provide custom computers/GUIs to interact with them.
|
||||||
*/
|
*/
|
||||||
//@FunctionalInterface
|
|
||||||
public interface IContainerComputer
|
public interface IContainerComputer
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.computer.core;
|
package dan200.computercraft.shared.computer.core;
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.ints.IntIterator;
|
import it.unimi.dsi.fastutil.ints.IntIterator;
|
||||||
@@ -11,7 +10,8 @@ import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
|||||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An {@link InputHandler} which keeps track of the current key and mouse state, and releases them when the container is closed.
|
* An {@link InputHandler} which keeps track of the current key and mouse state, and releases them when the container
|
||||||
|
* is closed.
|
||||||
*/
|
*/
|
||||||
public class InputState implements InputHandler
|
public class InputState implements InputHandler
|
||||||
{
|
{
|
||||||
@@ -31,10 +31,7 @@ public class InputState implements InputHandler
|
|||||||
public void queueEvent( String event, Object[] arguments )
|
public void queueEvent( String event, Object[] arguments )
|
||||||
{
|
{
|
||||||
IComputer computer = owner.getComputer();
|
IComputer computer = owner.getComputer();
|
||||||
if( computer != null )
|
if( computer != null ) computer.queueEvent( event, arguments );
|
||||||
{
|
|
||||||
computer.queueEvent( event, arguments );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -42,10 +39,7 @@ public class InputState implements InputHandler
|
|||||||
{
|
{
|
||||||
keysDown.add( key );
|
keysDown.add( key );
|
||||||
IComputer computer = owner.getComputer();
|
IComputer computer = owner.getComputer();
|
||||||
if( computer != null )
|
if( computer != null ) computer.keyDown( key, repeat );
|
||||||
{
|
|
||||||
computer.keyDown( key, repeat );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -53,10 +47,7 @@ public class InputState implements InputHandler
|
|||||||
{
|
{
|
||||||
keysDown.remove( key );
|
keysDown.remove( key );
|
||||||
IComputer computer = owner.getComputer();
|
IComputer computer = owner.getComputer();
|
||||||
if( computer != null )
|
if( computer != null ) computer.keyUp( key );
|
||||||
{
|
|
||||||
computer.keyUp( key );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -67,10 +58,7 @@ public class InputState implements InputHandler
|
|||||||
lastMouseDown = button;
|
lastMouseDown = button;
|
||||||
|
|
||||||
IComputer computer = owner.getComputer();
|
IComputer computer = owner.getComputer();
|
||||||
if( computer != null )
|
if( computer != null ) computer.mouseClick( button, x, y );
|
||||||
{
|
|
||||||
computer.mouseClick( button, x, y );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -81,10 +69,7 @@ public class InputState implements InputHandler
|
|||||||
lastMouseDown = -1;
|
lastMouseDown = -1;
|
||||||
|
|
||||||
IComputer computer = owner.getComputer();
|
IComputer computer = owner.getComputer();
|
||||||
if( computer != null )
|
if( computer != null ) computer.mouseUp( button, x, y );
|
||||||
{
|
|
||||||
computer.mouseUp( button, x, y );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -95,10 +80,7 @@ public class InputState implements InputHandler
|
|||||||
lastMouseDown = button;
|
lastMouseDown = button;
|
||||||
|
|
||||||
IComputer computer = owner.getComputer();
|
IComputer computer = owner.getComputer();
|
||||||
if( computer != null )
|
if( computer != null ) computer.mouseDrag( button, x, y );
|
||||||
{
|
|
||||||
computer.mouseDrag( button, x, y );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -108,10 +90,7 @@ public class InputState implements InputHandler
|
|||||||
lastMouseY = y;
|
lastMouseY = y;
|
||||||
|
|
||||||
IComputer computer = owner.getComputer();
|
IComputer computer = owner.getComputer();
|
||||||
if( computer != null )
|
if( computer != null ) computer.mouseScroll( direction, x, y );
|
||||||
{
|
|
||||||
computer.mouseScroll( direction, x, y );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close()
|
public void close()
|
||||||
@@ -120,15 +99,9 @@ public class InputState implements InputHandler
|
|||||||
if( computer != null )
|
if( computer != null )
|
||||||
{
|
{
|
||||||
IntIterator keys = keysDown.iterator();
|
IntIterator keys = keysDown.iterator();
|
||||||
while( keys.hasNext() )
|
while( keys.hasNext() ) computer.keyUp( keys.nextInt() );
|
||||||
{
|
|
||||||
computer.keyUp( keys.nextInt() );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( lastMouseDown != -1 )
|
if( lastMouseDown != -1 ) computer.mouseUp( lastMouseDown, lastMouseX, lastMouseY );
|
||||||
{
|
|
||||||
computer.mouseUp( lastMouseDown, lastMouseX, lastMouseY );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
keysDown.clear();
|
keysDown.clear();
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.computer.core;
|
package dan200.computercraft.shared.computer.core;
|
||||||
|
|
||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.ComputerCraft;
|
||||||
@@ -24,6 +23,7 @@ import dan200.computercraft.shared.network.client.ComputerDataClientMessage;
|
|||||||
import dan200.computercraft.shared.network.client.ComputerDeletedClientMessage;
|
import dan200.computercraft.shared.network.client.ComputerDeletedClientMessage;
|
||||||
import dan200.computercraft.shared.network.client.ComputerTerminalClientMessage;
|
import dan200.computercraft.shared.network.client.ComputerTerminalClientMessage;
|
||||||
import me.shedaniel.cloth.api.utils.v1.GameInstanceUtils;
|
import me.shedaniel.cloth.api.utils.v1.GameInstanceUtils;
|
||||||
|
import net.minecraft.SharedConstants;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
@@ -38,32 +38,27 @@ import java.io.InputStream;
|
|||||||
public class ServerComputer extends ServerTerminal implements IComputer, IComputerEnvironment
|
public class ServerComputer extends ServerTerminal implements IComputer, IComputerEnvironment
|
||||||
{
|
{
|
||||||
private final int instanceID;
|
private final int instanceID;
|
||||||
|
|
||||||
|
private Level level;
|
||||||
|
private BlockPos position;
|
||||||
|
|
||||||
private final ComputerFamily family;
|
private final ComputerFamily family;
|
||||||
private final Computer computer;
|
private final Computer computer;
|
||||||
private Level world;
|
|
||||||
private BlockPos position;
|
|
||||||
private CompoundTag userData;
|
private CompoundTag userData;
|
||||||
private boolean changed;
|
private boolean changed;
|
||||||
|
|
||||||
private boolean changedLastFrame;
|
private boolean changedLastFrame;
|
||||||
private int ticksSincePing;
|
private int ticksSincePing;
|
||||||
|
|
||||||
public ServerComputer( Level world, int computerID, String label, int instanceID, ComputerFamily family, int terminalWidth, int terminalHeight )
|
public ServerComputer( Level level, int computerID, String label, int instanceID, ComputerFamily family, int terminalWidth, int terminalHeight )
|
||||||
{
|
{
|
||||||
super( family != ComputerFamily.NORMAL, terminalWidth, terminalHeight );
|
super( family != ComputerFamily.NORMAL, terminalWidth, terminalHeight );
|
||||||
this.instanceID = instanceID;
|
this.instanceID = instanceID;
|
||||||
|
|
||||||
this.world = world;
|
this.level = level;
|
||||||
position = null;
|
|
||||||
|
|
||||||
this.family = family;
|
this.family = family;
|
||||||
computer = new Computer( this, getTerminal(), computerID );
|
computer = new Computer( this, getTerminal(), computerID );
|
||||||
computer.setLabel( label );
|
computer.setLabel( label );
|
||||||
userData = null;
|
|
||||||
changed = false;
|
|
||||||
|
|
||||||
changedLastFrame = false;
|
|
||||||
ticksSincePing = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ComputerFamily getFamily()
|
public ComputerFamily getFamily()
|
||||||
@@ -71,14 +66,14 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput
|
|||||||
return family;
|
return family;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Level getWorld()
|
public Level getLevel()
|
||||||
{
|
{
|
||||||
return world;
|
return level;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setWorld( Level world )
|
public void setLevel( Level level )
|
||||||
{
|
{
|
||||||
this.world = world;
|
this.level = level;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockPos getPosition()
|
public BlockPos getPosition()
|
||||||
@@ -123,6 +118,11 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput
|
|||||||
return ticksSincePing > 100;
|
return ticksSincePing > 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasOutputChanged()
|
||||||
|
{
|
||||||
|
return changedLastFrame;
|
||||||
|
}
|
||||||
|
|
||||||
public void unload()
|
public void unload()
|
||||||
{
|
{
|
||||||
computer.unload();
|
computer.unload();
|
||||||
@@ -142,86 +142,94 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput
|
|||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void broadcastState( boolean force )
|
|
||||||
{
|
|
||||||
if( hasOutputChanged() || force )
|
|
||||||
{
|
|
||||||
// Send computer state to all clients
|
|
||||||
MinecraftServer server = GameInstanceUtils.getServer();
|
|
||||||
if( server != null )
|
|
||||||
{
|
|
||||||
NetworkHandler.sendToAllPlayers( server, createComputerPacket() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( hasTerminalChanged() || force )
|
|
||||||
{
|
|
||||||
MinecraftServer server = GameInstanceUtils.getServer();
|
|
||||||
if( server != null )
|
|
||||||
{
|
|
||||||
// Send terminal state to clients who are currently interacting with the computer.
|
|
||||||
|
|
||||||
NetworkMessage packet = null;
|
|
||||||
for( Player player : server.getPlayerList()
|
|
||||||
.getPlayers() )
|
|
||||||
{
|
|
||||||
if( isInteracting( player ) )
|
|
||||||
{
|
|
||||||
if( packet == null )
|
|
||||||
{
|
|
||||||
packet = createTerminalPacket();
|
|
||||||
}
|
|
||||||
NetworkHandler.sendToPlayer( player, packet );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasOutputChanged()
|
|
||||||
{
|
|
||||||
return changedLastFrame;
|
|
||||||
}
|
|
||||||
|
|
||||||
private NetworkMessage createComputerPacket()
|
private NetworkMessage createComputerPacket()
|
||||||
{
|
{
|
||||||
return new ComputerDataClientMessage( this );
|
return new ComputerDataClientMessage( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isInteracting( Player player )
|
|
||||||
{
|
|
||||||
return getContainer( player ) != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected NetworkMessage createTerminalPacket()
|
protected NetworkMessage createTerminalPacket()
|
||||||
{
|
{
|
||||||
return new ComputerTerminalClientMessage( getInstanceID(), write() );
|
return new ComputerTerminalClientMessage( getInstanceID(), write() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
public void broadcastState( boolean force )
|
||||||
public IContainerComputer getContainer( Player player )
|
|
||||||
{
|
{
|
||||||
if( player == null )
|
if( hasOutputChanged() || force )
|
||||||
{
|
{
|
||||||
return null;
|
// Send computer state to all clients
|
||||||
|
NetworkHandler.sendToAllPlayers( createComputerPacket() );
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractContainerMenu container = player.containerMenu;
|
if( hasTerminalChanged() || force )
|
||||||
if( !(container instanceof IContainerComputer) )
|
|
||||||
{
|
{
|
||||||
return null;
|
// Send terminal state to clients who are currently interacting with the computer.
|
||||||
}
|
MinecraftServer server = GameInstanceUtils.getServer();
|
||||||
|
|
||||||
IContainerComputer computerContainer = (IContainerComputer) container;
|
NetworkMessage packet = null;
|
||||||
return computerContainer.getComputer() != this ? null : computerContainer;
|
for( Player player : server.getPlayerList().getPlayers() )
|
||||||
|
{
|
||||||
|
if( isInteracting( player ) )
|
||||||
|
{
|
||||||
|
if( packet == null ) packet = createTerminalPacket();
|
||||||
|
NetworkHandler.sendToPlayer( player, packet );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void sendComputerState( Player player )
|
||||||
|
{
|
||||||
|
// Send state to client
|
||||||
|
NetworkHandler.sendToPlayer( player, createComputerPacket() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendTerminalState( Player player )
|
||||||
|
{
|
||||||
|
// Send terminal state to client
|
||||||
|
NetworkHandler.sendToPlayer( player, createTerminalPacket() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void broadcastDelete()
|
||||||
|
{
|
||||||
|
// Send deletion to client
|
||||||
|
NetworkHandler.sendToAllPlayers( new ComputerDeletedClientMessage( getInstanceID() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setID( int id )
|
||||||
|
{
|
||||||
|
computer.setID( id );
|
||||||
|
}
|
||||||
|
|
||||||
|
// IComputer
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getInstanceID()
|
public int getInstanceID()
|
||||||
{
|
{
|
||||||
return instanceID;
|
return instanceID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getID()
|
||||||
|
{
|
||||||
|
return computer.getID();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLabel()
|
||||||
|
{
|
||||||
|
return computer.getLabel();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOn()
|
||||||
|
{
|
||||||
|
return computer.isOn();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCursorDisplayed()
|
||||||
|
{
|
||||||
|
return computer.isOn() && computer.isBlinking();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void turnOn()
|
public void turnOn()
|
||||||
{
|
{
|
||||||
@@ -229,8 +237,6 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput
|
|||||||
computer.turnOn();
|
computer.turnOn();
|
||||||
}
|
}
|
||||||
|
|
||||||
// IComputer
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void shutdown()
|
public void shutdown()
|
||||||
{
|
{
|
||||||
@@ -252,82 +258,24 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput
|
|||||||
computer.queueEvent( event, arguments );
|
computer.queueEvent( event, arguments );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isOn()
|
|
||||||
{
|
|
||||||
return computer.isOn();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCursorDisplayed()
|
|
||||||
{
|
|
||||||
return computer.isOn() && computer.isBlinking();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sendComputerState( Player player )
|
|
||||||
{
|
|
||||||
// Send state to client
|
|
||||||
NetworkHandler.sendToPlayer( player, createComputerPacket() );
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sendTerminalState( Player player )
|
|
||||||
{
|
|
||||||
// Send terminal state to client
|
|
||||||
NetworkHandler.sendToPlayer( player, createTerminalPacket() );
|
|
||||||
}
|
|
||||||
|
|
||||||
public void broadcastDelete()
|
|
||||||
{
|
|
||||||
// Send deletion to client
|
|
||||||
MinecraftServer server = GameInstanceUtils.getServer();
|
|
||||||
if( server != null )
|
|
||||||
{
|
|
||||||
NetworkHandler.sendToAllPlayers( server, new ComputerDeletedClientMessage( getInstanceID() ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getID()
|
|
||||||
{
|
|
||||||
return computer.getID();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setID( int id )
|
|
||||||
{
|
|
||||||
computer.setID( id );
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLabel()
|
|
||||||
{
|
|
||||||
return computer.getLabel();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLabel( String label )
|
|
||||||
{
|
|
||||||
computer.setLabel( label );
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getRedstoneOutput( ComputerSide side )
|
public int getRedstoneOutput( ComputerSide side )
|
||||||
{
|
{
|
||||||
return computer.getEnvironment()
|
return computer.getEnvironment().getExternalRedstoneOutput( side );
|
||||||
.getExternalRedstoneOutput( side );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRedstoneInput( ComputerSide side, int level )
|
public void setRedstoneInput( ComputerSide side, int level )
|
||||||
{
|
{
|
||||||
computer.getEnvironment()
|
computer.getEnvironment().setRedstoneInput( side, level );
|
||||||
.setRedstoneInput( side, level );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getBundledRedstoneOutput( ComputerSide side )
|
public int getBundledRedstoneOutput( ComputerSide side )
|
||||||
{
|
{
|
||||||
return computer.getEnvironment()
|
return computer.getEnvironment().getExternalBundledRedstoneOutput( side );
|
||||||
.getExternalBundledRedstoneOutput( side );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBundledRedstoneInput( ComputerSide side, int combination )
|
public void setBundledRedstoneInput( ComputerSide side, int combination )
|
||||||
{
|
{
|
||||||
computer.getEnvironment()
|
computer.getEnvironment().setBundledRedstoneInput( side, combination );
|
||||||
.setBundledRedstoneInput( side, combination );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAPI( ILuaAPI api )
|
public void addAPI( ILuaAPI api )
|
||||||
@@ -335,62 +283,39 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput
|
|||||||
computer.addApi( api );
|
computer.addApi( api );
|
||||||
}
|
}
|
||||||
|
|
||||||
// IComputerEnvironment implementation
|
|
||||||
|
|
||||||
public void setPeripheral( ComputerSide side, IPeripheral peripheral )
|
public void setPeripheral( ComputerSide side, IPeripheral peripheral )
|
||||||
{
|
{
|
||||||
computer.getEnvironment()
|
computer.getEnvironment().setPeripheral( side, peripheral );
|
||||||
.setPeripheral( side, peripheral );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IPeripheral getPeripheral( ComputerSide side )
|
public IPeripheral getPeripheral( ComputerSide side )
|
||||||
{
|
{
|
||||||
return computer.getEnvironment()
|
return computer.getEnvironment().getPeripheral( side );
|
||||||
.getPeripheral( side );
|
}
|
||||||
|
|
||||||
|
public void setLabel( String label )
|
||||||
|
{
|
||||||
|
computer.setLabel( label );
|
||||||
|
}
|
||||||
|
|
||||||
|
// IComputerEnvironment implementation
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getTimeOfDay()
|
||||||
|
{
|
||||||
|
return (level.getDayTime() + 6000) % 24000 / 1000.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getDay()
|
public int getDay()
|
||||||
{
|
{
|
||||||
return (int) ((world.getDayTime() + 6000) / 24000) + 1;
|
return (int) ((level.getDayTime() + 6000) / 24000) + 1;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public double getTimeOfDay()
|
|
||||||
{
|
|
||||||
return (world.getDayTime() + 6000) % 24000 / 1000.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getComputerSpaceLimit()
|
|
||||||
{
|
|
||||||
return ComputerCraft.computerSpaceLimit;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public String getHostString()
|
|
||||||
{
|
|
||||||
return String.format( "ComputerCraft %s (Minecraft %s)", ComputerCraftAPI.getInstalledVersion(), "1.16.4" );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public String getUserAgent()
|
|
||||||
{
|
|
||||||
return ComputerCraft.MOD_ID + "/" + ComputerCraftAPI.getInstalledVersion();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int assignNewID()
|
|
||||||
{
|
|
||||||
return ComputerCraftAPI.createUniqueNumberedSaveDir( world, "computer" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IWritableMount createSaveDirMount( String subPath, long capacity )
|
public IWritableMount createSaveDirMount( String subPath, long capacity )
|
||||||
{
|
{
|
||||||
return ComputerCraftAPI.createSaveDirMount( world, subPath, capacity );
|
return ComputerCraftAPI.createSaveDirMount( level, subPath, capacity );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -404,4 +329,46 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput
|
|||||||
{
|
{
|
||||||
return ComputerCraftAPIImpl.getResourceFile( domain, subPath );
|
return ComputerCraftAPIImpl.getResourceFile( domain, subPath );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getComputerSpaceLimit()
|
||||||
|
{
|
||||||
|
return ComputerCraft.computerSpaceLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String getHostString()
|
||||||
|
{
|
||||||
|
return String.format( "ComputerCraft %s (Minecraft %s)", ComputerCraftAPI.getInstalledVersion(), SharedConstants.getCurrentVersion() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String getUserAgent()
|
||||||
|
{
|
||||||
|
return ComputerCraft.MOD_ID + "/" + ComputerCraftAPI.getInstalledVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int assignNewID()
|
||||||
|
{
|
||||||
|
return ComputerCraftAPI.createUniqueNumberedSaveDir( level, "computer" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public IContainerComputer getContainer( Player player )
|
||||||
|
{
|
||||||
|
if( player == null ) return null;
|
||||||
|
|
||||||
|
AbstractContainerMenu container = player.containerMenu;
|
||||||
|
if( !(container instanceof IContainerComputer computerContainer) ) return null;
|
||||||
|
|
||||||
|
return computerContainer.getComputer() != this ? null : computerContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isInteracting( Player player )
|
||||||
|
{
|
||||||
|
return getContainer( player ) != null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.shared.computer.core;
|
package dan200.computercraft.shared.computer.core;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@@ -35,18 +34,6 @@ public class ServerComputerRegistry extends ComputerRegistry<ServerComputer>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void reset()
|
|
||||||
{
|
|
||||||
//System.out.println( "RESET SERVER COMPUTERS" );
|
|
||||||
for( ServerComputer computer : getComputers() )
|
|
||||||
{
|
|
||||||
computer.unload();
|
|
||||||
}
|
|
||||||
super.reset();
|
|
||||||
//System.out.println( getComputers().size() + " SERVER COMPUTERS" );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void add( int instanceID, ServerComputer computer )
|
public void add( int instanceID, ServerComputer computer )
|
||||||
{
|
{
|
||||||
@@ -70,19 +57,25 @@ public class ServerComputerRegistry extends ComputerRegistry<ServerComputer>
|
|||||||
//System.out.println( getComputers().size() + " SERVER COMPUTERS" );
|
//System.out.println( getComputers().size() + " SERVER COMPUTERS" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reset()
|
||||||
|
{
|
||||||
|
//System.out.println( "RESET SERVER COMPUTERS" );
|
||||||
|
for( ServerComputer computer : getComputers() )
|
||||||
|
{
|
||||||
|
computer.unload();
|
||||||
|
}
|
||||||
|
super.reset();
|
||||||
|
//System.out.println( getComputers().size() + " SERVER COMPUTERS" );
|
||||||
|
}
|
||||||
|
|
||||||
public ServerComputer lookup( int computerID )
|
public ServerComputer lookup( int computerID )
|
||||||
{
|
{
|
||||||
if( computerID < 0 )
|
if( computerID < 0 ) return null;
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
for( ServerComputer computer : getComputers() )
|
for( ServerComputer computer : getComputers() )
|
||||||
{
|
{
|
||||||
if( computer.getID() == computerID )
|
if( computer.getID() == computerID ) return computer;
|
||||||
{
|
|
||||||
return computer;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user