1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-02-14 18:10:05 +00:00

Merge branch 'mc-1.15.x' into mc-1.16.x

This commit is contained in:
Jonathan Coates 2021-05-20 18:30:10 +01:00
commit 8b8692ba53
178 changed files with 2362 additions and 551 deletions

View File

@ -16,6 +16,3 @@ indent_size = 2
[*.yml]
indent_size = 2
[*.properties]
insert_final_newline = false

17
.github/matchers/checkstyle.json vendored Normal file
View File

@ -0,0 +1,17 @@
{
"problemMatcher": [
{
"owner": "checkstyle",
"pattern": [
{
"regexp": "^([a-z]+) ([\\w./-]+):(\\d+):(\\d+): (.*)$",
"severity": 1,
"file": 2,
"line": 3,
"column": 4,
"message": 5
}
]
}
]
}

18
.github/matchers/illuaminate.json vendored Normal file
View File

@ -0,0 +1,18 @@
{
"problemMatcher": [
{
"owner": "illuaminate",
"severity": "warning",
"pattern": [
{
"regexp": "^([\\w./-]+):\\[(\\d+):(\\d+)\\-(?:\\d+):(?:\\d+)\\]: (.*) \\[([a-z:-]+)\\]$",
"file": 1,
"line": 2,
"column": 3,
"message": 4,
"code": 5
}
]
}
]
}

15
.github/matchers/junit.json vendored Normal file
View File

@ -0,0 +1,15 @@
{
"problemMatcher": [
{
"owner": "junit",
"pattern": [
{
"regexp": "^## ([\\w./-]+):(\\d+): (.*)$",
"file": 1,
"line": 2,
"message": 3
}
]
}
]
}

View File

