1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-09-04 03:17: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:
Toad-Dev
2021-12-03 16:06:45 -08:00
parent 34760d3de4
commit f880396286
259 changed files with 7703 additions and 9250 deletions

View File

@@ -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

View File

@@ -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 {

View File

@@ -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:

View File

@@ -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;

View File

@@ -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) server).callGetResourceManager();
ReloadableResourceManager manager = (ReloadableResourceManager) ((MinecraftServerAccess) GameInstanceUtils.getServer()).callGetResourceManager();
try
{
return manager.getResource( new ResourceLocation( domain, subPath ) )
.getInputStream();
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,15 +100,10 @@ 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();
ReloadableResourceManager manager = (ReloadableResourceManager) ((MinecraftServerAccess) GameInstanceUtils.getServer()).callGetResourceManager();
ResourceMount mount = ResourceMount.get( domain, subPath, manager );
return mount.exists( "" ) ? mount : null;
}
return null;
}
@Override
public void registerPeripheralProvider( @Nonnull IPeripheralProvider provider )
@@ -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()

View File

@@ -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();

View File

@@ -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 ) );
}
}
}

View File

@@ -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;

View File

@@ -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.
*

View File

@@ -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;
}
}

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -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;

View File

@@ -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";
}
}

View File

@@ -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 )

View File

@@ -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;
}
}

View File

@@ -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;

View File

@@ -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 )
);
}
}

View File

@@ -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;

View File

@@ -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 );
}
}

View File

@@ -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 );
}
}

View File

@@ -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 );
}
}

View File

@@ -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;
}
}

View File

@@ -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 );

View File

@@ -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 );

View File

@@ -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 )

View File

@@ -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 )
)
) );
}

View File

@@ -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 );

View File

@@ -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 );
return active && visible && mouseX >= innerX && mouseY >= innerY && mouseX < innerX + innerWidth && mouseY < innerY + innerHeight;
}
// Filter the string
clipboard = SharedConstants.filterText( clipboard );
if( !clipboard.isEmpty() )
public void update()
{
// Clip to 512 characters and queue the event
if( clipboard.length() > 512 )
if( terminateTimer >= 0 && terminateTimer < TERMINATE_TIME && (terminateTimer += 0.05f) > TERMINATE_TIME )
{
clipboard = clipboard.substring( 0, 512 );
}
queueEvent( "paste", clipboard );
computer.queueEvent( "terminate" );
}
return true;
}
}
}
if( key >= 0 && terminateTimer < 0 && rebootTimer < 0 && shutdownTimer < 0 )
if( shutdownTimer >= 0 && shutdownTimer < TERMINATE_TIME && (shutdownTimer += 0.05f) > TERMINATE_TIME )
{
// Queue the "key" event and add to the down set
boolean repeat = keysDown.get( key );
keysDown.set( key );
computer.keyDown( key, repeat );
computer.shutdown();
}
return true;
}
@Override
public boolean keyReleased( int key, int scancode, int modifiers )
if( rebootTimer >= 0 && rebootTimer < TERMINATE_TIME && (rebootTimer += 0.05f) > TERMINATE_TIME )
{
// Queue the "key_up" event and remove from the down set
if( key >= 0 && keysDown.get( key ) )
{
keysDown.set( key, false );
computer.keyUp( key );
computer.reboot();
}
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
@@ -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 )

View File

@@ -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 );
}

View File

@@ -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();

View File

@@ -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();
}
}

View File

@@ -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 );
}

View File

@@ -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();
}
}

View File

@@ -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 )
);
}
}

View File

@@ -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();

View File

@@ -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" );

View File

@@ -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 )));
}
}

View File

@@ -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 )

View File

@@ -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,39 +204,36 @@ 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;
}
}
}
private static void tboVertex( VertexConsumer builder, Matrix4f matrix, float x, float y )
{

View File

@@ -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;

View File

@@ -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;

View File

@@ -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() );
}
}

