Add in the base registry
This commit is contained in:
parent
eebcb0467e
commit
18442c2298
@ -18,6 +18,7 @@ public class NativePatchBukkit {
|
||||
private static MethodHandle getLocationNative;
|
||||
private static MethodHandle getWorldNative;
|
||||
private static MethodHandle freeStringNative;
|
||||
private static MethodHandle getRegistryDataNative;
|
||||
|
||||
// Struct layout matching Rust's #[repr(C)] AbilitiesFFI
|
||||
private static final StructLayout ABILITIES_LAYOUT =
|
||||
@ -184,7 +185,8 @@ public class NativePatchBukkit {
|
||||
long setAbilitiesAddr,
|
||||
long getLocationAddr,
|
||||
long freeStringAddr,
|
||||
long getWorldAddr
|
||||
long getWorldAddr,
|
||||
long getRegistryDataAddr
|
||||
) {
|
||||
// void rust_send_message(const char* uuid, const char* message)
|
||||
sendMessageNative = LINKER.downcallHandle(
|
||||
@ -240,6 +242,11 @@ public class NativePatchBukkit {
|
||||
FunctionDescriptor.ofVoid(ValueLayout.ADDRESS)
|
||||
);
|
||||
|
||||
// const char* rust_get_registry_entries(const char* registry_name)
|
||||
getRegistryDataNative = LINKER.downcallHandle(
|
||||
MemorySegment.ofAddress(getRegistryDataAddr),
|
||||
FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.ADDRESS)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -401,4 +408,26 @@ public class NativePatchBukkit {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data for a registry (entries + tags) as JSON.
|
||||
*
|
||||
* @param registryName The registry identifier (e.g. "sound_event", "block")
|
||||
* @return JSON string with "entries" and "tags" fields, or null if registry unknown
|
||||
*/
|
||||
public static String getRegistryData(String registryName) {
|
||||
try (Arena arena = Arena.ofConfined()) {
|
||||
MemorySegment nameStr = arena.allocateFrom(registryName);
|
||||
MemorySegment resultPtr = (MemorySegment) getRegistryDataNative.invokeExact(nameStr);
|
||||
|
||||
if (resultPtr.equals(MemorySegment.NULL)) return null;
|
||||
|
||||
try {
|
||||
return resultPtr.reinterpret(Long.MAX_VALUE).getString(0);
|
||||
} finally {
|
||||
freeRustString(resultPtr);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
throw new RuntimeException("Failed to get registry data: " + registryName, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
package org.patchbukkit.registry;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import io.papermc.paper.registry.RegistryKey;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.util.Map;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.GenericArrayType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.lang.reflect.WildcardType;
|
||||
|
||||
|
||||
@Deprecated
|
||||
public final class LegacyRegistryIdentifiers {
|
||||
|
||||
public static final Map<Class<?>, RegistryKey<?>> CLASS_TO_KEY_MAP;
|
||||
|
||||
static {
|
||||
final ImmutableMap.Builder<Class<?>, RegistryKey<?>> builder = ImmutableMap.builder();
|
||||
try {
|
||||
for (final Field field : RegistryKey.class.getFields()) {
|
||||
if (field.getType() == RegistryKey.class) {
|
||||
// get the legacy type from the RegistryKey generic parameter on the field
|
||||
final Class<?> legacyType = LegacyRegistryIdentifiers.erase(((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0]);
|
||||
builder.put(legacyType, (RegistryKey<?>) field.get(null));
|
||||
}
|
||||
}
|
||||
} catch (final ReflectiveOperationException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
CLASS_TO_KEY_MAP = builder.build();
|
||||
}
|
||||
|
||||
private static Class<?> erase(Type type) {
|
||||
if (type instanceof Class<?> clazz) {
|
||||
return clazz;
|
||||
} else if (type instanceof ParameterizedType parameterized) {
|
||||
return (Class<?>) parameterized.getRawType();
|
||||
} else if (type instanceof GenericArrayType arrayType) {
|
||||
return Array.newInstance(erase(arrayType.getGenericComponentType()), 0).getClass();
|
||||
} else if (type instanceof TypeVariable<?> typeVar) {
|
||||
return erase(typeVar.getBounds()[0]);
|
||||
} else if (type instanceof WildcardType wildcard) {
|
||||
return erase(wildcard.getUpperBounds()[0]);
|
||||
}
|
||||
throw new IllegalArgumentException("Unsupported type: " + type);
|
||||
}
|
||||
|
||||
private LegacyRegistryIdentifiers() {
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,143 @@
|
||||
package org.patchbukkit.registry;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import io.papermc.paper.registry.RegistryKey;
|
||||
import io.papermc.paper.registry.tag.Tag;
|
||||
import io.papermc.paper.registry.tag.TagKey;
|
||||
import org.bukkit.Keyed;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.Registry;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.patchbukkit.bridge.NativePatchBukkit;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class PatchBukkitRegistry<B extends Keyed> implements Registry<B> {
|
||||
|
||||
private final Map<NamespacedKey, B> entries = new LinkedHashMap<>();
|
||||
private final Map<String, PatchBukkitTag<B>> tags = new LinkedHashMap<>();
|
||||
|
||||
/**
|
||||
* Build a registry by fetching JSON from the native side and parsing
|
||||
* entries and tags from the combined response.
|
||||
*
|
||||
* Expected JSON shape:
|
||||
* {
|
||||
* "entries": [{"name": "...", "id": ...}, ...],
|
||||
* "tags": {"minecraft:logs": ["minecraft:oak_log", ...], ...}
|
||||
* }
|
||||
*
|
||||
* @param registryName The native registry name (e.g. "sound_event")
|
||||
* @param registryKey The Paper RegistryKey for this registry
|
||||
* @param factory Converts a single JsonObject into a B instance
|
||||
*/
|
||||
public PatchBukkitRegistry(
|
||||
String registryName,
|
||||
RegistryKey<B> registryKey,
|
||||
Function<JsonObject, B> factory
|
||||
) {
|
||||
String json = NativePatchBukkit.getRegistryData(registryName);
|
||||
if (json == null) return;
|
||||
|
||||
JsonObject root = JsonParser.parseString(json).getAsJsonObject();
|
||||
|
||||
JsonArray entriesArray = root.getAsJsonArray("entries");
|
||||
if (entriesArray != null) {
|
||||
for (JsonElement element : entriesArray) {
|
||||
B value = factory.apply(element.getAsJsonObject());
|
||||
if (value != null) {
|
||||
entries.put(value.getKey(), value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JsonElement tagsElement = root.get("tags");
|
||||
if (tagsElement != null && tagsElement.isJsonObject()) {
|
||||
loadTags(tagsElement.getAsJsonObject(), registryKey);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadTags(JsonObject tagMap, RegistryKey<B> registryKey) {
|
||||
for (Map.Entry<String, JsonElement> entry : tagMap.entrySet()) {
|
||||
String tagName = entry.getKey();
|
||||
JsonArray members = entry.getValue().getAsJsonArray();
|
||||
|
||||
Set<NamespacedKey> memberKeys = new LinkedHashSet<>();
|
||||
for (JsonElement member : members) {
|
||||
String raw = member.getAsString();
|
||||
// Tag values may or may not have "minecraft:" prefix
|
||||
NamespacedKey key;
|
||||
if (raw.contains(":")) {
|
||||
key = NamespacedKey.fromString(raw);
|
||||
} else {
|
||||
key = new NamespacedKey(NamespacedKey.MINECRAFT, raw);
|
||||
}
|
||||
if (key != null) memberKeys.add(key);
|
||||
}
|
||||
|
||||
NamespacedKey tagKeyName = tagName.contains(":")
|
||||
? NamespacedKey.fromString(tagName)
|
||||
: new NamespacedKey(NamespacedKey.MINECRAFT, tagName);
|
||||
|
||||
if (tagKeyName == null) continue;
|
||||
|
||||
TagKey<B> tagKey = TagKey.create(registryKey, tagKeyName);
|
||||
tags.put(tagName, new PatchBukkitTag<>(tagKey, registryKey, memberKeys));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable B get(NamespacedKey key) {
|
||||
return entries.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable NamespacedKey getKey(B value) {
|
||||
return value.getKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTag(TagKey<B> key) {
|
||||
return tags.containsKey(key.key().asString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Tag<B> getTag(TagKey<B> key) {
|
||||
PatchBukkitTag<B> tag = tags.get(key.key().asString());
|
||||
if (tag == null) {
|
||||
throw new NoSuchElementException("Unknown tag: " + key.key().asString());
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Collection<Tag<B>> getTags() {
|
||||
return Collections.unmodifiableCollection(tags.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Stream<B> stream() {
|
||||
return entries.values().stream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Stream<NamespacedKey> keyStream() {
|
||||
return entries.keySet().stream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return entries.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Iterator<B> iterator() {
|
||||
return Collections.unmodifiableCollection(entries.values()).iterator();
|
||||
}
|
||||
}
|
||||
@ -4,19 +4,77 @@ import io.papermc.paper.registry.RegistryAccess;
|
||||
import io.papermc.paper.registry.RegistryKey;
|
||||
import org.bukkit.Keyed;
|
||||
import org.bukkit.Registry;
|
||||
import org.bukkit.Sound;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.patchbukkit.bridge.NativePatchBukkit;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class PatchBukkitRegistryAccess implements RegistryAccess {
|
||||
private static final Map<RegistryKey<?>, Registry<?>> instances = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Maps a RegistryKey to (native registry name, factory function).
|
||||
* Add an entry here for each registry you support.
|
||||
*/
|
||||
private static final Map<RegistryKey<?>, RegistryFactory<?>> FACTORIES = Map.of(
|
||||
RegistryKey.SOUND_EVENT, new RegistryFactory<>(
|
||||
"sound_event",
|
||||
RegistryKey.SOUND_EVENT,
|
||||
json -> new PatchBukkitSound(
|
||||
json.get("name").getAsString(),
|
||||
json.get("id").getAsInt()
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
private record RegistryFactory<B extends Keyed>(
|
||||
String nativeRegistryName,
|
||||
RegistryKey<B> registryKey,
|
||||
Function<JsonObject, B> factory
|
||||
) {}
|
||||
|
||||
@Override
|
||||
public <T extends Keyed> @Nullable Registry<T> getRegistry(Class<T> type) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getRegistry'");
|
||||
final RegistryKey<T> registryKey = byType(type);
|
||||
return this.getRegistry(registryKey);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@Override
|
||||
public <T extends Keyed> Registry<T> getRegistry(RegistryKey<T> registryKey) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getRegistry'");
|
||||
if (registryKey == null) return null;
|
||||
|
||||
return (Registry<T>) instances.computeIfAbsent(registryKey, key -> {
|
||||
RegistryFactory<?> factoryEntry = FACTORIES.get(key);
|
||||
if (factoryEntry != null) {
|
||||
return buildRegistry(factoryEntry);
|
||||
}
|
||||
|
||||
// We return an empty registry for unsupported types, since if we don't the server will crash immediately when the registry class is first loaded
|
||||
return new PatchBukkitRegistry<>(
|
||||
key.key().value(),
|
||||
(RegistryKey) key,
|
||||
json -> null
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
private static <B extends Keyed> PatchBukkitRegistry<B> buildRegistry(RegistryFactory<B> factory) {
|
||||
return new PatchBukkitRegistry<>(
|
||||
factory.nativeRegistryName(),
|
||||
factory.registryKey(),
|
||||
factory.factory()
|
||||
);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "deprecation"})
|
||||
public static <T extends Keyed> @Nullable RegistryKey<T> byType(final Class<T> type) {
|
||||
return (RegistryKey<T>) LegacyRegistryIdentifiers.CLASS_TO_KEY_MAP.get(type);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,62 @@
|
||||
package org.patchbukkit.registry;
|
||||
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.Sound;
|
||||
|
||||
public class PatchBukkitSound implements Sound {
|
||||
|
||||
private final NamespacedKey namespacedKey;
|
||||
private final Key adventureKey;
|
||||
private final String enumName;
|
||||
private final int protocolId;
|
||||
|
||||
public PatchBukkitSound(String soundName, int protocolId) {
|
||||
this.namespacedKey = new NamespacedKey(NamespacedKey.MINECRAFT, soundName);
|
||||
this.adventureKey = Key.key(Key.MINECRAFT_NAMESPACE, soundName);
|
||||
this.protocolId = protocolId;
|
||||
this.enumName = soundName.toUpperCase().replace('.', '_');
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamespacedKey getKey() {
|
||||
return namespacedKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key key() {
|
||||
return adventureKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int ordinal() {
|
||||
return protocolId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return enumName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Sound other) {
|
||||
return Integer.compare(this.ordinal(), other.ordinal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof Sound other)) return false;
|
||||
return namespacedKey.equals(other.getKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return namespacedKey.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PatchBukkitSound{" + namespacedKey + "}";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
package org.patchbukkit.registry;
|
||||
|
||||
import io.papermc.paper.registry.RegistryKey;
|
||||
import io.papermc.paper.registry.TypedKey;
|
||||
import io.papermc.paper.registry.tag.Tag;
|
||||
import io.papermc.paper.registry.tag.TagKey;
|
||||
import org.bukkit.Keyed;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.Registry;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class PatchBukkitTag<B extends Keyed> implements Tag<B> {
|
||||
|
||||
private final TagKey<B> tagKey;
|
||||
private final Set<TypedKey<B>> memberKeys;
|
||||
|
||||
public PatchBukkitTag(TagKey<B> tagKey, RegistryKey<B> registryKey, Set<NamespacedKey> rawKeys) {
|
||||
this.tagKey = tagKey;
|
||||
this.memberKeys = rawKeys.stream()
|
||||
.map(k -> TypedKey.create(registryKey, k))
|
||||
.collect(Collectors.toUnmodifiableSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public TagKey<B> tagKey() {
|
||||
return tagKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Unmodifiable Collection<TypedKey<B>> values() {
|
||||
return memberKeys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Unmodifiable Collection<B> resolve(Registry<B> registry) {
|
||||
List<B> resolved = new ArrayList<>();
|
||||
for (TypedKey<B> key : memberKeys) {
|
||||
B value = registry.get(key.key());
|
||||
if (value != null) resolved.add(value);
|
||||
}
|
||||
return Collections.unmodifiableList(resolved);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(TypedKey<B> valueKey) {
|
||||
return memberKeys.contains(valueKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegistryKey<B> registryKey() {
|
||||
return tagKey.registryKey();
|
||||
}
|
||||
}
|
||||
93
rust/Cargo.lock
generated
93
rust/Cargo.lock
generated
@ -1695,10 +1695,12 @@ dependencies = [
|
||||
"log",
|
||||
"pumpkin",
|
||||
"pumpkin-api-macros",
|
||||
"pumpkin-util",
|
||||
"pumpkin-data 0.1.0-dev+1.21.11 (git+https://github.com/BjornTheProgrammer/Pumpkin.git?branch=master)",
|
||||
"pumpkin-util 0.1.0-dev+1.21.11 (git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master)",
|
||||
"rust-embed",
|
||||
"serde",
|
||||
"serde-saphyr",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
"uuid",
|
||||
"walkdir",
|
||||
@ -1977,12 +1979,12 @@ dependencies = [
|
||||
"num-bigint",
|
||||
"pkcs8 0.11.0-rc.10",
|
||||
"pumpkin-config",
|
||||
"pumpkin-data",
|
||||
"pumpkin-data 0.1.0-dev+1.21.11 (git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master)",
|
||||
"pumpkin-inventory",
|
||||
"pumpkin-macros",
|
||||
"pumpkin-nbt",
|
||||
"pumpkin-nbt 0.1.0-dev+1.21.11 (git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master)",
|
||||
"pumpkin-protocol",
|
||||
"pumpkin-util",
|
||||
"pumpkin-util 0.1.0-dev+1.21.11 (git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master)",
|
||||
"pumpkin-world",
|
||||
"rand",
|
||||
"rsa",
|
||||
@ -2019,12 +2021,32 @@ version = "0.1.0-dev+1.21.11"
|
||||
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#f93be68caa3969502c13d5d284da59fe1017ed9a"
|
||||
dependencies = [
|
||||
"log",
|
||||
"pumpkin-util",
|
||||
"pumpkin-util 0.1.0-dev+1.21.11 (git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master)",
|
||||
"serde",
|
||||
"toml",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pumpkin-data"
|
||||
version = "0.1.0-dev+1.21.11"
|
||||
source = "git+https://github.com/BjornTheProgrammer/Pumpkin.git?branch=master#007b97eed8243cf744cb0353b12438db8eab2938"
|
||||
dependencies = [
|
||||
"crc-fast",
|
||||
"heck",
|
||||
"indexmap",
|
||||
"phf",
|
||||
"proc-macro2",
|
||||
"pumpkin-nbt 0.1.0-dev+1.21.11 (git+https://github.com/BjornTheProgrammer/Pumpkin.git?branch=master)",
|
||||
"pumpkin-util 0.1.0-dev+1.21.11 (git+https://github.com/BjornTheProgrammer/Pumpkin.git?branch=master)",
|
||||
"quote",
|
||||
"rayon",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_json5",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pumpkin-data"
|
||||
version = "0.1.0-dev+1.21.11"
|
||||
@ -2035,8 +2057,8 @@ dependencies = [
|
||||
"indexmap",
|
||||
"phf",
|
||||
"proc-macro2",
|
||||
"pumpkin-nbt",
|
||||
"pumpkin-util",
|
||||
"pumpkin-nbt 0.1.0-dev+1.21.11 (git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master)",
|
||||
"pumpkin-util 0.1.0-dev+1.21.11 (git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master)",
|
||||
"quote",
|
||||
"rayon",
|
||||
"serde",
|
||||
@ -2052,9 +2074,9 @@ source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#f93be68caa
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
"log",
|
||||
"pumpkin-data",
|
||||
"pumpkin-data 0.1.0-dev+1.21.11 (git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master)",
|
||||
"pumpkin-protocol",
|
||||
"pumpkin-util",
|
||||
"pumpkin-util 0.1.0-dev+1.21.11 (git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master)",
|
||||
"pumpkin-world",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
@ -2067,11 +2089,23 @@ source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#f93be68caa
|
||||
dependencies = [
|
||||
"proc-macro-error2",
|
||||
"proc-macro2",
|
||||
"pumpkin-data",
|
||||
"pumpkin-data 0.1.0-dev+1.21.11 (git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master)",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pumpkin-nbt"
|
||||
version = "0.1.0-dev+1.21.11"
|
||||
source = "git+https://github.com/BjornTheProgrammer/Pumpkin.git?branch=master#007b97eed8243cf744cb0353b12438db8eab2938"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"cesu8",
|
||||
"flate2",
|
||||
"serde",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pumpkin-nbt"
|
||||
version = "0.1.0-dev+1.21.11"
|
||||
@ -2094,10 +2128,10 @@ dependencies = [
|
||||
"bitflags",
|
||||
"bytes",
|
||||
"cfb8",
|
||||
"pumpkin-data",
|
||||
"pumpkin-data 0.1.0-dev+1.21.11 (git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master)",
|
||||
"pumpkin-macros",
|
||||
"pumpkin-nbt",
|
||||
"pumpkin-util",
|
||||
"pumpkin-nbt 0.1.0-dev+1.21.11 (git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master)",
|
||||
"pumpkin-util 0.1.0-dev+1.21.11 (git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master)",
|
||||
"pumpkin-world",
|
||||
"serde",
|
||||
"take_mut",
|
||||
@ -2106,6 +2140,31 @@ dependencies = [
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pumpkin-util"
|
||||
version = "0.1.0-dev+1.21.11"
|
||||
source = "git+https://github.com/BjornTheProgrammer/Pumpkin.git?branch=master#007b97eed8243cf744cb0353b12438db8eab2938"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"bytes",
|
||||
"colored",
|
||||
"ecdsa",
|
||||
"enum_dispatch",
|
||||
"md5",
|
||||
"num-derive",
|
||||
"num-traits",
|
||||
"p384",
|
||||
"proc-macro2",
|
||||
"pumpkin-nbt 0.1.0-dev+1.21.11 (git+https://github.com/BjornTheProgrammer/Pumpkin.git?branch=master)",
|
||||
"quote",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"syn",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pumpkin-util"
|
||||
version = "0.1.0-dev+1.21.11"
|
||||
@ -2121,7 +2180,7 @@ dependencies = [
|
||||
"num-traits",
|
||||
"p384",
|
||||
"proc-macro2",
|
||||
"pumpkin-nbt",
|
||||
"pumpkin-nbt 0.1.0-dev+1.21.11 (git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master)",
|
||||
"quote",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@ -2152,9 +2211,9 @@ dependencies = [
|
||||
"num-traits",
|
||||
"num_cpus",
|
||||
"pumpkin-config",
|
||||
"pumpkin-data",
|
||||
"pumpkin-nbt",
|
||||
"pumpkin-util",
|
||||
"pumpkin-data 0.1.0-dev+1.21.11 (git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master)",
|
||||
"pumpkin-nbt 0.1.0-dev+1.21.11 (git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master)",
|
||||
"pumpkin-util 0.1.0-dev+1.21.11 (git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master)",
|
||||
"rand",
|
||||
"rustc-hash",
|
||||
"ruzstd",
|
||||
|
||||
@ -8,6 +8,7 @@ crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
pumpkin = { git = "https://github.com/Pumpkin-MC/Pumpkin.git", branch = "master", package = "pumpkin" }
|
||||
pumpkin-data = { git = "https://github.com/BjornTheProgrammer/Pumpkin.git", branch = "master", package = "pumpkin-data" }
|
||||
pumpkin-util = { git = "https://github.com/Pumpkin-MC/Pumpkin.git", branch = "master", package = "pumpkin-util" }
|
||||
pumpkin-api-macros = { git = "https://github.com/Pumpkin-MC/Pumpkin.git", branch = "master", package = "pumpkin-api-macros" }
|
||||
|
||||
@ -20,12 +21,13 @@ rust-embed = { version = "8.11.0", features = ["interpolate-folder-path"] }
|
||||
walkdir = "2"
|
||||
zip = "7.2"
|
||||
|
||||
serde-saphyr = "0.0.16"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
|
||||
anyhow = "1.0"
|
||||
uuid = "1.20.0"
|
||||
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
serde-saphyr = "0.0.16"
|
||||
|
||||
[build-dependencies]
|
||||
j4rs = { version = "0.24", artifact = "cdylib", lib = true }
|
||||
env_logger = "0.11.8"
|
||||
|
||||
@ -9,6 +9,7 @@ pub mod events;
|
||||
pub mod location;
|
||||
pub mod memory;
|
||||
pub mod message;
|
||||
pub mod registry;
|
||||
pub mod utils;
|
||||
pub mod world;
|
||||
|
||||
@ -42,6 +43,7 @@ pub fn initialize_callbacks(jvm: &Jvm) -> Result<()> {
|
||||
let get_location_addr = location::rust_get_location as *const () as i64;
|
||||
let free_string_addr = memory::rust_free_string as *const () as i64;
|
||||
let get_world_addr = world::rust_get_world as *const () as i64;
|
||||
let rust_get_registry_data_addr = registry::rust_get_registry_data as *const () as i64;
|
||||
|
||||
jvm.invoke_static(
|
||||
"org.patchbukkit.bridge.NativePatchBukkit",
|
||||
@ -54,6 +56,7 @@ pub fn initialize_callbacks(jvm: &Jvm) -> Result<()> {
|
||||
InvocationArg::try_from(get_location_addr)?.into_primitive()?,
|
||||
InvocationArg::try_from(free_string_addr)?.into_primitive()?,
|
||||
InvocationArg::try_from(get_world_addr)?.into_primitive()?,
|
||||
InvocationArg::try_from(rust_get_registry_data_addr)?.into_primitive()?,
|
||||
],
|
||||
)?;
|
||||
|
||||
|
||||
60
rust/src/java/native_callbacks/registry.rs
Normal file
60
rust/src/java/native_callbacks/registry.rs
Normal file
@ -0,0 +1,60 @@
|
||||
use std::{collections::HashMap, ffi::CString, os::raw::c_char};
|
||||
|
||||
use serde::Serialize;
|
||||
use serde_json::Value;
|
||||
|
||||
use crate::java::native_callbacks::utils::get_string;
|
||||
|
||||
#[derive(Serialize, Debug, Clone)]
|
||||
struct Registry {
|
||||
pub entries: Vec<Value>,
|
||||
pub tags: HashMap<String, Vec<String>>,
|
||||
}
|
||||
|
||||
impl Registry {
|
||||
pub fn new(entries: Vec<Value>, tags: HashMap<String, Vec<String>>) -> Self {
|
||||
Registry { entries, tags }
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn rust_get_registry_data(registry_name: *const c_char) -> *const c_char {
|
||||
let name = get_string(registry_name);
|
||||
|
||||
let registry: Option<Registry> = match name.as_ref() {
|
||||
"sound_event" => {
|
||||
let entries: Vec<serde_json::Value> = pumpkin_data::sound::Sound::slice()
|
||||
.iter()
|
||||
.map(|s| {
|
||||
serde_json::json!({
|
||||
"name": s.to_name(),
|
||||
"id": *s as u16
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
Some(Registry::new(entries, HashMap::new()))
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let registry = match registry {
|
||||
Some(registry) => registry,
|
||||
None => return std::ptr::null(),
|
||||
};
|
||||
|
||||
let json_str = match serde_json::to_string(®istry) {
|
||||
Ok(json_str) => json_str,
|
||||
Err(err) => {
|
||||
log::error!("Failed to serialize registry: {}", err);
|
||||
return std::ptr::null();
|
||||
}
|
||||
};
|
||||
|
||||
match CString::new(json_str) {
|
||||
Ok(cstring) => cstring.into_raw(),
|
||||
Err(err) => {
|
||||
log::error!("Failed to convert registry string to CString: {}", err);
|
||||
return std::ptr::null_mut();
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user