@ -23,10 +23,15 @@ jobs:
restore-keys: |
${{ runner.os }}-gradle-
- name: Disable Gradle daemon
run: |
mkdir -p ~/.gradle
echo "org.gradle.daemon=false" >> ~/.gradle/gradle.properties
- name: Build with Gradle
run: |
./gradlew assemble --no-daemon || ./gradlew assemble --no-daemon
./gradlew downloadAssets --no-daemon || ./gradlew downloadAssets --no-daemon
./gradlew assemble || ./gradlew assemble
./gradlew downloadAssets || ./gradlew downloadAssets
./gradlew build
- name: Upload Jar
@ -36,18 +41,21 @@ jobs:
path: build/libs
- name: Upload Coverage
run: bash <(curl -s https://codecov.io/bash)
continue-on-error: true
uses: codecov/codecov-action@v1
- name: Generate Java documentation stubs
run: ./gradlew luaJavadoc --no-daemon
- name: Parse test reports
run: ./tools/parse-reports.py
if: ${{ failure() }}
- name: Lint Lua code
- name: Cache pre-commit
uses: actions/cache@v2
with:
path: ~/.cache/pre-commit
key: ${{ runner.os }}-pre-commit-${{ hashFiles('config/pre-commit/config.yml') }}
restore-keys: |
${{ runner.os }}-pre-commit-
- name: Run linters
run: |
test -d bin || mkdir bin
test -f bin/illuaminate || wget -q -Obin/illuaminate https://squiddev.cc/illuaminate/linux-x86-64/illuaminate
chmod +x bin/illuaminate
bin/illuaminate lint
- name: Check whitespace
run: python3 tools/check-lines.py
pip install pre-commit
pre-commit run --config config/pre-commit/config.yml --show-diff-on-failure --all --color=always

View File

@ -65,7 +65,7 @@ Gradle should be your entrypoint to building most documentation. There's two tas
#### Writing documentation
illuaminate's documentation system is not currently documented (somewhat ironic), but is _largely_ the same as
[ldoc][ldoc]. Documentation comments are written in Markdown,
[ldoc][ldoc]. Documentation comments are written in Markdown,
Our markdown engine does _not_ support GitHub flavoured markdown, and so does not support all the features one might
expect (such as tables). It is very much recommended that you build and preview the docs locally first.
@ -77,18 +77,18 @@ entire test suite (and some additional bits of verification).
Before we get into writing tests, it's worth mentioning the various test suites that CC: Tweaked has:
- "Core" Java (`./src/test/java`): These test core bits of the mod which don't require any Minecraft interaction.
This includes the `@LuaFunction` system, file system code, etc...
These tests are run by `./gradlew test`.
- CraftOS (`./src/test/resources/test-rom/`): These tests are written in Lua, and ensure the Lua environment, libraries
and programs work as expected. These are (generally) written to be able to be run on emulators too, to provide some
sort of compliance test.
These tests are run by the '"Core" Java' test suite, and so are also run with `./gradlew test`.
- In-game (`./src/test/java/dan200/computercraft/ingame/`): These tests are run on an actual Minecraft server, using
[the same system Mojang do][mc-test]. The aim of these is to test in-game behaviour of blocks and peripherals.
These are run by `./gradlew testInGame`.
## CraftOS tests

14
LICENSE
View File

@ -19,14 +19,14 @@ Mod: The mod code designated by the present license, in source form, binary
form, as obtained standalone, as part of a wider distribution or resulting from
the compilation of the original or modified sources.
Dependency: Code required for the mod to work properly. This includes
Dependency: Code required for the mod to work properly. This includes
dependencies required to compile the code as well as any file or modification
that is explicitly or implicitly required for the mod to be working.
1. Scope
--------
The present license is granted to any user of the mod. As a prerequisite,
The present license is granted to any user of the mod. As a prerequisite,
a user must own a legally acquired copy of Minecraft
2. Liability
@ -41,13 +41,13 @@ or misuse of this mod fall on the user.
3. Play rights
--------------
The user is allowed to install this mod on a Minecraft client or server and to play
The user is allowed to install this mod on a Minecraft client or server and to play
without restriction.
4. Modification rights
----------------------
The user has the right to decompile the source code, look at either the
The user has the right to decompile the source code, look at either the
decompiled version or the original source code, and to modify it.
5. Distribution of original or modified copy rights
@ -61,10 +61,10 @@ include:
- patch to its source or binary files
- any copy of a portion of its binary source files
The user is allowed to redistribute this mod partially, in totality, or
The user is allowed to redistribute this mod partially, in totality, or
included in a distribution.
When distributing binary files, the user must provide means to obtain its
When distributing binary files, the user must provide means to obtain its
entire set of sources or modified sources at no cost.
All distributions of this mod must remain licensed under the CCPL.
@ -92,7 +92,7 @@ must be made available at no cost and remain licensed under the CCPL.
---------------
If you choose to contribute code or assets to be included in this mod, you
agree that, if added to to the main repository at
agree that, if added to to the main repository at
https://github.com/dan200/ComputerCraft, your contributions will be covered by
this license, and that Daniel Ratcliffe will retain the right to re-license the
mod, including your contributions, in part or in whole, under other licenses.

View File

@ -142,10 +142,7 @@ dependencies {
runtimeOnly fg.deobf("mezz.jei:jei-1.16.4:7.6.0.58")
compileOnly 'com.google.auto.service:auto-service:1.0-rc7'
annotationProcessor 'com.google.auto.service:auto-service:1.0-rc7'
shade 'org.squiddev:Cobalt:0.5.1-SNAPSHOT'
shade 'org.squiddev:Cobalt:0.5.2-SNAPSHOT'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.7.0'
@ -156,7 +153,7 @@ dependencies {
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.8'
testAnnotationProcessor 'org.spongepowered:mixin:0.8.2:processor'
cctJavadoc 'cc.tweaked:cct-javadoc:1.3.0'
cctJavadoc 'cc.tweaked:cct-javadoc:1.4.0'
}
// Compile tasks

View File

@ -2488,4 +2488,4 @@
</option>
</inspection_tool>
</profile>
</component>
</component>

View File

@ -58,4 +58,4 @@
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
</codeStyleSettings>
</code_scheme>
</code_scheme>

View File

@ -0,0 +1,55 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.2.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-merge-conflict
# Quick syntax checkers
- id: check-xml
- id: check-yaml
- id: check-toml
- id: check-json
exclude: "tsconfig\\.json$"
- repo: https://github.com/editorconfig-checker/editorconfig-checker.python
rev: 2.3.5
hooks:
- id: editorconfig-checker
args: ['-disable-indentation']
exclude: "^(.*\\.(bat)|LICENSE)$"
- repo: local
hooks:
- id: checkstyle
name: Check Java codestyle
files: ".*\\.java$"
language: system
entry: ./gradlew checkstyleMain checkstyleTest
pass_filenames: false
require_serial: true
- id: license
name: Check Java license headers
files: ".*\\.java$"
language: system
entry: ./gradlew licenseFormat
pass_filenames: false
require_serial: true
- id: illuaminate
name: Check Lua code
files: ".*\\.(lua|java|md)"
language: script
entry: config/pre-commit/illuaminate-lint.sh
pass_filenames: false
require_serial: true
exclude: |
(?x)^(
src/generated|
src/test/resources/test-rom/data/json-parsing/|
src/test/server-files/|
config/idea/
)

View File

@ -0,0 +1,16 @@
#!/usr/bin/env sh
set -e
test -d bin || mkdir bin
test -f bin/illuaminate || curl -s -obin/illuaminate https://squiddev.cc/illuaminate/linux-x86-64/illuaminate
chmod +x bin/illuaminate
if [ -n ${GITHUB_ACTIONS+x} ]; then
# Register a problem matcher (see https://github.com/actions/toolkit/blob/master/docs/problem-matchers.md)
# for illuaminate.
echo "::add-matcher::.github/matchers/illuaminate.json"
trap 'echo "::remove-matcher owner=illuaminate::"' EXIT
fi
./gradlew luaJavadoc
bin/illuaminate lint

View File

@ -20,7 +20,7 @@ Prints each key when the user presses it, and if the key is being held.
```lua
while true do
local event, key, is_held = os.pullEvent("key")
local event, key, is_held = os.pullEvent("key")
print(("%s held=%s"):format(keys.getName(key), is_held))
end
```

View File

@ -1,5 +1,5 @@
# Mod properties
mod_version=1.95.3
mod_version=1.96.0
# Minecraft properties (update mods.toml when changing)
mc_version=1.16.4

View File

@ -8,7 +8,6 @@ package dan200.computercraft;
import dan200.computercraft.api.turtle.event.TurtleAction;
import dan200.computercraft.core.apis.http.options.Action;
import dan200.computercraft.core.apis.http.options.AddressRule;
import dan200.computercraft.core.asm.GenericSource;
import dan200.computercraft.shared.Config;
import dan200.computercraft.shared.Registry;
import dan200.computercraft.shared.computer.core.ClientComputerRegistry;
@ -17,7 +16,6 @@ import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer;
import dan200.computercraft.shared.pocket.peripherals.PocketModem;
import dan200.computercraft.shared.pocket.peripherals.PocketSpeaker;
import dan200.computercraft.shared.turtle.upgrades.*;
import dan200.computercraft.shared.util.ServiceUtil;
import net.minecraftforge.fml.common.Mod;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -117,6 +115,5 @@ public final class ComputerCraft
{
Config.setup();
Registry.setup();
GenericSource.setup( () -> ServiceUtil.loadServicesForge( GenericSource.class ) );
}
}

View File

@ -8,6 +8,7 @@ package dan200.computercraft;
import dan200.computercraft.api.ComputerCraftAPI.IComputerCraftAPI;
import dan200.computercraft.api.filesystem.IMount;
import dan200.computercraft.api.filesystem.IWritableMount;
import dan200.computercraft.api.lua.GenericSource;
import dan200.computercraft.api.lua.ILuaAPIFactory;
import dan200.computercraft.api.media.IMediaProvider;
import dan200.computercraft.api.network.IPacketNetwork;
@ -18,9 +19,11 @@ import dan200.computercraft.api.pocket.IPocketUpgrade;
import dan200.computercraft.api.redstone.IBundledRedstoneProvider;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.core.apis.ApiFactories;
import dan200.computercraft.core.asm.GenericMethod;
import dan200.computercraft.core.filesystem.FileMount;
import dan200.computercraft.core.filesystem.ResourceMount;
import dan200.computercraft.shared.*;
import dan200.computercraft.shared.peripheral.generic.GenericPeripheralProvider;
import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork;
import dan200.computercraft.shared.util.IDAssigner;
import dan200.computercraft.shared.wired.WiredNode;
@ -31,6 +34,7 @@ import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.server.ServerLifecycleHooks;
@ -108,6 +112,18 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
Peripherals.register( provider );
}
@Override
public void registerGenericSource( @Nonnull GenericSource source )
{
GenericMethod.register( source );
}
@Override
public void registerGenericCapability( @Nonnull Capability<?> capability )
{
GenericPeripheralProvider.addCapability( capability );
}
@Override
public void registerTurtleUpgrade( @Nonnull ITurtleUpgrade upgrade )
{

View File

@ -7,6 +7,7 @@ package dan200.computercraft.api;
import dan200.computercraft.api.filesystem.IMount;
import dan200.computercraft.api.filesystem.IWritableMount;
import dan200.computercraft.api.lua.GenericSource;
import dan200.computercraft.api.lua.ILuaAPIFactory;
import dan200.computercraft.api.media.IMedia;
import dan200.computercraft.api.media.IMediaProvider;
@ -23,6 +24,7 @@ import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import javax.annotation.Nonnull;
@ -116,7 +118,7 @@ public final class ComputerCraftAPI
}
/**
* Registers a peripheral provider to convert blocks into {@link IPeripheral} implementations.
* rers a peripheral provider to convert blocks into {@link IPeripheral} implementations.
*
* @param provider The peripheral provider to register.
* @see IPeripheral
@ -127,6 +129,28 @@ public final class ComputerCraftAPI
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 capability that can be used by generic peripherals.
*
* @param capability The capability to register.
* @see GenericSource
*/
public static void registerGenericCapability( @Nonnull Capability<?> capability )
{
getInstance().registerGenericCapability( capability );
}
/**
* 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
@ -258,6 +282,10 @@ public final class ComputerCraftAPI
void registerPeripheralProvider( @Nonnull IPeripheralProvider provider );
void registerGenericSource( @Nonnull GenericSource source );
void registerGenericCapability( @Nonnull Capability<?> capability );
void registerTurtleUpgrade( @Nonnull ITurtleUpgrade upgrade );
void registerBundledRedstoneProvider( @Nonnull IBundledRedstoneProvider provider );

View File

@ -0,0 +1,60 @@
/*
* 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.ResourceLocation;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.items.IItemHandler;
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
ResourceLocation id();
}

View File

@ -47,7 +47,10 @@ public class ComputerBorderRenderer
private static final int 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 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;
@ -101,15 +104,15 @@ public class ComputerBorderRenderer
public static void render( Matrix4f transform, IVertexBuilder 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, IVertexBuilder buffer, int x, int y, int z, int width, int height, int borderHeight, float r, float g, float b )
public static void render( Matrix4f transform, IVertexBuilder buffer, int x, int y, int z, int width, int height, boolean withLight, float r, float g, 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 endY = y + height;
@ -125,28 +128,18 @@ public class ComputerBorderRenderer
// Bottom bar. We allow for drawing a stretched version, which allows for additional elements (such as the
// 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
{
renderLine( x, endY, 0, BORDER, endX - x, BORDER );
renderCorner( x - BORDER, endY, CORNER_LEFT_X, CORNER_BOTTOM_Y );
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.
renderTexture( x - BORDER, endY, CORNER_LEFT_X, CORNER_BOTTOM_Y, BORDER, BORDER / 2 );
renderTexture( x, endY, 0, BORDER, width, BORDER / 2, BORDER, BORDER / 2 );
renderTexture( endX, endY, CORNER_RIGHT_X, CORNER_BOTTOM_Y, BORDER, BORDER / 2 );
renderTexture( x - BORDER, endY + BORDER / 2, CORNER_LEFT_X, CORNER_BOTTOM_Y + GAP, BORDER, bottomHeight, BORDER, GAP );
renderTexture( x, endY + BORDER / 2, 0, BORDER + GAP, width, bottomHeight, BORDER, GAP );
renderTexture( endX, endY + BORDER / 2, CORNER_RIGHT_X, CORNER_BOTTOM_Y + GAP, BORDER, bottomHeight, BORDER, GAP );
renderTexture( x - BORDER, endY + bottomHeight + BORDER / 2, CORNER_LEFT_X, CORNER_BOTTOM_Y + BORDER / 2, BORDER, BORDER / 2 );
renderTexture( x, endY + bottomHeight + BORDER / 2, 0, BORDER + BORDER / 2, width, BORDER / 2 );
renderTexture( endX, endY + bottomHeight + BORDER / 2, CORNER_RIGHT_X, CORNER_BOTTOM_Y + BORDER / 2, BORDER, BORDER / 2 );
}
}
private void renderCorner( int x, int y, int u, int v )

View File

@ -30,8 +30,7 @@ import org.lwjgl.opengl.GL11;
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT;
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_WIDTH;
import static dan200.computercraft.client.render.ComputerBorderRenderer.BORDER;
import static dan200.computercraft.client.render.ComputerBorderRenderer.MARGIN;
import static dan200.computercraft.client.render.ComputerBorderRenderer.*;
/**
* Emulates map rendering for pocket computers.
@ -39,8 +38,6 @@ import static dan200.computercraft.client.render.ComputerBorderRenderer.MARGIN;
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT )
public final class ItemPocketRenderer extends ItemMapLikeRenderer
{
private static final int LIGHT_HEIGHT = 8;
private static final ItemPocketRenderer INSTANCE = new ItemPocketRenderer();
private ItemPocketRenderer()
@ -131,7 +128,7 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
BufferBuilder buffer = tessellator.getBuilder();
buffer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR_TEX );
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.end();
}

View File

@ -89,7 +89,7 @@ final class LuaDateTime
formatter.appendValue( ChronoField.HOUR_OF_DAY, 2 );
break;
case 'I':
formatter.appendValue( ChronoField.HOUR_OF_AMPM );
formatter.appendValue( ChronoField.HOUR_OF_AMPM, 2 );
break;
case 'j':
formatter.appendValue( ChronoField.DAY_OF_YEAR, 3 );

View File

@ -11,10 +11,7 @@ import com.google.common.cache.LoadingCache;
import com.google.common.primitives.Primitives;
import com.google.common.reflect.TypeToken;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.lua.IArguments;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.lua.LuaFunction;
import dan200.computercraft.api.lua.MethodResult;
import dan200.computercraft.api.lua.*;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
@ -111,7 +108,7 @@ public final class Generator<T>
addMethod( methods, method, annotation, instance );
}
for( GenericSource.GenericMethod method : GenericSource.GenericMethod.all() )
for( GenericMethod method : GenericMethod.all() )
{
if( !method.target.isAssignableFrom( klass ) ) continue;

View File

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

View File

@ -1,120 +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 dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.lua.LuaFunction;
import dan200.computercraft.shared.peripheral.generic.GenericPeripheralProvider;
import dan200.computercraft.shared.util.ServiceUtil;
import net.minecraft.util.ResourceLocation;
import javax.annotation.Nonnull;
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;
/**
* 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.
*
* This is used by the generic peripheral system ({@link GenericPeripheralProvider}) to provide methods for arbitrary
* tile entities. Eventually this'll be be exposed in the public API. Until it is stabilised, it will remain in this
* package - do not use it in external mods!
*/
public interface GenericSource
{
/**
* 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
ResourceLocation id();
/**
* Register a stream of generic sources.
*
* @param sources The source of generic methods.
* @see ServiceUtil For ways to load this. Sadly {@link java.util.ServiceLoader} is broken under Forge, but we don't
* want to add a hard-dep on Forge within core either.
*/
static void setup( Supplier<Stream<GenericSource>> sources )
{
GenericMethod.sources = sources;
}
/**
* A generic method is a method belonging to a {@link GenericSource} with a known target.
*/
class GenericMethod
{
final Method method;
final LuaFunction annotation;
final Class<?> target;
static Supplier<Stream<GenericSource>> sources;
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;
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() );
}
}
}