View File

@@ -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 )
{
}
}

View File

@@ -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

View File

@@ -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/&#42;/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.

View File

@@ -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;
}

View File

@@ -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 )
{

View File

@@ -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();

View File

@@ -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() )

View File

@@ -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;
}
}

View File

@@ -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 );
}
}
}

View File

@@ -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 )
{

View File

@@ -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 )
{

View File

@@ -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();
}
}

View 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 );
}
}
}

View File

@@ -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,
};
}

View File

@@ -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 );

View File

@@ -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 );

View File

@@ -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 );
}
}

View File

@@ -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 ) );

View File

@@ -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() );
}
}

View File

@@ -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() );
}
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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() );
}
}

View File

@@ -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()

View File

@@ -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();
}
}

View File

@@ -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,18 +95,12 @@ 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 ) ) )
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
@@ -177,9 +108,11 @@ public final class HelpingArgumentBuilder extends LiteralArgumentBuilder<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 ) )
.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;
}
}

View File

@@ -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 );
}
}

View File

@@ -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

View File

@@ -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();
}
}
}

View File

@@ -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 );
}

View File

@@ -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 type.get().create( pos, state );
}
return null;
@Nonnull
@Override
@Deprecated
public RenderShape getRenderShape( @Nonnull BlockState state )
{
return RenderShape.MODEL;
}
}

View File

@@ -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();
}
}
}

View File

@@ -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 );
}

View File

@@ -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();

View File

@@ -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 );

View File

@@ -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 );
}
}
}

View File

@@ -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 );
}
}
}

View File

@@ -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

View File

@@ -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,9 +184,11 @@ 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.
@@ -192,27 +196,35 @@ public class CommandAPI implements ILuaAPI
* @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 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 );
if( !level.isInWorldBounds( position ) ) throw new LuaException( "Co-ordinates out of range" );
return getBlockInfo( level, position );
}
else
@Nonnull
private Level getLevel( @Nonnull Optional<String> id ) throws LuaException
{
throw new LuaException( "Co-ordinates out of range" );
}
Level currentLevel = computer.getLevel();
if( currentLevel == null ) throw new LuaException( "No world exists" );
if( !id.isPresent() ) return currentLevel;
ResourceLocation dimensionId = ResourceLocation.tryParse( id.get() );
if( dimensionId == null ) throw new LuaException( "Invalid dimension name" );
Level level = currentLevel.getServer().getLevel( ResourceKey.create( Registry.DIMENSION_REGISTRY, dimensionId ) );
if( level == null ) throw new LuaException( "Unknown dimension" );
return level;
}
}

View File

@@ -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 );
}
}

View File

@@ -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 )
super.setPlacedBy( world, pos, state, placer, stack );
BlockEntity tile = world.getBlockEntity( pos );
if( !world.isClientSide && tile instanceof IComputerTile computer && stack.getItem() instanceof IComputerItem item )
{
computer.serverTick();
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 );
}
}

View File

@@ -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();
}
}

View File

@@ -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();

View File

@@ -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;
}
}

View File

@@ -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() );
}
}

View File

@@ -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,70 +205,105 @@ 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 )
{
return;
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 )
{
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()
@@ -401,45 +311,31 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
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 )
{

View File

@@ -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

View File

@@ -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
}

View File

@@ -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();
}
}

View File

@@ -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;

View File

@@ -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();
}

View File

@@ -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
{
/**

View File

@@ -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();

View File

@@ -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();
NetworkMessage packet = null;
for( Player player : server.getPlayerList().getPlayers() )
{
if( isInteracting( player ) )
{
if( packet == null ) packet = createTerminalPacket();
NetworkHandler.sendToPlayer( player, packet );
}
}
}
}
IContainerComputer computerContainer = (IContainerComputer) container;
return computerContainer.getComputer() != this ? null : computerContainer;
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;
}
}

View File

@@ -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