mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-10-23 01:47:38 +00:00
@@ -50,7 +50,7 @@ dependencies {
|
|||||||
|
|
||||||
compile 'javax.vecmath:vecmath:1.5.2'
|
compile 'javax.vecmath:vecmath:1.5.2'
|
||||||
|
|
||||||
shade 'org.squiddev:Cobalt:0.5.1-SNAPSHOT'
|
shade 'org.squiddev:Cobalt:0.5.2-SNAPSHOT'
|
||||||
|
|
||||||
modRuntime "me.shedaniel:RoughlyEnoughItems-api:5.8.9"
|
modRuntime "me.shedaniel:RoughlyEnoughItems-api:5.8.9"
|
||||||
modRuntime "me.shedaniel:RoughlyEnoughItems:5.8.9"
|
modRuntime "me.shedaniel:RoughlyEnoughItems:5.8.9"
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
org.gradle.jvmargs=-Xmx1G
|
org.gradle.jvmargs=-Xmx1G
|
||||||
|
|
||||||
# Mod properties
|
# Mod properties
|
||||||
mod_version=1.95.3-beta
|
mod_version=1.96.0-beta
|
||||||
|
|
||||||
# Minecraft properties
|
# Minecraft properties
|
||||||
mc_version=1.16.5
|
mc_version=1.16.5
|
||||||
|
@@ -21,7 +21,6 @@ import dan200.computercraft.api.turtle.event.TurtleAction;
|
|||||||
import dan200.computercraft.core.apis.http.options.Action;
|
import dan200.computercraft.core.apis.http.options.Action;
|
||||||
import dan200.computercraft.core.apis.http.options.AddressRule;
|
import dan200.computercraft.core.apis.http.options.AddressRule;
|
||||||
import dan200.computercraft.core.apis.http.websocket.Websocket;
|
import dan200.computercraft.core.apis.http.websocket.Websocket;
|
||||||
import dan200.computercraft.core.asm.GenericSource;
|
|
||||||
import dan200.computercraft.shared.common.ColourableRecipe;
|
import dan200.computercraft.shared.common.ColourableRecipe;
|
||||||
import dan200.computercraft.shared.computer.core.ClientComputerRegistry;
|
import dan200.computercraft.shared.computer.core.ClientComputerRegistry;
|
||||||
import dan200.computercraft.shared.computer.core.ServerComputerRegistry;
|
import dan200.computercraft.shared.computer.core.ServerComputerRegistry;
|
||||||
@@ -39,7 +38,6 @@ import dan200.computercraft.shared.turtle.recipes.TurtleUpgradeRecipe;
|
|||||||
import dan200.computercraft.shared.util.Config;
|
import dan200.computercraft.shared.util.Config;
|
||||||
import dan200.computercraft.shared.util.ImpostorRecipe;
|
import dan200.computercraft.shared.util.ImpostorRecipe;
|
||||||
import dan200.computercraft.shared.util.ImpostorShapelessRecipe;
|
import dan200.computercraft.shared.util.ImpostorShapelessRecipe;
|
||||||
import dan200.computercraft.shared.util.ServiceUtil;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
@@ -132,7 +130,6 @@ public final class ComputerCraft implements ModInitializer {
|
|||||||
Registry.register(Registry.LOOT_CONDITION_TYPE, new Identifier(ComputerCraft.MOD_ID, "player_creative"), PlayerCreativeLootCondition.TYPE);
|
Registry.register(Registry.LOOT_CONDITION_TYPE, new Identifier(ComputerCraft.MOD_ID, "player_creative"), PlayerCreativeLootCondition.TYPE);
|
||||||
Registry.register(Registry.LOOT_CONDITION_TYPE, new Identifier(ComputerCraft.MOD_ID, "has_id"), HasComputerIdLootCondition.TYPE);
|
Registry.register(Registry.LOOT_CONDITION_TYPE, new Identifier(ComputerCraft.MOD_ID, "has_id"), HasComputerIdLootCondition.TYPE);
|
||||||
init();
|
init();
|
||||||
GenericSource.setup( () -> ServiceUtil.loadServices( GenericSource.class ));
|
|
||||||
FabricLoader.getInstance().getModContainer(MOD_ID).ifPresent(modContainer -> {
|
FabricLoader.getInstance().getModContainer(MOD_ID).ifPresent(modContainer -> {
|
||||||
ResourceManagerHelper.registerBuiltinResourcePack(new Identifier(MOD_ID, "classic"), modContainer, ResourcePackActivationType.NORMAL);
|
ResourceManagerHelper.registerBuiltinResourcePack(new Identifier(MOD_ID, "classic"), modContainer, ResourcePackActivationType.NORMAL);
|
||||||
ResourceManagerHelper.registerBuiltinResourcePack(new Identifier(MOD_ID, "overhaul"), modContainer, ResourcePackActivationType.NORMAL);
|
ResourceManagerHelper.registerBuiltinResourcePack(new Identifier(MOD_ID, "overhaul"), modContainer, ResourcePackActivationType.NORMAL);
|
||||||
|
@@ -16,6 +16,7 @@ import javax.annotation.Nullable;
|
|||||||
import dan200.computercraft.api.ComputerCraftAPI.IComputerCraftAPI;
|
import dan200.computercraft.api.ComputerCraftAPI.IComputerCraftAPI;
|
||||||
import dan200.computercraft.api.filesystem.IMount;
|
import dan200.computercraft.api.filesystem.IMount;
|
||||||
import dan200.computercraft.api.filesystem.IWritableMount;
|
import dan200.computercraft.api.filesystem.IWritableMount;
|
||||||
|
import dan200.computercraft.api.lua.GenericSource;
|
||||||
import dan200.computercraft.api.lua.ILuaAPIFactory;
|
import dan200.computercraft.api.lua.ILuaAPIFactory;
|
||||||
import dan200.computercraft.api.media.IMediaProvider;
|
import dan200.computercraft.api.media.IMediaProvider;
|
||||||
import dan200.computercraft.api.network.IPacketNetwork;
|
import dan200.computercraft.api.network.IPacketNetwork;
|
||||||
@@ -26,6 +27,7 @@ import dan200.computercraft.api.pocket.IPocketUpgrade;
|
|||||||
import dan200.computercraft.api.redstone.IBundledRedstoneProvider;
|
import dan200.computercraft.api.redstone.IBundledRedstoneProvider;
|
||||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||||
import dan200.computercraft.core.apis.ApiFactories;
|
import dan200.computercraft.core.apis.ApiFactories;
|
||||||
|
import dan200.computercraft.core.asm.GenericMethod;
|
||||||
import dan200.computercraft.core.filesystem.FileMount;
|
import dan200.computercraft.core.filesystem.FileMount;
|
||||||
import dan200.computercraft.core.filesystem.ResourceMount;
|
import dan200.computercraft.core.filesystem.ResourceMount;
|
||||||
import dan200.computercraft.mixin.MinecraftServerAccess;
|
import dan200.computercraft.mixin.MinecraftServerAccess;
|
||||||
@@ -143,6 +145,12 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI {
|
|||||||
PocketUpgrades.register(upgrade);
|
PocketUpgrades.register(upgrade);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerGenericSource( @Nonnull GenericSource source )
|
||||||
|
{
|
||||||
|
GenericMethod.register( source );
|
||||||
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public IPacketNetwork getWirelessNetwork() {
|
public IPacketNetwork getWirelessNetwork() {
|
||||||
|
@@ -11,6 +11,7 @@ import javax.annotation.Nullable;
|
|||||||
|
|
||||||
import dan200.computercraft.api.filesystem.IMount;
|
import dan200.computercraft.api.filesystem.IMount;
|
||||||
import dan200.computercraft.api.filesystem.IWritableMount;
|
import dan200.computercraft.api.filesystem.IWritableMount;
|
||||||
|
import dan200.computercraft.api.lua.GenericSource;
|
||||||
import dan200.computercraft.api.lua.ILuaAPIFactory;
|
import dan200.computercraft.api.lua.ILuaAPIFactory;
|
||||||
import dan200.computercraft.api.media.IMedia;
|
import dan200.computercraft.api.media.IMedia;
|
||||||
import dan200.computercraft.api.media.IMediaProvider;
|
import dan200.computercraft.api.media.IMediaProvider;
|
||||||
@@ -136,6 +137,17 @@ public final class ComputerCraftAPI {
|
|||||||
getInstance().registerPeripheralProvider(provider);
|
getInstance().registerPeripheralProvider(provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a method source for generic peripherals.
|
||||||
|
*
|
||||||
|
* @param source The method source to register.
|
||||||
|
* @see GenericSource
|
||||||
|
*/
|
||||||
|
public static void registerGenericSource( @Nonnull GenericSource source )
|
||||||
|
{
|
||||||
|
getInstance().registerGenericSource( source );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
* 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.
|
* recommended to call this during the load() method of your mod.
|
||||||
@@ -238,6 +250,8 @@ public final class ComputerCraftAPI {
|
|||||||
|
|
||||||
void registerPeripheralProvider(@Nonnull IPeripheralProvider provider);
|
void registerPeripheralProvider(@Nonnull IPeripheralProvider provider);
|
||||||
|
|
||||||
|
void registerGenericSource( @Nonnull GenericSource source );
|
||||||
|
|
||||||
void registerTurtleUpgrade(@Nonnull ITurtleUpgrade upgrade);
|
void registerTurtleUpgrade(@Nonnull ITurtleUpgrade upgrade);
|
||||||
|
|
||||||
void registerBundledRedstoneProvider(@Nonnull IBundledRedstoneProvider provider);
|
void registerBundledRedstoneProvider(@Nonnull IBundledRedstoneProvider provider);
|
||||||
|
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* 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.lua;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
|
import dan200.computercraft.api.peripheral.IPeripheralProvider;
|
||||||
|
import dan200.computercraft.core.asm.LuaMethod;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A generic source of {@link LuaMethod} functions.
|
||||||
|
*
|
||||||
|
* Unlike normal objects ({@link IDynamicLuaObject} or {@link IPeripheral}), methods do not target this object but
|
||||||
|
* instead are defined as {@code static} and accept their target as the first parameter. This allows you to inject
|
||||||
|
* methods onto objects you do not own, as well as declaring methods for a specific "trait" (for instance, a
|
||||||
|
* {@link Capability}).
|
||||||
|
*
|
||||||
|
* Currently the "generic peripheral" system is incompatible with normal peripherals. Normal {@link IPeripheralProvider}
|
||||||
|
* or {@link IPeripheral} implementations take priority. Tile entities which use this system are given a peripheral name
|
||||||
|
* determined by their id, rather than any peripheral provider. This will hopefully change in the future, once a suitable
|
||||||
|
* design has been established.
|
||||||
|
*
|
||||||
|
* For example, the main CC: Tweaked mod defines a generic source for inventories, which works on {@link IItemHandler}s:
|
||||||
|
*
|
||||||
|
* <pre>{@code
|
||||||
|
* public class InventoryMethods implements GenericSource {
|
||||||
|
* \@LuaFunction( mainThread = true )
|
||||||
|
* public static int size(IItemHandler inventory) {
|
||||||
|
* return inventory.getSlots();
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // ...
|
||||||
|
* }
|
||||||
|
* }</pre>
|
||||||
|
*
|
||||||
|
* @see ComputerCraftAPI#registerGenericSource(GenericSource)
|
||||||
|
* @see ComputerCraftAPI#registerGenericCapability(Capability) New capabilities (those not built into Forge) must be
|
||||||
|
* explicitly given to the generic peripheral system, as there is no way to enumerate all capabilities.
|
||||||
|
*/
|
||||||
|
public interface GenericSource
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* A unique identifier for this generic source.
|
||||||
|
*
|
||||||
|
* This is currently unused, but may be used in the future to allow disabling specific sources. It is recommended
|
||||||
|
* to return an identifier using your mod's ID.
|
||||||
|
*
|
||||||
|
* @return This source's identifier.
|
||||||
|
*/
|
||||||
|
@Nonnull
|
||||||
|
Identifier id();
|
||||||
|
}
|
@@ -38,7 +38,10 @@ public class ComputerBorderRenderer {
|
|||||||
private static final int CORNER_LEFT_X = BORDER;
|
private static final int CORNER_LEFT_X = BORDER;
|
||||||
private static final int CORNER_RIGHT_X = CORNER_LEFT_X + BORDER;
|
private static final int CORNER_RIGHT_X = CORNER_LEFT_X + BORDER;
|
||||||
private static final int BORDER_RIGHT_X = 36;
|
private static final int BORDER_RIGHT_X = 36;
|
||||||
private static final int GAP = 4;
|
private static final int LIGHT_BORDER_Y = 56;
|
||||||
|
private static final int LIGHT_CORNER_Y = 80;
|
||||||
|
|
||||||
|
public static final int LIGHT_HEIGHT = 8;
|
||||||
private static final float TEX_SCALE = 1 / 256.0f;
|
private static final float TEX_SCALE = 1 / 256.0f;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@@ -89,15 +92,16 @@ public class ComputerBorderRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void render(Matrix4f transform, VertexConsumer buffer, int x, int y, int z, int width, int height, float r, float g, float b) {
|
public static void render(Matrix4f transform, VertexConsumer buffer, int x, int y, int z, int width, int height, float r, float g, float b) {
|
||||||
render(transform, buffer, x, y, z, width, height, 0, r, g, b);
|
render( transform, buffer, x, y, z, width, height, false, r, g, b );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void render(Matrix4f transform, VertexConsumer buffer, int x, int y, int z, int width, int height, int borderHeight, float r, float g,
|
public static void render( Matrix4f transform, VertexConsumer buffer, int x, int y, int z, int width, int height, boolean withLight, float r, float g, float b )
|
||||||
float b) {
|
{
|
||||||
new ComputerBorderRenderer(transform, buffer, z, r, g, b).doRender(x, y, width, height, borderHeight);
|
new ComputerBorderRenderer( transform, buffer, z, r, g, b ).doRender( x, y, width, height, withLight );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void doRender(int x, int y, int width, int height, int bottomHeight) {
|
public void doRender( int x, int y, int width, int height, boolean withLight )
|
||||||
|
{
|
||||||
int endX = x + width;
|
int endX = x + width;
|
||||||
int endY = y + height;
|
int endY = y + height;
|
||||||
|
|
||||||
@@ -112,24 +116,17 @@ public class ComputerBorderRenderer {
|
|||||||
|
|
||||||
// Bottom bar. We allow for drawing a stretched version, which allows for additional elements (such as the
|
// Bottom bar. We allow for drawing a stretched version, which allows for additional elements (such as the
|
||||||
// pocket computer's lights).
|
// pocket computer's lights).
|
||||||
if (bottomHeight <= 0) {
|
if( withLight )
|
||||||
|
{
|
||||||
|
renderTexture( x, endY, 0, LIGHT_BORDER_Y, endX - x, BORDER + LIGHT_HEIGHT, BORDER, BORDER + LIGHT_HEIGHT );
|
||||||
|
renderTexture( x - BORDER, endY, CORNER_LEFT_X, LIGHT_CORNER_Y, BORDER, BORDER + LIGHT_HEIGHT );
|
||||||
|
renderTexture( endX, endY, CORNER_RIGHT_X, LIGHT_CORNER_Y, BORDER, BORDER + LIGHT_HEIGHT );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
this.renderLine(x, endY, 0, BORDER, endX - x, BORDER);
|
this.renderLine(x, endY, 0, BORDER, endX - x, BORDER);
|
||||||
this.renderCorner(x - BORDER, endY, CORNER_LEFT_X, CORNER_BOTTOM_Y);
|
this.renderCorner(x - BORDER, endY, CORNER_LEFT_X, CORNER_BOTTOM_Y);
|
||||||
this.renderCorner(endX, endY, CORNER_RIGHT_X, CORNER_BOTTOM_Y);
|
this.renderCorner(endX, endY, CORNER_RIGHT_X, CORNER_BOTTOM_Y);
|
||||||
} else {
|
|
||||||
// Bottom left, middle, right. We do this in three portions: the top inner corners, an extended region for
|
|
||||||
// lights, and then the bottom outer corners.
|
|
||||||
this.renderTexture(x - BORDER, endY, CORNER_LEFT_X, CORNER_BOTTOM_Y, BORDER, BORDER / 2);
|
|
||||||
this.renderTexture(x, endY, 0, BORDER, width, BORDER / 2, BORDER, BORDER / 2);
|
|
||||||
this.renderTexture(endX, endY, CORNER_RIGHT_X, CORNER_BOTTOM_Y, BORDER, BORDER / 2);
|
|
||||||
|
|
||||||
this.renderTexture(x - BORDER, endY + BORDER / 2, CORNER_LEFT_X, CORNER_BOTTOM_Y + GAP, BORDER, bottomHeight, BORDER, GAP);
|
|
||||||
this.renderTexture(x, endY + BORDER / 2, 0, BORDER + GAP, width, bottomHeight, BORDER, GAP);
|
|
||||||
this.renderTexture(endX, endY + BORDER / 2, CORNER_RIGHT_X, CORNER_BOTTOM_Y + GAP, BORDER, bottomHeight, BORDER, GAP);
|
|
||||||
|
|
||||||
this.renderTexture(x - BORDER, endY + bottomHeight + BORDER / 2, CORNER_LEFT_X, CORNER_BOTTOM_Y + BORDER / 2, BORDER, BORDER / 2);
|
|
||||||
this.renderTexture(x, endY + bottomHeight + BORDER / 2, 0, BORDER + BORDER / 2, width, BORDER / 2);
|
|
||||||
this.renderTexture(endX, endY + bottomHeight + BORDER / 2, CORNER_RIGHT_X, CORNER_BOTTOM_Y + BORDER / 2, BORDER, BORDER / 2);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
package dan200.computercraft.client.render;
|
package dan200.computercraft.client.render;
|
||||||
|
|
||||||
|
import static dan200.computercraft.client.render.ComputerBorderRenderer.*;
|
||||||
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT;
|
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT;
|
||||||
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_WIDTH;
|
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_WIDTH;
|
||||||
import static dan200.computercraft.client.render.ComputerBorderRenderer.BORDER;
|
import static dan200.computercraft.client.render.ComputerBorderRenderer.BORDER;
|
||||||
@@ -31,12 +32,13 @@ import net.minecraft.client.util.math.Vector3f;
|
|||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.util.math.Matrix4f;
|
import net.minecraft.util.math.Matrix4f;
|
||||||
|
|
||||||
|
import static dan200.computercraft.client.render.ComputerBorderRenderer.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emulates map rendering for pocket computers.
|
* Emulates map rendering for pocket computers.
|
||||||
*/
|
*/
|
||||||
public final class ItemPocketRenderer extends ItemMapLikeRenderer {
|
public final class ItemPocketRenderer extends ItemMapLikeRenderer {
|
||||||
public static final ItemPocketRenderer INSTANCE = new ItemPocketRenderer();
|
public static final ItemPocketRenderer INSTANCE = new ItemPocketRenderer();
|
||||||
private static final int LIGHT_HEIGHT = 8;
|
|
||||||
|
|
||||||
private ItemPocketRenderer() {
|
private ItemPocketRenderer() {
|
||||||
}
|
}
|
||||||
@@ -108,7 +110,7 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer {
|
|||||||
BufferBuilder buffer = tessellator.getBuffer();
|
BufferBuilder buffer = tessellator.getBuffer();
|
||||||
buffer.begin(GL11.GL_QUADS, VertexFormats.POSITION_COLOR_TEXTURE);
|
buffer.begin(GL11.GL_QUADS, VertexFormats.POSITION_COLOR_TEXTURE);
|
||||||
|
|
||||||
ComputerBorderRenderer.render(transform, buffer, 0, 0, 0, width, height, LIGHT_HEIGHT, r, g, b);
|
ComputerBorderRenderer.render(transform, buffer, 0, 0, 0, width, height, true, r, g, b);
|
||||||
|
|
||||||
tessellator.draw();
|
tessellator.draw();
|
||||||
}
|
}
|
||||||
|
@@ -36,10 +36,7 @@ import com.google.common.cache.LoadingCache;
|
|||||||
import com.google.common.primitives.Primitives;
|
import com.google.common.primitives.Primitives;
|
||||||
import com.google.common.reflect.TypeToken;
|
import com.google.common.reflect.TypeToken;
|
||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.ComputerCraft;
|
||||||
import dan200.computercraft.api.lua.IArguments;
|
import dan200.computercraft.api.lua.*;
|
||||||
import dan200.computercraft.api.lua.LuaException;
|
|
||||||
import dan200.computercraft.api.lua.LuaFunction;
|
|
||||||
import dan200.computercraft.api.lua.MethodResult;
|
|
||||||
import org.objectweb.asm.ClassWriter;
|
import org.objectweb.asm.ClassWriter;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
import org.objectweb.asm.Type;
|
import org.objectweb.asm.Type;
|
||||||
@@ -120,10 +117,9 @@ public final class Generator<T> {
|
|||||||
this.addMethod(methods, method, annotation, instance);
|
this.addMethod(methods, method, annotation, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (GenericSource.GenericMethod method : GenericSource.GenericMethod.all()) {
|
for( GenericMethod method : GenericMethod.all() )
|
||||||
if (!method.target.isAssignableFrom(klass)) {
|
{
|
||||||
continue;
|
if( !method.target.isAssignableFrom( klass ) ) continue;
|
||||||
}
|
|
||||||
|
|
||||||
T instance = this.methodCache.getUnchecked(method.method)
|
T instance = this.methodCache.getUnchecked(method.method)
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
|
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* 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.core.asm;
|
||||||
|
|
||||||
|
import dan200.computercraft.ComputerCraft;
|
||||||
|
import dan200.computercraft.api.lua.GenericSource;
|
||||||
|
import dan200.computercraft.api.lua.LuaFunction;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A generic method is a method belonging to a {@link GenericSource} with a known target.
|
||||||
|
*/
|
||||||
|
public class GenericMethod
|
||||||
|
{
|
||||||
|
final Method method;
|
||||||
|
final LuaFunction annotation;
|
||||||
|
final Class<?> target;
|
||||||
|
|
||||||
|
private static final List<GenericSource> sources = new ArrayList<>();
|
||||||
|
private static List<GenericMethod> cache;
|
||||||
|
|
||||||
|
GenericMethod( Method method, LuaFunction annotation, Class<?> target )
|
||||||
|
{
|
||||||
|
this.method = method;
|
||||||
|
this.annotation = annotation;
|
||||||
|
this.target = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find all public static methods annotated with {@link LuaFunction} which belong to a {@link GenericSource}.
|
||||||
|
*
|
||||||
|
* @return All available generic methods.
|
||||||
|
*/
|
||||||
|
static List<GenericMethod> all()
|
||||||
|
{
|
||||||
|
if( cache != null ) return cache;
|
||||||
|
return cache = sources.stream()
|
||||||
|
.flatMap( x -> Arrays.stream( x.getClass().getDeclaredMethods() ) )
|
||||||
|
.map( method ->
|
||||||
|
{
|
||||||
|
LuaFunction annotation = method.getAnnotation( LuaFunction.class );
|
||||||
|
if( annotation == null ) return null;
|
||||||
|
|
||||||
|
if( !Modifier.isStatic( method.getModifiers() ) )
|
||||||
|
{
|
||||||
|
ComputerCraft.log.error( "GenericSource method {}.{} should be static.", method.getDeclaringClass(), method.getName() );
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type[] types = method.getGenericParameterTypes();
|
||||||
|
if( types.length == 0 )
|
||||||
|
{
|
||||||
|
ComputerCraft.log.error( "GenericSource method {}.{} has no parameters.", method.getDeclaringClass(), method.getName() );
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Class<?> target = Reflect.getRawType( method, types[0], false );
|
||||||
|
if( target == null ) return null;
|
||||||
|
|
||||||
|
return new GenericMethod( method, annotation, target );
|
||||||
|
} )
|
||||||
|
.filter( Objects::nonNull )
|
||||||
|
.collect( Collectors.toList() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static synchronized void register( @Nonnull GenericSource source )
|
||||||
|
{
|
||||||
|
Objects.requireNonNull( source, "Source cannot be null" );
|
||||||
|
|
||||||
|
if( cache != null )
|
||||||
|
{
|
||||||
|
ComputerCraft.log.warn( "Registering a generic source {} after cache has been built. This source will be ignored.", cache );
|
||||||
|
}
|
||||||
|
|
||||||
|
sources.add( source );
|
||||||
|
}
|
||||||
|
}
|
@@ -1,114 +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.core.asm;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.lang.reflect.Modifier;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
|
|
||||||
import dan200.computercraft.ComputerCraft;
|
|
||||||
import dan200.computercraft.api.lua.LuaFunction;
|
|
||||||
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A generic source of {@link LuaMethod} functions. This allows for injecting methods onto objects you do not own.
|
|
||||||
*
|
|
||||||
* Unlike conventional Lua objects, the annotated methods should be {@code static}, with their target as the first parameter.
|
|
||||||
*/
|
|
||||||
public interface GenericSource {
|
|
||||||
/**
|
|
||||||
* Register a stream of generic sources.
|
|
||||||
*
|
|
||||||
* @param sources The source of generic methods.
|
|
||||||
*/
|
|
||||||
static void setup(Supplier<Stream<GenericSource>> sources) {
|
|
||||||
GenericMethod.sources = sources;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A unique identifier for this generic source. This may be used in the future to allow disabling specific sources.
|
|
||||||
*
|
|
||||||
* @return This source's identifier.
|
|
||||||
*/
|
|
||||||
@Nonnull
|
|
||||||
Identifier id();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A generic method is a method belonging to a {@link GenericSource} with a known target.
|
|
||||||
*/
|
|
||||||
class GenericMethod {
|
|
||||||
static Supplier<Stream<GenericSource>> sources;
|
|
||||||
private static List<GenericMethod> cache;
|
|
||||||
final Method method;
|
|
||||||
final LuaFunction annotation;
|
|
||||||
final Class<?> target;
|
|
||||||
|
|
||||||
GenericMethod(Method method, LuaFunction annotation, Class<?> target) {
|
|
||||||
this.method = method;
|
|
||||||
this.annotation = annotation;
|
|
||||||
this.target = target;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find all public static methods annotated with {@link LuaFunction} which belong to a {@link GenericSource}.
|
|
||||||
*
|
|
||||||
* @return All available generic methods.
|
|
||||||
*/
|
|
||||||
static List<GenericMethod> all() {
|
|
||||||
if (cache != null) {
|
|
||||||
return cache;
|
|
||||||
}
|
|
||||||
if (sources == null) {
|
|
||||||
ComputerCraft.log.warn("Getting GenericMethods without a provider");
|
|
||||||
return cache = Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
return cache = sources.get()
|
|
||||||
.flatMap(x -> Arrays.stream(x.getClass()
|
|
||||||
.getDeclaredMethods()))
|
|
||||||
.map(method -> {
|
|
||||||
LuaFunction annotation = method.getAnnotation(LuaFunction.class);
|
|
||||||
if (annotation == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Modifier.isStatic(method.getModifiers())) {
|
|
||||||
ComputerCraft.log.error("GenericSource method {}.{} should be static.",
|
|
||||||
method.getDeclaringClass(),
|
|
||||||
method.getName());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type[] types = method.getGenericParameterTypes();
|
|
||||||
if (types.length == 0) {
|
|
||||||
ComputerCraft.log.error("GenericSource method {}.{} has no parameters.",
|
|
||||||
method.getDeclaringClass(),
|
|
||||||
method.getName());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Class<?> target = Reflect.getRawType(method, types[0], false);
|
|
||||||
if (target == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new GenericMethod(method, annotation, target);
|
|
||||||
})
|
|
||||||
.filter(Objects::nonNull)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -31,7 +31,7 @@ import com.google.common.io.ByteStreams;
|
|||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.ComputerCraft;
|
||||||
import dan200.computercraft.api.filesystem.IMount;
|
import dan200.computercraft.api.filesystem.IMount;
|
||||||
import dan200.computercraft.core.apis.handles.ArrayByteChannel;
|
import dan200.computercraft.core.apis.handles.ArrayByteChannel;
|
||||||
|
import dan200.computercraft.shared.util.IoUtil;
|
||||||
import net.minecraft.resource.ReloadableResourceManager;
|
import net.minecraft.resource.ReloadableResourceManager;
|
||||||
import net.minecraft.resource.Resource;
|
import net.minecraft.resource.Resource;
|
||||||
import net.minecraft.resource.ResourceManager;
|
import net.minecraft.resource.ResourceManager;
|
||||||
@@ -108,8 +108,8 @@ public final class ResourceMount implements IMount {
|
|||||||
|
|
||||||
if( !hasAny )
|
if( !hasAny )
|
||||||
{
|
{
|
||||||
ComputerCraft.log.warn("Cannot find any files under /data/{}/{} for resource mount.", namespace, subPath);
|
ComputerCraft.log.warn( "Cannot find any files under /data/{}/{} for resource mount.", namespace, subPath );
|
||||||
if( newRoot != null )
|
if( existingNamespace != null )
|
||||||
{
|
{
|
||||||
ComputerCraft.log.warn("There are files under /data/{}/{} though. Did you get the wrong namespace?", existingNamespace, subPath);
|
ComputerCraft.log.warn("There are files under /data/{}/{} though. Did you get the wrong namespace?", existingNamespace, subPath);
|
||||||
}
|
}
|
||||||
@@ -186,13 +186,19 @@ public final class ResourceMount implements IMount {
|
|||||||
return new ArrayByteChannel(contents);
|
return new ArrayByteChannel(contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
try (InputStream stream = this.manager.getResource(file.identifier)
|
try
|
||||||
.getInputStream()) {
|
{
|
||||||
if (stream.available() > MAX_CACHED_SIZE) {
|
InputStream stream = manager.getResource( file.identifier ).getInputStream();
|
||||||
return Channels.newChannel(stream);
|
if( stream.available() > MAX_CACHED_SIZE ) return Channels.newChannel( stream );
|
||||||
}
|
|
||||||
|
|
||||||
contents = ByteStreams.toByteArray(stream);
|
try
|
||||||
|
{
|
||||||
|
contents = ByteStreams.toByteArray( stream );
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
IoUtil.closeQuietly( stream );
|
||||||
|
}
|
||||||
CONTENTS_CACHE.put(file, contents);
|
CONTENTS_CACHE.put(file, contents);
|
||||||
return new ArrayByteChannel(contents);
|
return new ArrayByteChannel(contents);
|
||||||
} catch (FileNotFoundException ignored) {
|
} catch (FileNotFoundException ignored) {
|
||||||
|
@@ -72,10 +72,11 @@ public final class ColourableRecipe extends SpecialCraftingRecipe {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (colourable.isEmpty()) {
|
if( colourable.isEmpty() ) return ItemStack.EMPTY;
|
||||||
return ItemStack.EMPTY;
|
|
||||||
}
|
ItemStack stack = ((IColouredItem) colourable.getItem()).withColour( colourable, tracker.getColour() );
|
||||||
return ((IColouredItem) colourable.getItem()).withColour(colourable, tracker.getColour());
|
stack.setCount( 1 );
|
||||||
|
return stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -5,30 +5,20 @@
|
|||||||
*/
|
*/
|
||||||
package dan200.computercraft.shared.peripheral.generic.methods;
|
package dan200.computercraft.shared.peripheral.generic.methods;
|
||||||
|
|
||||||
import com.google.auto.service.AutoService;
|
|
||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.ComputerCraft;
|
||||||
|
import dan200.computercraft.api.lua.GenericSource;
|
||||||
import dan200.computercraft.api.lua.LuaException;
|
import dan200.computercraft.api.lua.LuaException;
|
||||||
import dan200.computercraft.api.lua.LuaFunction;
|
import dan200.computercraft.api.lua.LuaFunction;
|
||||||
import dan200.computercraft.api.peripheral.IComputerAccess;
|
import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
import dan200.computercraft.core.asm.GenericSource;
|
|
||||||
import dan200.computercraft.shared.peripheral.generic.data.ItemData;
|
import dan200.computercraft.shared.peripheral.generic.data.ItemData;
|
||||||
import dan200.computercraft.shared.util.InventoryUtil;
|
import dan200.computercraft.shared.util.InventoryUtil;
|
||||||
import dan200.computercraft.shared.util.ItemStorage;
|
import dan200.computercraft.shared.util.ItemStorage;
|
||||||
import net.minecraft.block.Block;
|
|
||||||
import net.minecraft.block.BlockState;
|
|
||||||
import net.minecraft.block.ChestBlock;
|
|
||||||
import net.minecraft.block.InventoryProvider;
|
|
||||||
import net.minecraft.block.entity.BlockEntity;
|
import net.minecraft.block.entity.BlockEntity;
|
||||||
import net.minecraft.block.entity.ChestBlockEntity;
|
|
||||||
import net.minecraft.inventory.Inventory;
|
import net.minecraft.inventory.Inventory;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.text.Text;
|
|
||||||
import net.minecraft.text.TranslatableText;
|
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
import net.minecraft.util.Nameable;
|
import net.minecraft.util.Nameable;
|
||||||
import net.minecraft.util.math.BlockPos;
|
|
||||||
import net.minecraft.world.World;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@@ -43,14 +33,13 @@ import static dan200.computercraft.shared.peripheral.generic.methods.ArgumentHel
|
|||||||
*
|
*
|
||||||
* @cc.module inventory
|
* @cc.module inventory
|
||||||
*/
|
*/
|
||||||
@AutoService( GenericSource.class )
|
|
||||||
public class InventoryMethods implements GenericSource
|
public class InventoryMethods implements GenericSource
|
||||||
{
|
{
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public Identifier id()
|
public Identifier id()
|
||||||
{
|
{
|
||||||
return new Identifier(ComputerCraft.MOD_ID, "inventory" );
|
return new Identifier( ComputerCraft.MOD_ID, "inventory" );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -85,8 +74,9 @@ public class InventoryMethods implements GenericSource
|
|||||||
* List all items in this inventory. This returns a table, with an entry for each slot.
|
* List all items in this inventory. This returns a table, with an entry for each slot.
|
||||||
*
|
*
|
||||||
* Each item in the inventory is represented by a table containing some basic information, much like
|
* Each item in the inventory is represented by a table containing some basic information, much like
|
||||||
* @link dan200.computercraft.shared.turtle.apis.TurtleAPI#getItemDetail includes. More information can be fetched
|
* {@link dan200.computercraft.shared.turtle.apis.TurtleAPI#getItemDetail} includes. More information can be fetched
|
||||||
* with {@link #getItemDetail}.
|
* with {@link #getItemDetail}. The table contains the item `name`, the `count` and an a (potentially nil) hash of
|
||||||
|
* the item's `nbt.` This NBT data doesn't contain anything useful, but allows you to distinguish identical items.
|
||||||
*
|
*
|
||||||
* The returned table is sparse, and so empty slots will be `nil` - it is recommended to loop over using `pairs`
|
* The returned table is sparse, and so empty slots will be `nil` - it is recommended to loop over using `pairs`
|
||||||
* rather than `ipairs`.
|
* rather than `ipairs`.
|
||||||
@@ -94,6 +84,14 @@ public class InventoryMethods implements GenericSource
|
|||||||
* @param inventory The current inventory.
|
* @param inventory The current inventory.
|
||||||
* @return All items in this inventory.
|
* @return All items in this inventory.
|
||||||
* @cc.treturn { (table|nil)... } All items in this inventory.
|
* @cc.treturn { (table|nil)... } All items in this inventory.
|
||||||
|
* @cc.usage Find an adjacent chest and print all items in it.
|
||||||
|
*
|
||||||
|
* <pre>{@code
|
||||||
|
* local chest = peripheral.find("minecraft:chest")
|
||||||
|
* for slot, item in pairs(chest.list()) do
|
||||||
|
* print(("%d x %s in slot %d"):format(item.count, item.name, slot))
|
||||||
|
* end
|
||||||
|
* }</pre>
|
||||||
*/
|
*/
|
||||||
@LuaFunction( mainThread = true )
|
@LuaFunction( mainThread = true )
|
||||||
public static Map<Integer, Map<String, ?>> list( Inventory inventory )
|
public static Map<Integer, Map<String, ?>> list( Inventory inventory )
|
||||||
@@ -114,11 +112,32 @@ public class InventoryMethods implements GenericSource
|
|||||||
/**
|
/**
|
||||||
* Get detailed information about an item.
|
* Get detailed information about an item.
|
||||||
*
|
*
|
||||||
|
* The returned information contains the same information as each item in
|
||||||
|
* {@link #list}, as well as additional details like the display name
|
||||||
|
* (`displayName`) and item durability (`damage`, `maxDamage`, `durability`).
|
||||||
|
*
|
||||||
|
* Some items include more information (such as enchantments) - it is
|
||||||
|
* recommended to print it out using @{textutils.serialize} or in the Lua
|
||||||
|
* REPL, to explore what is available.
|
||||||
|
*
|
||||||
* @param inventory The current inventory.
|
* @param inventory The current inventory.
|
||||||
* @param slot The slot to get information about.
|
* @param slot The slot to get information about.
|
||||||
* @return Information about the item in this slot, or {@code nil} if not present.
|
* @return Information about the item in this slot, or {@code nil} if not present.
|
||||||
* @throws LuaException If the slot is out of range.
|
* @throws LuaException If the slot is out of range.
|
||||||
* @cc.treturn table Information about the item in this slot, or {@code nil} if not present.
|
* @cc.treturn table Information about the item in this slot, or {@code nil} if not present.
|
||||||
|
* @cc.usage Print some information about the first in a chest.
|
||||||
|
*
|
||||||
|
* <pre>{@code
|
||||||
|
* local chest = peripheral.find("minecraft:chest")
|
||||||
|
* local item = chest.getItemDetail(1)
|
||||||
|
* if not item then print("No item") return end
|
||||||
|
*
|
||||||
|
* print(("%s (%s)"):format(item.displayName, item.name))
|
||||||
|
* print(("Count: %d/%d"):format(item.count, item.maxCount))
|
||||||
|
* if item.damage then
|
||||||
|
* print(("Damage: %d/%d"):format(item.damage, item.maxDamage))
|
||||||
|
* end
|
||||||
|
* }</pre>
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
@LuaFunction( mainThread = true )
|
@LuaFunction( mainThread = true )
|
||||||
@@ -132,6 +151,33 @@ public class InventoryMethods implements GenericSource
|
|||||||
return stack.isEmpty() ? null : ItemData.fill( new HashMap<>(), stack );
|
return stack.isEmpty() ? null : ItemData.fill( new HashMap<>(), stack );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the maximum number of items which can be stored in this slot.
|
||||||
|
*
|
||||||
|
* Typically this will be limited to 64 items. However, some inventories (such as barrels or caches) can store
|
||||||
|
* hundreds or thousands of items in one slot.
|
||||||
|
*
|
||||||
|
* @param inventory Inventory to probe.
|
||||||
|
* @param slot The slot
|
||||||
|
* @return The maximum number of items in this slot.
|
||||||
|
* @throws LuaException If the slot is out of range.
|
||||||
|
* @cc.usage Count the maximum number of items an adjacent chest can hold.
|
||||||
|
* <pre>{@code
|
||||||
|
* local chest = peripheral.find("minecraft:chest")
|
||||||
|
* local total = 0
|
||||||
|
* for i = 1, chest.size() do
|
||||||
|
* total = total + chest.getItemLimit(i)
|
||||||
|
* end
|
||||||
|
* print(total)
|
||||||
|
* }</pre>
|
||||||
|
*/
|
||||||
|
@LuaFunction( mainThread = true )
|
||||||
|
public static int getItemLimit( Inventory inventory, int slot ) throws LuaException
|
||||||
|
{
|
||||||
|
assertBetween( slot, 1, inventory.size(), "Slot out of range (%s)" );
|
||||||
|
return inventory.getMaxCountPerStack();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Push items from one inventory to another connected one.
|
* Push items from one inventory to another connected one.
|
||||||
*
|
*
|
||||||
|
@@ -9,6 +9,7 @@ package dan200.computercraft.shared.peripheral.monitor;
|
|||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.turtle.FakePlayer;
|
||||||
import dan200.computercraft.shared.common.BlockGeneric;
|
import dan200.computercraft.shared.common.BlockGeneric;
|
||||||
|
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
@@ -71,9 +72,14 @@ public class BlockMonitor extends BlockGeneric {
|
|||||||
BlockEntity entity = world.getBlockEntity(pos);
|
BlockEntity entity = world.getBlockEntity(pos);
|
||||||
if (entity instanceof TileMonitor && !world.isClient) {
|
if (entity instanceof TileMonitor && !world.isClient) {
|
||||||
TileMonitor monitor = (TileMonitor) entity;
|
TileMonitor monitor = (TileMonitor) entity;
|
||||||
monitor.contractNeighbours();
|
// Defer the block update if we're being placed by another TE. See #691
|
||||||
monitor.contract();
|
if ( livingEntity == null || livingEntity instanceof FakePlayer )
|
||||||
monitor.expand();
|
{
|
||||||
|
monitor.updateNeighborsDeferred();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
monitor.updateNeighbors();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -54,6 +54,7 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile {
|
|||||||
private ServerMonitor m_serverMonitor;
|
private ServerMonitor m_serverMonitor;
|
||||||
private ClientMonitor m_clientMonitor;
|
private ClientMonitor m_clientMonitor;
|
||||||
private MonitorPeripheral peripheral;
|
private MonitorPeripheral peripheral;
|
||||||
|
private boolean needsUpdate = false;
|
||||||
private boolean m_destroyed = false;
|
private boolean m_destroyed = false;
|
||||||
private boolean visiting = false;
|
private boolean visiting = false;
|
||||||
private int m_width = 1;
|
private int m_width = 1;
|
||||||
@@ -98,6 +99,12 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void blockTick() {
|
public void blockTick() {
|
||||||
|
if ( needsUpdate )
|
||||||
|
{
|
||||||
|
needsUpdate = false;
|
||||||
|
updateNeighbors();
|
||||||
|
}
|
||||||
|
|
||||||
if (this.m_xIndex != 0 || this.m_yIndex != 0 || this.m_serverMonitor == null) {
|
if (this.m_xIndex != 0 || this.m_yIndex != 0 || this.m_serverMonitor == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -530,6 +537,18 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateNeighborsDeferred()
|
||||||
|
{
|
||||||
|
needsUpdate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateNeighbors()
|
||||||
|
{
|
||||||
|
contractNeighbours();
|
||||||
|
contract();
|
||||||
|
expand();
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings ("StatementWithEmptyBody")
|
@SuppressWarnings ("StatementWithEmptyBody")
|
||||||
void expand() {
|
void expand() {
|
||||||
while (this.mergeLeft() || this.mergeRight() || this.mergeUp() || this.mergeDown()) {
|
while (this.mergeLeft() || this.mergeRight() || this.mergeUp() || this.mergeDown()) {
|
||||||
|
@@ -661,6 +661,18 @@ public class TurtleAPI implements ILuaAPI {
|
|||||||
* @return The turtle command result.
|
* @return The turtle command result.
|
||||||
* @cc.treturn boolean Whether there is a block in front of the turtle.
|
* @cc.treturn boolean Whether there is a block in front of the turtle.
|
||||||
* @cc.treturn table|string Information about the block in front, or a message explaining that there is no block.
|
* @cc.treturn table|string Information about the block in front, or a message explaining that there is no block.
|
||||||
|
* @cc.usage <pre>{@code
|
||||||
|
* local has_block, data = turtle.inspect()
|
||||||
|
* if has_block then
|
||||||
|
* print(textutils.serialize(data))
|
||||||
|
* -- {
|
||||||
|
* -- name = "minecraft:oak_log",
|
||||||
|
* -- state = { axis = "x" },
|
||||||
|
* -- tags = { ["minecraft:logs"] = true, ... },
|
||||||
|
* -- }
|
||||||
|
* else
|
||||||
|
* print("No block in front of the turtle")
|
||||||
|
* end}</pre>
|
||||||
*/
|
*/
|
||||||
@LuaFunction
|
@LuaFunction
|
||||||
public final MethodResult inspect() {
|
public final MethodResult inspect() {
|
||||||
@@ -700,6 +712,7 @@ public class TurtleAPI implements ILuaAPI {
|
|||||||
* cost of taking longer to run.
|
* cost of taking longer to run.
|
||||||
* @return The command result.
|
* @return The command result.
|
||||||
* @throws LuaException If the slot is out of range.
|
* @throws LuaException If the slot is out of range.
|
||||||
|
* @see InventoryMethods#getItemDetail Describes the information returned by a detailed query.
|
||||||
* @cc.treturn nil|table Information about the given slot, or {@code nil} if it is empty.
|
* @cc.treturn nil|table Information about the given slot, or {@code nil} if it is empty.
|
||||||
* @cc.usage Print the current slot, assuming it contains 13 dirt.
|
* @cc.usage Print the current slot, assuming it contains 13 dirt.
|
||||||
*
|
*
|
||||||
|
@@ -1,29 +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.util;
|
|
||||||
|
|
||||||
import dan200.computercraft.ComputerCraft;
|
|
||||||
import dan200.computercraft.api.ComputerCraftAPI;
|
|
||||||
import org.objectweb.asm.Type;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.ServiceLoader;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
import java.util.stream.StreamSupport;
|
|
||||||
|
|
||||||
public final class ServiceUtil
|
|
||||||
{
|
|
||||||
private static final Type AUTO_SERVICE = Type.getType( "Lcom/google/auto/service/AutoService;" );
|
|
||||||
|
|
||||||
private ServiceUtil()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> Stream<T> loadServices( Class<T> target )
|
|
||||||
{
|
|
||||||
return StreamSupport.stream( ServiceLoader.load( target, ServiceUtil.class.getClassLoader() ).spliterator(), false );
|
|
||||||
}
|
|
||||||
}
|
|
Binary file not shown.
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 2.3 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 352 B |
Binary file not shown.
Before Width: | Height: | Size: 426 B After Width: | Height: | Size: 347 B |
@@ -16,22 +16,7 @@ end
|
|||||||
|
|
||||||
if _VERSION == "Lua 5.1" then
|
if _VERSION == "Lua 5.1" then
|
||||||
-- If we're on Lua 5.1, install parts of the Lua 5.2/5.3 API so that programs can be written against it
|
-- If we're on Lua 5.1, install parts of the Lua 5.2/5.3 API so that programs can be written against it
|
||||||
local type = type
|
|
||||||
local nativeload = load
|
local nativeload = load
|
||||||
local nativeloadstring = loadstring
|
|
||||||
local nativesetfenv = setfenv
|
|
||||||
|
|
||||||
-- Historically load/loadstring would handle the chunk name as if it has
|
|
||||||
-- been prefixed with "=". We emulate that behaviour here.
|
|
||||||
local function prefix(chunkname)
|
|
||||||
if type(chunkname) ~= "string" then return chunkname end
|
|
||||||
local head = chunkname:sub(1, 1)
|
|
||||||
if head == "=" or head == "@" then
|
|
||||||
return chunkname
|
|
||||||
else
|
|
||||||
return "=" .. chunkname
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function load(x, name, mode, env)
|
function load(x, name, mode, env)
|
||||||
expect(1, x, "function", "string")
|
expect(1, x, "function", "string")
|
||||||
@@ -40,29 +25,11 @@ if _VERSION == "Lua 5.1" then
|
|||||||
expect(4, env, "table", "nil")
|
expect(4, env, "table", "nil")
|
||||||
|
|
||||||
local ok, p1, p2 = pcall(function()
|
local ok, p1, p2 = pcall(function()
|
||||||
if type(x) == "string" then
|
local result, err = nativeload(x, name, mode, env)
|
||||||
local result, err = nativeloadstring(x, name)
|
if result and env then
|
||||||
if result then
|
|
||||||
if env then
|
|
||||||
env._ENV = env
|
env._ENV = env
|
||||||
nativesetfenv(result, env)
|
|
||||||
end
|
|
||||||
return result
|
|
||||||
else
|
|
||||||
return nil, err
|
|
||||||
end
|
|
||||||
else
|
|
||||||
local result, err = nativeload(x, name)
|
|
||||||
if result then
|
|
||||||
if env then
|
|
||||||
env._ENV = env
|
|
||||||
nativesetfenv(result, env)
|
|
||||||
end
|
|
||||||
return result
|
|
||||||
else
|
|
||||||
return nil, err
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
return result, err
|
||||||
end)
|
end)
|
||||||
if ok then
|
if ok then
|
||||||
return p1, p2
|
return p1, p2
|
||||||
@@ -81,7 +48,7 @@ if _VERSION == "Lua 5.1" then
|
|||||||
math.log10 = nil
|
math.log10 = nil
|
||||||
table.maxn = nil
|
table.maxn = nil
|
||||||
else
|
else
|
||||||
loadstring = function(string, chunkname) return nativeloadstring(string, prefix(chunkname)) end
|
loadstring = function(string, chunkname) return nativeload(string, chunkname) end
|
||||||
|
|
||||||
-- Inject a stub for the old bit library
|
-- Inject a stub for the old bit library
|
||||||
_G.bit = {
|
_G.bit = {
|
||||||
|
@@ -1,4 +1,22 @@
|
|||||||
New features in CC: Restitched 1.95.3
|
# New features in CC: Restitched 1.96.0
|
||||||
|
|
||||||
|
* Use lightGrey for folders within the "list" program.
|
||||||
|
* Add getLimit to inventory peripherals.
|
||||||
|
* Expose the generic peripheral system to the public API.
|
||||||
|
* Add cc.expect.range (Lupus590).
|
||||||
|
* Allow calling cc.expect directly (MCJack123).
|
||||||
|
* Numerous improvements to documentation.
|
||||||
|
|
||||||
|
And several bug fixes:
|
||||||
|
* Fix paintutils.drawLine incorrectly sorting coordinates (lilyzeiset).
|
||||||
|
* Improve JEI's handling of turtle/pocket upgrade recipes.
|
||||||
|
* Correctly handle sparse arrays in cc.pretty.
|
||||||
|
* Fix crashes when a turtle places a monitor (baeuric).
|
||||||
|
* Fix very large resource files being considered empty.
|
||||||
|
* Allow turtles to use compostors.
|
||||||
|
* Fix dupe bug when colouring turtles.
|
||||||
|
|
||||||
|
# New features in CC: Restitched 1.95.3
|
||||||
|
|
||||||
Several bug fixes:
|
Several bug fixes:
|
||||||
* Correctly serialise sparse arrays into JSON (livegamer999)
|
* Correctly serialise sparse arrays into JSON (livegamer999)
|
||||||
|
@@ -1,9 +1,19 @@
|
|||||||
New features in CC: Restitched 1.95.3
|
New features in CC: Restitched 1.96.0
|
||||||
|
|
||||||
Several bug fixes:
|
* Use lightGrey for folders within the "list" program.
|
||||||
* Correctly serialise sparse arrays into JSON (livegamer999)
|
* Add getLimit to inventory peripherals.
|
||||||
* Fix rs.getBundledInput returning the output instead (SkyTheCodeMaster)
|
* Expose the generic peripheral system to the public API.
|
||||||
* Programs run via edit are now a little better behaved (Wojbie)
|
* Add cc.expect.range (Lupus590).
|
||||||
* Add User-Agent to a websocket's headers.
|
* Allow calling cc.expect directly (MCJack123).
|
||||||
|
* Numerous improvements to documentation.
|
||||||
|
|
||||||
|
And several bug fixes:
|
||||||
|
* Fix paintutils.drawLine incorrectly sorting coordinates (lilyzeiset).
|
||||||
|
* Improve JEI's handling of turtle/pocket upgrade recipes.
|
||||||
|
* Correctly handle sparse arrays in cc.pretty.
|
||||||
|
* Fix crashes when a turtle places a monitor (baeuric).
|
||||||
|
* Fix very large resource files being considered empty.
|
||||||
|
* Allow turtles to use compostors.
|
||||||
|
* Fix dupe bug when colouring turtles.
|
||||||
|
|
||||||
Type "help changelog" to see the full version history.
|
Type "help changelog" to see the full version history.
|
||||||
|
@@ -88,7 +88,34 @@ local function field(tbl, index, ...)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return {
|
local function is_nan(num)
|
||||||
|
return num ~= num
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Expect a number to be within a specific range.
|
||||||
|
--
|
||||||
|
-- @tparam number num, The value to check.
|
||||||
|
-- @tparam number min The minimum value, if nil then `-math.huge` is used.
|
||||||
|
-- @tparam number max The maximum value, if nil then `math.huge` is used.
|
||||||
|
-- @return The given `value`.
|
||||||
|
-- @throws If the value is outside of the allowed range.
|
||||||
|
local function range(num, min, max)
|
||||||
|
expect(1, num, "number")
|
||||||
|
min = expect(2, min, "number", "nil") or -math.huge
|
||||||
|
max = expect(3, max, "number", "nil") or math.huge
|
||||||
|
if min > max then
|
||||||
|
error("min must be less than or equal to max)", 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
if is_nan(num) or num < min or num > max then
|
||||||
|
error(("number outside of range (expected %s to be within %s and %s)"):format(num, min, max), 3)
|
||||||
|
end
|
||||||
|
|
||||||
|
return num
|
||||||
|
end
|
||||||
|
|
||||||
|
return setmetatable({
|
||||||
expect = expect,
|
expect = expect,
|
||||||
field = field,
|
field = field,
|
||||||
}
|
range = range,
|
||||||
|
}, { __call = function(_, ...) return expect(...) end })
|
||||||
|
@@ -409,18 +409,24 @@ local function pretty_impl(obj, options, tracking)
|
|||||||
local doc = setmetatable({ tag = "concat", n = 1, space_line }, Doc)
|
local doc = setmetatable({ tag = "concat", n = 1, space_line }, Doc)
|
||||||
|
|
||||||
local length, keys, keysn = #obj, {}, 1
|
local length, keys, keysn = #obj, {}, 1
|
||||||
for k in pairs(obj) do keys[keysn], keysn = k, keysn + 1 end
|
for k in pairs(obj) do
|
||||||
|
if type(k) ~= "number" or k % 1 ~= 0 or k < 1 or k > length then
|
||||||
|
keys[keysn], keysn = k, keysn + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
table.sort(keys, key_compare)
|
table.sort(keys, key_compare)
|
||||||
|
|
||||||
for i = 1, keysn - 1 do
|
for i = 1, length do
|
||||||
if i > 1 then append(doc, comma) append(doc, space_line) end
|
if i > 1 then append(doc, comma) append(doc, space_line) end
|
||||||
|
append(doc, pretty_impl(obj[i], options, tracking))
|
||||||
|
end
|
||||||
|
|
||||||
|
for i = 1, keysn - 1 do
|
||||||
|
if i > 1 or length >= 1 then append(doc, comma) append(doc, space_line) end
|
||||||
|
|
||||||
local k = keys[i]
|
local k = keys[i]
|
||||||
local v = obj[k]
|
local v = obj[k]
|
||||||
local ty = type(k)
|
if type(k) == "string" and not keywords[k] and k:match("^[%a_][%a%d_]*$") then
|
||||||
if ty == "number" and k % 1 == 0 and k >= 1 and k <= length then
|
|
||||||
append(doc, pretty_impl(v, options, tracking))
|
|
||||||
elseif ty == "string" and not keywords[k] and k:match("^[%a_][%a%d_]*$") then
|
|
||||||
append(doc, text(k .. " = "))
|
append(doc, text(k .. " = "))
|
||||||
append(doc, pretty_impl(v, options, tracking))
|
append(doc, pretty_impl(v, options, tracking))
|
||||||
else
|
else
|
||||||
|
@@ -33,5 +33,5 @@ table.sort(tFiles)
|
|||||||
if term.isColour() then
|
if term.isColour() then
|
||||||
textutils.pagedTabulate(colors.green, tDirs, colors.white, tFiles)
|
textutils.pagedTabulate(colors.green, tDirs, colors.white, tFiles)
|
||||||
else
|
else
|
||||||
textutils.pagedTabulate(tDirs, tFiles)
|
textutils.pagedTabulate(colors.lightGray, tDirs, colors.white, tFiles)
|
||||||
end
|
end
|
||||||
|
Reference in New Issue
Block a user