View File

@ -12,6 +12,7 @@ import com.google.common.io.ByteStreams;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.filesystem.IMount;
import dan200.computercraft.core.apis.handles.ArrayByteChannel;
import dan200.computercraft.shared.util.IoUtil;
import net.minecraft.resources.IReloadableResourceManager;
import net.minecraft.resources.IResource;
import net.minecraft.resources.IResourceManager;
@ -122,7 +123,7 @@ public final class ResourceMount implements IMount
if( !hasAny )
{
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 );
}
@ -244,11 +245,20 @@ public final class ResourceMount implements IMount
byte[] contents = CONTENTS_CACHE.getIfPresent( file );
if( contents != null ) return new ArrayByteChannel( contents );
try( InputStream stream = manager.getResource( file.identifier ).getInputStream() )
try
{
InputStream stream = manager.getResource( file.identifier ).getInputStream();
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 );
return new ArrayByteChannel( contents );
}

View File

@ -246,7 +246,7 @@ public final class Registry
{
// Upgrades
ComputerCraft.TurtleUpgrades.wirelessModemNormal = new TurtleModem( false, new ResourceLocation( ComputerCraft.MOD_ID, "wireless_modem_normal" ) );
TurtleUpgrades.register( ComputerCraft.TurtleUpgrades.wirelessModemNormal );
ComputerCraftAPI.registerTurtleUpgrade( ComputerCraft.TurtleUpgrades.wirelessModemNormal );
ComputerCraft.TurtleUpgrades.wirelessModemAdvanced = new TurtleModem( true, new ResourceLocation( ComputerCraft.MOD_ID, "wireless_modem_advanced" ) );
ComputerCraftAPI.registerTurtleUpgrade( ComputerCraft.TurtleUpgrades.wirelessModemAdvanced );

View File

@ -79,7 +79,10 @@ public final class ColourableRecipe extends SpecialRecipe
}
if( colourable.isEmpty() ) return ItemStack.EMPTY;
return ((IColouredItem) colourable.getItem()).withColour( colourable, tracker.getColour() );
ItemStack stack = ((IColouredItem) colourable.getItem()).withColour( colourable, tracker.getColour() );
stack.setCount( 1 );
return stack;
}
@Override

