mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-10-15 14:07:38 +00:00
Compare commits
7 Commits
v1.20.1-1.
...
mc-1.20.x
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b9ed66983d | ||
![]() |
d0fbec6c6b | ||
![]() |
a683697e8c | ||
![]() |
9e233a916f | ||
![]() |
5a9e21ccc3 | ||
![]() |
5f16909d4b | ||
![]() |
00475b9bb0 |
@@ -81,11 +81,10 @@ public abstract class AbstractInventoryMethods<T> implements GenericPeripheral {
|
||||
* recommended to print it out using [`textutils.serialize`] or in the Lua
|
||||
* REPL, to explore what is available.
|
||||
* <p>
|
||||
* > [Deprecated fields][!INFO]
|
||||
* > Older versions of CC: Tweaked exposed an {@code itemGroups} field, listing the
|
||||
* > creative tabs an item was available under. This information is no longer available on
|
||||
* > more recent versions of the game, and so this field will always be empty. Do not use this
|
||||
* > field in new code!
|
||||
* > [Missing fields][!INFO]
|
||||
* > CC: Tweaked exposes an {@code itemGroups} field, listing the creative tabs an
|
||||
* > item is available under. This information is not available on Minecraft 1.19.3
|
||||
* > to 1.20.3, and so this field will be empty on those versions.
|
||||
*
|
||||
* @param inventory The current inventory.
|
||||
* @param slot The slot to get information about.
|
||||
|
@@ -54,7 +54,7 @@ public final class InventoryUtil {
|
||||
*/
|
||||
public static int getInventorySlotFromCompartment(Player player, int slot, ItemStack stack) {
|
||||
if (stack.isEmpty()) throw new IllegalArgumentException("Cannot search for empty stack");
|
||||
if (player.getInventory().getItem(slot) == stack) return slot;
|
||||
if (slot >= 0 && slot < Inventory.INVENTORY_SIZE && player.getInventory().getItem(slot) == stack) return slot;
|
||||
if (player.getInventory().getItem(Inventory.SLOT_OFFHAND) == stack) return Inventory.SLOT_OFFHAND;
|
||||
return -1;
|
||||
}
|
||||
|
@@ -61,4 +61,14 @@ public class ObjectLuaTable implements LuaTable<Object, Object> {
|
||||
public Set<Entry<Object, Object>> entrySet() {
|
||||
return map.entrySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return this == o || o instanceof Map<?, ?> otherMap && map.equals(otherMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return map.hashCode();
|
||||
}
|
||||
}
|
||||
|
@@ -73,6 +73,22 @@ final class Generator<T> {
|
||||
addArgType(argMethodMap, Map.class, "Table");
|
||||
addArgType(argMethodMap, String.class, "String");
|
||||
addArgType(argMethodMap, ByteBuffer.class, "Bytes");
|
||||
argMethodMap.put(LuaTable.class, new ArgMethods(
|
||||
// i -> new ObjectLuaTable(getTable(i))
|
||||
MethodHandles.filterReturnValue(
|
||||
LOOKUP.findVirtual(IArguments.class, "getTable", MethodType.methodType(Map.class, int.class)),
|
||||
LOOKUP.findConstructor(ObjectLuaTable.class, MethodType.methodType(void.class, Map.class))
|
||||
.asType(MethodType.methodType(LuaTable.class, Map.class))
|
||||
),
|
||||
// i -> optTable(i).map(ObjectLuaTable::new)
|
||||
MethodHandles.filterReturnValue(
|
||||
LOOKUP.findVirtual(IArguments.class, "optTable", MethodType.methodType(Optional.class, int.class)),
|
||||
MethodHandles.insertArguments(
|
||||
LOOKUP.findVirtual(Optional.class, "map", MethodType.methodType(Optional.class, Function.class)),
|
||||
1, (Function<Map<?, ?>, LuaTable<?, ?>>) ObjectLuaTable::new
|
||||
)
|
||||
)
|
||||
));
|
||||
argMethods = Map.copyOf(argMethodMap);
|
||||
|
||||
ARG_TABLE_UNSAFE = ArgMethods.of(LuaTable.class, "TableUnsafe");
|
||||
@@ -335,10 +351,9 @@ final class Generator<T> {
|
||||
}
|
||||
|
||||
private static @Nullable ArgMethods getArgMethods(Class<?> type, boolean unsafe) {
|
||||
var getter = argMethods.get(type);
|
||||
if (getter != null) return getter;
|
||||
if (type == LuaTable.class && unsafe) return ARG_TABLE_UNSAFE;
|
||||
return null;
|
||||
|
||||
return argMethods.get(type);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -20,13 +20,8 @@ import static org.squiddev.cobalt.Constants.NAME;
|
||||
final class VarargArguments implements IArguments {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(VarargArguments.class);
|
||||
|
||||
private static final VarargArguments EMPTY = new VarargArguments(Constants.NONE);
|
||||
private static boolean reportedIllegalGet;
|
||||
|
||||
static {
|
||||
EMPTY.escapes = EMPTY.closed = true;
|
||||
}
|
||||
|
||||
private final Varargs varargs;
|
||||
|
||||
private volatile boolean closed;
|
||||
@@ -51,7 +46,7 @@ final class VarargArguments implements IArguments {
|
||||
}
|
||||
|
||||
static VarargArguments of(Varargs values) {
|
||||
return values == Constants.NONE ? EMPTY : new VarargArguments(values);
|
||||
return new VarargArguments(values);
|
||||
}
|
||||
|
||||
boolean isClosed() {
|
||||
@@ -138,9 +133,7 @@ final class VarargArguments implements IArguments {
|
||||
if (count < 0) throw new IllegalStateException("count cannot be negative");
|
||||
if (count == 0) return this;
|
||||
|
||||
var newArgs = varargs.subargs(count + 1);
|
||||
if (newArgs == Constants.NONE) return EMPTY;
|
||||
return new VarargArguments(newArgs, this, count);
|
||||
return new VarargArguments(varargs.subargs(count + 1), this, count);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -616,7 +616,8 @@ do
|
||||
end
|
||||
|
||||
local function parse_ident(str, pos)
|
||||
local _, last, val = find(str, '^([%a][%w_]*)', pos)
|
||||
local _, last, val = find(str, '^([%w_+.-]+)', pos)
|
||||
if not last then error_at(pos, "Expected object key") end
|
||||
return val, last + 1
|
||||
end
|
||||
|
||||
@@ -864,7 +865,7 @@ values do not serialise cleanly into JSON.
|
||||
A consequence of this is that an empty table will always be serialised to an object,
|
||||
not an array. [`textutils.empty_json_array`] may be used to express an empty array.
|
||||
|
||||
- Lua strings are an a sequence of raw bytes, and do not have any specific encoding.
|
||||
- Lua strings are a sequence of raw bytes, and do not have any specific encoding.
|
||||
However, JSON strings must be valid unicode. By default, non-ASCII characters in a
|
||||
string are serialised to their unicode code point (for instance, `"\xfe"` is
|
||||
converted to `"\u00fe"`). The `unicode_strings` option may be set to treat all input
|
||||
|
@@ -8,8 +8,8 @@ Convert between streams of DFPWM audio data and a list of amplitudes.
|
||||
DFPWM (Dynamic Filter Pulse Width Modulation) is an audio codec designed by GreaseMonkey. It's a relatively compact
|
||||
format compared to raw PCM data, only using 1 bit per sample, but is simple enough to encode and decode in real time.
|
||||
|
||||
Typically DFPWM audio is read from [the filesystem][`fs.ReadHandle`] or a [a web request][`http.Response`] as a string,
|
||||
and converted a format suitable for [`speaker.playAudio`].
|
||||
Typically DFPWM audio is read from [the filesystem][`fs.ReadHandle`] or [a web request][`http.Response`] as a string,
|
||||
and converted to a format suitable for [`speaker.playAudio`].
|
||||
|
||||
## Encoding and decoding files
|
||||
This module exposes two key functions, [`make_decoder`] and [`make_encoder`], which construct a new decoder or encoder.
|
||||
|
@@ -10,6 +10,7 @@ import dan200.computercraft.core.computer.ComputerSide;
|
||||
import dan200.computercraft.core.methods.LuaMethod;
|
||||
import dan200.computercraft.core.methods.NamedMethod;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
@@ -123,6 +124,17 @@ public class GeneratorTest {
|
||||
assertThrows(LuaException.class, () -> apply(methods, new EnumMethods(), "getEnum", "not as side"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLuaTable() throws LuaException {
|
||||
var methods = GENERATOR.getMethods(TableMethods.class);
|
||||
assertThat(methods, containsInAnyOrder(named("getTable"), named("optTable")));
|
||||
|
||||
assertThat(apply(methods, new TableMethods(), "getTable", Map.of("x", "y")), one(is(Map.of("x", "y"))));
|
||||
assertThat(apply(methods, new TableMethods(), "optTable", Map.of("x", "y")), one(is(Map.of("x", "y"))));
|
||||
assertThat(apply(methods, new TableMethods(), "optTable"), one(nullValue()));
|
||||
assertThrows(LuaException.class, () -> apply(methods, new TableMethods(), "getTable", "not a table"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMainThread() throws LuaException {
|
||||
var methods = GENERATOR.getMethods(MainThread.class);
|
||||
@@ -277,6 +289,18 @@ public class GeneratorTest {
|
||||
}
|
||||
}
|
||||
|
||||
public static class TableMethods {
|
||||
@LuaFunction
|
||||
public final LuaTable<?, ?> getTable(LuaTable<?, ?> table) {
|
||||
return table;
|
||||
}
|
||||
|
||||
@LuaFunction
|
||||
public final @Nullable LuaTable<?, ?> optTable(Optional<LuaTable<?, ?>> table) {
|
||||
return table.orElse(null);
|
||||
}
|
||||
}
|
||||
|
||||
public static class MainThread {
|
||||
@LuaFunction(mainThread = true)
|
||||
public final void go() {
|
||||
@@ -288,10 +312,6 @@ public class GeneratorTest {
|
||||
public final void withUnsafe(LuaTable<?, ?> table) {
|
||||
}
|
||||
|
||||
@LuaFunction
|
||||
public final void withoutUnsafe(LuaTable<?, ?> table) {
|
||||
}
|
||||
|
||||
@LuaFunction(unsafe = true, mainThread = true)
|
||||
public final void invalid(LuaTable<?, ?> table) {
|
||||
}
|
||||
|
@@ -246,11 +246,25 @@ describe("The textutils library", function()
|
||||
describe("parses using NBT-style syntax", function()
|
||||
local function exp(x)
|
||||
local res, err = textutils.unserializeJSON(x, { nbt_style = true })
|
||||
if not res then error(err, 2) end
|
||||
if not res then fail(err) end
|
||||
return expect(res)
|
||||
end
|
||||
|
||||
local function exp_err(x)
|
||||
local res, err = textutils.unserializeJSON(x, { nbt_style = true })
|
||||
if res ~= nil then
|
||||
fail(("Expected %q not to parse, but returned %s"):format(x, textutils.serialise(res)))
|
||||
end
|
||||
return expect(err)
|
||||
end
|
||||
|
||||
it("basic objects", function()
|
||||
exp([[{ a: 1, b:2 }]]):same { a = 1, b = 2 }
|
||||
exp("{ a: 1, b:2 }"):same { a = 1, b = 2 }
|
||||
exp("{0+_-.aA: 1}"):same { ["0+_-.aA"] = 1 }
|
||||
exp("{}"):same {}
|
||||
|
||||
exp_err("{: 123}"):eq("Malformed JSON at position 2: Expected object key")
|
||||
exp_err("{#: 123}"):eq("Malformed JSON at position 2: Expected object key")
|
||||
end)
|
||||
|
||||
it("suffixed numbers", function()
|
||||
@@ -258,9 +272,21 @@ describe("The textutils library", function()
|
||||
exp("1.1d"):eq(1.1)
|
||||
end)
|
||||
|
||||
it("strings", function()
|
||||
exp("'123'"):eq("123")
|
||||
exp("\"123\""):eq("123")
|
||||
describe("strings", function()
|
||||
it("empty quoted strings", function()
|
||||
exp("''"):eq("")
|
||||
exp("\"\""):eq("")
|
||||
end)
|
||||
|
||||
pending("unquoted strings", function()
|
||||
exp("hello"):eq("hello")
|
||||
exp("0+_-.aA"):eq("0+_-.aA")
|
||||
end)
|
||||
|
||||
it("quoted strings", function()
|
||||
exp("'123'"):eq("123")
|
||||
exp("\"123\""):eq("123")
|
||||
end)
|
||||
end)
|
||||
|
||||
it("typed arrays", function()
|
||||
|
Reference in New Issue
Block a user