mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-09-04 19:37:55 +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:
|
||||
file: .gitpod.Dockerfile
|
||||
file: config/gitpod/Dockerfile
|
||||
|
||||
ports:
|
||||
- port: 25565
|
||||
@@ -7,12 +7,14 @@ ports:
|
||||
|
||||
vscode:
|
||||
extensions:
|
||||
- eamodio.gitlens
|
||||
- github.vscode-pull-request-github
|
||||
- ms-azuretools.vscode-docker
|
||||
- redhat.java
|
||||
- richardwillis.vscode-gradle
|
||||
- vscjava.vscode-java-debug
|
||||
- vscode.github
|
||||
|
||||
|
||||
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.kotlinx:kotlinx-coroutines-core:1.5.1'
|
||||
|
||||
cctJavadoc 'cc.tweaked:cct-javadoc:1.4.1'
|
||||
cctJavadoc 'cc.tweaked:cct-javadoc:1.4.2'
|
||||
}
|
||||
|
||||
processResources {
|
||||
|
@@ -2,7 +2,7 @@
|
||||
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
|
||||
Prints a message when a redstone input changes:
|
||||
|
@@ -3,12 +3,11 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft;
|
||||
|
||||
import dan200.computercraft.core.apis.http.options.Action;
|
||||
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.computer.core.ClientComputerRegistry;
|
||||
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.Logger;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
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 static final String MOD_ID = "computercraft";
|
||||
|
||||
// Configuration fields
|
||||
public static int computerSpaceLimit = 1000 * 1000;
|
||||
public static int floppySpaceLimit = 125 * 1000;
|
||||
public static int maximumFilesOpen = 128;
|
||||
public static boolean disableLua51Features = false;
|
||||
public static String defaultComputerSettings = "";
|
||||
public static boolean debugEnable = true;
|
||||
public static boolean logComputerErrors = true;
|
||||
public static boolean commandRequireCreative = true;
|
||||
|
||||
@@ -64,10 +59,11 @@ public final class ComputerCraft implements ModInitializer
|
||||
|
||||
public static boolean httpEnabled = 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( "*", null, Action.ALLOW.toPartial() )
|
||||
) );
|
||||
);
|
||||
|
||||
public static int httpMaxRequests = 16;
|
||||
public static int httpMaxWebsockets = 4;
|
||||
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 maxNotesPerTick = 8;
|
||||
public static MonitorRenderer monitorRenderer = MonitorRenderer.BEST;
|
||||
public static double monitorDistanceSq = 4096;
|
||||
public static int monitorDistance = 65;
|
||||
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 pocketTermHeight = 20;
|
||||
|
||||
public static int monitorWidth = 8;
|
||||
public static int monitorHeight = 6;
|
||||
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft;
|
||||
|
||||
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.Direction;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.packs.resources.ReloadableResourceManager;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
@@ -59,36 +57,24 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
||||
|
||||
public static InputStream getResourceFile( String domain, String subPath )
|
||||
{
|
||||
MinecraftServer server = GameInstanceUtils.getServer();
|
||||
if( server != null )
|
||||
ReloadableResourceManager manager = (ReloadableResourceManager) ((MinecraftServerAccess) GameInstanceUtils.getServer()).callGetResourceManager();
|
||||
try
|
||||
{
|
||||
ReloadableResourceManager manager = (ReloadableResourceManager) ((MinecraftServerAccess) server).callGetResourceManager();
|
||||
try
|
||||
{
|
||||
return manager.getResource( new ResourceLocation( domain, subPath ) )
|
||||
.getInputStream();
|
||||
}
|
||||
catch( IOException ignored )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return manager.getResource( new ResourceLocation( domain, subPath ) ).getInputStream();
|
||||
}
|
||||
catch( IOException ignored )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String getInstalledVersion()
|
||||
{
|
||||
if( version != null )
|
||||
{
|
||||
return version;
|
||||
}
|
||||
return version = FabricLoader.getInstance()
|
||||
.getModContainer( ComputerCraft.MOD_ID )
|
||||
.map( x -> x.getMetadata()
|
||||
.getVersion()
|
||||
.toString() )
|
||||
if( version != null ) return version;
|
||||
return version = FabricLoader.getInstance().getModContainer( ComputerCraft.MOD_ID )
|
||||
.map( x -> x.getMetadata().getVersion().toString() )
|
||||
.orElse( "unknown" );
|
||||
}
|
||||
|
||||
@@ -114,14 +100,9 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
||||
@Override
|
||||
public IMount createResourceMount( @Nonnull String domain, @Nonnull String subPath )
|
||||
{
|
||||
MinecraftServer server = GameInstanceUtils.getServer();
|
||||
if( server != null )
|
||||
{
|
||||
ReloadableResourceManager manager = (ReloadableResourceManager) ((MinecraftServerAccess) server).callGetResourceManager();
|
||||
ResourceMount mount = ResourceMount.get( domain, subPath, manager );
|
||||
return mount.exists( "" ) ? mount : null;
|
||||
}
|
||||
return null;
|
||||
ReloadableResourceManager manager = (ReloadableResourceManager) ((MinecraftServerAccess) GameInstanceUtils.getServer()).callGetResourceManager();
|
||||
ResourceMount mount = ResourceMount.get( domain, subPath, manager );
|
||||
return mount.exists( "" ) ? mount : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -130,12 +111,24 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
||||
Peripherals.register( provider );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerGenericSource( @Nonnull GenericSource source )
|
||||
{
|
||||
GenericMethod.register( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerTurtleUpgrade( @Nonnull ITurtleUpgrade upgrade )
|
||||
{
|
||||
TurtleUpgrades.register( upgrade );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerPocketUpgrade( @Nonnull IPocketUpgrade upgrade )
|
||||
{
|
||||
PocketUpgrades.register( upgrade );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerBundledRedstoneProvider( @Nonnull IBundledRedstoneProvider provider )
|
||||
{
|
||||
@@ -154,18 +147,6 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
||||
MediaProviders.register( provider );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerPocketUpgrade( @Nonnull IPocketUpgrade upgrade )
|
||||
{
|
||||
PocketUpgrades.register( upgrade );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerGenericSource( @Nonnull GenericSource source )
|
||||
{
|
||||
GenericMethod.register( source );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public IPacketNetwork getWirelessNetwork()
|
||||
|
@@ -36,19 +36,14 @@ import javax.annotation.Nullable;
|
||||
*/
|
||||
public final class ComputerCraftAPI
|
||||
{
|
||||
public static final String MOD_ID = "computercraft";
|
||||
|
||||
@Nonnull
|
||||
public static String 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.
|
||||
*
|
||||
@@ -139,9 +134,9 @@ public final class ComputerCraftAPI
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new turtle turtle for use in ComputerCraft. After calling this,
|
||||
* users should be able to craft Turtles with your new turtle. It is recommended to call
|
||||
* this during the load() method of your mod.
|
||||
* Registers a new turtle upgrade for use in ComputerCraft. After calling this,
|
||||
* users should be able to craft Turtles with your upgrade's ItemStack. It is
|
||||
* recommended to call this during the load() method of your mod.
|
||||
*
|
||||
* @param upgrade The turtle upgrade to register.
|
||||
* @see ITurtleUpgrade
|
||||
@@ -151,6 +146,19 @@ public final class ComputerCraftAPI
|
||||
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.
|
||||
*
|
||||
@@ -188,11 +196,6 @@ public final class ComputerCraftAPI
|
||||
getInstance().registerMediaProvider( provider );
|
||||
}
|
||||
|
||||
public static void registerPocketUpgrade( @Nonnull IPocketUpgrade upgrade )
|
||||
{
|
||||
getInstance().registerPocketUpgrade( upgrade );
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to get the game-wide wireless network.
|
||||
*
|
||||
@@ -273,14 +276,13 @@ public final class ComputerCraftAPI
|
||||
|
||||
void registerTurtleUpgrade( @Nonnull ITurtleUpgrade upgrade );
|
||||
|
||||
void registerPocketUpgrade( @Nonnull IPocketUpgrade upgrade );
|
||||
|
||||
void registerBundledRedstoneProvider( @Nonnull IBundledRedstoneProvider provider );
|
||||
|
||||
int getBundledRedstoneOutput( @Nonnull Level world, @Nonnull BlockPos pos, @Nonnull Direction side );
|
||||
|
||||
void registerMediaProvider( @Nonnull IMediaProvider provider );
|
||||
|
||||
void registerPocketUpgrade( @Nonnull IPocketUpgrade upgrade );
|
||||
|
||||
@Nonnull
|
||||
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.
|
||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||
*/
|
||||
|
||||
package dan200.computercraft.api.client;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
@@ -9,6 +9,8 @@ import dan200.computercraft.api.lua.LuaFunction;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* The interface that defines a peripheral.
|
||||
@@ -30,6 +32,18 @@ public interface IPeripheral
|
||||
@Nonnull
|
||||
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.
|
||||
*
|
||||
|
@@ -6,9 +6,13 @@
|
||||
package dan200.computercraft.api.peripheral;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* The type of a {@link GenericPeripheral}.
|
||||
@@ -18,13 +22,19 @@ import javax.annotation.Nullable;
|
||||
*/
|
||||
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 Set<String> additionalTypes;
|
||||
|
||||
public PeripheralType( String type )
|
||||
public PeripheralType( String type, Set<String> additionalTypes )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
import dan200.computercraft.api.ComputerCraftAPI;
|
||||
import dan200.computercraft.api.IUpgradeBase;
|
||||
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
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.
|
||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||
*/
|
||||
|
||||
package dan200.computercraft.api.turtle;
|
||||
|
||||
import dan200.computercraft.shared.util.NonNullSupplier;
|
||||
import net.minecraft.Util;
|
||||
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* A base class for {@link ITurtleUpgrade}s.
|
||||
@@ -26,9 +21,9 @@ public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade
|
||||
private final ResourceLocation id;
|
||||
private final TurtleUpgradeType type;
|
||||
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.type = type;
|
||||
@@ -36,39 +31,9 @@ public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade
|
||||
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 )
|
||||
{
|
||||
this( id, type, () -> 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 ) );
|
||||
this( id, type, IUpgradeBase.getDefaultAdjective( id ), stack );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@@ -96,32 +61,6 @@ public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade
|
||||
@Override
|
||||
public final ItemStack getCraftingItem()
|
||||
{
|
||||
return stack.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 );
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@
|
||||
package dan200.computercraft.api.turtle;
|
||||
|
||||
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.peripheral.IPeripheral;
|
||||
import net.fabricmc.api.EnvType;
|
||||
|
@@ -3,10 +3,11 @@
|
||||
* 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;
|
||||
package dan200.computercraft.api.upgrades;
|
||||
|
||||
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
@@ -81,4 +82,18 @@ public interface IUpgradeBase
|
||||
if( craftingShareTag == null ) return shareTag.isEmpty();
|
||||
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.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.shared.ComputerCraftRegistry;
|
||||
import dan200.computercraft.shared.Registry;
|
||||
import dan200.computercraft.shared.common.IColouredItem;
|
||||
import dan200.computercraft.shared.media.items.ItemDisk;
|
||||
import dan200.computercraft.shared.media.items.ItemTreasureDisk;
|
||||
@@ -34,6 +33,7 @@ import java.util.function.Consumer;
|
||||
public final class ClientRegistry
|
||||
{
|
||||
private static final String[] EXTRA_MODELS = new String[] {
|
||||
// Turtle upgrades
|
||||
"turtle_modem_normal_off_left",
|
||||
"turtle_modem_normal_on_left",
|
||||
"turtle_modem_normal_off_right",
|
||||
@@ -49,6 +49,7 @@ public final class ClientRegistry
|
||||
"turtle_speaker_upgrade_left",
|
||||
"turtle_speaker_upgrade_right",
|
||||
|
||||
// Turtle block renderer
|
||||
"turtle_colour",
|
||||
"turtle_elf_overlay",
|
||||
};
|
||||
@@ -85,10 +86,10 @@ public final class ClientRegistry
|
||||
{
|
||||
ColorProviderRegistry.ITEM.register( ( stack, layer ) -> {
|
||||
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,
|
||||
ComputerCraftRegistry.ModItems.TREASURE_DISK );
|
||||
Registry.ModItems.TREASURE_DISK );
|
||||
|
||||
ColorProviderRegistry.ITEM.register( ( stack, layer ) -> {
|
||||
switch( layer )
|
||||
@@ -102,12 +103,12 @@ public final class ClientRegistry
|
||||
int light = ItemPocketComputer.getLightState( stack );
|
||||
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
|
||||
ColorProviderRegistry.ITEM.register( ( stack, tintIndex ) -> tintIndex == 0 ? ((IColouredItem) stack.getItem()).getColour( stack ) : 0xFFFFFF,
|
||||
ComputerCraftRegistry.ModBlocks.TURTLE_NORMAL,
|
||||
ComputerCraftRegistry.ModBlocks.TURTLE_ADVANCED );
|
||||
Registry.ModBlocks.TURTLE_NORMAL,
|
||||
Registry.ModBlocks.TURTLE_ADVANCED );
|
||||
}
|
||||
|
||||
private static BakedModel bake( ModelBakery loader, UnbakedModel model, ResourceLocation identifier )
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client;
|
||||
|
||||
import dan200.computercraft.fabric.mixin.ChatComponentAccess;
|
||||
@@ -25,17 +24,19 @@ public class ClientTableFormatter implements TableFormatter
|
||||
{
|
||||
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
|
||||
@Nullable
|
||||
public Component getPadding( Component component, int width )
|
||||
{
|
||||
int extraWidth = width - getWidth( component );
|
||||
if( extraWidth <= 0 )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if( extraWidth <= 0 ) return null;
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
private static Font renderer()
|
||||
{
|
||||
return Minecraft.getInstance().font;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnPadding()
|
||||
{
|
||||
@@ -71,7 +67,7 @@ public class ClientTableFormatter implements TableFormatter
|
||||
|
||||
// TODO: Trim the text if it goes over the allowed length
|
||||
// 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 );
|
||||
((ChatComponentAccess) chat).callAddMessage( component, id );
|
||||
}
|
||||
@@ -86,10 +82,7 @@ public class ClientTableFormatter implements TableFormatter
|
||||
int height = TableFormatter.super.display( table );
|
||||
lastHeights.put( table.getId(), height );
|
||||
|
||||
for( int i = height; i < lastHeight; i++ )
|
||||
{
|
||||
((ChatComponentAccess) chat).callRemoveById( i + table.getId() );
|
||||
}
|
||||
for( int i = height; i < lastHeight; i++ ) ((ChatComponentAccess) chat).callRemoveById( i + table.getId() );
|
||||
return height;
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client;
|
||||
|
||||
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>
|
||||
{
|
||||
|
||||
private static final Component OK = new TranslatableComponent( "gui.ok" );
|
||||
private static final Component CANCEL = new TranslatableComponent( "gui.cancel" );
|
||||
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 );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
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
|
||||
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
|
||||
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()
|
||||
{
|
||||
if( minecraft.screen instanceof OptionScreen ) ((OptionScreen) minecraft.screen).disable();
|
||||
if( minecraft.screen instanceof OptionScreen screen ) screen.disable();
|
||||
NetworkHandler.sendToServer( new ContinueUploadMessage( computer.getInstanceID(), true ) );
|
||||
}
|
||||
|
||||
@@ -224,5 +226,4 @@ public abstract class ComputerScreenBase<T extends ContainerComputerBase> extend
|
||||
() -> minecraft.setScreen( this )
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -3,19 +3,17 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.vertex.Tesselator;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.mojang.math.Matrix4f;
|
||||
import com.mojang.math.Transformation;
|
||||
import dan200.computercraft.client.FrameInfo;
|
||||
import dan200.computercraft.client.render.RenderTypes;
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
import dan200.computercraft.core.terminal.TextBuffer;
|
||||
import dan200.computercraft.shared.util.Colour;
|
||||
import dan200.computercraft.shared.util.Palette;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
@@ -24,25 +22,138 @@ import javax.annotation.Nullable;
|
||||
|
||||
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 static final ResourceLocation FONT = new ResourceLocation( "computercraft", "textures/gui/term_font.png" );
|
||||
|
||||
public static final int FONT_HEIGHT = 9;
|
||||
public static final int FONT_WIDTH = 6;
|
||||
public static final float WIDTH = 256.0f;
|
||||
|
||||
public static final float BACKGROUND_START = (WIDTH - 6.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()
|
||||
{
|
||||
}
|
||||
|
||||
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 )
|
||||
public static float toGreyscale( double[] rgb )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
@@ -66,223 +177,49 @@ public final class FixedWidthFontRenderer
|
||||
|
||||
// Draw char
|
||||
int index = text.charAt( i );
|
||||
if( index > 255 )
|
||||
{
|
||||
index = '?';
|
||||
}
|
||||
if( index > 255 ) index = '?';
|
||||
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,
|
||||
@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 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 )
|
||||
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();
|
||||
int height = terminal.getHeight();
|
||||
|
||||
// Top and bottom margins
|
||||
drawBackground( transform,
|
||||
buffer,
|
||||
x,
|
||||
y - topMarginSize,
|
||||
terminal.getBackgroundColourLine( 0 ),
|
||||
palette,
|
||||
greyscale,
|
||||
leftMarginSize,
|
||||
rightMarginSize,
|
||||
topMarginSize );
|
||||
drawBackground(
|
||||
transform, buffer, x, y - topMarginSize,
|
||||
terminal.getBackgroundColourLine( 0 ), palette, greyscale,
|
||||
leftMarginSize, rightMarginSize, topMarginSize
|
||||
);
|
||||
|
||||
drawBackground( transform,
|
||||
buffer,
|
||||
x,
|
||||
y + height * FONT_HEIGHT,
|
||||
terminal.getBackgroundColourLine( height - 1 ),
|
||||
palette,
|
||||
greyscale,
|
||||
leftMarginSize,
|
||||
rightMarginSize,
|
||||
bottomMarginSize );
|
||||
drawBackground(
|
||||
transform, buffer, x, y + height * FONT_HEIGHT,
|
||||
terminal.getBackgroundColourLine( height - 1 ), palette, greyscale,
|
||||
leftMarginSize, rightMarginSize, bottomMarginSize
|
||||
);
|
||||
|
||||
// The main text
|
||||
for( int i = 0; i < height; i++ )
|
||||
{
|
||||
drawString( transform,
|
||||
buffer,
|
||||
x,
|
||||
y + FixedWidthFontRenderer.FONT_HEIGHT * i,
|
||||
terminal.getLine( i ),
|
||||
terminal.getTextColourLine( i ),
|
||||
terminal.getBackgroundColourLine( i ),
|
||||
palette,
|
||||
greyscale,
|
||||
leftMarginSize,
|
||||
rightMarginSize, FULL_BRIGHT_LIGHTMAP );
|
||||
drawString(
|
||||
transform, buffer, x, y + FixedWidthFontRenderer.FONT_HEIGHT * i,
|
||||
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,
|
||||
boolean greyscale )
|
||||
public static void drawCursor(
|
||||
@Nonnull Matrix4f transform, @Nonnull VertexConsumer buffer, float x, float y,
|
||||
@Nonnull Terminal terminal, boolean greyscale
|
||||
)
|
||||
{
|
||||
Palette palette = terminal.getPalette();
|
||||
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,
|
||||
boolean greyscale, float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize )
|
||||
public static void drawTerminal(
|
||||
@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 );
|
||||
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,
|
||||
float bottomMarginSize, float leftMarginSize, float rightMarginSize )
|
||||
public static void drawTerminal(
|
||||
@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()
|
||||
.renderBuffers()
|
||||
.bufferSource();
|
||||
MultiBufferSource.BufferSource renderer = MultiBufferSource.immediate( Tesselator.getInstance().getBuilder() );
|
||||
VertexConsumer buffer = renderer.getBuffer( RenderTypes.TERMINAL_WITH_DEPTH );
|
||||
drawTerminal( transform, buffer, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize );
|
||||
renderer.endBatch();
|
||||
}
|
||||
|
||||
public static void drawTerminal( float x, float y, @Nonnull Terminal terminal, boolean greyscale, float topMarginSize, float bottomMarginSize,
|
||||
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 )
|
||||
public static void drawEmptyTerminal( @Nonnull Matrix4f transform, @Nonnull MultiBufferSource renderer, float x, float y, float width, float height )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
MultiBufferSource.BufferSource renderer = Minecraft.getInstance()
|
||||
.renderBuffers()
|
||||
.bufferSource();
|
||||
MultiBufferSource.BufferSource renderer = MultiBufferSource.immediate( Tesselator.getInstance().getBuilder() );
|
||||
drawEmptyTerminal( transform, renderer, x, y, width, height );
|
||||
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 )
|
||||
{
|
||||
Colour colour = Colour.BLACK;
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
@@ -20,14 +19,15 @@ import net.minecraft.world.entity.player.Inventory;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
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>
|
||||
{
|
||||
private final int termWidth;
|
||||
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 );
|
||||
this.termWidth = termWidth;
|
||||
@@ -37,19 +37,31 @@ public final class GuiComputer<T extends ContainerComputerBase> extends Computer
|
||||
imageHeight = WidgetTerminal.getHeight( termHeight ) + BORDER * 2;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
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 )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
return new GuiComputer<>( container, inventory, component, container.getWidth(), container.getHeight() );
|
||||
return new GuiComputer<>(
|
||||
container, inventory, component,
|
||||
container.getWidth(), container.getHeight()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -63,9 +75,11 @@ public final class GuiComputer<T extends ContainerComputerBase> extends Computer
|
||||
@Override
|
||||
public void renderBg( @Nonnull PoseStack stack, float partialTicks, int mouseX, int mouseY )
|
||||
{
|
||||
// Draw a border around the terminal
|
||||
ComputerBorderRenderer.render(
|
||||
getTexture( family ), terminal.x, terminal.y, getBlitOffset(),
|
||||
RenderTypes.FULL_BRIGHT_LIGHTMAP, terminal.getWidth(), terminal.getHeight() );
|
||||
ComputerBorderRenderer.getTexture( family ), terminal.x, terminal.y, getBlitOffset(),
|
||||
RenderTypes.FULL_BRIGHT_LIGHTMAP, terminal.getWidth(), terminal.getHeight()
|
||||
);
|
||||
ComputerSidebar.renderBackground( stack, leftPos, topPos + sidebarYOffset );
|
||||
}
|
||||
}
|
||||
|
@@ -3,14 +3,12 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive;
|
||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
@@ -26,6 +24,14 @@ public class GuiDiskDrive extends AbstractContainerScreen<ContainerDiskDrive>
|
||||
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
|
||||
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 );
|
||||
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.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
@@ -25,14 +24,6 @@ public class GuiPrinter extends AbstractContainerScreen<ContainerPrinter>
|
||||
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
|
||||
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 );
|
||||
blit( transform, leftPos, topPos, 0, 0, imageWidth, imageHeight );
|
||||
|
||||
if( getMenu().isPrinting() )
|
||||
{
|
||||
blit( transform, leftPos + 34, topPos + 21, 176, 0, 25, 45 );
|
||||
}
|
||||
if( getMenu().isPrinting() ) 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.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.Tesselator;
|
||||
import com.mojang.math.Matrix4f;
|
||||
import dan200.computercraft.core.terminal.TextBuffer;
|
||||
import dan200.computercraft.shared.common.ContainerHeldItem;
|
||||
import dan200.computercraft.shared.media.items.ItemPrintout;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.network.chat.Component;
|
||||
@@ -40,54 +39,72 @@ public class GuiPrintout extends AbstractContainerScreen<ContainerHeldItem>
|
||||
|
||||
String[] text = ItemPrintout.getText( container.getStack() );
|
||||
this.text = new TextBuffer[text.length];
|
||||
for( int i = 0; i < this.text.length; i++ )
|
||||
{
|
||||
this.text[i] = new TextBuffer( text[i] );
|
||||
}
|
||||
for( int i = 0; i < this.text.length; i++ ) this.text[i] = new TextBuffer( text[i] );
|
||||
|
||||
String[] colours = ItemPrintout.getColours( container.getStack() );
|
||||
this.colours = new TextBuffer[colours.length];
|
||||
for( int i = 0; i < this.colours.length; i++ )
|
||||
{
|
||||
this.colours[i] = new TextBuffer( colours[i] );
|
||||
}
|
||||
for( int i = 0; i < this.colours.length; i++ ) this.colours[i] = new TextBuffer( colours[i] );
|
||||
|
||||
page = 0;
|
||||
pages = Math.max( this.text.length / ItemPrintout.LINES_PER_PAGE, 1 );
|
||||
book = ((ItemPrintout) container.getStack()
|
||||
.getItem()).getType() == ItemPrintout.Type.BOOK;
|
||||
book = ((ItemPrintout) container.getStack().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
|
||||
public boolean mouseScrolled( double x, double y, double delta )
|
||||
{
|
||||
if( super.mouseScrolled( x, y, delta ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if( super.mouseScrolled( x, y, delta ) ) return true;
|
||||
if( delta < 0 )
|
||||
{
|
||||
// Scroll up goes to the next page
|
||||
if( page < pages - 1 )
|
||||
{
|
||||
page++;
|
||||
}
|
||||
if( page < pages - 1 ) page++;
|
||||
return true;
|
||||
}
|
||||
|
||||
if( delta > 0 )
|
||||
{
|
||||
// Scroll down goes to the previous page
|
||||
if( page > 0 )
|
||||
{
|
||||
page--;
|
||||
}
|
||||
if( page > 0 ) page--;
|
||||
return true;
|
||||
}
|
||||
|
||||
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
|
||||
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.
|
||||
}
|
||||
|
||||
@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.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
@@ -20,12 +19,12 @@ import net.minecraft.world.entity.player.Inventory;
|
||||
|
||||
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>
|
||||
{
|
||||
private static final ResourceLocation BACKGROUND_NORMAL = new ResourceLocation( "computercraft", "textures/gui/turtle_normal.png" );
|
||||
private static final ResourceLocation BACKGROUND_ADVANCED = new ResourceLocation( "computercraft", "textures/gui/turtle_advanced.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.MOD_ID, "textures/gui/turtle_advanced.png" );
|
||||
|
||||
private static final int TEX_WIDTH = 254;
|
||||
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 )
|
||||
{
|
||||
super( container, player, title, BORDER );
|
||||
|
||||
family = container.getFamily();
|
||||
|
||||
imageWidth = TEX_WIDTH + ComputerSidebar.WIDTH;
|
||||
imageHeight = TEX_HEIGHT;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -52,23 +50,22 @@ public class GuiTurtle extends ComputerScreenBase<ContainerTurtle>
|
||||
}
|
||||
|
||||
@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;
|
||||
RenderSystem.setShaderTexture( 0, advanced ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL );
|
||||
blit( transform, leftPos + ComputerSidebar.WIDTH, topPos, 0, 0, TEX_WIDTH, TEX_HEIGHT );
|
||||
|
||||
// Draw selection slot
|
||||
int slot = getMenu().getSelectedSlot();
|
||||
if( slot >= 0 )
|
||||
{
|
||||
RenderSystem.setShaderColor( 1.0F, 1.0F, 1.0F, 1.0F );
|
||||
int slotX = slot % 4;
|
||||
int slotY = slot / 4;
|
||||
blit( transform, leftPos + ContainerTurtle.TURTLE_START_X - 2 + slotX * 18, topPos + ContainerTurtle.PLAYER_START_Y - 2 + slotY * 18,
|
||||
0,
|
||||
217,
|
||||
24,
|
||||
24 );
|
||||
blit( transform,
|
||||
leftPos + TURTLE_START_X - 2 + slotX * 18, topPos + PLAYER_START_Y - 2 + slotY * 18,
|
||||
0, 217, 24, 24
|
||||
);
|
||||
}
|
||||
|
||||
RenderSystem.setShaderTexture( 0, advanced ? ComputerBorderRenderer.BACKGROUND_ADVANCED : ComputerBorderRenderer.BACKGROUND_NORMAL );
|
||||
|
@@ -43,9 +43,10 @@ public class NoTermComputerScreen<T extends ContainerComputerBase> extends Scree
|
||||
@Override
|
||||
protected void init()
|
||||
{
|
||||
this.passEvents = true;
|
||||
passEvents = true; // Pass mouse vents through to the game's mouse handler.
|
||||
minecraft.mouseHandler.grabMouse();
|
||||
minecraft.screen = this;
|
||||
|
||||
super.init();
|
||||
minecraft.keyboardHandler.setSendRepeatsToGui( true );
|
||||
|
||||
@@ -102,7 +103,7 @@ public class NoTermComputerScreen<T extends ContainerComputerBase> extends Scree
|
||||
}
|
||||
|
||||
@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 );
|
||||
|
||||
|
@@ -49,9 +49,9 @@ public final class OptionScreen extends Screen
|
||||
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 )
|
||||
|
@@ -8,7 +8,6 @@ package dan200.computercraft.client.gui.widgets;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.client.render.ComputerBorderRenderer;
|
||||
import dan200.computercraft.shared.command.text.ChatHelpers;
|
||||
import dan200.computercraft.shared.computer.core.ClientComputer;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.gui.components.AbstractWidget;
|
||||
@@ -55,10 +54,10 @@ public final class ComputerSidebar
|
||||
TEXTURE, TEX_SIZE, TEX_SIZE, b -> toggleComputer( computer ),
|
||||
() -> computer.isOn() ? Arrays.asList(
|
||||
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(
|
||||
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" ),
|
||||
Arrays.asList(
|
||||
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.vertex.PoseStack;
|
||||
import dan200.computercraft.shared.util.NonNullSupplier;
|
||||
import net.minecraft.client.gui.components.Button;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.network.chat.Component;
|
||||
@@ -16,7 +17,6 @@ import net.minecraft.resources.ResourceLocation;
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
import java.util.function.IntSupplier;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* 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 textureWidth;
|
||||
private final int textureHeight;
|
||||
private final Supplier<List<Component>> tooltip;
|
||||
private final NonNullSupplier<List<Component>> tooltip;
|
||||
|
||||
public DynamicImageButton(
|
||||
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(
|
||||
Screen screen, int x, int y, int width, int height, IntSupplier xTexStart, int yTexStart, int yDiffTex,
|
||||
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 );
|
||||
@@ -76,7 +76,7 @@ public class DynamicImageButton extends Button
|
||||
blit( stack, x, y, xTexStart.getAsInt(), yTex, width, height, textureWidth, textureHeight );
|
||||
RenderSystem.enableDepthTest();
|
||||
|
||||
if( isHoveredOrFocused() ) renderToolTip( stack, mouseX, mouseY );
|
||||
if( isHovered ) renderToolTip( stack, mouseX, mouseY );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@@ -87,11 +87,10 @@ public class DynamicImageButton extends Button
|
||||
return tooltip.isEmpty() ? TextComponent.EMPTY : tooltip.get( 0 );
|
||||
}
|
||||
|
||||
// @Override
|
||||
@Override
|
||||
public void renderToolTip( @Nonnull PoseStack stack, int mouseX, int mouseY )
|
||||
{
|
||||
List<Component> tooltip = this.tooltip.get();
|
||||
|
||||
if( !tooltip.isEmpty() )
|
||||
{
|
||||
screen.renderComponentTooltip( stack, tooltip, mouseX, mouseY );
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.gui.widgets;
|
||||
|
||||
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
|
||||
{
|
||||
// Queue the "char" event
|
||||
queueEvent( "char", Character.toString( ch ) );
|
||||
computer.queueEvent( "char", new Object[] { Character.toString( ch ) } );
|
||||
}
|
||||
|
||||
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
|
||||
@@ -175,113 +263,27 @@ public class WidgetTerminal extends AbstractWidget
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyPressed( int key, int scancode, int modifiers )
|
||||
private boolean inTermRegion( double mouseX, double mouseY )
|
||||
{
|
||||
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 );
|
||||
}
|
||||
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;
|
||||
return active && visible && mouseX >= innerX && mouseY >= innerY && mouseX < innerX + innerWidth && mouseY < innerY + innerHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyReleased( int key, int scancode, int modifiers )
|
||||
public void update()
|
||||
{
|
||||
// Queue the "key_up" event and remove from the down set
|
||||
if( key >= 0 && keysDown.get( key ) )
|
||||
if( terminateTimer >= 0 && terminateTimer < TERMINATE_TIME && (terminateTimer += 0.05f) > TERMINATE_TIME )
|
||||
{
|
||||
keysDown.set( key, false );
|
||||
computer.keyUp( key );
|
||||
computer.queueEvent( "terminate" );
|
||||
}
|
||||
|
||||
switch( key )
|
||||
if( shutdownTimer >= 0 && shutdownTimer < TERMINATE_TIME && (shutdownTimer += 0.05f) > TERMINATE_TIME )
|
||||
{
|
||||
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;
|
||||
computer.shutdown();
|
||||
}
|
||||
|
||||
return true;
|
||||
if( rebootTimer >= 0 && rebootTimer < TERMINATE_TIME && (rebootTimer += 0.05f) > TERMINATE_TIME )
|
||||
{
|
||||
computer.reboot();
|
||||
}
|
||||
}
|
||||
|
||||
@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
|
||||
public void render( @Nonnull PoseStack transform, int mouseX, int mouseY, float partialTicks )
|
||||
{
|
||||
@@ -362,9 +326,9 @@ public class WidgetTerminal extends AbstractWidget
|
||||
}
|
||||
|
||||
@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 )
|
||||
|
@@ -15,7 +15,7 @@ import dan200.computercraft.client.render.TileEntityTurtleRenderer;
|
||||
import dan200.computercraft.client.render.TurtleModelLoader;
|
||||
import dan200.computercraft.client.render.TurtlePlayerRenderer;
|
||||
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.IColouredItem;
|
||||
import dan200.computercraft.shared.common.TileGeneric;
|
||||
@@ -73,17 +73,17 @@ public final class ComputerCraftProxyClient implements ClientModInitializer
|
||||
registerContainers();
|
||||
|
||||
// While turtles themselves are not transparent, their upgrades may be.
|
||||
BlockRenderLayerMap.INSTANCE.putBlock( ComputerCraftRegistry.ModBlocks.TURTLE_NORMAL, RenderType.translucent() );
|
||||
BlockRenderLayerMap.INSTANCE.putBlock( ComputerCraftRegistry.ModBlocks.TURTLE_ADVANCED, RenderType.translucent() );
|
||||
BlockRenderLayerMap.INSTANCE.putBlock( Registry.ModBlocks.TURTLE_NORMAL, RenderType.translucent() );
|
||||
BlockRenderLayerMap.INSTANCE.putBlock( Registry.ModBlocks.TURTLE_ADVANCED, RenderType.translucent() );
|
||||
// Monitors' textures have transparent fronts and so count as cutouts.
|
||||
BlockRenderLayerMap.INSTANCE.putBlock( ComputerCraftRegistry.ModBlocks.MONITOR_NORMAL, RenderType.cutout() );
|
||||
BlockRenderLayerMap.INSTANCE.putBlock( ComputerCraftRegistry.ModBlocks.MONITOR_ADVANCED, RenderType.cutout() );
|
||||
BlockRenderLayerMap.INSTANCE.putBlock( Registry.ModBlocks.MONITOR_NORMAL, RenderType.cutout() );
|
||||
BlockRenderLayerMap.INSTANCE.putBlock( Registry.ModBlocks.MONITOR_ADVANCED, RenderType.cutout() );
|
||||
|
||||
// Setup TESRs
|
||||
BlockEntityRendererRegistry.register( ComputerCraftRegistry.ModTiles.MONITOR_NORMAL, TileEntityMonitorRenderer::new );
|
||||
BlockEntityRendererRegistry.register( ComputerCraftRegistry.ModTiles.MONITOR_ADVANCED, TileEntityMonitorRenderer::new );
|
||||
BlockEntityRendererRegistry.register( ComputerCraftRegistry.ModTiles.TURTLE_NORMAL, TileEntityTurtleRenderer::new );
|
||||
BlockEntityRendererRegistry.register( ComputerCraftRegistry.ModTiles.TURTLE_ADVANCED, TileEntityTurtleRenderer::new );
|
||||
BlockEntityRendererRegistry.register( Registry.ModBlockEntities.MONITOR_NORMAL, TileEntityMonitorRenderer::new );
|
||||
BlockEntityRendererRegistry.register( Registry.ModBlockEntities.MONITOR_ADVANCED, TileEntityMonitorRenderer::new );
|
||||
BlockEntityRendererRegistry.register( Registry.ModBlockEntities.TURTLE_NORMAL, TileEntityTurtleRenderer::new );
|
||||
BlockEntityRendererRegistry.register( Registry.ModBlockEntities.TURTLE_ADVANCED, TileEntityTurtleRenderer::new );
|
||||
|
||||
ClientSpriteRegistryCallback.event( InventoryMenu.BLOCK_ATLAS )
|
||||
.register( ClientRegistry::onTextureStitchEvent );
|
||||
@@ -92,17 +92,17 @@ public final class ComputerCraftProxyClient implements ClientModInitializer
|
||||
TurtleModelLoader.INSTANCE.loadModel(
|
||||
name ) : null );
|
||||
|
||||
EntityRendererRegistry.register( ComputerCraftRegistry.ModEntities.TURTLE_PLAYER, TurtlePlayerRenderer::new );
|
||||
EntityRendererRegistry.register( Registry.ModEntities.TURTLE_PLAYER, TurtlePlayerRenderer::new );
|
||||
|
||||
registerItemProperty( "state",
|
||||
( stack, world, player, integer ) -> ItemPocketComputer.getState( stack )
|
||||
.ordinal(),
|
||||
() -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_NORMAL,
|
||||
() -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_ADVANCED );
|
||||
() -> Registry.ModItems.POCKET_COMPUTER_NORMAL,
|
||||
() -> Registry.ModItems.POCKET_COMPUTER_ADVANCED );
|
||||
registerItemProperty( "state",
|
||||
( stack, world, player, integer ) -> IColouredItem.getColourBasic( stack ) != -1 ? 1 : 0,
|
||||
() -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_NORMAL,
|
||||
() -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_ADVANCED );
|
||||
() -> Registry.ModItems.POCKET_COMPUTER_NORMAL,
|
||||
() -> Registry.ModItems.POCKET_COMPUTER_ADVANCED );
|
||||
ClientRegistry.onItemColours();
|
||||
|
||||
initEvents();
|
||||
@@ -111,18 +111,18 @@ public final class ComputerCraftProxyClient implements ClientModInitializer
|
||||
// My IDE doesn't think so, but we do actually need these generics.
|
||||
private static void registerContainers()
|
||||
{
|
||||
ScreenRegistry.<ContainerComputerBase, GuiComputer<ContainerComputerBase>>register( ComputerCraftRegistry.ModContainers.COMPUTER, GuiComputer::create );
|
||||
ScreenRegistry.<ContainerComputerBase, GuiComputer<ContainerComputerBase>>register( ComputerCraftRegistry.ModContainers.POCKET_COMPUTER,
|
||||
ScreenRegistry.<ContainerComputerBase, GuiComputer<ContainerComputerBase>>register( Registry.ModContainers.COMPUTER, GuiComputer::create );
|
||||
ScreenRegistry.<ContainerComputerBase, GuiComputer<ContainerComputerBase>>register( Registry.ModContainers.POCKET_COMPUTER,
|
||||
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 );
|
||||
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.<ContainerDiskDrive, GuiDiskDrive>register( ComputerCraftRegistry.ModContainers.DISK_DRIVE, GuiDiskDrive::new );
|
||||
ScreenRegistry.<ContainerHeldItem, GuiPrintout>register( ComputerCraftRegistry.ModContainers.PRINTOUT, GuiPrintout::new );
|
||||
ScreenRegistry.<ContainerPrinter, GuiPrinter>register( Registry.ModContainers.PRINTER, GuiPrinter::new );
|
||||
ScreenRegistry.<ContainerDiskDrive, GuiDiskDrive>register( Registry.ModContainers.DISK_DRIVE, GuiDiskDrive::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 );
|
||||
}
|
||||
|
||||
|
@@ -3,14 +3,13 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.mojang.math.Matrix3f;
|
||||
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.CableShapes;
|
||||
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();
|
||||
|
||||
// We only care about instances with both cable and modem.
|
||||
if( state.getBlock() != ComputerCraftRegistry.ModBlocks.CABLE || state.getValue( BlockCable.MODEM )
|
||||
.getFacing() == null || !state.getValue( BlockCable.CABLE ) )
|
||||
if( state.getBlock() != Registry.ModBlocks.CABLE || state.getValue( BlockCable.MODEM ).getFacing() == null || !state.getValue( BlockCable.CABLE ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
HitResult hitResult = Minecraft.getInstance().hitResult;
|
||||
|
||||
Vec3 hitPos = hitResult != null ? hitResult.getLocation() : new Vec3( d, e, f );
|
||||
|
||||
VoxelShape shape = WorldUtil.isVecInside( CableShapes.getModemShape( state ),
|
||||
hitPos.subtract( pos.getX(),
|
||||
pos.getY(),
|
||||
pos.getZ() ) ) ? CableShapes.getModemShape( state ) : CableShapes.getCableShape(
|
||||
state );
|
||||
VoxelShape shape = WorldUtil.isVecInside( CableShapes.getModemShape( state ), hitPos.subtract( pos.getX(), pos.getY(), pos.getZ() ) )
|
||||
? CableShapes.getModemShape( state )
|
||||
: CableShapes.getCableShape( state );
|
||||
|
||||
Vec3 cameraPos = info.getPosition();
|
||||
|
||||
double xOffset = pos.getX() - cameraPos.x();
|
||||
double yOffset = pos.getY() - cameraPos.y();
|
||||
double zOffset = pos.getZ() - cameraPos.z();
|
||||
Matrix4f matrix4f = stack.last()
|
||||
.pose();
|
||||
|
||||
Matrix4f matrix4f = stack.last().pose();
|
||||
Matrix3f normal = stack.last().normal();
|
||||
shape.forAllEdges( ( x1, y1, z1, x2, y2, z2 ) -> {
|
||||
float xDelta = (float) (x2 - x1);
|
||||
@@ -72,11 +70,13 @@ public final class CableHighlightRenderer
|
||||
yDelta = yDelta / 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 )
|
||||
.normal( normal, xDelta, yDelta, zDelta )
|
||||
.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 )
|
||||
.normal( normal, xDelta, yDelta, zDelta )
|
||||
.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_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" );
|
||||
|
||||
private static final Matrix4f IDENTITY = new Matrix4f();
|
||||
|
||||
static
|
||||
{
|
||||
IDENTITY.setIdentity();
|
||||
}
|
||||
|
||||
/**
|
||||
* The margin between the terminal and its border.
|
||||
*/
|
||||
public static final int MARGIN = 2;
|
||||
|
||||
/**
|
||||
* The width of the terminal border.
|
||||
*/
|
||||
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_BOTTOM_Y = CORNER_TOP_Y + BORDER;
|
||||
private static final int CORNER_LEFT_X = BORDER;
|
||||
@@ -40,21 +49,16 @@ public class ComputerBorderRenderer
|
||||
private static final int LIGHT_CORNER_Y = 80;
|
||||
|
||||
public static final int LIGHT_HEIGHT = 8;
|
||||
|
||||
public static final int TEX_SIZE = 256;
|
||||
private static final float TEX_SCALE = 1 / (float) TEX_SIZE;
|
||||
|
||||
static
|
||||
{
|
||||
IDENTITY.setIdentity();
|
||||
}
|
||||
|
||||
private final Matrix4f transform;
|
||||
private final VertexConsumer builder;
|
||||
private final int light;
|
||||
private final int z;
|
||||
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 )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
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 );
|
||||
@@ -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 )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
builder.vertex( transform, x, y + height, z )
|
||||
.color( r, g, b, 1.0f )
|
||||
.uv( u * TEX_SCALE, (v + textureHeight) * TEX_SCALE )
|
||||
.uv2( light )
|
||||
.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();
|
||||
builder.vertex( transform, x, y + height, z ).color( r, g, b, 1.0f ).uv( u * TEX_SCALE, (v + textureHeight) * TEX_SCALE ).uv2( light ).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.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Vector3f;
|
||||
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.renderer.ItemInHandRenderer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.block.model.ItemTransforms;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.entity.HumanoidArm;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
@Environment( EnvType.CLIENT )
|
||||
public abstract class ItemMapLikeRenderer
|
||||
{
|
||||
public void renderItemFirstPerson(
|
||||
PoseStack transform, MultiBufferSource render, int lightTexture, InteractionHand hand, float pitch, float equipProgress,
|
||||
float swingProgress, ItemStack stack
|
||||
)
|
||||
/**
|
||||
* 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 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;
|
||||
|
||||
@@ -37,17 +43,60 @@ public abstract class ItemMapLikeRenderer
|
||||
}
|
||||
else
|
||||
{
|
||||
renderItemFirstPersonSide( transform,
|
||||
render,
|
||||
lightTexture,
|
||||
renderItemFirstPersonSide(
|
||||
transform, render, lightTexture,
|
||||
hand == InteractionHand.MAIN_HAND ? player.getMainArm() : player.getMainArm().getOpposite(),
|
||||
equipProgress,
|
||||
swingProgress,
|
||||
stack );
|
||||
equipProgress, swingProgress, stack
|
||||
);
|
||||
}
|
||||
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.
|
||||
*
|
||||
@@ -58,9 +107,9 @@ public abstract class ItemMapLikeRenderer
|
||||
* @param equipProgress The equip progress of this item
|
||||
* @param swingProgress The swing progress of this item
|
||||
* @param stack The stack to render
|
||||
* @see ItemInHandRenderer#renderTwoHandedMap(PoseStack, MultiBufferSource, int, float, float, float)
|
||||
*/
|
||||
private void renderItemFirstPersonCenter( PoseStack transform, MultiBufferSource render, int combinedLight, float pitch, float equipProgress,
|
||||
float swingProgress, ItemStack stack )
|
||||
private void renderItemFirstPersonCenter( PoseStack transform, MultiBufferSource render, int combinedLight, float pitch, float equipProgress, float swingProgress, ItemStack stack )
|
||||
{
|
||||
Minecraft minecraft = Minecraft.getInstance();
|
||||
ItemInHandRenderer renderer = minecraft.getItemInHandRenderer();
|
||||
@@ -91,60 +140,4 @@ public abstract class ItemMapLikeRenderer
|
||||
|
||||
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.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.*;
|
||||
import com.mojang.math.Matrix4f;
|
||||
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.pocket.items.ItemPocketComputer;
|
||||
import dan200.computercraft.shared.util.Colour;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
@@ -39,7 +35,7 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
|
||||
}
|
||||
|
||||
@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 );
|
||||
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 );
|
||||
|
||||
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 );
|
||||
|
||||
// Render the main frame
|
||||
@@ -75,26 +71,21 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
|
||||
ComputerFamily family = item.getFamily();
|
||||
int frameColour = item.getColour( stack );
|
||||
|
||||
Matrix4f matrix = transform.last()
|
||||
.pose();
|
||||
renderFrame( matrix, render, family, frameColour, light, width, height );
|
||||
Matrix4f matrix = transform.last().pose();
|
||||
renderFrame( matrix, renderer, family, frameColour, light, width, height );
|
||||
|
||||
// Render the light
|
||||
int lightColour = ItemPocketComputer.getLightState( stack );
|
||||
if( lightColour == -1 )
|
||||
{
|
||||
lightColour = Colour.BLACK.getHex();
|
||||
}
|
||||
renderLight( matrix, lightColour, width, height );
|
||||
if( lightColour == -1 ) lightColour = Colour.BLACK.getHex();
|
||||
renderLight( matrix, renderer, lightColour, width, height );
|
||||
|
||||
if( computer != null && terminal != null )
|
||||
{
|
||||
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
|
||||
);
|
||||
FixedWidthFontRenderer.drawBlocker( transform.last().pose(), render, 0, 0, width, height );
|
||||
|
||||
FixedWidthFontRenderer.drawBlocker( transform.last().pose(), renderer, 0, 0, width, height );
|
||||
}
|
||||
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 )
|
||||
{
|
||||
RenderSystem.enableBlend();
|
||||
Minecraft.getInstance()
|
||||
.getTextureManager()
|
||||
.bindForSetup( 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 g = ((colour >>> 8) & 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 g = ((colour >>> 8) & 0xFF) / 255.0f;
|
||||
float b = (colour & 0xFF) / 255.0f;
|
||||
float z = 0.001f;
|
||||
|
||||
Tesselator tessellator = Tesselator.getInstance();
|
||||
BufferBuilder buffer = tessellator.getBuilder();
|
||||
buffer.begin( VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR );
|
||||
buffer.vertex( transform, width - LIGHT_HEIGHT * 2, height + LIGHT_HEIGHT + BORDER / 2.0f, 0 )
|
||||
.color( r, g, b, 1.0f )
|
||||
.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();
|
||||
VertexConsumer buffer = render.getBuffer( RenderTypes.POSITION_COLOR );
|
||||
buffer.vertex( transform, width - LIGHT_HEIGHT * 2, height + LIGHT_HEIGHT + BORDER / 2.0f, z ).color( r, g, b, 1.0f ).endVertex();
|
||||
buffer.vertex( transform, width, height + LIGHT_HEIGHT + BORDER / 2.0f, z ).color( r, g, b, 1.0f ).endVertex();
|
||||
buffer.vertex( transform, width, height + BORDER / 2.0f, z ).color( r, g, b, 1.0f ).endVertex();
|
||||
buffer.vertex( transform, width - LIGHT_HEIGHT * 2, height + BORDER / 2.0f, z ).color( r, g, b, 1.0f ).endVertex();
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
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
|
||||
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;
|
||||
|
||||
// Non-books will be left aligned
|
||||
if( !book )
|
||||
{
|
||||
width += offsetAt( pages );
|
||||
}
|
||||
if( !book ) width += offsetAt( pages );
|
||||
|
||||
double visualWidth = width, visualHeight = height;
|
||||
|
||||
@@ -70,27 +81,11 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer
|
||||
transform.scale( scale, scale, scale );
|
||||
transform.translate( (max - width) / 2.0, (max - height) / 2.0, 0.0 );
|
||||
|
||||
Matrix4f matrix = transform.last()
|
||||
.pose();
|
||||
Matrix4f matrix = transform.last().pose();
|
||||
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 ) );
|
||||
}
|
||||
|
||||
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;
|
||||
drawText(
|
||||
matrix, render, X_TEXT_MARGIN, Y_TEXT_MARGIN, 0, light,
|
||||
ItemPrintout.getText( stack ), ItemPrintout.getColours( stack )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
@@ -27,8 +26,8 @@ import java.util.EnumSet;
|
||||
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
|
||||
* intrusive outline on top of the screen.
|
||||
* Overrides monitor highlighting to only render the outline of the <em>whole</em> monitor, rather than the current
|
||||
* block. This means you do not get an intrusive outline on top of the screen.
|
||||
*/
|
||||
@Environment( EnvType.CLIENT )
|
||||
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.
|
||||
if( entity.isCrouching() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if( entity.isCrouching() ) return false;
|
||||
|
||||
Level world = entity.getCommandSenderWorld();
|
||||
|
||||
BlockEntity tile = world.getBlockEntity( pos );
|
||||
if( !(tile instanceof TileMonitor monitor) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if( !(tile instanceof TileMonitor monitor) ) return false;
|
||||
|
||||
// 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 );
|
||||
Direction front = monitor.getFront();
|
||||
faces.remove( front );
|
||||
if( monitor.getXIndex() != 0 )
|
||||
{
|
||||
faces.remove( monitor.getRight()
|
||||
.getOpposite() );
|
||||
}
|
||||
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() );
|
||||
}
|
||||
if( monitor.getXIndex() != 0 ) faces.remove( monitor.getRight().getOpposite() );
|
||||
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()
|
||||
.getPosition();
|
||||
matrixStack.pushPose();
|
||||
matrixStack.translate( pos.getX() - cameraPos.x(), pos.getY() - cameraPos.y(), pos.getZ() - cameraPos.z() );
|
||||
Vec3 cameraPos = Minecraft.getInstance().gameRenderer.getMainCamera().getPosition();
|
||||
transformStack.pushPose();
|
||||
transformStack.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
|
||||
Matrix4f transform = matrixStack.last()
|
||||
.pose();
|
||||
Matrix3f normal = matrixStack.last().normal();
|
||||
if( faces.contains( NORTH ) || faces.contains( WEST ) )
|
||||
{
|
||||
line( vertexConsumer, transform, normal, 0, 0, 0, UP );
|
||||
}
|
||||
if( faces.contains( SOUTH ) || faces.contains( WEST ) )
|
||||
{
|
||||
line( vertexConsumer, transform, normal, 0, 0, 1, UP );
|
||||
}
|
||||
if( faces.contains( NORTH ) || faces.contains( EAST ) )
|
||||
{
|
||||
line( vertexConsumer, transform, normal, 1, 0, 0, UP );
|
||||
}
|
||||
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();
|
||||
Matrix4f transform = transformStack.last().pose();
|
||||
Matrix3f normal = transformStack.last().normal();
|
||||
if( faces.contains( NORTH ) || faces.contains( WEST ) ) line( buffer, transform, normal, 0, 0, 0, UP );
|
||||
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 );
|
||||
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( DOWN ) ) line( buffer, transform, normal, 0, 0, 1, EAST );
|
||||
if( faces.contains( NORTH ) || faces.contains( UP ) ) line( buffer, transform, normal, 0, 1, 0, EAST );
|
||||
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( 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 );
|
||||
if( faces.contains( EAST ) || faces.contains( UP ) ) line( buffer, transform, normal, 1, 1, 0, SOUTH );
|
||||
|
||||
transformStack.popPose();
|
||||
return true;
|
||||
}
|
||||
|
||||
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 )
|
||||
.normal( normal, direction.getStepX(), direction.getStepY(), direction.getStepZ() )
|
||||
.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 )
|
||||
.normal( normal, direction.getStepX(), direction.getStepY(), direction.getStepZ() )
|
||||
.endVertex();
|
||||
|
@@ -29,13 +29,13 @@ public class MonitorTextureBufferShader extends ShaderInstance
|
||||
private final Uniform width;
|
||||
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" );
|
||||
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 );
|
||||
|
||||
Uniform tbo = getUniformChecked( "Tbo" );
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
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
|
||||
{
|
||||
private static final float BG_SIZE = 256.0f;
|
||||
|
||||
/**
|
||||
* Width of a page.
|
||||
*/
|
||||
public static final int X_SIZE = 172;
|
||||
|
||||
/**
|
||||
* Height of a page.
|
||||
*/
|
||||
public static final int Y_SIZE = 209;
|
||||
|
||||
/**
|
||||
* Padding between the left and right of a page and the text.
|
||||
*/
|
||||
public static final int X_TEXT_MARGIN = 13;
|
||||
|
||||
/**
|
||||
* Padding between the top and bottom of a page and the text.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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_X = X_SIZE + 4 * X_FOLD_SIZE;
|
||||
|
||||
@@ -53,18 +59,11 @@ public final class PrintoutRenderer
|
||||
VertexConsumer buffer = renderer.getBuffer( RenderTypes.PRINTOUT_TEXT );
|
||||
for( int line = 0; line < LINES_PER_PAGE && line < text.length; line++ )
|
||||
{
|
||||
FixedWidthFontRenderer.drawString( transform,
|
||||
buffer,
|
||||
x,
|
||||
y + line * FONT_HEIGHT,
|
||||
text[start + line],
|
||||
colours[start + line],
|
||||
null,
|
||||
Palette.DEFAULT,
|
||||
false,
|
||||
0,
|
||||
0,
|
||||
light );
|
||||
FixedWidthFontRenderer.drawString( transform, buffer,
|
||||
x, y + line * FONT_HEIGHT, 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 );
|
||||
for( int line = 0; line < LINES_PER_PAGE && line < text.length; line++ )
|
||||
{
|
||||
FixedWidthFontRenderer.drawString( transform,
|
||||
buffer,
|
||||
x,
|
||||
y + line * FONT_HEIGHT,
|
||||
new TextBuffer( text[start + line] ),
|
||||
new TextBuffer( colours[start + line] ),
|
||||
null,
|
||||
Palette.DEFAULT,
|
||||
false,
|
||||
0,
|
||||
0,
|
||||
light );
|
||||
FixedWidthFontRenderer.drawString( transform, buffer,
|
||||
x, y + line * FONT_HEIGHT,
|
||||
new TextBuffer( text[start + line] ), 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 );
|
||||
|
||||
// Draw centre panel (just stretched texture, sorry).
|
||||
drawTexture( transform,
|
||||
buffer,
|
||||
x - offset,
|
||||
y,
|
||||
z - 0.02f,
|
||||
X_SIZE + offset * 2,
|
||||
Y_SIZE,
|
||||
COVER_X + COVER_SIZE / 2.0f,
|
||||
COVER_SIZE,
|
||||
COVER_SIZE,
|
||||
Y_SIZE,
|
||||
light );
|
||||
drawTexture( transform, buffer,
|
||||
x - offset, y, 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;
|
||||
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 );
|
||||
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
|
||||
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
|
||||
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++ )
|
||||
{
|
||||
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.
|
||||
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 )
|
||||
{
|
||||
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 );
|
||||
}
|
||||
|
||||
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 )
|
||||
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 )
|
||||
{
|
||||
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 );
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
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 javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class RenderTypes
|
||||
{
|
||||
|
||||
public static final int FULL_BRIGHT_LIGHTMAP = (0xF << 4) | (0xF << 20);
|
||||
|
||||
@Nullable
|
||||
public static MonitorTextureBufferShader monitorTboShader;
|
||||
|
||||
@Nullable
|
||||
public static ShaderInstance terminalShader;
|
||||
|
||||
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.BLOCKER;
|
||||
public static final RenderType TERMINAL_BLOCKER = Types.TERMINAL_BLOCKER;
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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 POSITION_COLOR = Types.POSITION_COLOR;
|
||||
@@ -53,24 +54,26 @@ public class RenderTypes
|
||||
|
||||
private static final class Types extends RenderStateShard
|
||||
{
|
||||
private static final VertexFormat.Mode GL_MODE = VertexFormat.Mode.TRIANGLES;
|
||||
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(
|
||||
private static final RenderStateShard.TextureStateShard TERM_FONT_TEXTURE = new TextureStateShard(
|
||||
FixedWidthFontRenderer.FONT,
|
||||
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()
|
||||
.setTextureState( TERM_FONT_TEXTURE ) // blur, minimap
|
||||
.setShaderState( new RenderStateShard.ShaderStateShard( RenderTypes::getMonitorTextureBufferShader ) )
|
||||
.setWriteMaskState( RenderType.COLOR_DEPTH_WRITE )
|
||||
.createCompositeState( false ) );
|
||||
.setTextureState( TERM_FONT_TEXTURE )
|
||||
.setShaderState( new ShaderStateShard( RenderTypes::getMonitorTextureBufferShader ) )
|
||||
.setWriteMaskState( COLOR_WRITE )
|
||||
.createCompositeState( false )
|
||||
);
|
||||
|
||||
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
|
||||
RenderType.CompositeState.builder()
|
||||
.setTextureState( TERM_FONT_TEXTURE )
|
||||
@@ -79,15 +82,18 @@ public class RenderTypes
|
||||
.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()
|
||||
.setTextureState( TERM_FONT_TEXTURE )
|
||||
.setShaderState( TERM_SHADER )
|
||||
.setWriteMaskState( DEPTH_WRITE )
|
||||
.createCompositeState( false ) );
|
||||
.createCompositeState( false )
|
||||
);
|
||||
|
||||
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
|
||||
RenderType.CompositeState.builder()
|
||||
.setTextureState( TERM_FONT_TEXTURE )
|
||||
@@ -95,8 +101,11 @@ public class RenderTypes
|
||||
.createCompositeState( false )
|
||||
);
|
||||
|
||||
/**
|
||||
* A variant of {@link #TERMINAL_WITH_DEPTH} which uses the lightmap rather than rendering fullbright.
|
||||
*/
|
||||
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
|
||||
RenderType.CompositeState.builder()
|
||||
.setTextureState( TERM_FONT_TEXTURE )
|
||||
|
@@ -3,10 +3,10 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.platform.MemoryTracker;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.*;
|
||||
import com.mojang.math.Matrix4f;
|
||||
@@ -35,27 +35,25 @@ import org.lwjgl.opengl.GL31;
|
||||
import javax.annotation.Nonnull;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static com.mojang.blaze3d.platform.MemoryTracker.create;
|
||||
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.*;
|
||||
|
||||
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 Matrix4f IDENTITY = Transformation.identity()
|
||||
.getMatrix();
|
||||
private static ByteBuffer tboContents;
|
||||
|
||||
private static final Matrix4f IDENTITY = Transformation.identity().getMatrix();
|
||||
|
||||
public TileEntityMonitorRenderer( BlockEntityRendererProvider.Context context )
|
||||
{
|
||||
// super( context );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render( @Nonnull TileMonitor monitor, float partialTicks, @Nonnull PoseStack transform, @Nonnull MultiBufferSource renderer,
|
||||
int lightmapCoord, int overlayLight )
|
||||
public void render( @Nonnull TileMonitor monitor, float partialTicks, @Nonnull PoseStack transform, @Nonnull MultiBufferSource renderer, int lightmapCoord, int overlayLight )
|
||||
{
|
||||
// Render from the origin monitor
|
||||
ClientMonitor originTerminal = monitor.getClientMonitor();
|
||||
@@ -86,15 +84,19 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito
|
||||
|
||||
// Setup initial transform
|
||||
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.getZ() - monitorPos.getZ() + 0.5 );
|
||||
originPos.getZ() - monitorPos.getZ() + 0.5
|
||||
);
|
||||
|
||||
transform.mulPose( Vector3f.YN.rotationDegrees( yaw ) );
|
||||
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,
|
||||
0.50 );
|
||||
0.5
|
||||
);
|
||||
double xSize = origin.getWidth() - 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
|
||||
// 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();
|
||||
|
||||
// Draw the background blocker
|
||||
FixedWidthFontRenderer.drawBlocker(
|
||||
transform.last().pose(), renderer,
|
||||
-MARGIN, MARGIN,
|
||||
(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() );
|
||||
}
|
||||
else
|
||||
{
|
||||
FixedWidthFontRenderer.drawEmptyTerminal( transform.last()
|
||||
.pose(),
|
||||
renderer,
|
||||
-MARGIN,
|
||||
MARGIN,
|
||||
(float) (xSize + 2 * MARGIN),
|
||||
(float) -(ySize + MARGIN * 2) );
|
||||
FixedWidthFontRenderer.drawEmptyTerminal(
|
||||
transform.last().pose(), renderer,
|
||||
-MARGIN, MARGIN,
|
||||
(float) (xSize + 2 * MARGIN), (float) -(ySize + MARGIN * 2)
|
||||
);
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
MonitorRenderer renderType = MonitorRenderer.current();
|
||||
boolean redraw = monitor.pollTerminalChanged();
|
||||
if( monitor.createBuffer( renderType ) )
|
||||
{
|
||||
redraw = true;
|
||||
}
|
||||
if( monitor.createBuffer( renderType ) ) redraw = true;
|
||||
|
||||
switch( renderType )
|
||||
{
|
||||
case TBO:
|
||||
{
|
||||
|
||||
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 )
|
||||
{
|
||||
int size = width * height * 3;
|
||||
if( tboContents == null || tboContents.capacity() < size )
|
||||
{
|
||||
tboContents = create( size );
|
||||
tboContents = MemoryTracker.create( size );
|
||||
}
|
||||
|
||||
ByteBuffer monitorBuffer = tboContents;
|
||||
@@ -204,37 +204,34 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito
|
||||
tboVertex( buffer, matrix, pixelWidth + xMargin, -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 );
|
||||
break;
|
||||
}
|
||||
|
||||
case VBO:
|
||||
{
|
||||
VertexBuffer vbo = monitor.buffer;
|
||||
if( redraw )
|
||||
{
|
||||
Tesselator tessellator = Tesselator.getInstance();
|
||||
BufferBuilder builder = tessellator.getBuilder();
|
||||
builder.begin( RenderTypes.TERMINAL_WITHOUT_DEPTH.mode(), RenderTypes.TERMINAL_WITHOUT_DEPTH.format() );
|
||||
FixedWidthFontRenderer.drawTerminalWithoutCursor( IDENTITY,
|
||||
builder,
|
||||
0,
|
||||
0,
|
||||
terminal,
|
||||
!monitor.isColour(),
|
||||
yMargin,
|
||||
yMargin,
|
||||
xMargin,
|
||||
xMargin );
|
||||
FixedWidthFontRenderer.drawTerminalWithoutCursor(
|
||||
IDENTITY, builder, 0, 0,
|
||||
terminal, !monitor.isColour(), yMargin, yMargin, xMargin, xMargin
|
||||
);
|
||||
|
||||
builder.end();
|
||||
vbo.upload( builder );
|
||||
}
|
||||
|
||||
renderer.getBuffer( RenderTypes.TERMINAL_WITHOUT_DEPTH );
|
||||
|
||||
RenderTypes.TERMINAL_WITHOUT_DEPTH.setupRenderState();
|
||||
vbo.drawWithShader( matrix, RenderSystem.getProjectionMatrix(), RenderTypes.getTerminalShader() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -47,7 +47,7 @@ public class TileEntityTurtleRenderer implements BlockEntityRenderer<TileTurtle>
|
||||
|
||||
private final Random random = new Random( 0 );
|
||||
|
||||
BlockEntityRenderDispatcher renderer;
|
||||
private final BlockEntityRenderDispatcher renderer;
|
||||
|
||||
public TileEntityTurtleRenderer( BlockEntityRendererProvider.Context context )
|
||||
{
|
||||
@@ -68,39 +68,28 @@ public class TileEntityTurtleRenderer implements BlockEntityRenderer<TileTurtle>
|
||||
|
||||
public static ModelResourceLocation getTurtleOverlayModel( ResourceLocation overlay, boolean christmas )
|
||||
{
|
||||
if( overlay != null )
|
||||
{
|
||||
return new ModelResourceLocation( overlay, "inventory" );
|
||||
}
|
||||
if( christmas )
|
||||
{
|
||||
return ELF_OVERLAY_MODEL;
|
||||
}
|
||||
if( overlay != null ) return new ModelResourceLocation( overlay, "inventory" );
|
||||
if( christmas ) return ELF_OVERLAY_MODEL;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render( @Nonnull TileTurtle turtle, float partialTicks, @Nonnull PoseStack transform, @Nonnull MultiBufferSource buffers,
|
||||
int lightmapCoord, int overlayLight )
|
||||
public void render( @Nonnull TileTurtle turtle, float partialTicks, @Nonnull PoseStack transform, @Nonnull MultiBufferSource buffers, int lightmapCoord, int overlayLight )
|
||||
{
|
||||
// Render the label
|
||||
String label = turtle.createProxy()
|
||||
.getLabel();
|
||||
String label = turtle.createProxy().getLabel();
|
||||
HitResult hit = renderer.cameraHitResult;
|
||||
if( label != null && hit.getType() == HitResult.Type.BLOCK && turtle.getBlockPos()
|
||||
.equals( ((BlockHitResult) hit).getBlockPos() ) )
|
||||
if( label != null && hit.getType() == HitResult.Type.BLOCK && turtle.getBlockPos().equals( ((BlockHitResult) hit).getBlockPos() ) )
|
||||
{
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
Font font = mc.font;
|
||||
|
||||
transform.pushPose();
|
||||
transform.translate( 0.5, 1.2, 0.5 );
|
||||
transform.mulPose( mc.getEntityRenderDispatcher()
|
||||
.cameraOrientation() );
|
||||
transform.mulPose( mc.getEntityRenderDispatcher().cameraOrientation() );
|
||||
transform.scale( -0.025f, -0.025f, 0.025f );
|
||||
|
||||
Matrix4f matrix = transform.last()
|
||||
.pose();
|
||||
Matrix4f matrix = transform.last().pose();
|
||||
int opacity = (int) (mc.options.getBackgroundOpacity( 0.25f ) * 255) << 24;
|
||||
float width = -font.width( label ) / 2.0f;
|
||||
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();
|
||||
}
|
||||
|
||||
private void renderUpgrade( @Nonnull PoseStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, TileTurtle turtle,
|
||||
TurtleSide side, float f )
|
||||
private void renderUpgrade( @Nonnull PoseStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, TileTurtle turtle, TurtleSide side, float f )
|
||||
{
|
||||
ITurtleUpgrade upgrade = turtle.getUpgrade( side );
|
||||
if( upgrade == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
if( upgrade == null ) return;
|
||||
transform.pushPose();
|
||||
|
||||
float toolAngle = turtle.getToolRenderAngle( side, f );
|
||||
@@ -170,18 +155,13 @@ public class TileEntityTurtleRenderer implements BlockEntityRenderer<TileTurtle>
|
||||
transform.popPose();
|
||||
}
|
||||
|
||||
private void renderModel( @Nonnull PoseStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight,
|
||||
ModelResourceLocation modelLocation, int[] tints )
|
||||
private void renderModel( @Nonnull PoseStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, ModelResourceLocation modelLocation, int[] tints )
|
||||
{
|
||||
ModelManager modelManager = Minecraft.getInstance()
|
||||
.getItemRenderer()
|
||||
.getItemModelShaper()
|
||||
.getModelManager();
|
||||
ModelManager modelManager = Minecraft.getInstance().getItemRenderer().getItemModelShaper().getModelManager();
|
||||
renderModel( transform, renderer, lightmapCoord, overlayLight, modelManager.getModel( modelLocation ), tints );
|
||||
}
|
||||
|
||||
private void renderModel( @Nonnull PoseStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, BakedModel model,
|
||||
int[] tints )
|
||||
private void renderModel( @Nonnull PoseStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, BakedModel model, int[] tints )
|
||||
{
|
||||
random.setSeed( 0 );
|
||||
renderQuads( transform, renderer, lightmapCoord, overlayLight, model.getQuads( null, null, random ), 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,
|
||||
List<BakedQuad> quads, int[] tints )
|
||||
private static void renderQuads( @Nonnull PoseStack transform, @Nonnull VertexConsumer buffer, int lightmapCoord, int overlayLight, List<BakedQuad> quads, int[] tints )
|
||||
{
|
||||
PoseStack.Pose matrix = transform.last();
|
||||
|
||||
@@ -202,10 +181,7 @@ public class TileEntityTurtleRenderer implements BlockEntityRenderer<TileTurtle>
|
||||
if( tints != null && bakedquad.isTinted() )
|
||||
{
|
||||
int idx = bakedquad.getTintIndex();
|
||||
if( idx >= 0 && idx < tints.length )
|
||||
{
|
||||
tint = tints[bakedquad.getTintIndex()];
|
||||
}
|
||||
if( idx >= 0 && idx < tints.length ) tint = tints[bakedquad.getTintIndex()];
|
||||
}
|
||||
|
||||
float f = (float) (tint >> 16 & 255) / 255.0F;
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import com.mojang.math.Transformation;
|
||||
@@ -32,8 +31,7 @@ public class TurtleMultiModel implements BakedModel
|
||||
private List<BakedQuad> generalQuads = null;
|
||||
private final Map<Direction, List<BakedQuad>> faceQuads = new EnumMap<>( Direction.class );
|
||||
|
||||
public TurtleMultiModel( BakedModel baseModel, BakedModel overlayModel, Transformation generalTransform, TransformedModel leftUpgradeModel,
|
||||
TransformedModel rightUpgradeModel )
|
||||
public TurtleMultiModel( BakedModel baseModel, BakedModel overlayModel, Transformation generalTransform, TransformedModel leftUpgradeModel, TransformedModel rightUpgradeModel )
|
||||
{
|
||||
// Get the models
|
||||
this.baseModel = baseModel;
|
||||
@@ -45,22 +43,17 @@ public class TurtleMultiModel implements BakedModel
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
public List<BakedQuad> getQuads( BlockState state, Direction side, @Nonnull Random rand )
|
||||
{
|
||||
if( side != null )
|
||||
{
|
||||
if( !faceQuads.containsKey( side ) )
|
||||
{
|
||||
faceQuads.put( side, buildQuads( state, side, rand ) );
|
||||
}
|
||||
if( !faceQuads.containsKey( side ) ) faceQuads.put( side, buildQuads( state, side, rand ) );
|
||||
return faceQuads.get( side );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( generalQuads == null )
|
||||
{
|
||||
generalQuads = buildQuads( state, side, rand );
|
||||
}
|
||||
if( generalQuads == null ) generalQuads = buildQuads( state, side, rand );
|
||||
return generalQuads;
|
||||
}
|
||||
}
|
||||
@@ -70,24 +63,20 @@ public class TurtleMultiModel implements BakedModel
|
||||
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 )
|
||||
{
|
||||
ModelTransformer.transformQuadsTo( quads, overlayModel.getQuads( state, side, rand ), generalTransform.getMatrix() );
|
||||
transformQuadsTo( quads, overlayModel.getQuads( state, side, rand ), generalTransform );
|
||||
}
|
||||
if( leftUpgradeModel != null )
|
||||
{
|
||||
Transformation upgradeTransform = generalTransform.compose( leftUpgradeModel.getMatrix() );
|
||||
ModelTransformer.transformQuadsTo( quads, leftUpgradeModel.getModel()
|
||||
.getQuads( state, side, rand ),
|
||||
upgradeTransform.getMatrix() );
|
||||
transformQuadsTo( quads, leftUpgradeModel.getModel().getQuads( state, side, rand ), upgradeTransform );
|
||||
}
|
||||
if( rightUpgradeModel != null )
|
||||
{
|
||||
Transformation upgradeTransform = generalTransform.compose( rightUpgradeModel.getMatrix() );
|
||||
ModelTransformer.transformQuadsTo( quads, rightUpgradeModel.getModel()
|
||||
.getQuads( state, side, rand ),
|
||||
upgradeTransform.getMatrix() );
|
||||
transformQuadsTo( quads, rightUpgradeModel.getModel().getQuads( state, side, rand ), upgradeTransform );
|
||||
}
|
||||
quads.trimToSize();
|
||||
return quads;
|
||||
@@ -105,18 +94,18 @@ public class TurtleMultiModel implements BakedModel
|
||||
return baseModel.isGui3d();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean usesBlockLight()
|
||||
{
|
||||
return baseModel.usesBlockLight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCustomRenderer()
|
||||
{
|
||||
return baseModel.isCustomRenderer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean usesBlockLight()
|
||||
{
|
||||
return baseModel.usesBlockLight();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
@@ -139,4 +128,9 @@ public class TurtleMultiModel implements BakedModel
|
||||
{
|
||||
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;
|
||||
|
||||
public class TurtlePlayerRenderer extends EntityRenderer<TurtlePlayer>
|
||||
{ //FIXME Make sure this isn't an issue. Context was EntityRenderDispatcher.
|
||||
public TurtlePlayerRenderer( EntityRendererProvider.Context context )
|
||||
{
|
||||
super( context );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render( @Nonnull TurtlePlayer entityIn, float entityYaw, float partialTicks, @Nonnull PoseStack transform,
|
||||
@Nonnull MultiBufferSource buffer, int packedLightIn )
|
||||
{
|
||||
public TurtlePlayerRenderer( EntityRendererProvider.Context renderManager )
|
||||
{
|
||||
super( renderManager );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@@ -33,4 +27,9 @@ public class TurtlePlayerRenderer extends EntityRenderer<TurtlePlayer>
|
||||
{
|
||||
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;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Transformation;
|
||||
import dan200.computercraft.api.client.TransformedModel;
|
||||
@@ -50,59 +49,18 @@ public class TurtleSmartItemModel implements BakedModel
|
||||
stack.translate( 0, 0, 1 );
|
||||
|
||||
identity = Transformation.identity();
|
||||
flip = new Transformation( stack.last()
|
||||
.pose() );
|
||||
flip = new Transformation( stack.last().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;
|
||||
@@ -121,7 +79,7 @@ public class TurtleSmartItemModel implements BakedModel
|
||||
{
|
||||
@Nonnull
|
||||
@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();
|
||||
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 );
|
||||
|
||||
BakedModel model = cachedModels.get( combo );
|
||||
if( model == null )
|
||||
{
|
||||
cachedModels.put( combo, model = buildModel( combo ) );
|
||||
}
|
||||
if( model == null ) cachedModels.put( combo, model = buildModel( combo ) );
|
||||
return model;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ItemOverrides getOverrides()
|
||||
{
|
||||
return overrides;
|
||||
}
|
||||
|
||||
private BakedModel buildModel( TurtleModelCombination combo )
|
||||
{
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
ModelManager modelManager = mc.getItemRenderer()
|
||||
.getItemModelShaper()
|
||||
.getModelManager();
|
||||
ModelManager modelManager = mc.getItemRenderer().getItemModelShaper().getModelManager();
|
||||
ModelResourceLocation overlayModelLocation = TileEntityTurtleRenderer.getTurtleOverlayModel( combo.overlay, combo.christmas );
|
||||
|
||||
BakedModel baseModel = combo.colour ? colourModel : familyModel;
|
||||
@@ -179,12 +139,6 @@ public class TurtleSmartItemModel implements BakedModel
|
||||
return familyModel.isGui3d();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean usesBlockLight()
|
||||
{
|
||||
return familyModel.usesBlockLight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCustomRenderer()
|
||||
{
|
||||
@@ -192,17 +146,17 @@ public class TurtleSmartItemModel implements BakedModel
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public TextureAtlasSprite getParticleIcon()
|
||||
public boolean usesBlockLight()
|
||||
{
|
||||
return familyModel.getParticleIcon();
|
||||
return familyModel.usesBlockLight();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ItemOverrides getOverrides()
|
||||
@Deprecated
|
||||
public TextureAtlasSprite getParticleIcon()
|
||||
{
|
||||
return overrides;
|
||||
return familyModel.getParticleIcon();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
|
@@ -484,7 +484,7 @@ public class FSAPI implements ILuaAPI
|
||||
*
|
||||
* This string is formatted like a normal path string, but can include any
|
||||
* 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}.
|
||||
*
|
||||
* @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.computer.ComputerSide;
|
||||
import dan200.computercraft.core.tracking.TrackingField;
|
||||
import dan200.computercraft.shared.util.LuaUtil;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
@@ -36,6 +37,7 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
|
||||
private final IPeripheral peripheral;
|
||||
|
||||
private final String type;
|
||||
private final Set<String> additionalTypes;
|
||||
private final Map<String, PeripheralMethod> methodMap;
|
||||
private boolean attached;
|
||||
|
||||
@@ -47,6 +49,7 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
|
||||
attached = false;
|
||||
|
||||
type = Objects.requireNonNull( peripheral.getType(), "Peripheral type cannot be null" );
|
||||
additionalTypes = peripheral.getAdditionalTypes();
|
||||
|
||||
methodMap = PeripheralAPI.getMethods( peripheral );
|
||||
}
|
||||
@@ -61,6 +64,11 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
|
||||
return type;
|
||||
}
|
||||
|
||||
public Set<String> getAdditionalTypes()
|
||||
{
|
||||
return additionalTypes;
|
||||
}
|
||||
|
||||
public Collection<String> getMethods()
|
||||
{
|
||||
return methodMap.keySet();
|
||||
@@ -298,7 +306,23 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
|
||||
synchronized( peripherals )
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@@ -100,7 +100,7 @@ public class BinaryWritableHandle extends HandleGeneric
|
||||
try
|
||||
{
|
||||
// Technically this is not needed
|
||||
if( writer instanceof FileChannel ) ((FileChannel) writer).force( false );
|
||||
if( writer instanceof FileChannel channel ) channel.force( false );
|
||||
}
|
||||
catch( IOException ignored )
|
||||
{
|
||||
|
@@ -153,7 +153,7 @@ public class WebsocketHandle implements Closeable
|
||||
return MethodResult.of();
|
||||
}
|
||||
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.
|
||||
return MethodResult.of();
|
||||
|
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
package dan200.computercraft.fabric.mixin;
|
||||
|
||||
import dan200.computercraft.shared.ComputerCraftRegistry;
|
||||
import dan200.computercraft.shared.Registry;
|
||||
import net.minecraft.advancements.CriteriaTriggers;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
@@ -33,7 +33,7 @@ public class MixinServerPlayerGameMode
|
||||
{
|
||||
BlockPos pos = hitResult.getBlockPos();
|
||||
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 );
|
||||
if( actionResult.consumesAction() )
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
@@ -34,18 +33,9 @@ public final class BundledRedstone
|
||||
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 )
|
||||
{
|
||||
if( !world.isInWorldBounds( pos ) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if( !world.isInWorldBounds( pos ) ) return -1;
|
||||
|
||||
// Try the providers in order:
|
||||
int combinedSignal = -1;
|
||||
@@ -67,4 +57,10 @@ public final class BundledRedstone
|
||||
|
||||
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.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
@@ -30,10 +29,7 @@ public final class MediaProviders
|
||||
|
||||
public static IMedia get( @Nonnull ItemStack stack )
|
||||
{
|
||||
if( stack.isEmpty() )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if( stack.isEmpty() ) return null;
|
||||
|
||||
// Try the handlers in order:
|
||||
for( IMediaProvider mediaProvider : providers )
|
||||
@@ -41,10 +37,7 @@ public final class MediaProviders
|
||||
try
|
||||
{
|
||||
IMedia media = mediaProvider.getMedia( stack );
|
||||
if( media != null )
|
||||
{
|
||||
return media;
|
||||
}
|
||||
if( media != null ) return media;
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
@@ -47,10 +46,7 @@ public final class Peripherals
|
||||
try
|
||||
{
|
||||
IPeripheral peripheral = peripheralProvider.getPeripheral( world, pos, side );
|
||||
if( peripheral != null )
|
||||
{
|
||||
return peripheral;
|
||||
}
|
||||
if( peripheral != null ) return peripheral;
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
|
@@ -15,6 +15,7 @@ import net.minecraft.world.item.ItemStack;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public final class PocketUpgrades
|
||||
{
|
||||
@@ -72,17 +73,18 @@ public final class PocketUpgrades
|
||||
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()
|
||||
{
|
||||
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[] {
|
||||
// ComputerCraft upgrades
|
||||
ComputerCraftRegistry.TurtleUpgrades.wirelessModemNormal,
|
||||
ComputerCraftRegistry.TurtleUpgrades.wirelessModemAdvanced,
|
||||
ComputerCraftRegistry.TurtleUpgrades.speaker,
|
||||
Registry.TurtleUpgrades.wirelessModemNormal,
|
||||
Registry.TurtleUpgrades.wirelessModemAdvanced,
|
||||
Registry.TurtleUpgrades.speaker,
|
||||
|
||||
// Vanilla Minecraft upgrades
|
||||
ComputerCraftRegistry.TurtleUpgrades.diamondPickaxe,
|
||||
ComputerCraftRegistry.TurtleUpgrades.diamondAxe,
|
||||
ComputerCraftRegistry.TurtleUpgrades.diamondSword,
|
||||
ComputerCraftRegistry.TurtleUpgrades.diamondShovel,
|
||||
ComputerCraftRegistry.TurtleUpgrades.diamondHoe,
|
||||
ComputerCraftRegistry.TurtleUpgrades.craftingTable,
|
||||
Registry.TurtleUpgrades.diamondPickaxe,
|
||||
Registry.TurtleUpgrades.diamondAxe,
|
||||
Registry.TurtleUpgrades.diamondSword,
|
||||
Registry.TurtleUpgrades.diamondShovel,
|
||||
Registry.TurtleUpgrades.diamondHoe,
|
||||
Registry.TurtleUpgrades.craftingTable,
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -6,7 +6,9 @@
|
||||
package dan200.computercraft.shared.command;
|
||||
|
||||
import dan200.computercraft.shared.util.IDAssigner;
|
||||
import me.shedaniel.cloth.api.utils.v1.GameInstanceUtils;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -28,6 +30,9 @@ public final class ClientCommands
|
||||
// Emulate the command on the client side
|
||||
if( message.startsWith( OPEN_COMPUTER ) )
|
||||
{
|
||||
MinecraftServer server = GameInstanceUtils.getServer();
|
||||
if( server == null || server.isDedicatedServer() ) return false;
|
||||
|
||||
String idStr = message.substring( OPEN_COMPUTER.length() ).trim();
|
||||
int id;
|
||||
try
|
||||
@@ -36,7 +41,7 @@ public final class ClientCommands
|
||||
}
|
||||
catch( NumberFormatException ignore )
|
||||
{
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
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.core.BlockPos;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.network.chat.TranslatableComponent;
|
||||
@@ -82,15 +83,15 @@ public final class CommandComputerCraft
|
||||
BlockPos pos = new BlockPos( source.getPosition() );
|
||||
|
||||
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 ) );
|
||||
}
|
||||
else if( a.getWorld() == world )
|
||||
else if( a.getLevel() == world )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if( b.getWorld() == world )
|
||||
else if( b.getLevel() == world )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@@ -171,15 +172,14 @@ public final class CommandComputerCraft
|
||||
.arg( "computer", oneComputer() )
|
||||
.executes( context -> {
|
||||
ServerComputer computer = getComputerArgument( context, "computer" );
|
||||
Level world = computer.getWorld();
|
||||
Level world = computer.getLevel();
|
||||
BlockPos pos = computer.getPosition();
|
||||
|
||||
if( world == null || pos == null ) throw TP_NOT_THERE.create();
|
||||
|
||||
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 )
|
||||
{
|
||||
player.connection.teleport(
|
||||
@@ -236,7 +236,7 @@ public final class CommandComputerCraft
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public MutableComponent getDisplayName()
|
||||
public Component getDisplayName()
|
||||
{
|
||||
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( "" );
|
||||
|
||||
@@ -333,14 +333,14 @@ public final class CommandComputerCraft
|
||||
|
||||
if( UserLevel.OWNER.test( source ) && isPlayer( source ) )
|
||||
{
|
||||
MutableComponent linkPath = linkStorage( computerId );
|
||||
Component linkPath = linkStorage( computerId );
|
||||
if( linkPath != null ) out.append( " " ).append( linkPath );
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
private static MutableComponent linkPosition( CommandSourceStack context, ServerComputer computer )
|
||||
private static Component linkPosition( CommandSourceStack context, ServerComputer computer )
|
||||
{
|
||||
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 );
|
||||
if( !file.isDirectory() ) return null;
|
||||
@@ -398,7 +398,7 @@ public final class CommandComputerCraft
|
||||
|
||||
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" );
|
||||
for( int i = 0; i < fields.size(); i++ ) headers[i + 1] = translate( fields.get( i ).translationKey() );
|
||||
TableBuilder table = new TableBuilder( TRACK_ID, headers );
|
||||
@@ -408,9 +408,9 @@ public final class CommandComputerCraft
|
||||
Computer computer = entry.getComputer();
|
||||
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;
|
||||
for( int i = 0; i < fields.size(); i++ ) row[i + 1] = text( entry.getFormatted( fields.get( i ) ) );
|
||||
table.row( row );
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.command;
|
||||
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
@@ -27,12 +26,13 @@ public final class CommandUtils
|
||||
public static boolean isPlayer( CommandSourceStack output )
|
||||
{
|
||||
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" )
|
||||
public static CompletableFuture<Suggestions> suggestOnServer( CommandContext<?> context, SuggestionsBuilder builder,
|
||||
Function<CommandContext<CommandSourceStack>, CompletableFuture<Suggestions>> supplier )
|
||||
public static CompletableFuture<Suggestions> suggestOnServer( CommandContext<?> context, SuggestionsBuilder builder, Function<CommandContext<CommandSourceStack>, CompletableFuture<Suggestions>> supplier )
|
||||
{
|
||||
Object source = context.getSource();
|
||||
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 )
|
||||
{
|
||||
String remaining = builder.getRemaining()
|
||||
.toLowerCase( Locale.ROOT );
|
||||
String remaining = builder.getRemaining().toLowerCase( Locale.ROOT );
|
||||
for( T choice : candidates )
|
||||
{
|
||||
String name = toString.apply( choice );
|
||||
if( !name.toLowerCase( Locale.ROOT )
|
||||
.startsWith( remaining ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if( !name.toLowerCase( Locale.ROOT ).startsWith( remaining ) ) continue;
|
||||
builder.suggest( name );
|
||||
}
|
||||
|
||||
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.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.command;
|
||||
|
||||
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 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 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_PLAYER = translated( "commands.computercraft.tp.not_player" );
|
||||
|
||||
public static final SimpleCommandExceptionType ARGUMENT_EXPECTED = translated( "argument.computercraft.argument_expected" );
|
||||
|
||||
private static SimpleCommandExceptionType translated( String key )
|
||||
{
|
||||
return new SimpleCommandExceptionType( new TranslatableComponent( key ) );
|
||||
|
@@ -67,6 +67,6 @@ public enum UserLevel implements Predicate<CommandSourceStack>
|
||||
Entity sender = source.getEntity();
|
||||
return server.isDedicatedServer()
|
||||
? 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.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.command.arguments;
|
||||
|
||||
import com.mojang.brigadier.arguments.ArgumentType;
|
||||
@@ -15,17 +14,10 @@ import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
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() );
|
||||
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 ) );
|
||||
ArgumentTypes.register( id.toString(), 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 );
|
||||
}
|
||||
|
||||
@SuppressWarnings( "unchecked" )
|
||||
private static <T extends ArgumentType<?>> void registerUnsafe( ResourceLocation id, Class<T> type, ArgumentSerializer<?> serializer )
|
||||
private static <T extends ArgumentType<?>> void register( ResourceLocation id, T instance )
|
||||
{
|
||||
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.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.command.arguments;
|
||||
|
||||
import com.mojang.brigadier.Message;
|
||||
@@ -43,10 +42,7 @@ public abstract class ChoiceArgumentType<T> implements ArgumentType<T>
|
||||
for( T choice : choices )
|
||||
{
|
||||
String choiceName = this.name.apply( choice );
|
||||
if( name.equals( choiceName ) )
|
||||
{
|
||||
return choice;
|
||||
}
|
||||
if( name.equals( choiceName ) ) return choice;
|
||||
}
|
||||
|
||||
reader.setCursor( start );
|
||||
@@ -56,16 +52,11 @@ public abstract class ChoiceArgumentType<T> implements ArgumentType<T>
|
||||
@Override
|
||||
public <S> CompletableFuture<Suggestions> listSuggestions( CommandContext<S> context, SuggestionsBuilder builder )
|
||||
{
|
||||
String remaining = builder.getRemaining()
|
||||
.toLowerCase( Locale.ROOT );
|
||||
String remaining = builder.getRemaining().toLowerCase( Locale.ROOT );
|
||||
for( T choice : choices )
|
||||
{
|
||||
String name = this.name.apply( choice );
|
||||
if( !name.toLowerCase( Locale.ROOT )
|
||||
.startsWith( remaining ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if( !name.toLowerCase( Locale.ROOT ).startsWith( remaining ) ) continue;
|
||||
builder.suggest( name, tooltip.apply( choice ) );
|
||||
}
|
||||
|
||||
@@ -76,10 +67,7 @@ public abstract class ChoiceArgumentType<T> implements ArgumentType<T>
|
||||
public Collection<String> getExamples()
|
||||
{
|
||||
List<String> items = choices instanceof Collection<?> ? new ArrayList<>( ((Collection<T>) choices).size() ) : new ArrayList<>();
|
||||
for( T choice : choices )
|
||||
{
|
||||
items.add( name.apply( choice ) );
|
||||
}
|
||||
for( T choice : choices ) items.add( name.apply( choice ) );
|
||||
items.sort( Comparator.naturalOrder() );
|
||||
return items;
|
||||
}
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.command.arguments;
|
||||
|
||||
import com.mojang.brigadier.StringReader;
|
||||
@@ -25,10 +24,6 @@ public final class ComputerArgumentType implements ArgumentType<ComputerArgument
|
||||
{
|
||||
private static final ComputerArgumentType INSTANCE = new ComputerArgumentType();
|
||||
|
||||
private ComputerArgumentType()
|
||||
{
|
||||
}
|
||||
|
||||
public static ComputerArgumentType oneComputer()
|
||||
{
|
||||
return INSTANCE;
|
||||
@@ -36,27 +31,24 @@ public final class ComputerArgumentType implements ArgumentType<ComputerArgument
|
||||
|
||||
public static ServerComputer getComputerArgument( CommandContext<CommandSourceStack> context, String name ) throws CommandSyntaxException
|
||||
{
|
||||
return context.getArgument( name, ComputerSupplier.class )
|
||||
.unwrap( context.getSource() );
|
||||
return context.getArgument( name, ComputerSupplier.class ).unwrap( context.getSource() );
|
||||
}
|
||||
|
||||
private ComputerArgumentType()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComputerSupplier parse( StringReader reader ) throws CommandSyntaxException
|
||||
{
|
||||
int start = reader.getCursor();
|
||||
ComputersSupplier supplier = ComputersArgumentType.someComputers()
|
||||
.parse( reader );
|
||||
String selector = reader.getString()
|
||||
.substring( start, reader.getCursor() );
|
||||
ComputersSupplier supplier = ComputersArgumentType.someComputers().parse( reader );
|
||||
String selector = reader.getString().substring( start, reader.getCursor() );
|
||||
|
||||
return s -> {
|
||||
Collection<ServerComputer> computers = supplier.unwrap( s );
|
||||
|
||||
if( computers.size() == 1 )
|
||||
{
|
||||
return computers.iterator()
|
||||
.next();
|
||||
}
|
||||
if( computers.size() == 1 ) return computers.iterator().next();
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
boolean first = true;
|
||||
@@ -84,15 +76,13 @@ public final class ComputerArgumentType implements ArgumentType<ComputerArgument
|
||||
@Override
|
||||
public <S> CompletableFuture<Suggestions> listSuggestions( CommandContext<S> context, SuggestionsBuilder builder )
|
||||
{
|
||||
return ComputersArgumentType.someComputers()
|
||||
.listSuggestions( context, builder );
|
||||
return ComputersArgumentType.someComputers().listSuggestions( context, builder );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getExamples()
|
||||
{
|
||||
return ComputersArgumentType.someComputers()
|
||||
.getExamples();
|
||||
return ComputersArgumentType.someComputers().getExamples();
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.command.arguments;
|
||||
|
||||
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 SOME = new ComputersArgumentType( true );
|
||||
|
||||
private static final List<String> EXAMPLES = Arrays.asList( "0", "#0", "@Label", "~Advanced" );
|
||||
private final boolean requireSome;
|
||||
|
||||
private ComputersArgumentType( boolean requireSome )
|
||||
{
|
||||
this.requireSome = requireSome;
|
||||
}
|
||||
private static final List<String> EXAMPLES = Arrays.asList(
|
||||
"0", "#0", "@Label", "~Advanced"
|
||||
);
|
||||
|
||||
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
|
||||
{
|
||||
return context.getArgument( name, ComputersSupplier.class )
|
||||
.unwrap( context.getSource() );
|
||||
return context.getArgument( name, ComputersSupplier.class ).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<>();
|
||||
for( ComputersSupplier supplier : suppliers )
|
||||
{
|
||||
computers.addAll( supplier.unwrap( source ) );
|
||||
}
|
||||
return computers;
|
||||
this.requireSome = requireSome;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -86,9 +77,7 @@ public final class ComputersArgumentType implements ArgumentType<ComputersArgume
|
||||
{
|
||||
reader.skip();
|
||||
String family = reader.readUnquotedString();
|
||||
computers = getComputers( x -> x.getFamily()
|
||||
.name()
|
||||
.equalsIgnoreCase( family ) );
|
||||
computers = getComputers( x -> x.getFamily().name().equalsIgnoreCase( family ) );
|
||||
}
|
||||
else if( kind == '#' )
|
||||
{
|
||||
@@ -107,14 +96,10 @@ public final class ComputersArgumentType implements ArgumentType<ComputersArgume
|
||||
|
||||
if( requireSome )
|
||||
{
|
||||
String selector = reader.getString()
|
||||
.substring( start, reader.getCursor() );
|
||||
String selector = reader.getString().substring( start, reader.getCursor() );
|
||||
return source -> {
|
||||
Collection<ServerComputer> matched = computers.unwrap( source );
|
||||
if( matched.isEmpty() )
|
||||
{
|
||||
throw COMPUTER_ARG_NONE.create( selector );
|
||||
}
|
||||
if( matched.isEmpty() ) throw COMPUTER_ARG_NONE.create( selector );
|
||||
return matched;
|
||||
};
|
||||
}
|
||||
@@ -169,8 +154,7 @@ public final class ComputersArgumentType implements ArgumentType<ComputersArgume
|
||||
for( ServerComputer computer : ComputerCraft.serverComputerRegistry.getComputers() )
|
||||
{
|
||||
String converted = renderer.apply( computer );
|
||||
if( converted != null && converted.toLowerCase( Locale.ROOT )
|
||||
.startsWith( remaining ) )
|
||||
if( converted != null && converted.toLowerCase( Locale.ROOT ).startsWith( remaining ) )
|
||||
{
|
||||
builder.suggest( converted );
|
||||
}
|
||||
@@ -179,16 +163,12 @@ public final class ComputersArgumentType implements ArgumentType<ComputersArgume
|
||||
|
||||
private static ComputersSupplier getComputers( Predicate<ServerComputer> predicate )
|
||||
{
|
||||
return s -> Collections.unmodifiableList( ComputerCraft.serverComputerRegistry.getComputers()
|
||||
return s -> Collections.unmodifiableList( ComputerCraft.serverComputerRegistry
|
||||
.getComputers()
|
||||
.stream()
|
||||
.filter( predicate )
|
||||
.collect( Collectors.toList() ) );
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ComputersSupplier
|
||||
{
|
||||
Collection<ServerComputer> unwrap( CommandSourceStack source ) throws CommandSyntaxException;
|
||||
.collect( Collectors.toList() )
|
||||
);
|
||||
}
|
||||
|
||||
public static class Serializer implements ArgumentSerializer<ComputersArgumentType>
|
||||
@@ -213,4 +193,17 @@ public final class ComputersArgumentType implements ArgumentType<ComputersArgume
|
||||
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.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.command.arguments;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
@@ -32,8 +31,8 @@ import java.util.function.BiConsumer;
|
||||
/**
|
||||
* 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
|
||||
* argument while there is input remaining.
|
||||
* 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 argument while there is input remaining.
|
||||
*
|
||||
* 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 )
|
||||
{
|
||||
reader.skipWhitespace();
|
||||
if( !reader.canRead() )
|
||||
{
|
||||
break;
|
||||
}
|
||||
if( !reader.canRead() ) break;
|
||||
|
||||
int startParse = reader.getCursor();
|
||||
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
|
||||
// was consumed.
|
||||
// We should probably review that this is sensible in the future.
|
||||
if( !hadSome )
|
||||
{
|
||||
throw some.createWithContext( reader );
|
||||
}
|
||||
if( !hadSome ) throw some.createWithContext( reader );
|
||||
|
||||
return Collections.unmodifiableList( out );
|
||||
}
|
||||
@@ -118,10 +111,7 @@ public final class RepeatArgumentType<T, U> implements ArgumentType<List<T>>
|
||||
|
||||
int cursor = reader.getCursor();
|
||||
reader.skipWhitespace();
|
||||
if( cursor == reader.getCursor() )
|
||||
{
|
||||
break;
|
||||
}
|
||||
if( cursor == reader.getCursor() ) break;
|
||||
previous = reader.getCursor();
|
||||
}
|
||||
|
||||
@@ -147,10 +137,7 @@ public final class RepeatArgumentType<T, U> implements ArgumentType<List<T>>
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@SuppressWarnings( {
|
||||
"unchecked",
|
||||
"rawtypes"
|
||||
} )
|
||||
@SuppressWarnings( { "unchecked", "rawtypes" } )
|
||||
public RepeatArgumentType<?, ?> deserializeFromNetwork( @Nonnull FriendlyByteBuf buf )
|
||||
{
|
||||
boolean isList = buf.readBoolean();
|
||||
@@ -170,12 +157,8 @@ public final class RepeatArgumentType<T, U> implements ArgumentType<List<T>>
|
||||
|
||||
private static Component getMessage( RepeatArgumentType<?, ?> arg )
|
||||
{
|
||||
Message message = arg.some.create()
|
||||
.getRawMessage();
|
||||
if( message instanceof Component )
|
||||
{
|
||||
return (Component) message;
|
||||
}
|
||||
Message message = arg.some.create().getRawMessage();
|
||||
if( message instanceof Component ) return (Component) message;
|
||||
return new TextComponent( message.getString() );
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.command.arguments;
|
||||
|
||||
import dan200.computercraft.core.tracking.TrackingField;
|
||||
@@ -17,8 +16,7 @@ public final class TrackingFieldArgumentType extends ChoiceArgumentType<Tracking
|
||||
|
||||
private TrackingFieldArgumentType()
|
||||
{
|
||||
super( TrackingField.fields()
|
||||
.values(), TrackingField::id, x -> translate( x.translationKey() ), Exceptions.TRACKING_FIELD_ARG_NONE );
|
||||
super( TrackingField.fields().values(), TrackingField::id, x -> translate( x.translationKey() ), Exceptions.TRACKING_FIELD_ARG_NONE );
|
||||
}
|
||||
|
||||
public static TrackingFieldArgumentType trackingField()
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.command.builder;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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;
|
||||
|
||||
public static CommandBuilder<CommandSourceStack> args()
|
||||
@@ -58,34 +58,38 @@ public class CommandBuilder<S> implements CommandNodeBuilder<S, Command<S>>
|
||||
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 )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
if( args.isEmpty() )
|
||||
{
|
||||
throw new IllegalStateException( "Cannot have empty arg chain builder" );
|
||||
}
|
||||
if( args.isEmpty() ) throw new IllegalStateException( "Cannot have empty arg chain builder" );
|
||||
|
||||
return command -> {
|
||||
// The node for no arguments
|
||||
ArgumentBuilder<S, ?> tail = tail( ctx -> command.run( ctx, empty.get() ) );
|
||||
|
||||
// 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!
|
||||
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" )
|
||||
private static <T> List<T> getList( CommandContext<?> context, String name )
|
||||
{
|
||||
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
|
||||
public CommandNode<S> executes( Command<S> command )
|
||||
{
|
||||
if( args.isEmpty() )
|
||||
{
|
||||
throw new IllegalStateException( "Cannot have empty arg chain builder" );
|
||||
}
|
||||
if( args.isEmpty() ) throw new IllegalStateException( "Cannot have empty arg chain builder" );
|
||||
|
||||
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.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.command.builder;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* An alternative to {@link LiteralArgumentBuilder} which also provides a {@code /... help} command, and defaults to that command when no arguments are
|
||||
* given.
|
||||
* An alternative to {@link LiteralArgumentBuilder} which also provides a {@code /... help} command, and defaults
|
||||
* to that command when no arguments are given.
|
||||
*/
|
||||
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 HelpingArgumentBuilder( String literal )
|
||||
@@ -48,69 +44,16 @@ public final class HelpingArgumentBuilder extends LiteralArgumentBuilder<Command
|
||||
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 -> {
|
||||
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;
|
||||
throw new IllegalStateException( "Cannot use executes on a HelpingArgumentBuilder" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> then( final ArgumentBuilder<CommandSourceStack, ?> argument )
|
||||
{
|
||||
if( getRedirect() != null )
|
||||
{
|
||||
throw new IllegalStateException( "Cannot add children to a redirected node" );
|
||||
}
|
||||
if( getRedirect() != null ) throw new IllegalStateException( "Cannot add children to a redirected node" );
|
||||
|
||||
if( argument instanceof HelpingArgumentBuilder )
|
||||
{
|
||||
@@ -138,12 +81,6 @@ public final class HelpingArgumentBuilder extends LiteralArgumentBuilder<Command
|
||||
return super.then( argument );
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> executes( final Command<CommandSourceStack> command )
|
||||
{
|
||||
throw new IllegalStateException( "Cannot use executes on a HelpingArgumentBuilder" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralCommandNode<CommandSourceStack> build()
|
||||
{
|
||||
@@ -158,28 +95,24 @@ public final class HelpingArgumentBuilder extends LiteralArgumentBuilder<Command
|
||||
private LiteralCommandNode<CommandSourceStack> buildImpl( String id, String command )
|
||||
{
|
||||
HelpCommand helpCommand = new HelpCommand( id, command );
|
||||
LiteralCommandNode<CommandSourceStack> node = new LiteralCommandNode<>( getLiteral(),
|
||||
helpCommand, getRequirement(),
|
||||
getRedirect(), getRedirectModifier(), isFork() );
|
||||
LiteralCommandNode<CommandSourceStack> node = new LiteralCommandNode<>( getLiteral(), helpCommand, getRequirement(), getRedirect(), getRedirectModifier(), isFork() );
|
||||
helpCommand.node = node;
|
||||
|
||||
// Set up a /... help command
|
||||
LiteralArgumentBuilder<CommandSourceStack> helpNode =
|
||||
LiteralArgumentBuilder.<CommandSourceStack>literal( "help" ).requires( x -> getArguments().stream()
|
||||
.anyMatch(
|
||||
y -> y.getRequirement()
|
||||
.test(
|
||||
x ) ) )
|
||||
.executes( helpCommand );
|
||||
LiteralArgumentBuilder<CommandSourceStack> helpNode = LiteralArgumentBuilder.<CommandSourceStack>literal( "help" )
|
||||
.requires( x -> getArguments().stream().anyMatch( y -> y.getRequirement().test( x ) ) )
|
||||
.executes( helpCommand );
|
||||
|
||||
// Add all normal command children to this and the help node
|
||||
for( CommandNode<CommandSourceStack> child : getArguments() )
|
||||
{
|
||||
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 ) )
|
||||
.build() );
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
// 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 );
|
||||
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 ) )
|
||||
.redirect( child.getChild( "help" ) )
|
||||
.build() );
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
node.addChild( helpNode.build() );
|
||||
@@ -198,6 +133,10 @@ public final class HelpingArgumentBuilder extends LiteralArgumentBuilder<Command
|
||||
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 final String id;
|
||||
@@ -213,9 +152,54 @@ public final class HelpingArgumentBuilder extends LiteralArgumentBuilder<Command
|
||||
@Override
|
||||
public int run( CommandContext<CommandSourceStack> context )
|
||||
{
|
||||
context.getSource()
|
||||
.sendSuccess( getHelp( context, node, id, command ), false );
|
||||
context.getSource().sendSuccess( getHelp( context, node, id, command ), false );
|
||||
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 )
|
||||
{
|
||||
MutableComponent component = new TextComponent( text == null ? "" : text );
|
||||
component.setStyle( component.getStyle().withColor( colour ) );
|
||||
return component;
|
||||
return new TextComponent( text == null ? "" : text ).withStyle( colour );
|
||||
}
|
||||
|
||||
public static <T extends MutableComponent> T coloured( T component, ChatFormatting colour )
|
||||
{
|
||||
component.setStyle( component.getStyle().withColor( colour ) );
|
||||
component.withStyle( colour );
|
||||
return component;
|
||||
}
|
||||
|
||||
@@ -46,10 +44,10 @@ public final class ChatHelpers
|
||||
return new TranslatableComponent( text == null ? "" : text, args );
|
||||
}
|
||||
|
||||
public static MutableComponent list( MutableComponent... children )
|
||||
public static MutableComponent list( Component... children )
|
||||
{
|
||||
MutableComponent component = new TextComponent( "" );
|
||||
for( MutableComponent child : children )
|
||||
for( Component child : children )
|
||||
{
|
||||
component.append( child );
|
||||
}
|
||||
@@ -69,12 +67,12 @@ public final class ChatHelpers
|
||||
: 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 );
|
||||
}
|
||||
|
||||
public static MutableComponent link( MutableComponent component, ClickEvent click, MutableComponent toolTip )
|
||||
public static Component link( Component component, ClickEvent click, Component toolTip )
|
||||
{
|
||||
Style style = component.getStyle();
|
||||
|
||||
@@ -82,9 +80,7 @@ public final class ChatHelpers
|
||||
style = style.withClickEvent( click );
|
||||
style = style.withHoverEvent( new HoverEvent( HoverEvent.Action.SHOW_TEXT, toolTip ) );
|
||||
|
||||
component.setStyle( style );
|
||||
|
||||
return component;
|
||||
return component.copy().withStyle( style );
|
||||
}
|
||||
|
||||
public static MutableComponent header( String text )
|
||||
@@ -95,9 +91,9 @@ public final class ChatHelpers
|
||||
public static MutableComponent copy( String text )
|
||||
{
|
||||
TextComponent name = new TextComponent( text );
|
||||
name.setStyle( name.getStyle()
|
||||
Style style = name.getStyle()
|
||||
.withClickEvent( new ClickEvent( ClickEvent.Action.COPY_TO_CLIPBOARD, text ) )
|
||||
.withHoverEvent( new HoverEvent( HoverEvent.Action.SHOW_TEXT, new TranslatableComponent( "gui.computercraft.tooltip.copy" ) ) ) );
|
||||
return name;
|
||||
.withHoverEvent( new HoverEvent( HoverEvent.Action.SHOW_TEXT, new TranslatableComponent( "gui.computercraft.tooltip.copy" ) ) );
|
||||
return name.withStyle( style );
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.command.text;
|
||||
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
@@ -27,10 +26,7 @@ public class ServerTableFormatter implements TableFormatter
|
||||
public Component getPadding( Component component, int width )
|
||||
{
|
||||
int extraWidth = width - getWidth( component );
|
||||
if( extraWidth <= 0 )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if( extraWidth <= 0 ) return null;
|
||||
return new TextComponent( StringUtils.repeat( ' ', extraWidth ) );
|
||||
}
|
||||
|
||||
@@ -43,8 +39,7 @@ public class ServerTableFormatter implements TableFormatter
|
||||
@Override
|
||||
public int getWidth( Component component )
|
||||
{
|
||||
return component.getString()
|
||||
.length();
|
||||
return component.getString().length();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.command.text;
|
||||
|
||||
import dan200.computercraft.shared.command.CommandUtils;
|
||||
@@ -21,17 +20,14 @@ import java.util.List;
|
||||
public class TableBuilder
|
||||
{
|
||||
private final int id;
|
||||
private int columns = -1;
|
||||
private final Component[] headers;
|
||||
private final ArrayList<Component[]> rows = new ArrayList<>();
|
||||
private int columns = -1;
|
||||
private int additional;
|
||||
|
||||
public TableBuilder( int id, @Nonnull Component... headers )
|
||||
{
|
||||
if( id < 0 )
|
||||
{
|
||||
throw new IllegalArgumentException( "ID must be positive" );
|
||||
}
|
||||
if( id < 0 ) throw new IllegalArgumentException( "ID must be positive" );
|
||||
this.id = id;
|
||||
this.headers = headers;
|
||||
columns = headers.length;
|
||||
@@ -39,47 +35,33 @@ public class TableBuilder
|
||||
|
||||
public TableBuilder( int id )
|
||||
{
|
||||
if( id < 0 )
|
||||
{
|
||||
throw new IllegalArgumentException( "ID must be positive" );
|
||||
}
|
||||
if( id < 0 ) throw new IllegalArgumentException( "ID must be positive" );
|
||||
this.id = id;
|
||||
headers = null;
|
||||
}
|
||||
|
||||
public TableBuilder( int id, @Nonnull String... headers )
|
||||
{
|
||||
if( id < 0 )
|
||||
{
|
||||
throw new IllegalArgumentException( "ID must be positive" );
|
||||
}
|
||||
if( id < 0 ) throw new IllegalArgumentException( "ID must be positive" );
|
||||
this.id = id;
|
||||
this.headers = new Component[headers.length];
|
||||
columns = headers.length;
|
||||
|
||||
for( int i = 0; i < headers.length; i++ )
|
||||
{
|
||||
this.headers[i] = ChatHelpers.header( headers[i] );
|
||||
}
|
||||
for( int i = 0; i < headers.length; i++ ) this.headers[i] = ChatHelpers.header( headers[i] );
|
||||
}
|
||||
|
||||
public void row( @Nonnull Component... row )
|
||||
{
|
||||
if( columns == -1 )
|
||||
{
|
||||
columns = row.length;
|
||||
}
|
||||
if( row.length != columns )
|
||||
{
|
||||
throw new IllegalArgumentException( "Row is the incorrect length" );
|
||||
}
|
||||
if( columns == -1 ) columns = row.length;
|
||||
if( row.length != columns ) throw new IllegalArgumentException( "Row is the incorrect length" );
|
||||
rows.add( row );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@@ -91,7 +73,8 @@ public class TableBuilder
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@@ -122,6 +105,20 @@ public class TableBuilder
|
||||
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 )
|
||||
{
|
||||
if( CommandUtils.isPlayer( source ) )
|
||||
@@ -135,19 +132,4 @@ public class TableBuilder
|
||||
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.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.command.text;
|
||||
|
||||
import net.minecraft.ChatFormatting;
|
||||
@@ -21,12 +20,30 @@ public interface TableFormatter
|
||||
Component SEPARATOR = 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 )
|
||||
{
|
||||
if( table.getColumns() <= 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if( table.getColumns() <= 0 ) return 0;
|
||||
|
||||
int rowId = table.getId();
|
||||
int columns = table.getColumns();
|
||||
@@ -35,10 +52,7 @@ public interface TableFormatter
|
||||
Component[] headers = table.getHeaders();
|
||||
if( headers != null )
|
||||
{
|
||||
for( int i = 0; i < columns; i++ )
|
||||
{
|
||||
maxWidths[i] = getWidth( headers[i] );
|
||||
}
|
||||
for( int i = 0; i < columns; i++ ) maxWidths[i] = getWidth( headers[i] );
|
||||
}
|
||||
|
||||
for( Component[] row : table.getRows() )
|
||||
@@ -46,28 +60,19 @@ public interface TableFormatter
|
||||
for( int i = 0; i < row.length; i++ )
|
||||
{
|
||||
int width = getWidth( row[i] );
|
||||
if( width > maxWidths[i] )
|
||||
{
|
||||
maxWidths[i] = width;
|
||||
}
|
||||
if( width > maxWidths[i] ) maxWidths[i] = width;
|
||||
}
|
||||
}
|
||||
|
||||
// Add a small amount of padding after each column
|
||||
{
|
||||
int padding = getColumnPadding();
|
||||
for( int i = 0; i < maxWidths.length - 1; i++ )
|
||||
{
|
||||
maxWidths[i] += padding;
|
||||
}
|
||||
for( int i = 0; i < maxWidths.length - 1; i++ ) maxWidths[i] += padding;
|
||||
}
|
||||
|
||||
// And compute the total width
|
||||
int totalWidth = (columns - 1) * getWidth( SEPARATOR );
|
||||
for( int x : maxWidths )
|
||||
{
|
||||
totalWidth += x;
|
||||
}
|
||||
for( int x : maxWidths ) totalWidth += x;
|
||||
|
||||
if( headers != null )
|
||||
{
|
||||
@@ -76,10 +81,7 @@ public interface TableFormatter
|
||||
{
|
||||
line.append( headers[i] );
|
||||
Component padding = getPadding( headers[i], maxWidths[i] );
|
||||
if( padding != null )
|
||||
{
|
||||
line.append( padding );
|
||||
}
|
||||
if( padding != null ) line.append( padding );
|
||||
line.append( SEPARATOR );
|
||||
}
|
||||
line.append( headers[columns - 1] );
|
||||
@@ -100,10 +102,7 @@ public interface TableFormatter
|
||||
{
|
||||
line.append( row[i] );
|
||||
Component padding = getPadding( row[i], maxWidths[i] );
|
||||
if( padding != null )
|
||||
{
|
||||
line.append( padding );
|
||||
}
|
||||
if( padding != null ) line.append( padding );
|
||||
line.append( SEPARATOR );
|
||||
}
|
||||
line.append( row[columns - 1] );
|
||||
@@ -117,25 +116,4 @@ public interface TableFormatter
|
||||
|
||||
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.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.common;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
@@ -23,66 +22,45 @@ import net.minecraft.world.phys.BlockHitResult;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Random;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
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 );
|
||||
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
|
||||
@Deprecated
|
||||
public final void onRemove( @Nonnull BlockState block, @Nonnull Level world, @Nonnull BlockPos pos, BlockState replace, boolean bool )
|
||||
{
|
||||
if( block.getBlock() == replace.getBlock() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
if( block.getBlock() == replace.getBlock() ) return;
|
||||
|
||||
BlockEntity tile = world.getBlockEntity( pos );
|
||||
super.onRemove( block, world, pos, replace, bool );
|
||||
world.removeBlockEntity( pos );
|
||||
if( tile instanceof TileGeneric )
|
||||
{
|
||||
((TileGeneric) tile).destroy();
|
||||
}
|
||||
if( tile instanceof TileGeneric generic ) generic.destroy();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
public final InteractionResult use( @Nonnull BlockState state, Level world, @Nonnull BlockPos pos, @Nonnull Player player, @Nonnull InteractionHand hand,
|
||||
@Nonnull BlockHitResult hit )
|
||||
public final InteractionResult use( @Nonnull BlockState state, Level world, @Nonnull BlockPos pos, @Nonnull Player player, @Nonnull InteractionHand hand, @Nonnull BlockHitResult hit )
|
||||
{
|
||||
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
|
||||
@@ -90,20 +68,21 @@ public abstract class BlockGeneric extends BaseEntityBlock
|
||||
public void tick( @Nonnull BlockState state, ServerLevel world, @Nonnull BlockPos pos, @Nonnull Random rand )
|
||||
{
|
||||
BlockEntity te = world.getBlockEntity( pos );
|
||||
if( te instanceof TileGeneric )
|
||||
{
|
||||
((TileGeneric) te).blockTick();
|
||||
}
|
||||
if( te instanceof TileGeneric generic ) generic.blockTick();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockEntity newBlockEntity( BlockPos pos, BlockState state )
|
||||
public BlockEntity newBlockEntity( @Nonnull BlockPos pos, @Nonnull BlockState state )
|
||||
{
|
||||
if( this.type != null )
|
||||
{
|
||||
return type.create( pos, state );
|
||||
}
|
||||
return null;
|
||||
return type.get().create( pos, state );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@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.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.common;
|
||||
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
import dan200.computercraft.shared.network.client.TerminalState;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
|
||||
public class ClientTerminal implements ITerminal
|
||||
{
|
||||
@@ -79,19 +77,4 @@ public class ClientTerminal implements ITerminal
|
||||
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.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.common;
|
||||
|
||||
import dan200.computercraft.shared.util.ColourTracker;
|
||||
@@ -21,8 +20,6 @@ import javax.annotation.Nonnull;
|
||||
|
||||
public final class ColourableRecipe extends CustomRecipe
|
||||
{
|
||||
public static final RecipeSerializer<?> SERIALIZER = new SimpleRecipeSerializer<>( ColourableRecipe::new );
|
||||
|
||||
private ColourableRecipe( ResourceLocation id )
|
||||
{
|
||||
super( id );
|
||||
@@ -36,17 +33,11 @@ public final class ColourableRecipe extends CustomRecipe
|
||||
for( int i = 0; i < inv.getContainerSize(); i++ )
|
||||
{
|
||||
ItemStack stack = inv.getItem( i );
|
||||
if( stack.isEmpty() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if( stack.isEmpty() ) continue;
|
||||
|
||||
if( stack.getItem() instanceof IColouredItem )
|
||||
{
|
||||
if( hasColourable )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if( hasColourable ) return false;
|
||||
hasColourable = true;
|
||||
}
|
||||
else if( ColourUtils.getStackColour( stack ) != null )
|
||||
@@ -74,9 +65,11 @@ public final class ColourableRecipe extends CustomRecipe
|
||||
{
|
||||
ItemStack stack = inv.getItem( i );
|
||||
|
||||
if( stack.isEmpty() )
|
||||
if( stack.isEmpty() ) continue;
|
||||
|
||||
if( stack.getItem() instanceof IColouredItem )
|
||||
{
|
||||
continue;
|
||||
colourable = stack;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -104,4 +97,6 @@ public final class ColourableRecipe extends CustomRecipe
|
||||
{
|
||||
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.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.common;
|
||||
|
||||
import dan200.computercraft.shared.ComputerCraftRegistry;
|
||||
import dan200.computercraft.shared.Registry;
|
||||
import dan200.computercraft.shared.network.container.HeldItemContainerData;
|
||||
import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
@@ -32,13 +31,12 @@ public class ContainerHeldItem extends AbstractContainerMenu
|
||||
super( type, id );
|
||||
|
||||
this.hand = hand;
|
||||
stack = player.getItemInHand( hand )
|
||||
.copy();
|
||||
stack = player.getItemInHand( hand ).copy();
|
||||
}
|
||||
|
||||
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
|
||||
@@ -50,10 +48,7 @@ public class ContainerHeldItem extends AbstractContainerMenu
|
||||
@Override
|
||||
public boolean stillValid( @Nonnull Player player )
|
||||
{
|
||||
if( !player.isAlive() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if( !player.isAlive() ) return false;
|
||||
|
||||
ItemStack stack = player.getItemInHand( hand );
|
||||
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.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.common;
|
||||
|
||||
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 )
|
||||
{
|
||||
Block block = world.getBlockState( pos )
|
||||
.getBlock();
|
||||
if( block instanceof IBundledRedstoneBlock )
|
||||
Block block = world.getBlockState( pos ).getBlock();
|
||||
if( block instanceof IBundledRedstoneBlock generic )
|
||||
{
|
||||
IBundledRedstoneBlock generic = (IBundledRedstoneBlock) block;
|
||||
if( generic.getBundledRedstoneConnectivity( world, pos, side ) )
|
||||
{
|
||||
return generic.getBundledRedstoneOutput( world, pos, side );
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.common;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
@@ -18,12 +17,6 @@ public interface IColouredItem
|
||||
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 )
|
||||
{
|
||||
ItemStack copy = stack.copy();
|
||||
@@ -31,20 +24,22 @@ public interface IColouredItem
|
||||
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 )
|
||||
{
|
||||
if( colour == -1 )
|
||||
{
|
||||
CompoundTag tag = stack.getTag();
|
||||
if( tag != null )
|
||||
{
|
||||
tag.remove( NBT_COLOUR );
|
||||
}
|
||||
if( tag != null ) tag.remove( NBT_COLOUR );
|
||||
}
|
||||
else
|
||||
{
|
||||
stack.getOrCreateTag()
|
||||
.putInt( NBT_COLOUR, colour );
|
||||
stack.getOrCreateTag().putInt( NBT_COLOUR, colour );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3,20 +3,18 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.common;
|
||||
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
import dan200.computercraft.shared.network.client.TerminalState;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class ServerTerminal implements ITerminal
|
||||
{
|
||||
private final boolean colour;
|
||||
private final AtomicBoolean terminalChanged = new AtomicBoolean( false );
|
||||
private Terminal terminal;
|
||||
private final AtomicBoolean terminalChanged = new AtomicBoolean( false );
|
||||
private boolean terminalChangedLastFrame = false;
|
||||
|
||||
public ServerTerminal( boolean colour )
|
||||
@@ -31,11 +29,6 @@ public class ServerTerminal implements ITerminal
|
||||
terminal = new Terminal( terminalWidth, terminalHeight, this::markTerminalChanged );
|
||||
}
|
||||
|
||||
protected void markTerminalChanged()
|
||||
{
|
||||
terminalChanged.set( true );
|
||||
}
|
||||
|
||||
protected void resize( int width, int height )
|
||||
{
|
||||
if( terminal == null )
|
||||
@@ -58,6 +51,11 @@ public class ServerTerminal implements ITerminal
|
||||
}
|
||||
}
|
||||
|
||||
protected void markTerminalChanged()
|
||||
{
|
||||
terminalChanged.set( true );
|
||||
}
|
||||
|
||||
public void update()
|
||||
{
|
||||
terminalChangedLastFrame = terminalChanged.getAndSet( false );
|
||||
@@ -84,17 +82,4 @@ public class ServerTerminal implements ITerminal
|
||||
{
|
||||
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.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.common;
|
||||
|
||||
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.InteractionResult;
|
||||
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.BlockEntityType;
|
||||
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()
|
||||
{
|
||||
}
|
||||
@@ -42,7 +43,7 @@ public abstract class TileGeneric extends BlockEntity
|
||||
setChanged();
|
||||
BlockPos pos = getBlockPos();
|
||||
BlockState state = getBlockState();
|
||||
getLevel().sendBlockUpdated( pos, state, state, 3 );
|
||||
getLevel().sendBlockUpdated( pos, state, state, Block.UPDATE_ALL );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@@ -70,26 +71,19 @@ public abstract class TileGeneric extends BlockEntity
|
||||
|
||||
public boolean isUsable( Player player, boolean ignoreRange )
|
||||
{
|
||||
if( player == null || !player.isAlive() || getLevel().getBlockEntity( getBlockPos() ) != this )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if( ignoreRange )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if( player == null || !player.isAlive() || getLevel().getBlockEntity( getBlockPos() ) != this ) return false;
|
||||
if( ignoreRange ) return true;
|
||||
|
||||
double range = getInteractRange( player );
|
||||
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
|
||||
public CompoundTag getUpdateTag()
|
||||
{
|
||||
CompoundTag nbt = new CompoundTag();
|
||||
writeDescription( nbt );
|
||||
return nbt;
|
||||
return this.saveWithoutMetadata();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
@@ -3,31 +3,32 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.computer.apis;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.mojang.brigadier.tree.CommandNode;
|
||||
import com.mojang.brigadier.tree.LiteralCommandNode;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.lua.*;
|
||||
import dan200.computercraft.shared.computer.blocks.TileCommandComputer;
|
||||
import dan200.computercraft.shared.peripheral.generic.data.BlockData;
|
||||
import dan200.computercraft.shared.util.NBTUtil;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
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.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.Property;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @cc.module commands
|
||||
* @cc.since 1.7
|
||||
*/
|
||||
public class CommandAPI implements ILuaAPI
|
||||
{
|
||||
@@ -44,29 +45,14 @@ public class CommandAPI implements ILuaAPI
|
||||
return new String[] { "commands" };
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 )
|
||||
private static Object createOutput( String output )
|
||||
{
|
||||
return doCommand( command );
|
||||
return new Object[] { output };
|
||||
}
|
||||
|
||||
private Object[] doCommand( String command )
|
||||
{
|
||||
MinecraftServer server = computer.getLevel()
|
||||
.getServer();
|
||||
MinecraftServer server = computer.getLevel().getServer();
|
||||
if( server == null || !server.isCommandBlockEnabled() )
|
||||
{
|
||||
return new Object[] { false, createOutput( "Command blocks disabled by server" ) };
|
||||
@@ -82,36 +68,64 @@ public class CommandAPI implements ILuaAPI
|
||||
}
|
||||
catch( Throwable t )
|
||||
{
|
||||
if( ComputerCraft.logComputerErrors )
|
||||
{
|
||||
ComputerCraft.log.error( "Error running command.", t );
|
||||
}
|
||||
if( ComputerCraft.logComputerErrors ) ComputerCraft.log.error( "Error running command.", 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.
|
||||
*
|
||||
* Unlike {@link #exec}, this will immediately return, instead of waiting for the command to execute. This allows you to run multiple commands at the
|
||||
* same time.
|
||||
* Unlike {@link #exec}, this will immediately return, instead of waiting for the
|
||||
* 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}
|
||||
* would return).
|
||||
* When this command has finished executing, it will queue a `task_complete`
|
||||
* event containing the result of executing this command (what {@link #exec} would
|
||||
* return).
|
||||
*
|
||||
* @param context The context this command executes under.
|
||||
* @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.
|
||||
* @throws LuaException (hidden) If the task cannot be created.
|
||||
* @cc.usage Asynchronously sets the block above the computer to stone.
|
||||
* <pre>
|
||||
* commands.execAsync("~ ~1 ~ minecraft:stone")
|
||||
* </pre>
|
||||
* <pre>{@code
|
||||
* commands.execAsync("setblock ~ ~1 ~ minecraft:stone")
|
||||
* }</pre>
|
||||
* @cc.see parallel One may also use the parallel API to run multiple commands at once.
|
||||
*/
|
||||
@LuaFunction
|
||||
@@ -131,33 +145,21 @@ public class CommandAPI implements ILuaAPI
|
||||
@LuaFunction( mainThread = true )
|
||||
public final List<String> list( IArguments args ) throws LuaException
|
||||
{
|
||||
MinecraftServer server = computer.getLevel()
|
||||
.getServer();
|
||||
MinecraftServer server = computer.getLevel().getServer();
|
||||
|
||||
if( server == null )
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
CommandNode<CommandSourceStack> node = server.getCommands()
|
||||
.getDispatcher()
|
||||
.getRoot();
|
||||
if( server == null ) return Collections.emptyList();
|
||||
CommandNode<CommandSourceStack> node = server.getCommands().getDispatcher().getRoot();
|
||||
for( int j = 0; j < args.count(); j++ )
|
||||
{
|
||||
String name = args.getString( j );
|
||||
node = node.getChild( name );
|
||||
if( !(node instanceof LiteralCommandNode) )
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
if( !(node instanceof LiteralCommandNode) ) return Collections.emptyList();
|
||||
}
|
||||
|
||||
List<String> result = new ArrayList<>();
|
||||
for( CommandNode<?> child : node.getChildren() )
|
||||
{
|
||||
if( child instanceof LiteralCommandNode<?> )
|
||||
{
|
||||
result.add( child.getName() );
|
||||
}
|
||||
if( child instanceof LiteralCommandNode<?> ) result.add( child.getName() );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -182,37 +184,47 @@ public class CommandAPI implements ILuaAPI
|
||||
/**
|
||||
* 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 minY The start y 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 maxY The end y coordinate of the range to query.
|
||||
* @param maxZ The end z 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 minZ The start z 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 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.
|
||||
* @throws LuaException If the coordinates are not within the world.
|
||||
* @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 )
|
||||
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
|
||||
Level world = computer.getLevel();
|
||||
BlockPos min = new BlockPos( Math.min( minX, maxX ), 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.isInWorldBounds( min ) || !world.isInWorldBounds( max ) )
|
||||
Level world = getLevel( dimension );
|
||||
BlockPos min = new BlockPos(
|
||||
Math.min( minX, maxX ),
|
||||
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" );
|
||||
}
|
||||
|
||||
int blocks = (max.getX() - min.getX() + 1) * (max.getY() - min.getY() + 1) * (max.getZ() - min.getZ() + 1);
|
||||
if( blocks > 4096 )
|
||||
{
|
||||
throw new LuaException( "Too many blocks" );
|
||||
}
|
||||
if( blocks > 4096 ) throw new LuaException( "Too many blocks" );
|
||||
|
||||
List<Map<?, ?>> results = new ArrayList<>( blocks );
|
||||
for( int y = min.getY(); y <= max.getY(); y++ )
|
||||
@@ -230,71 +242,45 @@ public class CommandAPI implements ILuaAPI
|
||||
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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @param x The x 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 x The x 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 dimension The dimension to query (e.g. "minecraft:overworld"). Defaults to the current dimension.
|
||||
* @return The given block's information.
|
||||
* @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 )
|
||||
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 world = computer.getLevel();
|
||||
Level level = getLevel( dimension );
|
||||
BlockPos position = new BlockPos( x, y, z );
|
||||
if( world.isInWorldBounds( position ) )
|
||||
{
|
||||
return getBlockInfo( world, position );
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new LuaException( "Co-ordinates out of range" );
|
||||
}
|
||||
if( !level.isInWorldBounds( position ) ) throw new LuaException( "Co-ordinates out of range" );
|
||||
return getBlockInfo( level, position );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private Level getLevel( @Nonnull Optional<String> id ) throws LuaException
|
||||
{
|
||||
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.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.computer.blocks;
|
||||
|
||||
import dan200.computercraft.shared.ComputerCraftRegistry;
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
import dan200.computercraft.shared.computer.core.ComputerState;
|
||||
import dan200.computercraft.shared.computer.items.ComputerItemFactory;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
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.state.BlockState;
|
||||
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.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 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 );
|
||||
registerDefaultState( defaultBlockState().setValue( FACING, Direction.NORTH )
|
||||
.setValue( STATE, ComputerState.OFF ) );
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockState getStateForPlacement( BlockPlaceContext placement )
|
||||
{
|
||||
return defaultBlockState().setValue( FACING,
|
||||
placement.getHorizontalDirection()
|
||||
.getOpposite() );
|
||||
registerDefaultState( defaultBlockState()
|
||||
.setValue( FACING, Direction.NORTH )
|
||||
.setValue( STATE, ComputerState.OFF )
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -53,27 +43,17 @@ public class BlockComputer extends BlockComputerBase<TileComputer>
|
||||
builder.add( FACING, STATE );
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockState getStateForPlacement( BlockPlaceContext placement )
|
||||
{
|
||||
return defaultBlockState().setValue( FACING, placement.getHorizontalDirection().getOpposite() );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected ItemStack getItem( TileComputerBase tile )
|
||||
{
|
||||
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.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.computer.blocks;
|
||||
|
||||
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.level.BlockGetter;
|
||||
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.BlockEntityTicker;
|
||||
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.Nullable;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public abstract class BlockComputerBase<T extends TileComputerBase> extends BlockGeneric implements IBundledRedstoneBlock
|
||||
{
|
||||
private static final ResourceLocation DROP = new ResourceLocation( ComputerCraft.MOD_ID, "computer" );
|
||||
|
||||
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 );
|
||||
this.family = family;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -53,10 +57,7 @@ public abstract class BlockComputerBase<T extends TileComputerBase> extends Bloc
|
||||
super.onPlace( state, world, pos, oldState, isMoving );
|
||||
|
||||
BlockEntity tile = world.getBlockEntity( pos );
|
||||
if( tile instanceof TileComputerBase )
|
||||
{
|
||||
((TileComputerBase) tile).updateInput();
|
||||
}
|
||||
if( tile instanceof TileComputerBase computer ) computer.updateInputsImmediately();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -66,39 +67,35 @@ public abstract class BlockComputerBase<T extends TileComputerBase> extends Bloc
|
||||
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
|
||||
@Deprecated
|
||||
public int getDirectSignal( @Nonnull BlockState state, BlockGetter world, @Nonnull BlockPos pos, @Nonnull Direction incomingSide )
|
||||
{
|
||||
BlockEntity entity = world.getBlockEntity( pos );
|
||||
if( !(entity instanceof TileComputerBase) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if( !(entity instanceof TileComputerBase computerEntity) ) return 0;
|
||||
|
||||
TileComputerBase computerEntity = (TileComputerBase) entity;
|
||||
ServerComputer computer = computerEntity.getServerComputer();
|
||||
if( computer == null )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if( computer == null ) return 0;
|
||||
|
||||
ComputerSide localSide = computerEntity.remapToLocalSide( incomingSide.getOpposite() );
|
||||
return computer.getRedstoneOutput( localSide );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
protected abstract ItemStack getItem( TileComputerBase tile );
|
||||
|
||||
public ComputerFamily getFamily()
|
||||
{
|
||||
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
|
||||
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 )
|
||||
{
|
||||
BlockEntity entity = world.getBlockEntity( pos );
|
||||
if( !(entity instanceof TileComputerBase) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if( !(entity instanceof TileComputerBase computerEntity) ) return 0;
|
||||
|
||||
TileComputerBase computerEntity = (TileComputerBase) entity;
|
||||
ServerComputer computer = computerEntity.getServerComputer();
|
||||
if( computer == null )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if( computer == null ) return 0;
|
||||
|
||||
ComputerSide localSide = computerEntity.remapToLocalSide( side );
|
||||
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
|
||||
@Override
|
||||
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 )
|
||||
{
|
||||
ItemStack result = getItem( (TileComputerBase) tile );
|
||||
if( !result.isEmpty() )
|
||||
{
|
||||
return result;
|
||||
}
|
||||
if( !result.isEmpty() ) return result;
|
||||
}
|
||||
|
||||
return super.getCloneItemStack( world, pos, state );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
protected abstract ItemStack getItem( TileComputerBase tile );
|
||||
@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 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.
|
||||
super.playerWillDestroy( world, pos, state, player );
|
||||
|
||||
if( !(world instanceof ServerLevel) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
ServerLevel serverWorld = (ServerLevel) world;
|
||||
if( !(world instanceof ServerLevel serverWorld) ) return;
|
||||
|
||||
// We drop the item here instead of doing it in the harvest method, as we should
|
||||
// drop computers for creative players too.
|
||||
|
||||
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 ).withRandom( world.random )
|
||||
LootContext.Builder context = new LootContext.Builder( serverWorld )
|
||||
.withRandom( world.random )
|
||||
.withParameter( LootContextParams.ORIGIN, Vec3.atCenterOf( pos ) )
|
||||
.withParameter( LootContextParams.TOOL, player.getMainHandItem() )
|
||||
.withParameter( LootContextParams.THIS_ENTITY, player )
|
||||
@@ -213,15 +164,27 @@ public abstract class BlockComputerBase<T extends TileComputerBase> extends Bloc
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@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 ) -> {
|
||||
if( tile instanceof TileComputerBase computer )
|
||||
{
|
||||
computer.serverTick();
|
||||
}
|
||||
};
|
||||
super.setPlacedBy( world, pos, state, placer, stack );
|
||||
|
||||
BlockEntity tile = world.getBlockEntity( pos );
|
||||
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.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.computer.blocks;
|
||||
|
||||
import dan200.computercraft.api.lua.LuaFunction;
|
||||
@@ -16,8 +15,8 @@ import javax.annotation.Nullable;
|
||||
/**
|
||||
* 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
|
||||
* {@code turtle}.
|
||||
* This allows for basic interaction with adjacent computers. Computers wrapped as peripherals will have the type
|
||||
* {@code computer} while turtles will be {@code turtle}.
|
||||
*
|
||||
* @cc.module computer
|
||||
*/
|
||||
@@ -39,19 +38,6 @@ public class ComputerPeripheral implements IPeripheral
|
||||
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.
|
||||
*/
|
||||
@@ -114,4 +100,17 @@ public class ComputerPeripheral implements IPeripheral
|
||||
{
|
||||
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.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.computer.blocks;
|
||||
|
||||
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.
|
||||
*/
|
||||
public class ComputerProxy
|
||||
public final class ComputerProxy
|
||||
{
|
||||
private final Supplier<TileComputerBase> get;
|
||||
|
||||
@@ -23,6 +22,11 @@ public class ComputerProxy
|
||||
this.get = get;
|
||||
}
|
||||
|
||||
TileComputerBase getTile()
|
||||
{
|
||||
return get.get();
|
||||
}
|
||||
|
||||
public void turnOn()
|
||||
{
|
||||
TileComputerBase tile = getTile();
|
||||
@@ -37,11 +41,6 @@ public class ComputerProxy
|
||||
}
|
||||
}
|
||||
|
||||
protected TileComputerBase getTile()
|
||||
{
|
||||
return get.get();
|
||||
}
|
||||
|
||||
public void shutdown()
|
||||
{
|
||||
TileComputerBase tile = getTile();
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.computer.blocks;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
@@ -32,75 +31,6 @@ import java.util.UUID;
|
||||
|
||||
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
|
||||
{
|
||||
private final Map<Integer, String> output = new HashMap<>();
|
||||
@@ -129,8 +59,7 @@ public class TileCommandComputer extends TileComputer
|
||||
@Override
|
||||
public boolean acceptsSuccess()
|
||||
{
|
||||
return getLevel().getGameRules()
|
||||
.getBoolean( GameRules.RULE_SENDCOMMANDFEEDBACK );
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -142,8 +71,69 @@ public class TileCommandComputer extends TileComputer
|
||||
@Override
|
||||
public boolean shouldInformAdmins()
|
||||
{
|
||||
return getLevel().getGameRules()
|
||||
.getBoolean( GameRules.RULE_COMMANDBLOCKOUTPUT );
|
||||
return getLevel().getGameRules().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.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.computer.blocks;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
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.ComputerState;
|
||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||
@@ -28,16 +27,35 @@ public class TileComputer extends TileComputerBase
|
||||
{
|
||||
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 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Direction getDirection()
|
||||
{
|
||||
return getBlockState().getValue( BlockComputer.FACING );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateBlockState( ComputerState newState )
|
||||
{
|
||||
@@ -48,64 +66,21 @@ public class TileComputer extends TileComputerBase
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Direction getDirection()
|
||||
{
|
||||
return getBlockState().getValue( BlockComputer.FACING );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ComputerSide remapLocalSide( ComputerSide localSide )
|
||||
{
|
||||
// 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.
|
||||
if( localSide == ComputerSide.RIGHT )
|
||||
{
|
||||
return ComputerSide.LEFT;
|
||||
}
|
||||
if( localSide == ComputerSide.LEFT )
|
||||
{
|
||||
return ComputerSide.RIGHT;
|
||||
}
|
||||
if( localSide == ComputerSide.RIGHT ) return ComputerSide.LEFT;
|
||||
if( localSide == ComputerSide.LEFT ) return ComputerSide.RIGHT;
|
||||
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
|
||||
@Override
|
||||
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.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.computer.blocks;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
@@ -28,6 +27,7 @@ import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.network.chat.TranslatableComponent;
|
||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
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.item.ItemStack;
|
||||
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.state.BlockState;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
@@ -46,26 +43,40 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Objects;
|
||||
|
||||
public abstract class TileComputerBase extends TileGeneric implements IComputerTile, IPeripheralTile, Nameable,
|
||||
ExtendedScreenHandlerFactory
|
||||
public abstract class TileComputerBase extends TileGeneric implements IComputerTile, IPeripheralTile, Nameable, ExtendedScreenHandlerFactory
|
||||
{
|
||||
private static final String NBT_ID = "ComputerId";
|
||||
private static final String NBT_LABEL = "Label";
|
||||
private static final String NBT_ON = "On";
|
||||
private final ComputerFamily family;
|
||||
protected String label = null;
|
||||
boolean startOn = false;
|
||||
|
||||
private int instanceID = -1;
|
||||
private int computerID = -1;
|
||||
protected String label = null;
|
||||
private boolean on = false;
|
||||
boolean startOn = 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 );
|
||||
this.family = family;
|
||||
}
|
||||
|
||||
protected void unload()
|
||||
{
|
||||
if( instanceID >= 0 )
|
||||
{
|
||||
if( !getLevel().isClientSide ) ComputerCraft.serverComputerRegistry.remove( instanceID );
|
||||
instanceID = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy()
|
||||
{
|
||||
@@ -82,16 +93,16 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
||||
unload();
|
||||
}
|
||||
|
||||
protected void unload()
|
||||
@Override
|
||||
public void setRemoved()
|
||||
{
|
||||
if( instanceID >= 0 )
|
||||
{
|
||||
if( !getLevel().isClientSide )
|
||||
{
|
||||
ComputerCraft.serverComputerRegistry.remove( instanceID );
|
||||
}
|
||||
instanceID = -1;
|
||||
}
|
||||
unload();
|
||||
super.setRemoved();
|
||||
}
|
||||
|
||||
protected boolean canNameWithTag( Player player )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@@ -104,8 +115,7 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
||||
// Label to rename computer
|
||||
if( !getLevel().isClientSide )
|
||||
{
|
||||
setLabel( currentItem.getHoverName()
|
||||
.getString() );
|
||||
setLabel( currentItem.getHoverName().getString() );
|
||||
currentItem.shrink( 1 );
|
||||
}
|
||||
return InteractionResult.SUCCESS;
|
||||
@@ -124,162 +134,32 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
||||
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
|
||||
public void onNeighbourChange( @Nonnull BlockPos neighbour )
|
||||
{
|
||||
updateInput( neighbour );
|
||||
updateInputAt( neighbour );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNeighbourTileEntityChange( @Nonnull BlockPos neighbour )
|
||||
{
|
||||
updateInput( neighbour );
|
||||
updateInputAt( neighbour );
|
||||
}
|
||||
|
||||
@Override
|
||||
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()
|
||||
protected void serverTick()
|
||||
{
|
||||
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( startOn || fresh && on )
|
||||
if( startOn || (fresh && on) )
|
||||
{
|
||||
computer.turnOn();
|
||||
startOn = false;
|
||||
@@ -292,33 +172,28 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
||||
label = computer.getLabel();
|
||||
on = computer.isOn();
|
||||
|
||||
if( computer.hasOutputChanged() )
|
||||
{
|
||||
updateOutput();
|
||||
}
|
||||
|
||||
// Update the block state if needed. We don't fire a block update intentionally,
|
||||
// as this only really is needed on the client side.
|
||||
updateBlockState( computer.getState() );
|
||||
|
||||
if( computer.hasOutputChanged() )
|
||||
{
|
||||
updateOutput();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateOutput()
|
||||
{
|
||||
// Update redstone
|
||||
updateBlock();
|
||||
for( Direction dir : DirectionUtil.FACINGS )
|
||||
{
|
||||
RedstoneUtil.propagateRedstoneOutput( getLevel(), getBlockPos(), dir );
|
||||
}
|
||||
// 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)
|
||||
if( computer.hasOutputChanged() ) updateOutput();
|
||||
}
|
||||
|
||||
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
|
||||
public void load( @Nonnull CompoundTag nbt )
|
||||
{
|
||||
@@ -330,116 +205,137 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
||||
on = startOn = nbt.getBoolean( NBT_ON );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveAdditional( @Nonnull CompoundTag nbt )
|
||||
protected boolean isPeripheralBlockedOnSide( ComputerSide localSide )
|
||||
{
|
||||
// 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 );
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRemoved()
|
||||
protected abstract Direction getDirection();
|
||||
|
||||
protected ComputerSide remapToLocalSide( Direction globalSide )
|
||||
{
|
||||
unload();
|
||||
super.setRemoved();
|
||||
return remapLocalSide( DirectionUtil.toLocal( getDirection(), globalSide ) );
|
||||
}
|
||||
|
||||
private void updateInput( BlockPos neighbour )
|
||||
protected ComputerSide remapLocalSide( ComputerSide localSide )
|
||||
{
|
||||
if( getLevel() == null || this.level.isClientSide )
|
||||
{
|
||||
return;
|
||||
}
|
||||
return localSide;
|
||||
}
|
||||
|
||||
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();
|
||||
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 )
|
||||
{
|
||||
BlockPos offset = worldPosition.relative( dir );
|
||||
BlockPos offset = getBlockPos().relative( dir );
|
||||
if( offset.equals( neighbour ) )
|
||||
{
|
||||
updateSideInput( computer, dir, offset );
|
||||
updateRedstoneInput( computer, dir, offset );
|
||||
invalidSides |= 1 << dir.ordinal();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If the position is not any adjacent one, update all inputs.
|
||||
this.updateInput();
|
||||
// If the position is not any adjacent one, update all inputs. This is pretty terrible, but some redstone mods
|
||||
// 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
|
||||
public final int getComputerID()
|
||||
{
|
||||
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
|
||||
public final String getLabel()
|
||||
{
|
||||
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
|
||||
public final void setLabel( String label )
|
||||
{
|
||||
if( this.level.isClientSide || Objects.equals( this.label, label ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
if( getLevel().isClientSide || Objects.equals( this.label, label ) ) return;
|
||||
|
||||
this.label = label;
|
||||
ServerComputer computer = getServerComputer();
|
||||
if( computer != null )
|
||||
{
|
||||
computer.setLabel( label );
|
||||
}
|
||||
if( computer != null ) computer.setLabel( label );
|
||||
setChanged();
|
||||
}
|
||||
|
||||
@@ -449,6 +345,64 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
||||
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 )
|
||||
{
|
||||
if( copy.computerID != computerID || copy.instanceID != instanceID )
|
||||
@@ -468,17 +422,17 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
||||
@Override
|
||||
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
|
||||
@Override
|
||||
public Component getName()
|
||||
{
|
||||
return hasCustomName() ? new TextComponent( label ) : new TranslatableComponent( getBlockState().getBlock()
|
||||
.getDescriptionId() );
|
||||
return hasCustomName()
|
||||
? new TextComponent( label )
|
||||
: new TranslatableComponent( getBlockState().getBlock().getDescriptionId() );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -487,13 +441,6 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
||||
return !Strings.isNullOrEmpty( label );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Component getDisplayName()
|
||||
{
|
||||
return Nameable.super.getDisplayName();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Component getCustomName()
|
||||
@@ -501,6 +448,13 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
||||
return hasCustomName() ? new TextComponent( label ) : null;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Component getDisplayName()
|
||||
{
|
||||
return Nameable.super.getDisplayName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeScreenOpeningData( ServerPlayer serverPlayerEntity, FriendlyByteBuf packetByteBuf )
|
||||
{
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.computer.core;
|
||||
|
||||
import dan200.computercraft.shared.common.ClientTerminal;
|
||||
@@ -19,7 +18,6 @@ public class ClientComputer extends ClientTerminal implements IComputer
|
||||
private boolean blinking = false;
|
||||
private CompoundTag userData = null;
|
||||
|
||||
|
||||
public ClientComputer( int instanceID )
|
||||
{
|
||||
super( false );
|
||||
@@ -45,6 +43,18 @@ public class ClientComputer extends ClientTerminal implements IComputer
|
||||
return instanceID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOn()
|
||||
{
|
||||
return on;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCursorDisplayed()
|
||||
{
|
||||
return on && blinking;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void turnOn()
|
||||
{
|
||||
@@ -73,24 +83,10 @@ public class ClientComputer extends ClientTerminal implements IComputer
|
||||
NetworkHandler.sendToServer( new QueueEventServerMessage( instanceID, event, arguments ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOn()
|
||||
{
|
||||
return on;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCursorDisplayed()
|
||||
{
|
||||
return on && blinking;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyDown( int key, boolean repeat )
|
||||
{
|
||||
NetworkHandler.sendToServer( new KeyEventServerMessage( instanceID,
|
||||
repeat ? KeyEventServerMessage.TYPE_REPEAT : KeyEventServerMessage.TYPE_DOWN,
|
||||
key ) );
|
||||
NetworkHandler.sendToServer( new KeyEventServerMessage( instanceID, repeat ? KeyEventServerMessage.TYPE_REPEAT : KeyEventServerMessage.TYPE_DOWN, key ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -3,10 +3,11 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.computer.core;
|
||||
|
||||
public enum ComputerFamily
|
||||
{
|
||||
NORMAL, ADVANCED, COMMAND
|
||||
NORMAL,
|
||||
ADVANCED,
|
||||
COMMAND
|
||||
}
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.computer.core;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -13,23 +12,15 @@ import java.util.Random;
|
||||
|
||||
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 sessionID;
|
||||
|
||||
protected ComputerRegistry()
|
||||
{
|
||||
computers = new HashMap<>();
|
||||
reset();
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
computers.clear();
|
||||
nextUnusedInstanceID = 0;
|
||||
sessionID = new Random().nextInt();
|
||||
}
|
||||
|
||||
public int getSessionID()
|
||||
{
|
||||
return sessionID;
|
||||
@@ -76,4 +67,11 @@ public class ComputerRegistry<T extends IComputer>
|
||||
{
|
||||
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.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.computer.core;
|
||||
|
||||
import net.minecraft.util.StringRepresentable;
|
||||
@@ -12,7 +11,9 @@ import javax.annotation.Nonnull;
|
||||
|
||||
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 texture;
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.computer.core;
|
||||
|
||||
import dan200.computercraft.shared.common.ITerminal;
|
||||
@@ -12,30 +11,27 @@ public interface IComputer extends ITerminal, InputHandler
|
||||
{
|
||||
int getInstanceID();
|
||||
|
||||
boolean isOn();
|
||||
|
||||
boolean isCursorDisplayed();
|
||||
|
||||
void turnOn();
|
||||
|
||||
void shutdown();
|
||||
|
||||
void reboot();
|
||||
|
||||
@Override
|
||||
void queueEvent( String event, Object[] arguments );
|
||||
|
||||
default void queueEvent( String event )
|
||||
{
|
||||
queueEvent( event, null );
|
||||
}
|
||||
|
||||
@Override
|
||||
void queueEvent( String event, Object[] arguments );
|
||||
|
||||
default ComputerState getState()
|
||||
{
|
||||
if( !isOn() )
|
||||
{
|
||||
return ComputerState.OFF;
|
||||
}
|
||||
if( !isOn() ) return ComputerState.OFF;
|
||||
return isCursorDisplayed() ? ComputerState.BLINKING : ComputerState.ON;
|
||||
}
|
||||
|
||||
boolean isOn();
|
||||
|
||||
boolean isCursorDisplayed();
|
||||
}
|
||||
|
@@ -3,12 +3,12 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.computer.core;
|
||||
|
||||
import dan200.computercraft.shared.computer.upload.FileSlice;
|
||||
import dan200.computercraft.shared.computer.upload.FileUpload;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
@@ -16,9 +16,9 @@ import java.util.List;
|
||||
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
|
||||
{
|
||||
/**
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.computer.core;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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
|
||||
{
|
||||
@@ -31,10 +31,7 @@ public class InputState implements InputHandler
|
||||
public void queueEvent( String event, Object[] arguments )
|
||||
{
|
||||
IComputer computer = owner.getComputer();
|
||||
if( computer != null )
|
||||
{
|
||||
computer.queueEvent( event, arguments );
|
||||
}
|
||||
if( computer != null ) computer.queueEvent( event, arguments );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -42,10 +39,7 @@ public class InputState implements InputHandler
|
||||
{
|
||||
keysDown.add( key );
|
||||
IComputer computer = owner.getComputer();
|
||||
if( computer != null )
|
||||
{
|
||||
computer.keyDown( key, repeat );
|
||||
}
|
||||
if( computer != null ) computer.keyDown( key, repeat );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -53,10 +47,7 @@ public class InputState implements InputHandler
|
||||
{
|
||||
keysDown.remove( key );
|
||||
IComputer computer = owner.getComputer();
|
||||
if( computer != null )
|
||||
{
|
||||
computer.keyUp( key );
|
||||
}
|
||||
if( computer != null ) computer.keyUp( key );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -67,10 +58,7 @@ public class InputState implements InputHandler
|
||||
lastMouseDown = button;
|
||||
|
||||
IComputer computer = owner.getComputer();
|
||||
if( computer != null )
|
||||
{
|
||||
computer.mouseClick( button, x, y );
|
||||
}
|
||||
if( computer != null ) computer.mouseClick( button, x, y );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -81,10 +69,7 @@ public class InputState implements InputHandler
|
||||
lastMouseDown = -1;
|
||||
|
||||
IComputer computer = owner.getComputer();
|
||||
if( computer != null )
|
||||
{
|
||||
computer.mouseUp( button, x, y );
|
||||
}
|
||||
if( computer != null ) computer.mouseUp( button, x, y );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -95,10 +80,7 @@ public class InputState implements InputHandler
|
||||
lastMouseDown = button;
|
||||
|
||||
IComputer computer = owner.getComputer();
|
||||
if( computer != null )
|
||||
{
|
||||
computer.mouseDrag( button, x, y );
|
||||
}
|
||||
if( computer != null ) computer.mouseDrag( button, x, y );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -108,10 +90,7 @@ public class InputState implements InputHandler
|
||||
lastMouseY = y;
|
||||
|
||||
IComputer computer = owner.getComputer();
|
||||
if( computer != null )
|
||||
{
|
||||
computer.mouseScroll( direction, x, y );
|
||||
}
|
||||
if( computer != null ) computer.mouseScroll( direction, x, y );
|
||||
}
|
||||
|
||||
public void close()
|
||||
@@ -120,15 +99,9 @@ public class InputState implements InputHandler
|
||||
if( computer != null )
|
||||
{
|
||||
IntIterator keys = keysDown.iterator();
|
||||
while( keys.hasNext() )
|
||||
{
|
||||
computer.keyUp( keys.nextInt() );
|
||||
}
|
||||
while( keys.hasNext() ) computer.keyUp( keys.nextInt() );
|
||||
|
||||
if( lastMouseDown != -1 )
|
||||
{
|
||||
computer.mouseUp( lastMouseDown, lastMouseX, lastMouseY );
|
||||
}
|
||||
if( lastMouseDown != -1 ) computer.mouseUp( lastMouseDown, lastMouseX, lastMouseY );
|
||||
}
|
||||
|
||||
keysDown.clear();
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.computer.core;
|
||||
|
||||
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.ComputerTerminalClientMessage;
|
||||
import me.shedaniel.cloth.api.utils.v1.GameInstanceUtils;
|
||||
import net.minecraft.SharedConstants;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
@@ -38,32 +38,27 @@ import java.io.InputStream;
|
||||
public class ServerComputer extends ServerTerminal implements IComputer, IComputerEnvironment
|
||||
{
|
||||
private final int instanceID;
|
||||
|
||||
private Level level;
|
||||
private BlockPos position;
|
||||
|
||||
private final ComputerFamily family;
|
||||
private final Computer computer;
|
||||
private Level world;
|
||||
private BlockPos position;
|
||||
private CompoundTag userData;
|
||||
private boolean changed;
|
||||
|
||||
private boolean changedLastFrame;
|
||||
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 );
|
||||
this.instanceID = instanceID;
|
||||
|
||||
this.world = world;
|
||||
position = null;
|
||||
|
||||
this.level = level;
|
||||
this.family = family;
|
||||
computer = new Computer( this, getTerminal(), computerID );
|
||||
computer.setLabel( label );
|
||||
userData = null;
|
||||
changed = false;
|
||||
|
||||
changedLastFrame = false;
|
||||
ticksSincePing = 0;
|
||||
}
|
||||
|
||||
public ComputerFamily getFamily()
|
||||
@@ -71,14 +66,14 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput
|
||||
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()
|
||||
@@ -123,6 +118,11 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput
|
||||
return ticksSincePing > 100;
|
||||
}
|
||||
|
||||
public boolean hasOutputChanged()
|
||||
{
|
||||
return changedLastFrame;
|
||||
}
|
||||
|
||||
public void unload()
|
||||
{
|
||||
computer.unload();
|
||||
@@ -142,86 +142,94 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput
|
||||
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()
|
||||
{
|
||||
return new ComputerDataClientMessage( this );
|
||||
}
|
||||
|
||||
protected boolean isInteracting( Player player )
|
||||
{
|
||||
return getContainer( player ) != null;
|
||||
}
|
||||
|
||||
protected NetworkMessage createTerminalPacket()
|
||||
{
|
||||
return new ComputerTerminalClientMessage( getInstanceID(), write() );
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public IContainerComputer getContainer( Player player )
|
||||
public void broadcastState( boolean force )
|
||||
{
|
||||
if( player == null )
|
||||
if( hasOutputChanged() || force )
|
||||
{
|
||||
return null;
|
||||
// Send computer state to all clients
|
||||
NetworkHandler.sendToAllPlayers( createComputerPacket() );
|
||||
}
|
||||
|
||||
AbstractContainerMenu container = player.containerMenu;
|
||||
if( !(container instanceof IContainerComputer) )
|
||||
if( hasTerminalChanged() || force )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
// Send terminal state to clients who are currently interacting with the computer.
|
||||
MinecraftServer server = GameInstanceUtils.getServer();
|
||||
|
||||
IContainerComputer computerContainer = (IContainerComputer) container;
|
||||
return computerContainer.getComputer() != this ? null : computerContainer;
|
||||
NetworkMessage packet = null;
|
||||
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
|
||||
public int getInstanceID()
|
||||
{
|
||||
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
|
||||
public void turnOn()
|
||||
{
|
||||
@@ -229,8 +237,6 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput
|
||||
computer.turnOn();
|
||||
}
|
||||
|
||||
// IComputer
|
||||
|
||||
@Override
|
||||
public void shutdown()
|
||||
{
|
||||
@@ -252,82 +258,24 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput
|
||||
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 )
|
||||
{
|
||||
return computer.getEnvironment()
|
||||
.getExternalRedstoneOutput( side );
|
||||
return computer.getEnvironment().getExternalRedstoneOutput( side );
|
||||
}
|
||||
|
||||
public void setRedstoneInput( ComputerSide side, int level )
|
||||
{
|
||||
computer.getEnvironment()
|
||||
.setRedstoneInput( side, level );
|
||||
computer.getEnvironment().setRedstoneInput( side, level );
|
||||
}
|
||||
|
||||
public int getBundledRedstoneOutput( ComputerSide side )
|
||||
{
|
||||
return computer.getEnvironment()
|
||||
.getExternalBundledRedstoneOutput( side );
|
||||
return computer.getEnvironment().getExternalBundledRedstoneOutput( side );
|
||||
}
|
||||
|
||||
public void setBundledRedstoneInput( ComputerSide side, int combination )
|
||||
{
|
||||
computer.getEnvironment()
|
||||
.setBundledRedstoneInput( side, combination );
|
||||
computer.getEnvironment().setBundledRedstoneInput( side, combination );
|
||||
}
|
||||
|
||||
public void addAPI( ILuaAPI api )
|
||||
@@ -335,62 +283,39 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput
|
||||
computer.addApi( api );
|
||||
}
|
||||
|
||||
// IComputerEnvironment implementation
|
||||
|
||||
public void setPeripheral( ComputerSide side, IPeripheral peripheral )
|
||||
{
|
||||
computer.getEnvironment()
|
||||
.setPeripheral( side, peripheral );
|
||||
computer.getEnvironment().setPeripheral( side, peripheral );
|
||||
}
|
||||
|
||||
public IPeripheral getPeripheral( ComputerSide side )
|
||||
{
|
||||
return computer.getEnvironment()
|
||||
.getPeripheral( side );
|
||||
return computer.getEnvironment().getPeripheral( side );
|
||||
}
|
||||
|
||||
public void setLabel( String label )
|
||||
{
|
||||
computer.setLabel( label );
|
||||
}
|
||||
|
||||
// IComputerEnvironment implementation
|
||||
|
||||
@Override
|
||||
public double getTimeOfDay()
|
||||
{
|
||||
return (level.getDayTime() + 6000) % 24000 / 1000.0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDay()
|
||||
{
|
||||
return (int) ((world.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" );
|
||||
return (int) ((level.getDayTime() + 6000) / 24000) + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IWritableMount createSaveDirMount( String subPath, long capacity )
|
||||
{
|
||||
return ComputerCraftAPI.createSaveDirMount( world, subPath, capacity );
|
||||
return ComputerCraftAPI.createSaveDirMount( level, subPath, capacity );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -404,4 +329,46 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput
|
||||
{
|
||||
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.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.computer.core;
|
||||
|
||||
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
|
||||
public void add( int instanceID, ServerComputer computer )
|
||||
{
|
||||
@@ -70,19 +57,25 @@ public class ServerComputerRegistry extends ComputerRegistry<ServerComputer>
|
||||
//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 )
|
||||
{
|
||||
if( computerID < 0 )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if( computerID < 0 ) return null;
|
||||
|
||||
for( ServerComputer computer : getComputers() )
|
||||
{
|
||||
if( computer.getID() == computerID )
|
||||
{
|
||||
return computer;
|
||||
}
|
||||
if( computer.getID() == computerID ) return computer;
|
||||
}
|
||||
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