View File

@ -15,22 +15,22 @@ import net.minecraft.world.World;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.common.util.NonNullConsumer;
import net.minecraftforge.energy.CapabilityEnergy;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.items.CapabilityItemHandler;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class GenericPeripheralProvider
{
private static final Capability<?>[] CAPABILITIES = new Capability<?>[] {
CapabilityItemHandler.ITEM_HANDLER_CAPABILITY,
CapabilityEnergy.ENERGY,
CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY,
};
private static final ArrayList<Capability<?>> capabilities = new ArrayList<>();
public static synchronized void addCapability( Capability<?> capability )
{
Objects.requireNonNull( capability, "Capability cannot be null" );
if( !capabilities.contains( capability ) ) capabilities.add( capability );
}
@Nullable
public static IPeripheral getPeripheral( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side, NonNullConsumer<LazyOptional<IPeripheral>> invalidate )
@ -43,7 +43,7 @@ public class GenericPeripheralProvider
List<NamedMethod<PeripheralMethod>> tileMethods = PeripheralMethod.GENERATOR.getMethods( tile.getClass() );
if( !tileMethods.isEmpty() ) addSaturated( saturated, tile, tileMethods );
for( Capability<?> capability : CAPABILITIES )
for( Capability<?> capability : capabilities )
{
LazyOptional<?> wrapper = tile.getCapability( capability );
wrapper.ifPresent( contents -> {

View File

@ -5,12 +5,11 @@
*/
package dan200.computercraft.shared.peripheral.generic.methods;
import com.google.auto.service.AutoService;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.lua.GenericSource;
import dan200.computercraft.api.lua.LuaFunction;
import dan200.computercraft.core.asm.GenericSource;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.energy.IEnergyStorage;
import net.minecraftforge.versions.forge.ForgeVersion;
import javax.annotation.Nonnull;
@ -26,14 +25,13 @@ import javax.annotation.Nonnull;
*
* @cc.module energy_storage
*/
@AutoService( GenericSource.class )
public class EnergyMethods implements GenericSource
{
@Nonnull
@Override
public ResourceLocation id()
{
return new ResourceLocation( ForgeVersion.MOD_ID, "energy" );
return new ResourceLocation( ComputerCraft.MOD_ID, "energy" );
}
/**

View File

@ -5,12 +5,12 @@
*/
package dan200.computercraft.shared.peripheral.generic.methods;
import com.google.auto.service.AutoService;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.lua.GenericSource;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.lua.LuaFunction;
import dan200.computercraft.api.peripheral.IComputerAccess;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.core.asm.GenericSource;
import dan200.computercraft.shared.peripheral.generic.data.FluidData;
import net.minecraft.fluid.Fluid;
import net.minecraft.util.ResourceLocation;
@ -20,7 +20,6 @@ import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.versions.forge.ForgeVersion;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -35,14 +34,13 @@ import static dan200.computercraft.shared.peripheral.generic.methods.ArgumentHel
*
* @cc.module fluid_storage
*/
@AutoService( GenericSource.class )
public class FluidMethods implements GenericSource
{
@Nonnull
@Override
public ResourceLocation id()
{
return new ResourceLocation( ForgeVersion.MOD_ID, "fluid" );
return new ResourceLocation( ComputerCraft.MOD_ID, "fluid" );
}
/**

View File

@ -5,12 +5,12 @@
*/
package dan200.computercraft.shared.peripheral.generic.methods;
import com.google.auto.service.AutoService;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.lua.GenericSource;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.lua.LuaFunction;
import dan200.computercraft.api.peripheral.IComputerAccess;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.core.asm.GenericSource;
import dan200.computercraft.shared.peripheral.generic.data.ItemData;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
@ -21,7 +21,6 @@ import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.items.wrapper.InvWrapper;
import net.minecraftforge.versions.forge.ForgeVersion;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -36,14 +35,13 @@ import static dan200.computercraft.shared.peripheral.generic.methods.ArgumentHel
*
* @cc.module inventory
*/
@AutoService( GenericSource.class )
public class InventoryMethods implements GenericSource
{
@Nonnull
@Override
public ResourceLocation id()
{
return new ResourceLocation( ForgeVersion.MOD_ID, "inventory" );
return new ResourceLocation( ComputerCraft.MOD_ID, "inventory" );
}
/**
@ -63,7 +61,8 @@ public class InventoryMethods implements GenericSource
*
* 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
* 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`
* rather than `ipairs`.
@ -71,6 +70,14 @@ public class InventoryMethods implements GenericSource
* @param inventory The current inventory.
* @return 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 )
public static Map<Integer, Map<String, ?>> list( IItemHandler inventory )
@ -89,11 +96,32 @@ public class InventoryMethods implements GenericSource
/**
* 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 slot The slot to get information about.
* @return Information about the item in this slot, or {@code nil} if not present.
* @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.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
@LuaFunction( mainThread = true )
@ -105,6 +133,33 @@ public class InventoryMethods implements GenericSource
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( IItemHandler inventory, int slot ) throws LuaException
{
assertBetween( slot, 1, inventory.getSlots(), "Slot out of range (%s)" );
return inventory.getSlotLimit( slot );
}
/**
* Push items from one inventory to another connected one.
*

View File

@ -20,6 +20,7 @@ import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.fml.RegistryObject;
import javax.annotation.Nonnull;
@ -85,9 +86,14 @@ public class BlockMonitor extends BlockGeneric
if( entity instanceof TileMonitor && !world.isClientSide )
{
TileMonitor monitor = (TileMonitor) entity;
monitor.contractNeighbours();
monitor.contract();
monitor.expand();
// Defer the block update if we're being placed by another TE. See #691
if ( livingEntity == null || livingEntity instanceof FakePlayer )
{
monitor.updateNeighborsDeferred();
return;
}
monitor.updateNeighbors();
}
}
}

View File

@ -55,6 +55,7 @@ public class TileMonitor extends TileGeneric
private LazyOptional<IPeripheral> peripheralCap;
private final Set<IComputerAccess> computers = new HashSet<>();
private boolean needsUpdate = false;
private boolean destroyed = false;
private boolean visiting = false;
@ -148,6 +149,12 @@ public class TileMonitor extends TileGeneric
@Override
public void blockTick()
{
if ( needsUpdate )
{
needsUpdate = false;
updateNeighbors();
}
if( xIndex != 0 || yIndex != 0 || serverMonitor == null ) return;
serverMonitor.clearChanged();
@ -526,6 +533,18 @@ public class TileMonitor extends TileGeneric
return true;
}
void updateNeighborsDeferred()
{
needsUpdate = true;
}
void updateNeighbors()
{
contractNeighbours();
contract();
expand();
}
@SuppressWarnings( "StatementWithEmptyBody" )
void expand()
{

View File

@ -23,6 +23,9 @@ import dan200.computercraft.shared.data.HasComputerIdLootCondition;
import dan200.computercraft.shared.data.PlayerCreativeLootCondition;
import dan200.computercraft.shared.media.items.RecordMedia;
import dan200.computercraft.shared.network.NetworkHandler;
import dan200.computercraft.shared.peripheral.generic.methods.EnergyMethods;
import dan200.computercraft.shared.peripheral.generic.methods.FluidMethods;
import dan200.computercraft.shared.peripheral.generic.methods.InventoryMethods;
import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork;
import dan200.computercraft.shared.util.NullStorage;
import net.minecraft.inventory.container.Container;
@ -32,15 +35,19 @@ import net.minecraft.loot.*;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.registry.Registry;
import net.minecraftforge.common.capabilities.CapabilityManager;
import net.minecraftforge.energy.CapabilityEnergy;
import net.minecraftforge.event.LootTableLoadEvent;
import net.minecraftforge.event.RegisterCommandsEvent;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.event.entity.player.PlayerContainerEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fml.DeferredWorkQueue;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.event.server.FMLServerStartedEvent;
import net.minecraftforge.fml.event.server.FMLServerStoppedEvent;
import net.minecraftforge.items.CapabilityItemHandler;
import java.util.Arrays;
import java.util.HashSet;
@ -55,11 +62,15 @@ public final class ComputerCraftProxyCommon
{
NetworkHandler.setup();
net.minecraftforge.fml.DeferredWorkQueue.runLater( () -> {
DeferredWorkQueue.runLater( () -> {
registerProviders();
ArgumentSerializers.register();
registerLoot();
} );
ComputerCraftAPI.registerGenericSource( new InventoryMethods() );
ComputerCraftAPI.registerGenericSource( new FluidMethods() );
ComputerCraftAPI.registerGenericSource( new EnergyMethods() );
}
public static void registerLoot()
@ -90,6 +101,12 @@ public final class ComputerCraftProxyCommon
// Register capabilities
CapabilityManager.INSTANCE.register( IWiredElement.class, new NullStorage<>(), () -> null );
CapabilityManager.INSTANCE.register( IPeripheral.class, new NullStorage<>(), () -> null );
// Register generic capabilities. This can technically be done off-thread, but we need it to happen
// after Forge's common setup, so this is easiest.
ComputerCraftAPI.registerGenericCapability( CapabilityItemHandler.ITEM_HANDLER_CAPABILITY );
ComputerCraftAPI.registerGenericCapability( CapabilityEnergy.ENERGY );
ComputerCraftAPI.registerGenericCapability( CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY );
}
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID )

View File

@ -16,6 +16,7 @@ import dan200.computercraft.core.apis.IAPIEnvironment;
import dan200.computercraft.core.asm.TaskCallback;
import dan200.computercraft.core.tracking.TrackingField;
import dan200.computercraft.shared.peripheral.generic.data.ItemData;
import dan200.computercraft.shared.peripheral.generic.methods.InventoryMethods;
import dan200.computercraft.shared.turtle.core.*;
import net.minecraft.item.ItemStack;
import net.minecraftforge.common.MinecraftForge;
@ -660,6 +661,18 @@ public class TurtleAPI implements ILuaAPI
* @return The turtle command result.
* @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.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
public final MethodResult inspect()
@ -702,6 +715,7 @@ public class TurtleAPI implements ILuaAPI
* more information about the item at the cost of taking longer to run.
* @return The command result.
* @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.usage Print the current slot, assuming it contains 13 dirt.
*

View File

@ -5,9 +5,11 @@
*/
package dan200.computercraft.shared.util;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.ISidedInventory;
import net.minecraft.inventory.ISidedInventoryProvider;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
@ -23,6 +25,7 @@ import net.minecraftforge.items.wrapper.SidedInvWrapper;
import org.apache.commons.lang3.tuple.Pair;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public final class InventoryUtil
{
@ -41,7 +44,8 @@ public final class InventoryUtil
// Methods for finding inventories:
public static IItemHandler getInventory( World world, BlockPos pos, Direction side )
@Nullable
public static IItemHandler getInventory( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side )
{
// Look for tile with inventory
TileEntity tileEntity = world.getBlockEntity( pos );
@ -52,7 +56,7 @@ public final class InventoryUtil
{
return itemHandler.orElseThrow( NullPointerException::new );
}
else if( side != null && tileEntity instanceof ISidedInventory )
else if( tileEntity instanceof ISidedInventory )
{
return new SidedInvWrapper( (ISidedInventory) tileEntity, side );
}
@ -62,6 +66,13 @@ public final class InventoryUtil
}
}
BlockState block = world.getBlockState( pos );
if( block.getBlock() instanceof ISidedInventoryProvider )
{
ISidedInventory inventory = ((ISidedInventoryProvider) block.getBlock()).getContainer( block, world, pos );
return new SidedInvWrapper( inventory, side );
}
// Look for entity with inventory
Vector3d vecStart = new Vector3d(
pos.getX() + 0.5 + 0.6 * side.getStepX(),

View File

@ -1,62 +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 net.minecraftforge.fml.ModList;
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 );
}
public static <T> Stream<T> loadServicesForge( Class<T> target )
{
Type type = Type.getType( target );
ClassLoader loader = ComputerCraftAPI.class.getClassLoader();
return ModList.get().getAllScanData().stream()
.flatMap( x -> x.getAnnotations().stream() )
.filter( x -> x.getAnnotationType().equals( AUTO_SERVICE ) )
.filter( x -> {
Object value = x.getAnnotationData().get( "value" );
return value instanceof List<?> && ((List<?>) value).contains( type );
} )
.flatMap( x -> {
try
{
Class<?> klass = loader.loadClass( x.getClassType().getClassName() );
if( !target.isAssignableFrom( klass ) )
{
ComputerCraft.log.error( "{} is not a subtype of {}", x.getClassType().getClassName(), target.getName() );
return Stream.empty();
}
Class<? extends T> casted = klass.asSubclass( target );
return Stream.of( casted.newInstance() );
}
catch( ReflectiveOperationException e )
{
ComputerCraft.log.error( "Cannot load {}", x.getClassType(), e );
return Stream.empty();
}
} );
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 456 B

After

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 534 B

After

Width:  |  Height:  |  Size: 476 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 475 B

After

Width:  |  Height:  |  Size: 417 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 584 B

After

Width:  |  Height:  |  Size: 526 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 575 B

After

Width:  |  Height:  |  Size: 517 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 503 B

After

Width:  |  Height:  |  Size: 404 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 633 B

After

Width:  |  Height:  |  Size: 534 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 525 B

After

Width:  |  Height:  |  Size: 426 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 641 B

After

Width:  |  Height:  |  Size: 560 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 635 B

After

Width:  |  Height:  |  Size: 554 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 421 B

After

Width:  |  Height:  |  Size: 193 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 501 B

After

Width:  |  Height:  |  Size: 214 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 439 B

After

Width:  |  Height:  |  Size: 199 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 327 B

After

Width:  |  Height:  |  Size: 217 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 290 B

After

Width:  |  Height:  |  Size: 195 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 327 B

After

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 327 B

After

Width:  |  Height:  |  Size: 217 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 290 B

After

Width:  |  Height:  |  Size: 195 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 546 B

After

Width:  |  Height:  |  Size: 488 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 548 B

After

Width:  |  Height:  |  Size: 490 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 416 B

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 418 B

After

Width:  |  Height:  |  Size: 360 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 342 B

After

Width:  |  Height:  |  Size: 284 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 263 B

After

Width:  |  Height:  |  Size: 205 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 353 B

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 508 B

After

Width:  |  Height:  |  Size: 450 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 365 B

After

Width:  |  Height:  |  Size: 307 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 306 B

After

Width:  |  Height:  |  Size: 248 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 357 B

After

Width:  |  Height:  |  Size: 299 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 282 B

After

Width:  |  Height:  |  Size: 224 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 194 B

After

Width:  |  Height:  |  Size: 136 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 285 B

After

Width:  |  Height:  |  Size: 227 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 234 B

After

Width:  |  Height:  |  Size: 176 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 227 B

After

Width:  |  Height:  |  Size: 169 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 294 B

After

Width:  |  Height:  |  Size: 236 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 518 B

After

Width:  |  Height:  |  Size: 460 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 210 B

After

Width:  |  Height:  |  Size: 152 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 292 B

After

Width:  |  Height:  |  Size: 234 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 580 B

After

Width:  |  Height:  |  Size: 522 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 553 B

After

Width:  |  Height:  |  Size: 495 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 542 B

After

Width:  |  Height:  |  Size: 484 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 571 B

After

Width:  |  Height:  |  Size: 513 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 569 B

After

Width:  |  Height:  |  Size: 511 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 545 B

After

Width:  |  Height:  |  Size: 487 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 566 B

After

Width:  |  Height:  |  Size: 508 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 535 B

After

Width:  |  Height:  |  Size: 477 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 580 B

After

Width:  |  Height:  |  Size: 522 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 522 B

After

Width:  |  Height:  |  Size: 464 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 545 B

After

Width:  |  Height:  |  Size: 487 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 556 B

After

Width:  |  Height:  |  Size: 498 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 503 B

After

Width:  |  Height:  |  Size: 445 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 527 B

After

Width:  |  Height:  |  Size: 469 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 563 B

After

Width:  |  Height:  |  Size: 505 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 524 B

After

Width:  |  Height:  |  Size: 466 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 540 B

After

Width:  |  Height:  |  Size: 482 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 566 B

After

Width:  |  Height:  |  Size: 508 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 545 B

After

Width:  |  Height:  |  Size: 487 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 569 B

After

Width:  |  Height:  |  Size: 511 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 290 B

After

Width:  |  Height:  |  Size: 195 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 278 B

After

Width:  |  Height:  |  Size: 186 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 237 B

After

Width:  |  Height:  |  Size: 182 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 267 B

After

Width:  |  Height:  |  Size: 193 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 248 B

After

Width:  |  Height:  |  Size: 175 B

Some files were not shown because too many files have changed in this diff Show More