mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-28 03:19:14 +00:00
@@ -91,10 +91,10 @@ tasks {
|
||||
relocate("org.apache.commons.io", "net.momirealms.craftengine.libraries.commons.io")
|
||||
relocate("org.bstats", "net.momirealms.craftengine.libraries.bstats")
|
||||
relocate("com.github.benmanes.caffeine", "net.momirealms.craftengine.libraries.caffeine")
|
||||
relocate("net.objecthunter.exp4j", "net.momirealms.craftengine.libraries.exp4j")
|
||||
relocate("net.bytebuddy", "net.momirealms.craftengine.libraries.bytebuddy")
|
||||
relocate("org.yaml.snakeyaml", "net.momirealms.craftengine.libraries.snakeyaml")
|
||||
relocate("org.ahocorasick", "net.momirealms.craftengine.libraries.ahocorasick")
|
||||
relocate("com.ezylang.evalex", "net.momirealms.craftengine.libraries.evalex")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,9 +26,6 @@ dependencies {
|
||||
compileOnly("pers.neige.neigeitems:NeigeItems:1.21.42")
|
||||
// Placeholder
|
||||
compileOnly("me.clip:placeholderapi:${rootProject.properties["placeholder_api_version"]}")
|
||||
// WorldEdit
|
||||
compileOnly("com.sk89q.worldedit:worldedit-core:7.2.19")
|
||||
compileOnly("com.sk89q.worldedit:worldedit-bukkit:7.2.19")
|
||||
// SlimeWorld
|
||||
compileOnly("com.infernalsuite.asp:api:4.0.0-SNAPSHOT")
|
||||
// ModelEngine
|
||||
@@ -44,6 +41,10 @@ dependencies {
|
||||
compileOnly("com.viaversion:viaversion-api:5.3.2")
|
||||
// Skript
|
||||
compileOnly("com.github.SkriptLang:Skript:2.11.0")
|
||||
// FAWE
|
||||
compileOnly(platform("com.intellectualsites.bom:bom-newest:1.52"))
|
||||
compileOnly("com.fastasyncworldedit:FastAsyncWorldEdit-Core")
|
||||
compileOnly("com.fastasyncworldedit:FastAsyncWorldEdit-Bukkit") { isTransitive = false }
|
||||
}
|
||||
|
||||
java {
|
||||
|
||||
@@ -2,8 +2,10 @@ package net.momirealms.craftengine.bukkit.compatibility.legacy.slimeworld;
|
||||
|
||||
import com.infernalsuite.aswm.api.events.LoadSlimeWorldEvent;
|
||||
import com.infernalsuite.aswm.api.world.SlimeWorld;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import net.momirealms.craftengine.core.world.WorldManager;
|
||||
import net.momirealms.craftengine.core.world.chunk.storage.CachedStorage;
|
||||
import net.momirealms.craftengine.core.world.chunk.storage.DefaultStorageAdaptor;
|
||||
import net.momirealms.craftengine.core.world.chunk.storage.WorldDataStorage;
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -22,7 +24,8 @@ public class LegacySlimeFormatStorageAdaptor extends DefaultStorageAdaptor imple
|
||||
@EventHandler
|
||||
public void onWorldLoad(LoadSlimeWorldEvent event) {
|
||||
org.bukkit.World world = Bukkit.getWorld(event.getSlimeWorld().getName());
|
||||
this.worldManager.loadWorld(this.worldManager.createWorld(this.worldManager.wrap(world), new LegacySlimeWorldDataStorage(event.getSlimeWorld())));
|
||||
this.worldManager.loadWorld(this.worldManager.createWorld(this.worldManager.wrap(world),
|
||||
Config.enableChunkCache() ? new CachedStorage<>(new LegacySlimeWorldDataStorage(event.getSlimeWorld())) : new LegacySlimeWorldDataStorage(event.getSlimeWorld())));
|
||||
}
|
||||
|
||||
public LegacySlimeFormatStorageAdaptor(WorldManager worldManager, int version) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.legacy.slimeworld;
|
||||
|
||||
import com.flowpowered.nbt.ByteArrayTag;
|
||||
import com.flowpowered.nbt.CompoundMap;
|
||||
import com.infernalsuite.aswm.api.world.SlimeChunk;
|
||||
import com.infernalsuite.aswm.api.world.SlimeWorld;
|
||||
import net.momirealms.craftengine.core.world.CEWorld;
|
||||
@@ -42,20 +41,8 @@ public class LegacySlimeWorldDataStorage implements WorldDataStorage {
|
||||
}
|
||||
}
|
||||
|
||||
private CompoundMap createOrGetDataMap(SlimeWorld world) {
|
||||
Optional<com.flowpowered.nbt.CompoundTag> optionalCompoundTag = world.getExtraData().getAsCompoundTag("craftengine");
|
||||
CompoundMap ccDataMap;
|
||||
if (optionalCompoundTag.isEmpty()) {
|
||||
ccDataMap = new CompoundMap();
|
||||
world.getExtraData().getValue().put(new com.flowpowered.nbt.CompoundTag("customcrops", ccDataMap));
|
||||
} else {
|
||||
ccDataMap = optionalCompoundTag.get().getValue();
|
||||
}
|
||||
return ccDataMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeChunkAt(@NotNull ChunkPos pos, @NotNull CEChunk chunk, boolean immediately) {
|
||||
public void writeChunkAt(@NotNull ChunkPos pos, @NotNull CEChunk chunk) {
|
||||
SlimeChunk slimeChunk = getWorld().getChunk(pos.x, pos.z);
|
||||
if (slimeChunk == null) return;
|
||||
CompoundTag nbt = DefaultChunkSerializer.serialize(chunk);
|
||||
|
||||
@@ -3,9 +3,11 @@ package net.momirealms.craftengine.bukkit.compatibility.slimeworld;
|
||||
import com.infernalsuite.asp.api.AdvancedSlimePaperAPI;
|
||||
import com.infernalsuite.asp.api.events.LoadSlimeWorldEvent;
|
||||
import com.infernalsuite.asp.api.world.SlimeWorld;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.util.ReflectionUtils;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import net.momirealms.craftengine.core.world.WorldManager;
|
||||
import net.momirealms.craftengine.core.world.chunk.storage.CachedStorage;
|
||||
import net.momirealms.craftengine.core.world.chunk.storage.DefaultStorageAdaptor;
|
||||
import net.momirealms.craftengine.core.world.chunk.storage.WorldDataStorage;
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -24,7 +26,8 @@ public class SlimeFormatStorageAdaptor extends DefaultStorageAdaptor implements
|
||||
@EventHandler
|
||||
public void onWorldLoad(LoadSlimeWorldEvent event) {
|
||||
org.bukkit.World world = Bukkit.getWorld(event.getSlimeWorld().getName());
|
||||
this.worldManager.loadWorld(this.worldManager.createWorld(this.worldManager.wrap(world), new SlimeWorldDataStorage(event.getSlimeWorld(), this)));
|
||||
this.worldManager.loadWorld(this.worldManager.createWorld(this.worldManager.wrap(world),
|
||||
Config.enableChunkCache() ? new CachedStorage<>(new SlimeWorldDataStorage(event.getSlimeWorld(), this)) : new SlimeWorldDataStorage(event.getSlimeWorld(), this)));
|
||||
}
|
||||
|
||||
public SlimeFormatStorageAdaptor(WorldManager worldManager) {
|
||||
|
||||
@@ -44,7 +44,7 @@ public class SlimeWorldDataStorage implements WorldDataStorage {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void writeChunkAt(@NotNull ChunkPos pos, @NotNull CEChunk chunk, boolean immediately) {
|
||||
public void writeChunkAt(@NotNull ChunkPos pos, @NotNull CEChunk chunk) {
|
||||
SlimeChunk slimeChunk = getWorld().getChunk(pos.x, pos.z);
|
||||
if (slimeChunk == null) return;
|
||||
CompoundTag nbt = DefaultChunkSerializer.serialize(chunk);
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.worldedit;
|
||||
|
||||
import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter;
|
||||
import com.fastasyncworldedit.bukkit.adapter.FaweAdapter;
|
||||
import com.fastasyncworldedit.core.configuration.Settings;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||
import com.sk89q.worldedit.event.extent.EditSessionEvent;
|
||||
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.util.eventbus.Subscribe;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.injector.BukkitInjector;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.core.block.EmptyBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.util.ReflectionUtils;
|
||||
import net.momirealms.craftengine.core.world.CEWorld;
|
||||
import net.momirealms.craftengine.core.world.ChunkPos;
|
||||
import net.momirealms.craftengine.core.world.SectionPos;
|
||||
import net.momirealms.craftengine.core.world.chunk.CEChunk;
|
||||
import net.momirealms.craftengine.core.world.chunk.CESection;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public class FastAsyncWorldEditDelegate extends AbstractDelegateExtent {
|
||||
private static int[] ordinalToIbdID;
|
||||
private final Set<CEChunk> chunksToSave;
|
||||
private final CEWorld ceWorld;
|
||||
private final Set<ChunkPos> brokenChunks = Collections.synchronizedSet(new HashSet<>());
|
||||
|
||||
protected FastAsyncWorldEditDelegate(EditSessionEvent event) {
|
||||
super(event.getExtent());
|
||||
this.chunksToSave = new HashSet<>();
|
||||
World weWorld = event.getWorld();
|
||||
org.bukkit.World world = Bukkit.getWorld(requireNonNull(weWorld).getName());
|
||||
CEWorld ceWorld = CraftEngine.instance().worldManager().getWorld(requireNonNull(world).getUID());
|
||||
this.ceWorld = requireNonNull(ceWorld);
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
Settings.settings().EXTENT.ALLOWED_PLUGINS.add(FastAsyncWorldEditDelegate.class.getCanonicalName());
|
||||
FaweAdapter<?, ?> adapter = (FaweAdapter<?, ?>) WorldEditPlugin.getInstance().getBukkitImplAdapter();
|
||||
Method ordinalToIbdIDMethod = ReflectionUtils.getDeclaredMethod(CachedBukkitAdapter.class, int.class.arrayType(), new String[]{"getOrdinalToIbdID"});
|
||||
try {
|
||||
assert ordinalToIbdIDMethod != null;
|
||||
ordinalToIbdID = (int[]) ordinalToIbdIDMethod.invoke(adapter);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException("Failed to init FastAsyncWorldEdit compatibility", e);
|
||||
}
|
||||
WorldEdit.getInstance().getEventBus().register(new Object() {
|
||||
@Subscribe
|
||||
@SuppressWarnings("unused")
|
||||
public void onEditSessionEvent(EditSessionEvent event) {
|
||||
World weWorld = event.getWorld();
|
||||
if (weWorld == null) return;
|
||||
if (event.getStage() == EditSession.Stage.BEFORE_CHANGE) {
|
||||
event.setExtent(new FastAsyncWorldEditDelegate(event));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void injectLevelChunk(Object chunkSource, CEChunk ceChunk) {
|
||||
ChunkPos pos = ceChunk.chunkPos();
|
||||
Object levelChunk = FastNMS.INSTANCE.method$ServerChunkCache$getChunk(chunkSource, pos.x, pos.z, false);
|
||||
if (levelChunk != null) {
|
||||
Object[] sections = FastNMS.INSTANCE.method$ChunkAccess$getSections(levelChunk);
|
||||
CESection[] ceSections = ceChunk.sections();
|
||||
for (int i = 0; i < ceSections.length; i++) {
|
||||
CESection ceSection = ceSections[i];
|
||||
Object section = sections[i];
|
||||
int finalI = i;
|
||||
BukkitInjector.injectLevelChunkSection(section, ceSection, ceChunk, new SectionPos(pos.x, ceChunk.sectionY(i), pos.z),
|
||||
(injected) -> sections[finalI] = injected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setBlocks(final Set<BlockVector3> vset, final Pattern pattern) {
|
||||
this.processBlocks(vset, pattern);
|
||||
return super.setBlocks(vset, pattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setBlocks(final Region region, final Pattern pattern) {
|
||||
this.processBlocks(region, pattern);
|
||||
return super.setBlocks(region, pattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> int setBlocks(final Region region, final B block) {
|
||||
this.processBlocks(region, block);
|
||||
return super.setBlocks(region, block);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int replaceBlocks(Region region, Mask mask, Pattern pattern) {
|
||||
this.processBlocks(region, pattern);
|
||||
return super.replaceBlocks(region, mask, pattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> int replaceBlocks(final Region region, final Set<BaseBlock> filter, final B replacement) {
|
||||
this.processBlocks(region, replacement);
|
||||
return super.replaceBlocks(region, filter, replacement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int replaceBlocks(final Region region, final Set<BaseBlock> filter, final Pattern pattern) {
|
||||
this.processBlocks(region, pattern);
|
||||
return super.replaceBlocks(region, filter, pattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends BlockStateHolder<T>> boolean setBlock(int x, int y, int z, T block) {
|
||||
BaseBlock oldBlockState = getBlock(x, y, z).toBaseBlock();
|
||||
this.processBlock(x, y, z, block.toBaseBlock(), oldBlockState);
|
||||
return super.setBlock(x, y, z, block);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends BlockStateHolder<T>> boolean setBlock(BlockVector3 position, T block) {
|
||||
BaseBlock oldBlockState = getBlock(position).toBaseBlock();
|
||||
this.processBlock(position.x(), position.y(), position.z(), block.toBaseBlock(), oldBlockState);
|
||||
return super.setBlock(position, block);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Operation commit() {
|
||||
Operation operation = super.commit();
|
||||
saveAllChunks();
|
||||
List<ChunkPos> chunks = new ArrayList<>(this.brokenChunks);
|
||||
this.brokenChunks.clear();
|
||||
Object worldServer = this.ceWorld.world().serverWorld();
|
||||
Object chunkSource = FastNMS.INSTANCE.method$ServerLevel$getChunkSource(worldServer);
|
||||
for (ChunkPos chunk : chunks) {
|
||||
CEChunk loaded = this.ceWorld.getChunkAtIfLoaded(chunk.longKey());
|
||||
// only inject loaded chunks
|
||||
if (loaded == null) continue;
|
||||
injectLevelChunk(chunkSource, loaded);
|
||||
}
|
||||
return operation;
|
||||
}
|
||||
|
||||
private void processBlocks(Iterable<BlockVector3> region, Pattern pattern) {
|
||||
for (BlockVector3 position : region) {
|
||||
BaseBlock blockState = pattern.applyBlock(position);
|
||||
BaseBlock oldBlockState = getBlock(position).toBaseBlock();
|
||||
int blockX = position.x();
|
||||
int blockY = position.y();
|
||||
int blockZ = position.z();
|
||||
this.processBlock(blockX, blockY, blockZ, blockState, oldBlockState);
|
||||
}
|
||||
}
|
||||
|
||||
private void processBlock(int blockX, int blockY, int blockZ, BaseBlock newBlock, BaseBlock oldBlock) {
|
||||
int chunkX = blockX >> 4;
|
||||
int chunkZ = blockZ >> 4;
|
||||
int newStateId = ordinalToIbdID[newBlock.getOrdinal()];
|
||||
int oldStateId = ordinalToIbdID[oldBlock.getOrdinal()];
|
||||
this.brokenChunks.add(ChunkPos.of(chunkX, chunkZ));
|
||||
//CraftEngine.instance().debug(() -> "Processing block at " + blockX + ", " + blockY + ", " + blockZ + ": " + oldStateId + " -> " + newStateId);
|
||||
if (BlockStateUtils.isVanillaBlock(newStateId) && BlockStateUtils.isVanillaBlock(oldStateId)) return;
|
||||
try {
|
||||
CEChunk ceChunk = Optional.ofNullable(this.ceWorld.getChunkAtIfLoaded(chunkX, chunkZ))
|
||||
.orElse(this.ceWorld.worldDataStorage().readChunkAt(this.ceWorld, new ChunkPos(chunkX, chunkZ)));
|
||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(newStateId);
|
||||
if (immutableBlockState == null) {
|
||||
ceChunk.setBlockState(blockX, blockY, blockZ, EmptyBlock.STATE);
|
||||
} else {
|
||||
ceChunk.setBlockState(blockX, blockY, blockZ, immutableBlockState);
|
||||
}
|
||||
this.chunksToSave.add(ceChunk);
|
||||
} catch (IOException e) {
|
||||
CraftEngine.instance().logger().warn("Error when recording FastAsyncWorldEdit operation blocks", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void saveAllChunks() {
|
||||
try {
|
||||
for (CEChunk ceChunk : this.chunksToSave) {
|
||||
CraftEngine.instance().debug(() -> "Saving chunk " + ceChunk.chunkPos());
|
||||
this.ceWorld.worldDataStorage().writeChunkAt(ceChunk.chunkPos(), ceChunk);
|
||||
}
|
||||
this.chunksToSave.clear();
|
||||
} catch (IOException e) {
|
||||
CraftEngine.instance().logger().warn("Error when recording FastAsyncWorldEdit operation chunks", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,8 +30,12 @@ public class WorldEditBlockRegister {
|
||||
this.isFAWE = isFAWE;
|
||||
CEBlockParser blockParser = new CEBlockParser(WorldEdit.getInstance());
|
||||
WorldEdit.getInstance().getBlockFactory().register(blockParser);
|
||||
if (isFAWE) {
|
||||
FastAsyncWorldEditDelegate.init();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public void register(Key id) throws ReflectiveOperationException {
|
||||
BlockType blockType = new BlockType(id.toString(), blockState -> blockState);
|
||||
this.field$BlockType$blockMaterial.set(blockType, LazyReference.from(() -> new BukkitBlockRegistry.BukkitBlockMaterial(null, Material.STONE)));
|
||||
@@ -45,6 +49,7 @@ public class WorldEditBlockRegister {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public Stream<String> getSuggestions(String input) {
|
||||
Set<String> namespacesInUse = manager.namespacesInUse();
|
||||
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
package net.momirealms.craftengine.bukkit.util;
|
||||
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.attribute.AttributeInstance;
|
||||
import org.bukkit.entity.ArmorStand;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
public class LegacyAttributeUtils {
|
||||
|
||||
public static void setMaxHealth(ArmorStand entity) {
|
||||
Objects.requireNonNull(entity.getAttribute(Attribute.GENERIC_MAX_HEALTH)).setBaseValue(0.01);
|
||||
}
|
||||
|
||||
public static double getLuck(Player player) {
|
||||
return Optional.ofNullable(player.getAttribute(Attribute.GENERIC_LUCK)).map(AttributeInstance::getValue).orElse(1d);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ tasks {
|
||||
relocate("org.apache.commons.io", "net.momirealms.craftengine.libraries.commons.io")
|
||||
relocate("org.bstats", "net.momirealms.craftengine.libraries.bstats")
|
||||
relocate("com.github.benmanes.caffeine", "net.momirealms.craftengine.libraries.caffeine")
|
||||
relocate("net.objecthunter.exp4j", "net.momirealms.craftengine.libraries.exp4j")
|
||||
relocate("com.ezylang.evalex", "net.momirealms.craftengine.libraries.evalex")
|
||||
relocate("net.bytebuddy", "net.momirealms.craftengine.libraries.bytebuddy")
|
||||
relocate("org.yaml.snakeyaml", "net.momirealms.craftengine.libraries.snakeyaml")
|
||||
relocate("org.ahocorasick", "net.momirealms.craftengine.libraries.ahocorasick")
|
||||
|
||||
@@ -168,6 +168,13 @@ debug_target_block:
|
||||
- /craftengine debug target-block
|
||||
- /ce debug target-block
|
||||
|
||||
debug_is_section_injected:
|
||||
enable: true
|
||||
permission: ce.command.debug.is_section_injected
|
||||
usage:
|
||||
- /craftengine debug is-section-injected
|
||||
- /ce debug is-section-injected
|
||||
|
||||
debug_test:
|
||||
enable: true
|
||||
permission: ce.command.debug.test
|
||||
|
||||
@@ -78,6 +78,8 @@ resource-pack:
|
||||
ip: "localhost"
|
||||
port: 8163
|
||||
protocol: "http"
|
||||
# The optional URL must be complete and include a trailing slash / at the end.
|
||||
#url: "http://localhost:8163/"
|
||||
deny-non-minecraft-request: true
|
||||
one-time-token: true
|
||||
rate-limit:
|
||||
@@ -343,16 +345,24 @@ light-system:
|
||||
force-update-light: false
|
||||
|
||||
chunk-system:
|
||||
# Unloaded chunks may be loaded soon. Delaying serialization can improve performance, especially for those double-dimension mob farms.
|
||||
delay-serialization: 20 # seconds -1 = disable
|
||||
# With cache system, those frequently load/unload chunks would consume fewer resources on serialization
|
||||
# Enabling this option will increase memory consumption to a certain extent
|
||||
cache-system: true
|
||||
# 1 = NONE | Compression Speed | Decompress Speed | Compression Ratio | Memory Usage |
|
||||
# 2 = DEFLATE | Medium-Slow Medium Moderate Low |
|
||||
# 3 = GZIP | Medium-Slow Medium Moderate Low |
|
||||
# 4 = LZ4 | Blazing-Fast Blazing-Fast Low Low |
|
||||
# 5 = ZSTD | Medium-Fast Fast High Medium |
|
||||
compression-method: 4
|
||||
# This might not work for some server forks that modify how Minecraft saves chunks.
|
||||
fast-palette-injection: false
|
||||
# Settings for injection
|
||||
injection:
|
||||
# Requires a restart to apply
|
||||
# SECTION: Inject the LevelChunkSection (Faster & Experimental) since 0.0.53
|
||||
# PALETTE: Inject the PalettedContainer
|
||||
target: PALETTE
|
||||
# Enables faster injection method
|
||||
# Note: May not work with certain server forks that alter chunk class structure (In most cases it won't conflict)
|
||||
use-fast-method: false
|
||||
# Auto-convert custom blocks -> vanilla blocks when unloading chunks
|
||||
#
|
||||
# - When ENABLED (true):
|
||||
|
||||
@@ -32,4 +32,5 @@ lz4=${lz4_version}
|
||||
netty-codec-http2=${netty_version}
|
||||
reactive-streams=${reactive_streams_version}
|
||||
amazon-sdk-s3=${amazon_awssdk_version}
|
||||
amazon-sdk-eventstream=${amazon_awssdk_eventstream_version}
|
||||
amazon-sdk-eventstream=${amazon_awssdk_eventstream_version}
|
||||
evalex=${evalex_version}
|
||||
@@ -1,72 +0,0 @@
|
||||
# Stores something that has not been implemented yet
|
||||
|
||||
########################################################################################################################################################################################################################
|
||||
# If you want to create more doors, you can use doors of other materials, such as birch. You can only create one custom door from each vanilla door.
|
||||
# Oak Door
|
||||
minecraft:oak_door[facing=north,half=lower,hinge=right,open=false,powered=true]: minecraft:oak_door[facing=north,half=lower,hinge=right,open=false,powered=false]
|
||||
minecraft:oak_door[facing=south,half=lower,hinge=right,open=false,powered=true]: minecraft:oak_door[facing=south,half=lower,hinge=right,open=false,powered=false]
|
||||
minecraft:oak_door[facing=east,half=lower,hinge=right,open=false,powered=true]: minecraft:oak_door[facing=east,half=lower,hinge=right,open=false,powered=false]
|
||||
minecraft:oak_door[facing=west,half=lower,hinge=right,open=false,powered=true]: minecraft:oak_door[facing=west,half=lower,hinge=right,open=false,powered=false]
|
||||
minecraft:oak_door[facing=north,half=lower,hinge=right,open=true,powered=true]: minecraft:oak_door[facing=north,half=lower,hinge=right,open=true,powered=false]
|
||||
minecraft:oak_door[facing=south,half=lower,hinge=right,open=true,powered=true]: minecraft:oak_door[facing=south,half=lower,hinge=right,open=true,powered=false]
|
||||
minecraft:oak_door[facing=east,half=lower,hinge=right,open=true,powered=true]: minecraft:oak_door[facing=east,half=lower,hinge=right,open=true,powered=false]
|
||||
minecraft:oak_door[facing=west,half=lower,hinge=right,open=true,powered=true]: minecraft:oak_door[facing=west,half=lower,hinge=right,open=true,powered=false]
|
||||
minecraft:oak_door[facing=north,half=lower,hinge=left,open=false,powered=true]: minecraft:oak_door[facing=north,half=lower,hinge=left,open=false,powered=false]
|
||||
minecraft:oak_door[facing=south,half=lower,hinge=left,open=false,powered=true]: minecraft:oak_door[facing=south,half=lower,hinge=left,open=false,powered=false]
|
||||
minecraft:oak_door[facing=east,half=lower,hinge=left,open=false,powered=true]: minecraft:oak_door[facing=east,half=lower,hinge=left,open=false,powered=false]
|
||||
minecraft:oak_door[facing=west,half=lower,hinge=left,open=false,powered=true]: minecraft:oak_door[facing=west,half=lower,hinge=left,open=false,powered=false]
|
||||
minecraft:oak_door[facing=north,half=lower,hinge=left,open=true,powered=true]: minecraft:oak_door[facing=north,half=lower,hinge=left,open=true,powered=false]
|
||||
minecraft:oak_door[facing=south,half=lower,hinge=left,open=true,powered=true]: minecraft:oak_door[facing=south,half=lower,hinge=left,open=true,powered=false]
|
||||
minecraft:oak_door[facing=east,half=lower,hinge=left,open=true,powered=true]: minecraft:oak_door[facing=east,half=lower,hinge=left,open=true,powered=false]
|
||||
minecraft:oak_door[facing=west,half=lower,hinge=left,open=true,powered=true]: minecraft:oak_door[facing=west,half=lower,hinge=left,open=true,powered=false]
|
||||
minecraft:oak_door[facing=north,half=upper,hinge=right,open=false,powered=true]: minecraft:oak_door[facing=north,half=upper,hinge=right,open=false,powered=false]
|
||||
minecraft:oak_door[facing=south,half=upper,hinge=right,open=false,powered=true]: minecraft:oak_door[facing=south,half=upper,hinge=right,open=false,powered=false]
|
||||
minecraft:oak_door[facing=east,half=upper,hinge=right,open=false,powered=true]: minecraft:oak_door[facing=east,half=upper,hinge=right,open=false,powered=false]
|
||||
minecraft:oak_door[facing=west,half=upper,hinge=right,open=false,powered=true]: minecraft:oak_door[facing=west,half=upper,hinge=right,open=false,powered=false]
|
||||
minecraft:oak_door[facing=north,half=upper,hinge=right,open=true,powered=true]: minecraft:oak_door[facing=north,half=upper,hinge=right,open=true,powered=false]
|
||||
minecraft:oak_door[facing=south,half=upper,hinge=right,open=true,powered=true]: minecraft:oak_door[facing=south,half=upper,hinge=right,open=true,powered=false]
|
||||
minecraft:oak_door[facing=east,half=upper,hinge=right,open=true,powered=true]: minecraft:oak_door[facing=east,half=upper,hinge=right,open=true,powered=false]
|
||||
minecraft:oak_door[facing=west,half=upper,hinge=right,open=true,powered=true]: minecraft:oak_door[facing=west,half=upper,hinge=right,open=true,powered=false]
|
||||
minecraft:oak_door[facing=north,half=upper,hinge=left,open=false,powered=true]: minecraft:oak_door[facing=north,half=upper,hinge=left,open=false,powered=false]
|
||||
minecraft:oak_door[facing=south,half=upper,hinge=left,open=false,powered=true]: minecraft:oak_door[facing=south,half=upper,hinge=left,open=false,powered=false]
|
||||
minecraft:oak_door[facing=east,half=upper,hinge=left,open=false,powered=true]: minecraft:oak_door[facing=east,half=upper,hinge=left,open=false,powered=false]
|
||||
minecraft:oak_door[facing=west,half=upper,hinge=left,open=false,powered=true]: minecraft:oak_door[facing=west,half=upper,hinge=left,open=false,powered=false]
|
||||
minecraft:oak_door[facing=north,half=upper,hinge=left,open=true,powered=true]: minecraft:oak_door[facing=north,half=upper,hinge=left,open=true,powered=false]
|
||||
minecraft:oak_door[facing=south,half=upper,hinge=left,open=true,powered=true]: minecraft:oak_door[facing=south,half=upper,hinge=left,open=true,powered=false]
|
||||
minecraft:oak_door[facing=east,half=upper,hinge=left,open=true,powered=true]: minecraft:oak_door[facing=east,half=upper,hinge=left,open=true,powered=false]
|
||||
minecraft:oak_door[facing=west,half=upper,hinge=left,open=true,powered=true]: minecraft:oak_door[facing=west,half=upper,hinge=left,open=true,powered=false]
|
||||
# You can create more trapdoor if you don't care the facing.
|
||||
# Oak Trapdoor
|
||||
minecraft:oak_trapdoor[facing=north,open=false,powered=true,waterlogged=false]: minecraft:oak_trapdoor[facing=north,open=false,powered=false,waterlogged=false]
|
||||
minecraft:oak_trapdoor[facing=north,open=false,powered=true,waterlogged=true]: minecraft:oak_trapdoor[facing=north,open=false,powered=false,waterlogged=true]
|
||||
minecraft:oak_trapdoor[facing=north,open=true,powered=true,waterlogged=false]: minecraft:oak_trapdoor[facing=north,open=true,powered=false,waterlogged=false]
|
||||
minecraft:oak_trapdoor[facing=north,open=true,powered=true,waterlogged=true]: minecraft:oak_trapdoor[facing=north,open=true,powered=false,waterlogged=true]
|
||||
minecraft:oak_trapdoor[facing=south,open=false,powered=true,waterlogged=false]: minecraft:oak_trapdoor[facing=south,open=false,powered=false,waterlogged=false]
|
||||
minecraft:oak_trapdoor[facing=south,open=false,powered=true,waterlogged=true]: minecraft:oak_trapdoor[facing=south,open=false,powered=false,waterlogged=true]
|
||||
minecraft:oak_trapdoor[facing=south,open=true,powered=true,waterlogged=false]: minecraft:oak_trapdoor[facing=south,open=true,powered=false,waterlogged=false]
|
||||
minecraft:oak_trapdoor[facing=south,open=true,powered=true,waterlogged=true]: minecraft:oak_trapdoor[facing=south,open=true,powered=false,waterlogged=true]
|
||||
minecraft:oak_trapdoor[facing=east,open=false,powered=true,waterlogged=false]: minecraft:oak_trapdoor[facing=east,open=false,powered=false,waterlogged=false]
|
||||
minecraft:oak_trapdoor[facing=east,open=false,powered=true,waterlogged=true]: minecraft:oak_trapdoor[facing=east,open=false,powered=false,waterlogged=true]
|
||||
minecraft:oak_trapdoor[facing=east,open=true,powered=true,waterlogged=false]: minecraft:oak_trapdoor[facing=east,open=true,powered=false,waterlogged=false]
|
||||
minecraft:oak_trapdoor[facing=east,open=true,powered=true,waterlogged=true]: minecraft:oak_trapdoor[facing=east,open=true,powered=false,waterlogged=true]
|
||||
minecraft:oak_trapdoor[facing=west,open=false,powered=true,waterlogged=false]: minecraft:oak_trapdoor[facing=west,open=false,powered=false,waterlogged=false]
|
||||
minecraft:oak_trapdoor[facing=west,open=false,powered=true,waterlogged=true]: minecraft:oak_trapdoor[facing=west,open=false,powered=false,waterlogged=true]
|
||||
minecraft:oak_trapdoor[facing=west,open=true,powered=true,waterlogged=false]: minecraft:oak_trapdoor[facing=west,open=true,powered=false,waterlogged=false]
|
||||
minecraft:oak_trapdoor[facing=west,open=true,powered=true,waterlogged=true]: minecraft:oak_trapdoor[facing=west,open=true,powered=false,waterlogged=true]
|
||||
# fence_gate
|
||||
minecraft:oak_fence_gate[facing=north,open=false,powered=true,in_wall=false]: minecraft:oak_fence_gate[facing=north,open=false,powered=false,in_wall=false]
|
||||
minecraft:oak_fence_gate[facing=north,open=false,powered=true,in_wall=true]: minecraft:oak_fence_gate[facing=north,open=false,powered=false,in_wall=true]
|
||||
minecraft:oak_fence_gate[facing=north,open=true,powered=true,in_wall=false]: minecraft:oak_fence_gate[facing=north,open=true,powered=false,in_wall=false]
|
||||
minecraft:oak_fence_gate[facing=north,open=true,powered=true,in_wall=true]: minecraft:oak_fence_gate[facing=north,open=true,powered=false,in_wall=true]
|
||||
minecraft:oak_fence_gate[facing=south,open=false,powered=true,in_wall=false]: minecraft:oak_fence_gate[facing=south,open=false,powered=false,in_wall=false]
|
||||
minecraft:oak_fence_gate[facing=south,open=false,powered=true,in_wall=true]: minecraft:oak_fence_gate[facing=south,open=false,powered=false,in_wall=true]
|
||||
minecraft:oak_fence_gate[facing=south,open=true,powered=true,in_wall=false]: minecraft:oak_fence_gate[facing=south,open=true,powered=false,in_wall=false]
|
||||
minecraft:oak_fence_gate[facing=south,open=true,powered=true,in_wall=true]: minecraft:oak_fence_gate[facing=south,open=true,powered=false,in_wall=true]
|
||||
minecraft:oak_fence_gate[facing=east,open=false,powered=true,in_wall=false]: minecraft:oak_fence_gate[facing=east,open=false,powered=false,in_wall=false]
|
||||
minecraft:oak_fence_gate[facing=east,open=false,powered=true,in_wall=true]: minecraft:oak_fence_gate[facing=east,open=false,powered=false,in_wall=true]
|
||||
minecraft:oak_fence_gate[facing=east,open=true,powered=true,in_wall=false]: minecraft:oak_fence_gate[facing=east,open=true,powered=false,in_wall=false]
|
||||
minecraft:oak_fence_gate[facing=east,open=true,powered=true,in_wall=true]: minecraft:oak_fence_gate[facing=east,open=true,powered=false,in_wall=true]
|
||||
minecraft:oak_fence_gate[facing=west,open=false,powered=true,in_wall=false]: minecraft:oak_fence_gate[facing=west,open=false,powered=false,in_wall=false]
|
||||
minecraft:oak_fence_gate[facing=west,open=false,powered=true,in_wall=true]: minecraft:oak_fence_gate[facing=west,open=false,powered=false,in_wall=true]
|
||||
minecraft:oak_fence_gate[facing=west,open=true,powered=true,in_wall=false]: minecraft:oak_fence_gate[facing=west,open=true,powered=false,in_wall=false]
|
||||
minecraft:oak_fence_gate[facing=west,open=true,powered=true,in_wall=true]: minecraft:oak_fence_gate[facing=west,open=true,powered=false,in_wall=true]
|
||||
@@ -1,7 +1,6 @@
|
||||
# Don't change this
|
||||
lang-version: "${lang_version}"
|
||||
|
||||
# Commands
|
||||
exception.invalid_syntax: "<red>Invalid syntax. Correct syntax: <white><arg:0></white></red>"
|
||||
exception.invalid_argument: "<red>Invalid argument. Reason: <white><arg:0></white></red>"
|
||||
exception.invalid_sender: "<red><arg:0> is not allowed to execute that command. Must be of type <arg:1></red>"
|
||||
@@ -70,6 +69,27 @@ warning.config.type.float: "<yellow>Issue found in file <arg:0> - Failed to load
|
||||
warning.config.type.double: "<yellow>Issue found in file <arg:0> - Failed to load '<arg:1>': Cannot cast '<arg:2>' to double type for option '<arg:3>'.</yellow>"
|
||||
warning.config.type.quaternionf: "<yellow>Issue found in file <arg:0> - Failed to load '<arg:1>': Cannot cast '<arg:2>' to Quaternionf type for option '<arg:3>'.</yellow>"
|
||||
warning.config.type.vector3f: "<yellow>Issue found in file <arg:0> - Failed to load '<arg:1>': Cannot cast '<arg:2>' to Vector3f type for option '<arg:3>'.</yellow>"
|
||||
warning.config.number.missing_type: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'type' argument for number argument.</yellow>"
|
||||
warning.config.number.invalid_type: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is using an invalid number argument type '<arg:2>'.</yellow>"
|
||||
warning.config.number.missing_argument: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the argument for 'number'.</yellow>"
|
||||
warning.config.number.invalid_format: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is using an invalid number format '<arg:2>'.</yellow>"
|
||||
warning.config.number.fixed.missing_value: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'value' argument for 'constant' number.</yellow>"
|
||||
warning.config.number.fixed.invalid_value: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is using the invalid 'value' argument '<arg:2>' for 'constant' number.</yellow>"
|
||||
warning.config.number.expression.missing_expression: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'expression' argument for 'expression' number.</yellow>"
|
||||
warning.config.number.uniform.missing_min: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'min' argument for 'uniform' number.</yellow>"
|
||||
warning.config.number.uniform.missing_max: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'max' argument for 'uniform' number.</yellow>"
|
||||
warning.config.condition.all_of.missing_terms: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'terms' argument for 'all_of' condition.</yellow>"
|
||||
warning.config.condition.all_of.invalid_terms_type: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' has a misconfigured 'all_of' condition, 'terms' should be a map list, current type: '<arg:2>'.</yellow>"
|
||||
warning.config.condition.any_of.missing_terms: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'terms' argument for 'any_of' condition.</yellow>"
|
||||
warning.config.condition.any_of.invalid_terms_type: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' has a misconfigured 'any_of' condition, 'terms' should be a map list, current type: '<arg:2>'.</yellow>"
|
||||
warning.config.condition.inverted.missing_term: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'term' argument for 'inverted' condition.</yellow>"
|
||||
warning.config.condition.inverted.invalid_term_type: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' has a misconfigured 'inverted' condition, 'term' should be a config section, current type: '<arg:2>'.</yellow>"
|
||||
warning.config.condition.enchantment.missing_predicate: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'predicate' argument for 'enchantment' condition.</yellow>"
|
||||
warning.config.condition.enchantment.invalid_predicate: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is using an invalid enchantment 'predicate' argument '<arg:2>'.</yellow>"
|
||||
warning.config.condition.match_block_property.missing_properties: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'properties' argument for 'match_block_property' condition.</yellow>"
|
||||
warning.config.condition.match_item.missing_id: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'id' argument for 'match_item' condition.</yellow>"
|
||||
warning.config.condition.table_bonus.missing_enchantment: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'enchantment' argument for 'table_bonus' condition.</yellow>"
|
||||
warning.config.condition.table_bonus.missing_chances: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'chances' argument for 'table_bonus' condition.</yellow>"
|
||||
warning.config.structure.not_section: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is expected to be a config section while it's actually a(n) '<arg:2>'.</yellow>"
|
||||
warning.config.image.duplicate: "<yellow>Issue found in file <arg:0> - Duplicated image '<arg:1>'. Please check if there is the same configuration in other files.</yellow>"
|
||||
warning.config.image.missing_height: "<yellow>Issue found in file <arg:0> - The image '<arg:1>' is missing the required 'height' argument.</yellow>"
|
||||
@@ -80,6 +100,7 @@ warning.config.image.invalid_font_chars: "<yellow>Issue found in file <arg:0> -
|
||||
warning.config.image.missing_char: "<yellow>Issue found in file <arg:0> - The image '<arg:1>' is missing the required 'char' argument.</yellow>"
|
||||
warning.config.image.codepoint_conflict: "<yellow>Issue found in file <arg:0> - The image '<arg:1>' is using a character '<arg:3>(<arg:4>)' in font <arg:2> that has been used by another image '<arg:5>'.</yellow>"
|
||||
warning.config.image.invalid_codepoint_grid: "<yellow>Issue found in file <arg:0> - Image '<arg:1>' has an invalid 'chars' codepoint grid.</yellow>"
|
||||
warning.config.image.invalid_char: "<yellow>Issue found in file <arg:0> - Image '<arg:1>' has a char parameter containing combining characters, which may result in image splitting.</yellow>"
|
||||
warning.config.image.file_not_found: "<yellow>Issue found in file <arg:0> - PNG file '<arg:2>' not found for image '<arg:1>'.</yellow>"
|
||||
warning.config.image.invalid_hex_value: "<yellow>Issue found in file <arg:0> - The image '<arg:1>' is using a unicode character '<arg:2>' that is not a valid hexadecimal (radix 16) value.</yellow>"
|
||||
warning.config.recipe.duplicate: "<yellow>Issue found in file <arg:0> - Duplicated recipe '<arg:1>'. Please check if there is the same configuration in other files.</yellow>"
|
||||
@@ -202,6 +223,8 @@ warning.config.block.behavior.leaves.missing_distance: "<yellow>Issue found in f
|
||||
warning.config.block.behavior.sapling.missing_stage: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'stage' property for 'sapling_block' behavior.</yellow>"
|
||||
warning.config.block.behavior.sapling.missing_feature: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'feature' argument for 'sapling_block' behavior.</yellow>"
|
||||
warning.config.block.behavior.strippable.missing_stripped: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'stripped' argument for 'strippable_block' behavior.</yellow>"
|
||||
warning.config.block.event.condition.missing_type: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'type' argument for event condition.</yellow>"
|
||||
warning.config.block.event.condition.invalid_type: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is using an invalid 'type' argument '<arg:2>' for event condition.</yellow>"
|
||||
warning.config.model.generation.missing_parent: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'parent' argument in 'generation' section.</yellow>"
|
||||
warning.config.model.generation.conflict: "<yellow>Issue found in file <arg:0> - Failed to generate model for '<arg:1>' as two or more configurations attempt to generate different json models with the same path: '<arg:2>'.</yellow>"
|
||||
warning.config.model.generation.texture.invalid: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' has a texture '<arg:2>' with path '<arg:3>' that contains illegal characters. Please read https://minecraft.wiki/w/Resource_location#Legal_characters.</yellow>"
|
||||
@@ -227,10 +250,6 @@ warning.config.loot_table.entry.exp.missing_count: "<yellow>Issue found in file
|
||||
warning.config.loot_table.entry.item.missing_item: "<yellow>Issue found in file <arg:0> - '<arg:1>' has a misconfigured loot table, entry 'item' is missing the required 'item' argument.</yellow>"
|
||||
warning.config.loot_table.condition.missing_type: "<yellow>Issue found in file <arg:0> - '<arg:1>' has a misconfigured loot table, one of the conditions is missing the required 'type' argument.</yellow>"
|
||||
warning.config.loot_table.condition.invalid_type: "<yellow>Issue found in file <arg:0> - '<arg:1>' has a misconfigured loot table, one of the conditions is using an invalid condition type '<arg:2>'.</yellow>"
|
||||
warning.config.loot_table.condition.table_bonus.missing_enchantment: "<yellow>Issue found in file <arg:0> - '<arg:1>' has a misconfigured loot table, 'table_bonus' condition is missing the required 'enchantment' argument.</yellow>"
|
||||
warning.config.loot_table.condition.table_bonus.missing_chances: "<yellow>Issue found in file <arg:0> - '<arg:1>' has a misconfigured loot table, 'table_bonus' condition is missing the required 'chances' argument.</yellow>"
|
||||
warning.config.loot_table.number.missing_type: "<yellow>Issue found in file <arg:0> - '<arg:1>' has a misconfigured loot table, one of the numbers is missing the required 'type' argument.</yellow>"
|
||||
warning.config.loot_table.number.invalid_type: "<yellow>Issue found in file <arg:0> - '<arg:1>' has a misconfigured loot table, one of the numbers is using an invalid number type '<arg:2>'.</yellow>"
|
||||
warning.config.host.missing_type: "<yellow>Issue found in config.yml at 'resource-pack.delivery.hosting' - Missing required 'type' argument for host.</yellow>"
|
||||
warning.config.host.invalid_type: "<yellow>Issue found in config.yml at 'resource-pack.delivery.hosting' - Host type '<arg:0>' is invalid. Please read https://mo-mi.gitbook.io/xiaomomi-plugins/craftengine/plugin-wiki/craftengine/resource-pack/host.</yellow>"
|
||||
warning.config.host.external.missing_url: "<yellow>Issue found in config.yml at 'resource-pack.delivery.hosting' - Missing required 'url' argument for external host.</yellow>"
|
||||
@@ -254,6 +273,7 @@ warning.config.host.s3.missing_secret: "<yellow>Issue found in config.yml at 're
|
||||
warning.config.host.s3.missing_upload_path: "<yellow>Issue found in config.yml at 'resource-pack.delivery.hosting' - Missing required 'upload-path' argument for s3 host.</yellow>"
|
||||
warning.config.host.self.missing_ip: "<yellow>Issue found in config.yml at 'resource-pack.delivery.hosting' - Missing required 'ip' argument for self host.</yellow>"
|
||||
warning.config.host.self.invalid_port: "<yellow>Issue found in config.yml at 'resource-pack.delivery.hosting' - Invalid port '<arg:0>' for self host.</yellow>"
|
||||
warning.config.host.self.invalid_url: "<yellow>Issue found in config.yml at 'resource-pack.delivery.hosting' - Invalid url '<arg:0>' for self host.</yellow>"
|
||||
warning.config.host.gitlab.missing_url: "<yellow>Issue found in config.yml at 'resource-pack.delivery.hosting' - Missing required 'gitlab-url' argument for gitlab host.</yellow>"
|
||||
warning.config.host.gitlab.missing_token: "<yellow>Issue found in config.yml at 'resource-pack.delivery.hosting' - Missing required 'access-token' argument for gitlab host.</yellow>"
|
||||
warning.config.host.gitlab.missing_project: "<yellow>Issue found in config.yml at 'resource-pack.delivery.hosting' - Missing required 'project-id' argument for gitlab host.</yellow>"
|
||||
@@ -273,4 +293,5 @@ warning.config.conflict_matcher.inverted.missing_term: "<yellow>Issue found in c
|
||||
warning.config.conflict_matcher.all_of.missing_terms: "<yellow>Issue found in config.yml at 'resource-pack.duplicated-files-handler' - Missing required 'terms' argument for 'all_of' matcher.</yellow>"
|
||||
warning.config.conflict_matcher.any_of.missing_terms: "<yellow>Issue found in config.yml at 'resource-pack.duplicated-files-handler' - Missing required 'terms' argument for 'any_of' matcher.</yellow>"
|
||||
warning.config.conflict_resolution.missing_type: "<yellow>Issue found in config.yml at 'resource-pack.duplicated-files-handler' - Missing required 'type' argument for one of the resolutions.</yellow>"
|
||||
warning.config.conflict_resolution.invalid_type: "<yellow>Issue found in config.yml at 'resource-pack.duplicated-files-handler' - One of the resolutions is using the invalid type '<arg:0>'.</yellow>"
|
||||
warning.config.conflict_resolution.invalid_type: "<yellow>Issue found in config.yml at 'resource-pack.duplicated-files-handler' - One of the resolutions is using the invalid type '<arg:0>'.</yellow>"
|
||||
warning.config.function.command.missing_command: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'command' argument for 'command' function.</yellow>"
|
||||
@@ -1,6 +1,6 @@
|
||||
# Don't change this
|
||||
lang-version: "${lang_version}"
|
||||
# Commands
|
||||
|
||||
exception.invalid_syntax: "<red>Geçersiz sözdizimi. Doğru kullanım: <white><arg:0></white></red>"
|
||||
exception.invalid_argument: "<red>Geçersiz argüman. Neden: <white><arg:0></white></red>"
|
||||
exception.invalid_sender: "<red><arg:0> bu komutu çalıştırmaya yetkili değil. <arg:1> türünde olmalı</red>"
|
||||
@@ -226,10 +226,6 @@ warning.config.loot_table.entry.exp.missing_count: "<yellow><arg:0> dosyasında
|
||||
warning.config.loot_table.entry.item.missing_item: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>', yanlış yapılandırılmış bir ganimet tablosuna sahip, 'item' girişi için gerekli 'item' argümanı eksik.</yellow>"
|
||||
warning.config.loot_table.condition.missing_type: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>', yanlış yapılandırılmış bir ganimet tablosuna sahip, koşullardan biri için gerekli 'type' argümanı eksik.</yellow>"
|
||||
warning.config.loot_table.condition.invalid_type: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>', yanlış yapılandırılmış bir ganimet tablosuna sahip, koşullardan biri geçersiz bir koşul türü '<arg:2>' kullanıyor.</yellow>"
|
||||
warning.config.loot_table.condition.table_bonus.missing_enchantment: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>', yanlış yapılandırılmış bir ganimet tablosuna sahip, 'table_bonus' koşulu için gerekli 'enchantment' argümanı eksik.</yellow>"
|
||||
warning.config.loot_table.condition.table_bonus.missing_chances: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>', yanlış yapılandırılmış bir ganimet tablosuna sahip, 'table_bonus' koşulu için gerekli 'chances' argümanı eksik.</yellow>"
|
||||
warning.config.loot_table.number.missing_type: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>', yanlış yapılandırılmış bir ganimet tablosuna sahip, sayılardan biri için gerekli 'type' argümanı eksik.</yellow>"
|
||||
warning.config.loot_table.number.invalid_type: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>', yanlış yapılandırılmış bir ganimet tablosuna sahip, sayılardan biri geçersiz bir sayı türü '<arg:2>' kullanıyor.</yellow>"
|
||||
warning.config.host.missing_type: "<yellow>config.yml dosyasında 'resource-pack.delivery.hosting' bölümünde sorun bulundu - Host için gerekli 'type' argümanı eksik.</yellow>"
|
||||
warning.config.host.invalid_type: "<yellow>config.yml dosyasında 'resource-pack.delivery.hosting' bölümünde sorun bulundu - Host türü '<arg:0>' geçersiz. Lütfen https://mo-mi.gitbook.io/xiaomomi-plugins/craftengine/plugin-wiki/craftengine/resource-pack/host sayfasını okuyun.</yellow>"
|
||||
warning.config.host.external.missing_url: "<yellow>config.yml dosyasında 'resource-pack.delivery.hosting' bölümünde sorun bulundu - Harici host için gerekli 'url' argümanı eksik.</yellow>"
|
||||
@@ -272,4 +268,4 @@ warning.config.conflict_matcher.inverted.missing_term: "<yellow>config.yml dosya
|
||||
warning.config.conflict_matcher.all_of.missing_terms: "<yellow>config.yml dosyasında 'resource-pack.duplicated-files-handler' bölümünde sorun bulundu - 'all_of' eşleştiricisi için gerekli 'terms' argümanı eksik.</yellow>"
|
||||
warning.config.conflict_matcher.any_of.missing_terms: "<yellow>config.yml dosyasında 'resource-pack.duplicated-files-handler' bölümünde sorun bulundu - 'any_of' eşleştiricisi için gerekli 'terms' argümanı eksik.</yellow>"
|
||||
warning.config.conflict_resolution.missing_type: "<yellow>config.yml dosyasında 'resource-pack.duplicated-files-handler' bölümünde sorun bulundu - Çözümlerden biri için gerekli 'type' argümanı eksik.</yellow>"
|
||||
warning.config.conflict_resolution.invalid_type: "<yellow>config.yml dosyasında 'resource-pack.duplicated-files-handler' bölümünde sorun bulundu - Çözümlerden biri geçersiz bir tür '<arg:0>' kullanıyor.</yellow>"
|
||||
warning.config.conflict_resolution.invalid_type: "<yellow>config.yml dosyasında 'resource-pack.duplicated-files-handler' bölümünde sorun bulundu - Çözümlerden biri geçersiz bir tür '<arg:0>' kullanıyor.</yellow>"
|
||||
@@ -1,7 +1,6 @@
|
||||
# 别动这个
|
||||
lang-version: "${lang_version}"
|
||||
|
||||
# 命令
|
||||
exception.invalid_syntax: "<red>无效语法. 正确语法: <white><arg:0></white></red>"
|
||||
exception.invalid_argument: "<red>无效参数. 原因: <white><arg:0></white></red>"
|
||||
exception.invalid_sender: "<red><arg:0> 不允许执行该命令. 执行者必须是 <arg:1></red>"
|
||||
@@ -40,11 +39,11 @@ argument.parse.failure.aggregate.failure: "<red>无效的组件 '<arg:0>': <arg:
|
||||
argument.parse.failure.either: "<red>无法从 '<arg:0>' 解析 <arg:1> 或 <arg:2></red>"
|
||||
argument.parse.failure.namedtextcolor: "<red>'<arg:0>' 不是颜色代码</red>"
|
||||
command.reload.config.success: "<white>重新加载配置完成. 耗时 <green><arg:0></green> 毫秒</white> <gray>(异步: <arg:1>ms | 同步: <arg:2>ms)</gray>"
|
||||
command.reload.config.failure: "<red>重新加载配置失败,请检查控制台日志</red>"
|
||||
command.reload.config.failure: "<red>重新加载配置失败, 请检查控制台日志</red>"
|
||||
command.reload.pack.success: "<white>资源包重新加载完成. 耗时 <green><arg:0></green> 毫秒</white>"
|
||||
command.reload.pack.failure: "<red>重新加载资源包失败,请检查控制台日志</red>"
|
||||
command.reload.pack.failure: "<red>重新加载资源包失败, 请检查控制台日志</red>"
|
||||
command.reload.all.success: "<white>全部重新加载完成. 耗时 <green><arg:0></green> 毫秒</white> <gray>(异步: <arg:1>ms | 同步: <arg:2>ms | 资源包: <arg:3>ms)</gray>"
|
||||
command.reload.all.failure: "<red>重新加载失败,请检查控制台日志</red>"
|
||||
command.reload.all.failure: "<red>重新加载失败, 请检查控制台日志</red>"
|
||||
command.item.get.success: "<white>获得<arg:0>个<arg:1></white>"
|
||||
command.item.get.failure.not_exist: "<red><lang:argument.item.id.invalid:'<arg:0>'></red>"
|
||||
command.item.give.success.single: "<lang:commands.give.success.single:'<arg:0>':'<arg:1>':'<arg:2>'>"
|
||||
@@ -70,6 +69,27 @@ warning.config.type.float: "<yellow>在文件 <arg:0> 发现问题 - 无法加
|
||||
warning.config.type.double: "<yellow>在文件 <arg:0> 发现问题 - 无法加载 '<arg:1>': 无法将 '<arg:2>' 转换为双精度类型 (选项 '<arg:3>')</yellow>"
|
||||
warning.config.type.quaternionf: "<yellow>在文件 <arg:0> 发现问题 - 无法加载 '<arg:1>': 无法将 '<arg:2>' 转换为四元数类型 (选项 '<arg:3>')</yellow>"
|
||||
warning.config.type.vector3f: "<yellow>在文件 <arg:0> 发现问题 - 无法加载 '<arg:1>': 无法将 '<arg:2>' 转换为三维向量类型 (选项 '<arg:3>')</yellow>"
|
||||
warning.config.number.missing_type: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 缺少数字类型所需的 'type' 参数</yellow>"
|
||||
warning.config.number.invalid_type: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 使用了无效的数字类型 '<arg:2>'</yellow>"
|
||||
warning.config.number.missing_argument: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 缺少数字参数</yellow>"
|
||||
warning.config.number.invalid_format: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 使用了无效的数字格式 '<arg:2>'</yellow>"
|
||||
warning.config.number.fixed.missing_value: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 缺少 'constant' 数字类型所需的 'value' 参数</yellow>"
|
||||
warning.config.number.fixed.invalid_value: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 使用了无效的常量值参数 '<arg:2>'</yellow>"
|
||||
warning.config.number.expression.missing_expression: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 缺少 'expression' 数字类型所需的 'expression' 参数</yellow>"
|
||||
warning.config.number.uniform.missing_min: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 缺少 'uniform' 数字类型所需的 'min' 参数</yellow>"
|
||||
warning.config.number.uniform.missing_max: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 缺少 'uniform' 数字类型所需的 'max' 参数</yellow>"
|
||||
warning.config.condition.all_of.missing_terms: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 缺少 'all_of' 条件所需的 'terms' 参数</yellow>"
|
||||
warning.config.condition.all_of.invalid_terms_type: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 的 'all_of' 条件配置错误, 'terms' 应为映射列表, 当前类型: '<arg:2>'</yellow>"
|
||||
warning.config.condition.any_of.missing_terms: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 缺少 'any_of' 条件所需的 'terms' 参数</yellow>"
|
||||
warning.config.condition.any_of.invalid_terms_type: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 的 'any_of' 条件配置错误, 'terms' 应为映射列表, 当前类型: '<arg:2>'</yellow>"
|
||||
warning.config.condition.inverted.missing_term: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 缺少 'inverted' 条件所需的 'term' 参数</yellow>"
|
||||
warning.config.condition.inverted.invalid_term_type: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 的 'inverted' 条件配置错误, 'term' 应为配置节点, 当前类型: '<arg:2>'</yellow>"
|
||||
warning.config.condition.enchantment.missing_predicate: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 缺少 'enchantment' 条件所需的 'predicate' 参数</yellow>"
|
||||
warning.config.condition.enchantment.invalid_predicate: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 使用了无效的附魔 'predicate' 参数 '<arg:2>'</yellow>"
|
||||
warning.config.condition.match_block_property.missing_properties: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 缺少 'match_block_property' 条件所需的 'properties' 参数</yellow>"
|
||||
warning.config.condition.match_item.missing_id: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 缺少 'match_item' 条件所需的 'id' 参数</yellow>"
|
||||
warning.config.condition.table_bonus.missing_enchantment: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 缺少 'table_bonus' 条件所需的 'enchantment' 参数</yellow>"
|
||||
warning.config.condition.table_bonus.missing_chances: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 缺少 'table_bonus' 条件所需的 'chances' 参数</yellow>"
|
||||
warning.config.structure.not_section: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 应为配置段落 但实际类型为 '<arg:2>'</yellow>"
|
||||
warning.config.image.duplicate: "<yellow>在文件 <arg:0> 发现问题 - 重复的图片配置 '<arg:1>' 请检查其他文件中是否存在相同配置</yellow>"
|
||||
warning.config.image.missing_height: "<yellow>在文件 <arg:0> 发现问题 - 图片 '<arg:1>' 缺少必需的 'height' 参数</yellow>"
|
||||
@@ -80,6 +100,7 @@ warning.config.image.invalid_font_chars: "<yellow>在文件 <arg:0> 发现问题
|
||||
warning.config.image.missing_char: "<yellow>在文件 <arg:0> 发现问题 - 图片 '<arg:1>' 缺少必需的 'char' 参数</yellow>"
|
||||
warning.config.image.codepoint_conflict: "<yellow>在文件 <arg:0> 发现问题 - 图片 '<arg:1>' 在字体 <arg:2> 中使用的字符 '<arg:3>(<arg:4>)' 已被其他图片 '<arg:5>' 占用</yellow>"
|
||||
warning.config.image.invalid_codepoint_grid: "<yellow>在文件 <arg:0> 发现问题 - 图片 '<arg:1>' 的 'chars' 码位网格无效</yellow>"
|
||||
warning.config.image.invalid_char: "<yellow>在文件 <arg:0> 发现问题 - 图片 '<arg:1>' 的 'char' 参数包含组合字符可能导致图片分裂</yellow>"
|
||||
warning.config.image.file_not_found: "<yellow>在文件 <arg:0> 发现问题 - 图片 '<arg:1>' 的 PNG 文件 '<arg:2>' 未找到</yellow>"
|
||||
warning.config.image.invalid_hex_value: "<yellow>在文件 <arg:0> 发现问题 - 图片 '<arg:1>' 使用的 Unicode 字符 '<arg:2>' 不是有效的十六进制值</yellow>"
|
||||
warning.config.recipe.duplicate: "<yellow>在文件 <arg:0> 发现问题 - 重复的配方 '<arg:1>' 请检查其他文件中是否存在相同配置</yellow>"
|
||||
@@ -202,6 +223,8 @@ warning.config.block.behavior.leaves.missing_distance: "<yellow>在文件 <arg:0
|
||||
warning.config.block.behavior.sapling.missing_stage: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'sapling_block' 行为缺少必需的 'stage' 属性</yellow>"
|
||||
warning.config.block.behavior.sapling.missing_feature: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'sapling_block' 行为缺少必需的 'feature' 参数</yellow>"
|
||||
warning.config.block.behavior.strippable.missing_stripped: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'strippable_block' 行为缺少必需的 'stripped' 参数</yellow>"
|
||||
warning.config.block.event.condition.missing_type: "<yellow>在文件 <arg:0> - 方块 '<arg:1>' 的事件条件缺少 'type' 参数</yellow>"
|
||||
warning.config.block.event.condition.invalid_type: "<yellow>在文件 <arg:0> - 方块 '<arg:1>' 使用了无效的事件条件类型 '<arg:2>'</yellow>"
|
||||
warning.config.model.generation.missing_parent: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 的 'generation' 段落缺少必需的 'parent' 参数</yellow>"
|
||||
warning.config.model.generation.conflict: "<yellow>在文件 <arg:0> 发现问题 - 无法为 '<arg:1>' 生成模型 存在多个配置尝试使用相同路径 '<arg:2>' 生成不同的 JSON 模型</yellow>"
|
||||
warning.config.model.generation.texture.invalid: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 的纹理 '<arg:2>' 路径 '<arg:3>' 包含非法字符 请参考 https://zh.minecraft.wiki/w/%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4ID#%E5%90%88%E6%B3%95%E5%AD%97%E7%AC%A6</yellow>"
|
||||
@@ -227,10 +250,6 @@ warning.config.loot_table.entry.exp.missing_count: "<yellow>在文件 <arg:0>
|
||||
warning.config.loot_table.entry.item.missing_item: "<yellow>在文件 <arg:0> 发现问题 - '<arg:1>' 的战利品表配置错误 'item' 条目缺少必需的 'item' 参数</yellow>"
|
||||
warning.config.loot_table.condition.missing_type: "<yellow>在文件 <arg:0> 发现问题 - '<arg:1>' 的战利品表配置错误 某个条件缺少必需的 'type' 参数</yellow>"
|
||||
warning.config.loot_table.condition.invalid_type: "<yellow>在文件 <arg:0> 发现问题 - '<arg:1>' 的战利品表配置错误 某个条件使用了无效的条件类型 '<arg:2>'</yellow>"
|
||||
warning.config.loot_table.condition.table_bonus.missing_enchantment: "<yellow>在文件 <arg:0> 发现问题 - '<arg:1>' 的战利品表配置错误 'table_bonus' 条件缺少必需的 'enchantment' 参数</yellow>"
|
||||
warning.config.loot_table.condition.table_bonus.missing_chances: "<yellow>在文件 <arg:0> 发现问题 - '<arg:1>' 的战利品表配置错误 'table_bonus' 条件缺少必需的 'chances' 参数</yellow>"
|
||||
warning.config.loot_table.number.missing_type: "<yellow>在文件 <arg:0> 发现问题 - '<arg:1>' 的战利品表配置错误 某个数值缺少必需的 'type' 参数</yellow>"
|
||||
warning.config.loot_table.number.invalid_type: "<yellow>在文件 <arg:0> 发现问题 - '<arg:1>' 的战利品表配置错误 某个数值使用了无效的数值类型 '<arg:2>'</yellow>"
|
||||
warning.config.host.missing_type: "<yellow>在 config.yml 的 'resource-pack.delivery.hosting' 处发现问题 - 缺少必需的 'type' 参数</yellow>"
|
||||
warning.config.host.invalid_type: "<yellow>在 config.yml 的 'resource-pack.delivery.hosting' 处发现问题 - 无效的托管类型 '' 请参考 https://mo-mi.gitbook.io/xiaomomi-plugins/craftengine/plugin-wiki/craftengine/resource-pack/host</yellow>"
|
||||
warning.config.host.external.missing_url: "<yellow>在 config.yml 的 'resource-pack.delivery.hosting' 处发现问题 - 外部托管缺少必需的 'url' 参数</yellow>"
|
||||
@@ -254,6 +273,7 @@ warning.config.host.s3.missing_secret: "<yellow>在 config.yml 的 'resource-pac
|
||||
warning.config.host.s3.missing_upload_path: "<yellow>在 config.yml 的 'resource-pack.delivery.hosting' 处发现问题 - S3 托管缺少必需的 'upload-path' 参数</yellow>"
|
||||
warning.config.host.self.missing_ip: "<yellow>在 config.yml 的 'resource-pack.delivery.hosting' 处发现问题 - 自托管托管缺少必需的 'ip' 参数</yellow>"
|
||||
warning.config.host.self.invalid_port: "<yellow>在 config.yml 的 'resource-pack.delivery.hosting' 处发现问题 - 自托管托管的端口 '<arg:0>' 无效</yellow>"
|
||||
warning.config.host.self.invalid_url: "<yellow>在 config.yml 的 'resource-pack.delivery.hosting' 处发现问题 - 自托管托管的 URL '<arg:0>' 无效</yellow>"
|
||||
warning.config.host.gitlab.missing_url: "<yellow>在 config.yml 的 'resource-pack.delivery.hosting' 处发现问题 - GitLab 托管缺少必需的 'gitlab-url' 参数</yellow>"
|
||||
warning.config.host.gitlab.missing_token: "<yellow>在 config.yml 的 'resource-pack.delivery.hosting' 处发现问题 - GitLab 托管缺少必需的 'access-token' 参数</yellow>"
|
||||
warning.config.host.gitlab.missing_project: "<yellow>在 config.yml 的 'resource-pack.delivery.hosting' 处发现问题 - GitLab 托管缺少必需的 'project-id' 参数</yellow>"
|
||||
|
||||
@@ -3,8 +3,8 @@ package net.momirealms.craftengine.bukkit.api;
|
||||
import net.momirealms.craftengine.bukkit.entity.BukkitEntity;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitBlockInWorld;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorld;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorldBlock;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Entity;
|
||||
@@ -26,7 +26,7 @@ public final class BukkitAdaptors {
|
||||
return new BukkitEntity(entity);
|
||||
}
|
||||
|
||||
public static BukkitWorldBlock adapt(final Block block) {
|
||||
return new BukkitWorldBlock(block);
|
||||
public static BukkitBlockInWorld adapt(final Block block) {
|
||||
return new BukkitBlockInWorld(block);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,11 +10,10 @@ import net.momirealms.craftengine.bukkit.world.BukkitWorld;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.UpdateOption;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.loot.parameter.LootParameters;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.CommonParameters;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import net.momirealms.craftengine.core.world.WorldEvents;
|
||||
@@ -172,13 +171,13 @@ public final class CraftEngineBlocks {
|
||||
Location location = block.getLocation();
|
||||
Vec3d vec3d = new Vec3d(location.getBlockX() + 0.5, location.getBlockY() + 0.5, location.getBlockZ() + 0.5);
|
||||
if (dropLoot) {
|
||||
ContextHolder.Builder builder = new ContextHolder.Builder().withParameter(LootParameters.WORLD, world).withParameter(LootParameters.LOCATION, vec3d);
|
||||
ContextHolder.Builder builder = new ContextHolder.Builder().withParameter(CommonParameters.WORLD, world).withParameter(CommonParameters.LOCATION, vec3d);
|
||||
BukkitServerPlayer serverPlayer = BukkitCraftEngine.instance().adapt(player);
|
||||
if (player != null) {
|
||||
builder.withParameter(LootParameters.PLAYER, serverPlayer);
|
||||
builder.withOptionalParameter(LootParameters.TOOL, serverPlayer.getItemInHand(InteractionHand.MAIN_HAND));
|
||||
builder.withParameter(CommonParameters.PLAYER, serverPlayer);
|
||||
//mark item builder.withOptionalParameter(CommonParameters.MAIN_HAND_ITEM, serverPlayer.getItemInHand(InteractionHand.MAIN_HAND));
|
||||
}
|
||||
for (Item<?> item : state.getDrops(builder, world)) {
|
||||
for (Item<?> item : state.getDrops(builder, world, serverPlayer)) {
|
||||
world.dropItemNaturally(vec3d, item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,12 +9,11 @@ import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorld;
|
||||
import net.momirealms.craftengine.core.entity.furniture.AnchorType;
|
||||
import net.momirealms.craftengine.core.entity.furniture.CustomFurniture;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.loot.LootTable;
|
||||
import net.momirealms.craftengine.core.loot.parameter.LootParameters;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.CommonParameters;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import org.bukkit.Location;
|
||||
@@ -271,13 +270,13 @@ public final class CraftEngineFurniture {
|
||||
World world = new BukkitWorld(location.getWorld());
|
||||
if (dropLoot && lootTable != null) {
|
||||
ContextHolder.Builder builder = ContextHolder.builder();
|
||||
builder.withParameter(LootParameters.LOCATION, vec3d);
|
||||
builder.withParameter(LootParameters.WORLD, world);
|
||||
builder.withParameter(CommonParameters.LOCATION, vec3d);
|
||||
builder.withParameter(CommonParameters.WORLD, world);
|
||||
if (player != null) {
|
||||
builder.withParameter(LootParameters.PLAYER, player);
|
||||
builder.withOptionalParameter(LootParameters.TOOL, player.getItemInHand(InteractionHand.MAIN_HAND));
|
||||
builder.withParameter(CommonParameters.PLAYER, player);
|
||||
//mark item builder.withOptionalParameter(CommonParameters.MAIN_HAND_ITEM, player.getItemInHand(InteractionHand.MAIN_HAND));
|
||||
}
|
||||
List<Item<ItemStack>> items = lootTable.getRandomItems(builder.build(), world);
|
||||
List<Item<ItemStack>> items = lootTable.getRandomItems(builder.build(), world, player);
|
||||
for (Item<ItemStack> item : items) {
|
||||
world.dropItemNaturally(vec3d, item);
|
||||
}
|
||||
|
||||
@@ -12,10 +12,10 @@ import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.loot.LootTable;
|
||||
import net.momirealms.craftengine.core.loot.parameter.LootParameters;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.CommonParameters;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.craftengine.core.util.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import org.bukkit.*;
|
||||
@@ -150,12 +150,12 @@ public class BlockEventListener implements Listener {
|
||||
}
|
||||
|
||||
// drop items
|
||||
ContextHolder.Builder builder = ContextHolder.builder();
|
||||
builder.withParameter(LootParameters.WORLD, world);
|
||||
builder.withParameter(LootParameters.LOCATION, vec3d);
|
||||
builder.withParameter(LootParameters.PLAYER, serverPlayer);
|
||||
builder.withOptionalParameter(LootParameters.TOOL, itemInHand);
|
||||
for (Item<Object> item : state.getDrops(builder, world)) {
|
||||
ContextHolder.Builder builder = ContextHolder.builder()
|
||||
.withParameter(CommonParameters.WORLD, world)
|
||||
.withParameter(CommonParameters.LOCATION, vec3d)
|
||||
.withParameter(CommonParameters.PLAYER, serverPlayer);
|
||||
//mark item .withOptionalParameter(CommonParameters.MAIN_HAND_ITEM, itemInHand);
|
||||
for (Item<Object> item : state.getDrops(builder, world, serverPlayer)) {
|
||||
world.dropItemNaturally(vec3d, item);
|
||||
}
|
||||
}
|
||||
@@ -171,14 +171,14 @@ public class BlockEventListener implements Listener {
|
||||
BukkitServerPlayer serverPlayer = this.plugin.adapt(player);
|
||||
net.momirealms.craftengine.core.world.World world = new BukkitWorld(player.getWorld());
|
||||
Vec3d vec3d = new Vec3d(location.getBlockX() + 0.5, location.getBlockY() + 0.5, location.getBlockZ() + 0.5);
|
||||
ContextHolder.Builder builder = ContextHolder.builder();
|
||||
builder.withParameter(LootParameters.WORLD, world);
|
||||
builder.withParameter(LootParameters.LOCATION, vec3d);
|
||||
builder.withParameter(LootParameters.PLAYER, serverPlayer);
|
||||
builder.withOptionalParameter(LootParameters.TOOL, serverPlayer.getItemInHand(InteractionHand.MAIN_HAND));
|
||||
ContextHolder.Builder builder = ContextHolder.builder()
|
||||
.withParameter(CommonParameters.WORLD, world)
|
||||
.withParameter(CommonParameters.LOCATION, vec3d)
|
||||
.withParameter(CommonParameters.PLAYER, serverPlayer);
|
||||
//mark item .withOptionalParameter(CommonParameters.MAIN_HAND_ITEM, serverPlayer.getItemInHand(InteractionHand.MAIN_HAND));
|
||||
ContextHolder contextHolder = builder.build();
|
||||
for (LootTable<?> lootTable : it.lootTables()) {
|
||||
for (Item<?> item : lootTable.getRandomItems(contextHolder, world)) {
|
||||
for (Item<?> item : lootTable.getRandomItems(contextHolder, world, serverPlayer)) {
|
||||
world.dropItemNaturally(vec3d, item);
|
||||
}
|
||||
}
|
||||
@@ -213,10 +213,10 @@ public class BlockEventListener implements Listener {
|
||||
Location location = block.getLocation();
|
||||
net.momirealms.craftengine.core.world.World world = new BukkitWorld(block.getWorld());
|
||||
Vec3d vec3d = new Vec3d(location.getBlockX() + 0.5, location.getBlockY() + 0.5, location.getBlockZ() + 0.5);
|
||||
ContextHolder.Builder builder = ContextHolder.builder();
|
||||
builder.withParameter(LootParameters.WORLD, world);
|
||||
builder.withParameter(LootParameters.LOCATION, vec3d);
|
||||
for (Item<?> item : immutableBlockState.getDrops(builder, world)) {
|
||||
ContextHolder.Builder builder = ContextHolder.builder()
|
||||
.withParameter(CommonParameters.WORLD, world)
|
||||
.withParameter(CommonParameters.LOCATION, vec3d);
|
||||
for (Item<?> item : immutableBlockState.getDrops(builder, world, null)) {
|
||||
world.dropItemNaturally(vec3d, item);
|
||||
}
|
||||
}
|
||||
@@ -232,11 +232,11 @@ public class BlockEventListener implements Listener {
|
||||
Vec3d vec3d = new Vec3d(location.getBlockX() + 0.5, location.getBlockY() + 0.5, location.getBlockZ() + 0.5);
|
||||
net.momirealms.craftengine.core.world.World world = new BukkitWorld(location.getWorld());
|
||||
ContextHolder.Builder builder = ContextHolder.builder();
|
||||
builder.withParameter(LootParameters.WORLD, world);
|
||||
builder.withParameter(LootParameters.LOCATION, vec3d);
|
||||
builder.withParameter(CommonParameters.WORLD, world);
|
||||
builder.withParameter(CommonParameters.LOCATION, vec3d);
|
||||
ContextHolder contextHolder = builder.build();
|
||||
for (LootTable<?> lootTable : it.lootTables()) {
|
||||
for (Item<?> item : lootTable.getRandomItems(contextHolder, world)) {
|
||||
for (Item<?> item : lootTable.getRandomItems(contextHolder, world, null)) {
|
||||
world.dropItemNaturally(vec3d, item);
|
||||
}
|
||||
}
|
||||
@@ -329,12 +329,12 @@ public class BlockEventListener implements Listener {
|
||||
if (state != null && !state.isEmpty()) {
|
||||
ContextHolder.Builder builder = ContextHolder.builder();
|
||||
Vec3d vec3d = Vec3d.atCenterOf(blockPos);
|
||||
builder.withParameter(LootParameters.LOCATION, vec3d);
|
||||
builder.withParameter(LootParameters.WORLD, world);
|
||||
builder.withParameter(CommonParameters.LOCATION, vec3d);
|
||||
builder.withParameter(CommonParameters.WORLD, world);
|
||||
if (yield < 1f) {
|
||||
builder.withParameter(LootParameters.EXPLOSION_RADIUS, 1.0f / yield);
|
||||
builder.withParameter(CommonParameters.EXPLOSION_RADIUS, 1.0f / yield);
|
||||
}
|
||||
for (Item<Object> item : state.getDrops(builder, world)) {
|
||||
for (Item<Object> item : state.getDrops(builder, world, null)) {
|
||||
world.dropItemNaturally(vec3d, item);
|
||||
}
|
||||
world.playBlockSound(vec3d, state.sounds().breakSound());
|
||||
|
||||
@@ -359,7 +359,7 @@ public class BukkitBlockManager extends AbstractBlockManager {
|
||||
|
||||
appearances = Map.of("default", pair.right());
|
||||
String internalBlock = pair.left().value() + "_" + internalId;
|
||||
Key internalBlockId = Key.of(CraftEngine.NAMESPACE, internalBlock);
|
||||
Key internalBlockId = Key.of(Key.DEFAULT_NAMESPACE, internalBlock);
|
||||
int internalBlockRegistryId = Optional.ofNullable(internalId2StateId.get(internalBlockId)).orElse(-1);
|
||||
if (internalBlockRegistryId == -1) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.invalid_real_id",
|
||||
@@ -408,7 +408,7 @@ public class BukkitBlockManager extends AbstractBlockManager {
|
||||
}
|
||||
int internalId = ResourceConfigUtils.getAsInt(variantSection.getOrDefault("id", -1), "id");
|
||||
Key baseBlock = tempTypeMap.get(appearance);
|
||||
Key internalBlockId = Key.of(CraftEngine.NAMESPACE, baseBlock.value() + "_" + internalId);
|
||||
Key internalBlockId = Key.of(Key.DEFAULT_NAMESPACE, baseBlock.value() + "_" + internalId);
|
||||
int internalBlockRegistryId = Optional.ofNullable(internalId2StateId.get(internalBlockId)).orElse(-1);
|
||||
if (internalBlockRegistryId == -1) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.invalid_real_id",
|
||||
@@ -782,7 +782,7 @@ public class BukkitBlockManager extends AbstractBlockManager {
|
||||
}
|
||||
|
||||
private Key createRealBlockKey(Key replacedBlock, int index) {
|
||||
return Key.of(CraftEngine.NAMESPACE, replacedBlock.value() + "_" + index);
|
||||
return Key.of(Key.DEFAULT_NAMESPACE, replacedBlock.value() + "_" + index);
|
||||
}
|
||||
|
||||
private Object createBlockProperties(Key realBlockKey) throws Exception {
|
||||
|
||||
@@ -5,9 +5,9 @@ import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorld;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.loot.parameter.LootParameters;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.util.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.CommonParameters;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import org.bukkit.entity.FallingBlock;
|
||||
import org.bukkit.event.EventHandler;
|
||||
@@ -32,15 +32,15 @@ public class FallingBlockRemoveListener implements Listener {
|
||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(stateId);
|
||||
if (immutableBlockState == null || immutableBlockState.isEmpty()) return;
|
||||
ContextHolder.Builder builder = ContextHolder.builder();
|
||||
builder.withParameter(LootParameters.FALLING_BLOCK, true);
|
||||
builder.withParameter(CommonParameters.FALLING_BLOCK, true);
|
||||
double x = Reflections.field$Entity$xo.getDouble(fallingBlockEntity);
|
||||
double y = Reflections.field$Entity$yo.getDouble(fallingBlockEntity);
|
||||
double z = Reflections.field$Entity$zo.getDouble(fallingBlockEntity);
|
||||
Vec3d vec3d = new Vec3d(x, y, z);
|
||||
net.momirealms.craftengine.core.world.World world = new BukkitWorld(fallingBlock.getWorld());
|
||||
builder.withParameter(LootParameters.LOCATION, vec3d);
|
||||
builder.withParameter(LootParameters.WORLD, world);
|
||||
for (Item<Object> item : immutableBlockState.getDrops(builder, world)) {
|
||||
builder.withParameter(CommonParameters.LOCATION, vec3d);
|
||||
builder.withParameter(CommonParameters.WORLD, world);
|
||||
for (Item<Object> item : immutableBlockState.getDrops(builder, world, null)) {
|
||||
world.dropItemNaturally(vec3d, item);
|
||||
}
|
||||
Object entityData = Reflections.field$Entity$entityData.get(fallingBlockEntity);
|
||||
|
||||
@@ -11,12 +11,12 @@ import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.loot.parameter.LootParameters;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.CommonParameters;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import net.momirealms.craftengine.core.util.Tuple;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.craftengine.core.util.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.core.world.WorldEvents;
|
||||
@@ -71,9 +71,9 @@ public class BushBlockBehavior extends BukkitBlockBehavior {
|
||||
BlockPos pos = LocationUtils.fromBlockPos(blockPos);
|
||||
Vec3d vec3d = Vec3d.atCenterOf(pos);
|
||||
net.momirealms.craftengine.core.world.World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level));
|
||||
builder.withParameter(LootParameters.LOCATION, vec3d);
|
||||
builder.withParameter(LootParameters.WORLD, world);
|
||||
for (Item<Object> item : previousState.getDrops(builder, world)) {
|
||||
builder.withParameter(CommonParameters.LOCATION, vec3d);
|
||||
builder.withParameter(CommonParameters.WORLD, world);
|
||||
for (Item<Object> item : previousState.getDrops(builder, world, null)) {
|
||||
world.dropItemNaturally(vec3d, item);
|
||||
}
|
||||
world.playBlockSound(vec3d, previousState.sounds().breakSound());
|
||||
|
||||
@@ -12,14 +12,14 @@ import net.momirealms.craftengine.core.block.UpdateOption;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.block.properties.IntegerProperty;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.loot.LootContext;
|
||||
import net.momirealms.craftengine.core.loot.number.NumberProvider;
|
||||
import net.momirealms.craftengine.core.loot.number.NumberProviders;
|
||||
import net.momirealms.craftengine.core.loot.parameter.LootParameters;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.SimpleContext;
|
||||
import net.momirealms.craftengine.core.plugin.context.number.NumberProvider;
|
||||
import net.momirealms.craftengine.core.plugin.context.number.NumberProviders;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.CommonParameters;
|
||||
import net.momirealms.craftengine.core.util.RandomUtils;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
import net.momirealms.craftengine.core.util.Tuple;
|
||||
import net.momirealms.craftengine.core.util.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.core.world.Vec3i;
|
||||
import net.momirealms.craftengine.shared.block.BlockBehavior;
|
||||
@@ -30,7 +30,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class CropBlockBehavior extends BushBlockBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
@@ -146,17 +145,19 @@ public class CropBlockBehavior extends BushBlockBehavior {
|
||||
int x = FastNMS.INSTANCE.field$Vec3i$x(pos);
|
||||
int y = FastNMS.INSTANCE.field$Vec3i$y(pos);
|
||||
int z = FastNMS.INSTANCE.field$Vec3i$z(pos);
|
||||
|
||||
net.momirealms.craftengine.core.world.World wrappedWorld = new BukkitWorld(world);
|
||||
int i = this.getAge(immutableBlockState) + this.boneMealBonus.getInt(new LootContext(wrappedWorld, ContextHolder.builder()
|
||||
.withParameter(LootParameters.WORLD, wrappedWorld)
|
||||
.withParameter(LootParameters.LOCATION, Vec3d.atCenterOf(new Vec3i(x, y, z)))
|
||||
.build(), ThreadLocalRandom.current(), 1));
|
||||
int i = this.getAge(immutableBlockState) + this.boneMealBonus.getInt(
|
||||
SimpleContext.of(
|
||||
ContextHolder.builder()
|
||||
.withParameter(CommonParameters.WORLD, new BukkitWorld(world))
|
||||
.withParameter(CommonParameters.LOCATION, Vec3d.atCenterOf(new Vec3i(x, y, z)))
|
||||
.build()
|
||||
)
|
||||
);
|
||||
int maxAge = this.ageProperty.max;
|
||||
if (i > maxAge) {
|
||||
i = maxAge;
|
||||
}
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(level, pos, immutableBlockState.with(this.ageProperty, i).customBlockState().handle(), UpdateOption.UPDATE_NONE.flags());
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(level, pos, immutableBlockState.with(this.ageProperty, i).customBlockState().handle(), UpdateOption.UPDATE_ALL.flags());
|
||||
if (sendParticles) {
|
||||
world.spawnParticle(ParticleUtils.getParticle("HAPPY_VILLAGER"), x + 0.5, y + 0.5, z + 0.5, 15, 0.25, 0.25, 0.25);
|
||||
}
|
||||
|
||||
@@ -10,10 +10,10 @@ import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.loot.parameter.LootParameters;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.CommonParameters;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.craftengine.core.util.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.shared.block.BlockBehavior;
|
||||
|
||||
@@ -91,15 +91,15 @@ public class FallingBlockBehavior extends BukkitBlockBehavior {
|
||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(stateId);
|
||||
if (immutableBlockState == null || immutableBlockState.isEmpty()) return;
|
||||
ContextHolder.Builder builder = ContextHolder.builder();
|
||||
builder.withParameter(LootParameters.FALLING_BLOCK, true);
|
||||
builder.withParameter(CommonParameters.FALLING_BLOCK, true);
|
||||
double x = Reflections.field$Entity$xo.getDouble(fallingBlockEntity);
|
||||
double y = Reflections.field$Entity$yo.getDouble(fallingBlockEntity);
|
||||
double z = Reflections.field$Entity$zo.getDouble(fallingBlockEntity);
|
||||
Vec3d vec3d = new Vec3d(x, y, z);
|
||||
net.momirealms.craftengine.core.world.World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level));
|
||||
builder.withParameter(LootParameters.LOCATION, vec3d);
|
||||
builder.withParameter(LootParameters.WORLD, world);
|
||||
for (Item<Object> item : immutableBlockState.getDrops(builder, world)) {
|
||||
builder.withParameter(CommonParameters.LOCATION, vec3d);
|
||||
builder.withParameter(CommonParameters.WORLD, world);
|
||||
for (Item<Object> item : immutableBlockState.getDrops(builder, world, null)) {
|
||||
world.dropItemNaturally(vec3d, item);
|
||||
}
|
||||
Object entityData = Reflections.field$Entity$entityData.get(fallingBlockEntity);
|
||||
|
||||
@@ -13,12 +13,12 @@ import net.momirealms.craftengine.core.block.UpdateOption;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.loot.parameter.LootParameters;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.CommonParameters;
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.craftengine.core.util.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.shared.block.BlockBehavior;
|
||||
@@ -125,9 +125,9 @@ public class LeavesBlockBehavior extends WaterLoggedBlockBehavior {
|
||||
Vec3d vec3d = Vec3d.atCenterOf(pos);
|
||||
net.momirealms.craftengine.core.world.World world = new BukkitWorld(bukkitWorld);
|
||||
ContextHolder.Builder builder = ContextHolder.builder()
|
||||
.withParameter(LootParameters.LOCATION, vec3d)
|
||||
.withParameter(LootParameters.WORLD, world);
|
||||
for (Item<Object> item : immutableBlockState.getDrops(builder, world)) {
|
||||
.withParameter(CommonParameters.LOCATION, vec3d)
|
||||
.withParameter(CommonParameters.WORLD, world);
|
||||
for (Item<Object> item : immutableBlockState.getDrops(builder, world, null)) {
|
||||
world.dropItemNaturally(vec3d, item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,9 +13,9 @@ import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.block.properties.IntegerProperty;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.loot.parameter.LootParameters;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.CommonParameters;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import net.momirealms.craftengine.core.util.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.core.world.WorldEvents;
|
||||
@@ -61,9 +61,9 @@ public class SugarCaneBlockBehavior extends BushBlockBehavior {
|
||||
Vec3d vec3d = Vec3d.atCenterOf(LocationUtils.fromBlockPos(blockPos));
|
||||
net.momirealms.craftengine.core.world.World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level));
|
||||
ContextHolder.Builder builder = ContextHolder.builder()
|
||||
.withParameter(LootParameters.LOCATION, vec3d)
|
||||
.withParameter(LootParameters.WORLD, world);
|
||||
for (Item<Object> item : currentState.getDrops(builder, world)) {
|
||||
.withParameter(CommonParameters.LOCATION, vec3d)
|
||||
.withParameter(CommonParameters.WORLD, world);
|
||||
for (Item<Object> item : currentState.getDrops(builder, world, null)) {
|
||||
world.dropItemNaturally(vec3d, item);
|
||||
}
|
||||
world.playBlockSound(vec3d, currentState.sounds().breakSound());
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package net.momirealms.craftengine.bukkit.entity;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorld;
|
||||
import net.momirealms.craftengine.core.entity.Entity;
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
@@ -49,7 +51,7 @@ public class BukkitEntity extends Entity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public World level() {
|
||||
public World world() {
|
||||
return new BukkitWorld(literalObject().getWorld());
|
||||
}
|
||||
|
||||
@@ -62,4 +64,9 @@ public class BukkitEntity extends Entity {
|
||||
public org.bukkit.entity.Entity literalObject() {
|
||||
return this.entity.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return KeyUtils.namespacedKey2Key(literalObject().getType().getKey());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,12 +28,12 @@ import net.momirealms.craftengine.core.pack.model.select.ChargeTypeSelectPropert
|
||||
import net.momirealms.craftengine.core.pack.model.select.TrimMaterialSelectProperty;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.registry.WritableRegistry;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import net.momirealms.craftengine.core.util.context.ContextHolder;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
|
||||
@@ -100,7 +100,7 @@ public class ItemEventListener implements Listener {
|
||||
|
||||
if (optionalItemBehaviors.isPresent()) {
|
||||
for (ItemBehavior itemBehavior : optionalItemBehaviors.get()) {
|
||||
InteractionResult result = itemBehavior.use(player.level(), player, hand);
|
||||
InteractionResult result = itemBehavior.use(player.world(), player, hand);
|
||||
if (result == InteractionResult.SUCCESS_AND_CANCEL) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
@@ -167,7 +167,7 @@ public class ItemEventListener implements Listener {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
int maxY = player.level().worldHeight().getMaxBuildHeight() - 1;
|
||||
int maxY = player.world().worldHeight().getMaxBuildHeight() - 1;
|
||||
if (direction == Direction.UP
|
||||
&& result != InteractionResult.SUCCESS
|
||||
&& pos.y() >= maxY
|
||||
|
||||
@@ -4,7 +4,7 @@ import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks;
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.block.behavior.StrippableBlockBehavior;
|
||||
import net.momirealms.craftengine.bukkit.util.*;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorldBlock;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitBlockInWorld;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.UpdateOption;
|
||||
@@ -43,7 +43,7 @@ public class AxeItemBehavior extends ItemBehavior {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public InteractionResult useOnBlock(UseOnContext context) {
|
||||
BukkitWorldBlock clicked = (BukkitWorldBlock) context.getLevel().getBlockAt(context.getClickedPos());
|
||||
BukkitBlockInWorld clicked = (BukkitBlockInWorld) context.getLevel().getBlockAt(context.getClickedPos());
|
||||
Block block = clicked.block();
|
||||
ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockDataToId(block.getBlockData()));
|
||||
if (state == null || state.isEmpty()) return InteractionResult.PASS;
|
||||
|
||||
@@ -8,7 +8,7 @@ import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorldBlock;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitBlockInWorld;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionResult;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
||||
@@ -32,7 +32,7 @@ public class BoneMealItemBehavior extends ItemBehavior {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
|
||||
BukkitWorldBlock clicked = (BukkitWorldBlock) context.getLevel().getBlockAt(context.getClickedPos());
|
||||
BukkitBlockInWorld clicked = (BukkitBlockInWorld) context.getLevel().getBlockAt(context.getClickedPos());
|
||||
Block block = clicked.block();
|
||||
ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockDataToId(block.getBlockData()));
|
||||
if (state == null || state.isEmpty()) return InteractionResult.PASS;
|
||||
|
||||
@@ -4,7 +4,7 @@ import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks;
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorldBlock;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitBlockInWorld;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.UpdateOption;
|
||||
@@ -35,7 +35,7 @@ public class BucketItemBehavior extends ItemBehavior {
|
||||
@Override
|
||||
public InteractionResult useOnBlock(UseOnContext context) {
|
||||
if (context.getPlayer().isAdventureMode()) return InteractionResult.PASS;
|
||||
BukkitWorldBlock clicked = (BukkitWorldBlock) context.getLevel().getBlockAt(context.getClickedPos());
|
||||
BukkitBlockInWorld clicked = (BukkitBlockInWorld) context.getLevel().getBlockAt(context.getClickedPos());
|
||||
Block block = clicked.block();
|
||||
ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockDataToId(block.getBlockData()));
|
||||
if (state == null || state.isEmpty()) return InteractionResult.PASS;
|
||||
|
||||
@@ -120,10 +120,6 @@ public class FurnitureItemBehavior extends ItemBehavior {
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
|
||||
if (!BukkitCraftEngine.instance().antiGrief().canPlace(bukkitPlayer, furnitureLocation)) {
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
|
||||
FurnitureAttemptPlaceEvent attemptPlaceEvent = new FurnitureAttemptPlaceEvent(bukkitPlayer, customFurniture, anchorType, furnitureLocation.clone(),
|
||||
DirectionUtils.toBlockFace(clickedFace), context.getHand(), world.getBlockAt(context.getClickedPos().x(), context.getClickedPos().y(), context.getClickedPos().z()));
|
||||
if (EventUtils.fireAndCheckCancel(attemptPlaceEvent)) {
|
||||
|
||||
@@ -4,7 +4,7 @@ import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks;
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorldBlock;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitBlockInWorld;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.UpdateOption;
|
||||
@@ -33,7 +33,7 @@ public class WaterBucketItemBehavior extends ItemBehavior {
|
||||
public InteractionResult useOnBlock(UseOnContext context) {
|
||||
if (context.getPlayer().isAdventureMode()) return InteractionResult.PASS;
|
||||
BlockPos pos = context.getClickedPos();
|
||||
BukkitWorldBlock clicked = (BukkitWorldBlock) context.getLevel().getBlockAt(pos);
|
||||
BukkitBlockInWorld clicked = (BukkitBlockInWorld) context.getLevel().getBlockAt(pos);
|
||||
Block block = clicked.block();
|
||||
ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockDataToId(block.getBlockData()));
|
||||
if (state == null || state.isEmpty()) return InteractionResult.PASS;
|
||||
|
||||
@@ -19,13 +19,13 @@ import net.momirealms.craftengine.core.item.recipe.input.CraftingInput;
|
||||
import net.momirealms.craftengine.core.item.recipe.input.SingleItemInput;
|
||||
import net.momirealms.craftengine.core.item.recipe.input.SmithingInput;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.util.AdventureHelper;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.Pair;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.craftengine.core.util.context.ContextHolder;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.Campfire;
|
||||
@@ -752,7 +752,7 @@ public class RecipeEventListener implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
Item<ItemStack> newItem = customItem.buildItem(ItemBuildContext.of(plugin.adapt(player), ContextHolder.EMPTY));
|
||||
Item<ItemStack> newItem = customItem.buildItem(ItemBuildContext.of(plugin.adapt(player)));
|
||||
int remainingDurability = totalMaxDamage - totalDamage;
|
||||
int newItemDamage = Math.max(0, newItem.maxDamage().get() - remainingDurability);
|
||||
newItem.damage(newItemDamage);
|
||||
|
||||
@@ -6,18 +6,17 @@ import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorld;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.loot.AbstractVanillaLootManager;
|
||||
import net.momirealms.craftengine.core.loot.LootTable;
|
||||
import net.momirealms.craftengine.core.loot.VanillaLoot;
|
||||
import net.momirealms.craftengine.core.loot.parameter.LootParameters;
|
||||
import net.momirealms.craftengine.core.pack.LoadingSequence;
|
||||
import net.momirealms.craftengine.core.pack.Pack;
|
||||
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.CommonParameters;
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import net.momirealms.craftengine.core.util.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
@@ -68,18 +67,19 @@ public class BukkitVanillaLootManager extends AbstractVanillaLootManager impleme
|
||||
net.momirealms.craftengine.core.world.World world = new BukkitWorld(entity.getWorld());
|
||||
Vec3d vec3d = new Vec3d(location.getBlockX() + 0.5, location.getBlockY() + 0.5, location.getBlockZ() + 0.5);
|
||||
ContextHolder.Builder builder = ContextHolder.builder();
|
||||
builder.withParameter(LootParameters.WORLD, world);
|
||||
builder.withParameter(LootParameters.LOCATION, vec3d);
|
||||
builder.withParameter(CommonParameters.WORLD, world);
|
||||
builder.withParameter(CommonParameters.LOCATION, vec3d);
|
||||
BukkitServerPlayer optionalPlayer = null;
|
||||
if (VersionHelper.isOrAbove1_20_5()) {
|
||||
if (event.getDamageSource().getCausingEntity() instanceof Player player) {
|
||||
BukkitServerPlayer serverPlayer = this.plugin.adapt(player);
|
||||
builder.withParameter(LootParameters.PLAYER, serverPlayer);
|
||||
builder.withOptionalParameter(LootParameters.TOOL, serverPlayer.getItemInHand(InteractionHand.MAIN_HAND));
|
||||
optionalPlayer = this.plugin.adapt(player);
|
||||
builder.withParameter(CommonParameters.PLAYER, optionalPlayer);
|
||||
//mark item builder.withOptionalParameter(CommonParameters.MAIN_HAND_ITEM, serverPlayer.getItemInHand(InteractionHand.MAIN_HAND));
|
||||
}
|
||||
}
|
||||
ContextHolder contextHolder = builder.build();
|
||||
for (LootTable<?> lootTable : loot.lootTables()) {
|
||||
for (Item<?> item : lootTable.getRandomItems(contextHolder, world)) {
|
||||
for (Item<?> item : lootTable.getRandomItems(contextHolder, world, optionalPlayer)) {
|
||||
world.dropItemNaturally(vec3d, item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,6 +75,7 @@ public class BukkitCraftEngine extends CraftEngine {
|
||||
super.classPathAppender = new ReflectionClassPathAppender(this);
|
||||
super.scheduler = new BukkitSchedulerAdapter(this);
|
||||
super.logger = new JavaPluginLogger(bootstrap.getLogger());
|
||||
super.platform = new BukkitPlatform();
|
||||
// find mod class if present
|
||||
Class<?> modClass = ReflectionUtils.getClazz(MOD_CLASS);
|
||||
if (modClass != null) {
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin;
|
||||
|
||||
import net.momirealms.craftengine.core.plugin.Platform;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
public class BukkitPlatform implements Platform {
|
||||
|
||||
@Override
|
||||
public void dispatchCommand(String command) {
|
||||
Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), command);
|
||||
}
|
||||
}
|
||||
@@ -46,6 +46,7 @@ public class BukkitCommandManager extends AbstractCommandManager<CommandSender>
|
||||
new DebugSetBlockCommand(this, plugin),
|
||||
new DebugSpawnFurnitureCommand(this, plugin),
|
||||
new DebugTargetBlockCommand(this, plugin),
|
||||
new DebugIsSectionInjectedCommand(this, plugin),
|
||||
new TotemAnimationCommand(this, plugin),
|
||||
new EnableResourceCommand(this, plugin),
|
||||
new DisableResourceCommand(this, plugin),
|
||||
|
||||
@@ -3,7 +3,9 @@ package net.momirealms.craftengine.bukkit.plugin.command;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.util.ComponentUtils;
|
||||
import net.momirealms.craftengine.core.plugin.command.sender.Sender;
|
||||
import net.momirealms.craftengine.core.plugin.command.sender.SenderFactory;
|
||||
import net.momirealms.craftengine.core.util.Tristate;
|
||||
@@ -47,7 +49,9 @@ public class BukkitSenderFactory extends SenderFactory<BukkitCraftEngine, Comman
|
||||
@Override
|
||||
protected void sendMessage(CommandSender sender, Component message) {
|
||||
// we can safely send async for players and the console - otherwise, send it sync
|
||||
if (sender instanceof Player || sender instanceof ConsoleCommandSender || sender instanceof RemoteConsoleCommandSender) {
|
||||
if (sender instanceof Player player) {
|
||||
FastNMS.INSTANCE.sendPacket(FastNMS.INSTANCE.method$CraftPlayer$getHandle(player), FastNMS.INSTANCE.constructor$ClientboundSystemChatPacket(ComponentUtils.adventureToMinecraft(message), false));
|
||||
} else if (sender instanceof ConsoleCommandSender || sender instanceof RemoteConsoleCommandSender) {
|
||||
audience(sender).sendMessage(message);
|
||||
} else {
|
||||
plugin().scheduler().executeSync(() -> audience(sender).sendMessage(message));
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.command.feature;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature;
|
||||
import net.momirealms.craftengine.bukkit.plugin.injector.BukkitInjector;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager;
|
||||
import net.momirealms.craftengine.core.plugin.command.sender.Sender;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
|
||||
import net.momirealms.craftengine.core.util.AdventureHelper;
|
||||
import net.momirealms.craftengine.core.world.chunk.CESection;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.parser.standard.StringParser;
|
||||
|
||||
public class DebugIsSectionInjectedCommand extends BukkitCommandFeature<CommandSender> {
|
||||
|
||||
public DebugIsSectionInjectedCommand(CraftEngineCommandManager<CommandSender> commandManager, CraftEngine plugin) {
|
||||
super(commandManager, plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Command.Builder<? extends CommandSender> assembleCommand(org.incendo.cloud.CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
|
||||
return builder
|
||||
.senderType(Player.class)
|
||||
.handler(context -> {
|
||||
Player player = context.sender();
|
||||
Chunk chunk = player.getChunk();
|
||||
Object worldServer = FastNMS.INSTANCE.field$CraftChunk$worldServer(chunk);
|
||||
Object chunkSource = FastNMS.INSTANCE.method$ServerLevel$getChunkSource(worldServer);
|
||||
Object levelChunk = FastNMS.INSTANCE.method$ServerChunkCache$getChunkAtIfLoadedMainThread(chunkSource, chunk.getX(), chunk.getZ());
|
||||
Object[] sections = FastNMS.INSTANCE.method$ChunkAccess$getSections(levelChunk);
|
||||
int i = 0;
|
||||
Sender sender = plugin().senderFactory().wrap(player);
|
||||
for (Object section : sections) {
|
||||
sender.sendMessage(Component.text("Section #" + i + ": " + BukkitInjector.isSectionInjected(section)));
|
||||
i++;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFeatureID() {
|
||||
return "debug_is_section_injected";
|
||||
}
|
||||
}
|
||||
@@ -68,7 +68,6 @@ public class ReloadCommand extends BukkitCommandFeature<CommandSender> {
|
||||
long time2 = System.currentTimeMillis();
|
||||
long packTime = time2 - time1;
|
||||
handleFeedback(context, MessageConstants.COMMAND_RELOAD_PACK_SUCCESS, Component.text(packTime));
|
||||
|
||||
} catch (Exception e) {
|
||||
handleFeedback(context, MessageConstants.COMMAND_RELOAD_PACK_FAILURE);
|
||||
plugin().logger().warn("Failed to generate resource pack", e);
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.command.feature;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
|
||||
import net.momirealms.craftengine.core.util.AdventureHelper;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.parser.standard.StringParser;
|
||||
|
||||
public class TestCommand extends BukkitCommandFeature<CommandSender> {
|
||||
|
||||
@@ -19,9 +21,11 @@ public class TestCommand extends BukkitCommandFeature<CommandSender> {
|
||||
public Command.Builder<? extends CommandSender> assembleCommand(org.incendo.cloud.CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
|
||||
return builder
|
||||
.senderType(Player.class)
|
||||
.required("text", StringParser.greedyStringParser())
|
||||
.handler(context -> {
|
||||
Player player = context.sender();
|
||||
player.getInventory().addItem(BukkitItemManager.instance().createWrappedItem(Key.from("default:topaz"), null).getItem());
|
||||
String text = "<red><arg:1:0912012><papi:player_name></red>";
|
||||
PlayerOptionalContext context1 = PlayerOptionalContext.of(plugin().adapt(context.sender()), ContextHolder.builder());
|
||||
plugin().senderFactory().wrap(context.sender()).sendMessage(AdventureHelper.customMiniMessage().deserialize(text, context1.tagResolvers()));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
import net.bytebuddy.implementation.bind.annotation.SuperCall;
|
||||
import net.bytebuddy.implementation.bind.annotation.This;
|
||||
import net.bytebuddy.implementation.bytecode.assign.Assigner;
|
||||
import net.bytebuddy.implementation.bytecode.assign.TypeCasting;
|
||||
import net.bytebuddy.implementation.bytecode.member.FieldAccess;
|
||||
import net.bytebuddy.implementation.bytecode.member.MethodReturn;
|
||||
@@ -51,7 +52,7 @@ import net.momirealms.craftengine.core.world.CEWorld;
|
||||
import net.momirealms.craftengine.core.world.SectionPos;
|
||||
import net.momirealms.craftengine.core.world.chunk.CEChunk;
|
||||
import net.momirealms.craftengine.core.world.chunk.CESection;
|
||||
import net.momirealms.craftengine.core.world.chunk.InjectedPalettedContainerHolder;
|
||||
import net.momirealms.craftengine.core.world.chunk.InjectedHolder;
|
||||
import net.momirealms.craftengine.shared.ObjectHolder;
|
||||
import net.momirealms.craftengine.shared.block.*;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@@ -69,12 +70,15 @@ import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class BukkitInjector {
|
||||
private static final ByteBuddy byteBuddy = new ByteBuddy(ClassFileVersion.JAVA_V17);
|
||||
private static final BukkitBlockShape STONE_SHAPE = new BukkitBlockShape(Reflections.instance$Blocks$STONE$defaultState);
|
||||
|
||||
private static Class<?> clazz$InjectedPalettedContainer;
|
||||
private static Class<?> clazz$InjectedLevelChunkSection;
|
||||
private static MethodHandle constructor$InjectedLevelChunkSection;
|
||||
|
||||
private static VarHandle varHandle$InjectedPalettedContainer$target;
|
||||
|
||||
@@ -100,36 +104,62 @@ public class BukkitInjector {
|
||||
clazz$InjectedPalettedContainer = byteBuddy
|
||||
.subclass(Reflections.clazz$PalettedContainer)
|
||||
.name("net.minecraft.world.level.chunk.InjectedPalettedContainer")
|
||||
.implement(InjectedPalettedContainerHolder.class)
|
||||
.defineField("target", Reflections.clazz$PalettedContainer, Visibility.PRIVATE)
|
||||
.defineField("ceworld", CEWorld.class, Visibility.PRIVATE)
|
||||
.implement(InjectedHolder.Palette.class)
|
||||
.defineField("target", Reflections.clazz$PalettedContainer, Visibility.PUBLIC)
|
||||
.defineField("active", boolean.class, Visibility.PUBLIC)
|
||||
.defineField("cesection", CESection.class, Visibility.PRIVATE)
|
||||
.defineField("cechunk", CEChunk.class, Visibility.PRIVATE)
|
||||
.defineField("cepos", SectionPos.class, Visibility.PRIVATE)
|
||||
.method(ElementMatchers.any()
|
||||
.and(ElementMatchers.not(ElementMatchers.is(Reflections.method$PalettedContainer$getAndSet)))
|
||||
.and(ElementMatchers.not(ElementMatchers.isDeclaredBy(Object.class)))
|
||||
// TODO Requires Paper Patch
|
||||
//.and(ElementMatchers.not(ElementMatchers.named("get").and(ElementMatchers.takesArguments(int.class)).and(ElementMatchers.returns(Object.class))))
|
||||
)
|
||||
.intercept(MethodDelegation.toField("target"))
|
||||
.method(ElementMatchers.is(Reflections.method$PalettedContainer$getAndSet))
|
||||
.intercept(MethodDelegation.to(GetAndSetInterceptor.INSTANCE))
|
||||
.method(ElementMatchers.named("target"))
|
||||
.intercept(FieldAccessor.ofField("target"))
|
||||
.method(ElementMatchers.named("setTarget"))
|
||||
.intercept(FieldAccessor.ofField("target").withAssigner(Assigner.DEFAULT, Assigner.Typing.DYNAMIC))
|
||||
.method(ElementMatchers.named("isActive").or(ElementMatchers.named("setActive")))
|
||||
.intercept(FieldAccessor.ofField("active"))
|
||||
.method(ElementMatchers.named("ceSection"))
|
||||
.intercept(FieldAccessor.ofField("cesection"))
|
||||
.method(ElementMatchers.named("ceChunk"))
|
||||
.intercept(FieldAccessor.ofField("cechunk"))
|
||||
.method(ElementMatchers.named("ceWorld"))
|
||||
.intercept(FieldAccessor.ofField("ceworld"))
|
||||
.method(ElementMatchers.named("cePos"))
|
||||
.intercept(FieldAccessor.ofField("cepos"))
|
||||
.make()
|
||||
.load(BukkitInjector.class.getClassLoader())
|
||||
.getLoaded();
|
||||
//varHandle$InjectedPalettedContainer$target = Objects.requireNonNull(ReflectionUtils.findVarHandle(clazz$InjectedPalettedContainer, "target", Reflections.clazz$PalettedContainer));
|
||||
|
||||
varHandle$InjectedPalettedContainer$target = Objects.requireNonNull(ReflectionUtils.findVarHandle(clazz$InjectedPalettedContainer, "target", Reflections.clazz$PalettedContainer));
|
||||
// Level Chunk Section
|
||||
clazz$InjectedLevelChunkSection = byteBuddy
|
||||
.subclass(Reflections.clazz$LevelChunkSection, ConstructorStrategy.Default.IMITATE_SUPER_CLASS_OPENING)
|
||||
.name("net.minecraft.world.level.chunk.InjectedLevelChunkSection")
|
||||
.implement(InjectedHolder.Section.class)
|
||||
.defineField("active", boolean.class, Visibility.PUBLIC)
|
||||
.defineField("cesection", CESection.class, Visibility.PRIVATE)
|
||||
.defineField("cechunk", CEChunk.class, Visibility.PRIVATE)
|
||||
.defineField("cepos", SectionPos.class, Visibility.PRIVATE)
|
||||
.method(ElementMatchers.is(Reflections.method$LevelChunkSection$setBlockState))
|
||||
.intercept(MethodDelegation.to(SetBlockStateInterceptor.INSTANCE))
|
||||
.method(ElementMatchers.named("ceSection"))
|
||||
.intercept(FieldAccessor.ofField("cesection"))
|
||||
.method(ElementMatchers.named("ceChunk"))
|
||||
.intercept(FieldAccessor.ofField("cechunk"))
|
||||
.method(ElementMatchers.named("cePos"))
|
||||
.intercept(FieldAccessor.ofField("cepos"))
|
||||
.method(ElementMatchers.named("isActive").or(ElementMatchers.named("setActive")))
|
||||
.intercept(FieldAccessor.ofField("active"))
|
||||
.make()
|
||||
.load(BukkitInjector.class.getClassLoader())
|
||||
.getLoaded();
|
||||
|
||||
constructor$InjectedLevelChunkSection = MethodHandles.publicLookup().in(clazz$InjectedLevelChunkSection)
|
||||
.findConstructor(clazz$InjectedLevelChunkSection, MethodType.methodType(void.class, Reflections.clazz$PalettedContainer, Reflections.clazz$PalettedContainer))
|
||||
.asType(MethodType.methodType(Reflections.clazz$LevelChunkSection, Reflections.clazz$PalettedContainer, Reflections.clazz$PalettedContainer));
|
||||
|
||||
// State Predicate
|
||||
DynamicType.Unloaded<?> alwaysTrue = byteBuddy
|
||||
@@ -388,40 +418,86 @@ public class BukkitInjector {
|
||||
// }
|
||||
// }
|
||||
|
||||
public synchronized static void injectLevelChunkSection(Object targetSection, CESection ceSection, CEWorld ceWorld, CEChunk chunk, SectionPos pos) {
|
||||
public synchronized static void injectLevelChunkSection(Object targetSection, CESection ceSection, CEChunk chunk, SectionPos pos, Consumer<Object> callback) {
|
||||
try {
|
||||
Object container = FastNMS.INSTANCE.field$LevelChunkSection$states(targetSection);
|
||||
if (!clazz$InjectedPalettedContainer.isInstance(container)) {
|
||||
InjectedPalettedContainerHolder injectedObject;
|
||||
if (Config.fastPaletteInjection()) {
|
||||
injectedObject = FastNMS.INSTANCE.createInjectedPalettedContainerHolder(container);
|
||||
if (Config.injectionTarget()) {
|
||||
Object container = FastNMS.INSTANCE.field$LevelChunkSection$states(targetSection);
|
||||
if (!(container instanceof InjectedHolder.Palette holder)) {
|
||||
InjectedHolder.Palette injectedObject;
|
||||
if (Config.fastInjection()) {
|
||||
injectedObject = FastNMS.INSTANCE.createInjectedPalettedContainerHolder(container);
|
||||
} else {
|
||||
injectedObject = (InjectedHolder.Palette) Reflections.UNSAFE.allocateInstance(clazz$InjectedPalettedContainer);
|
||||
injectedObject.setTarget(container);
|
||||
//varHandle$InjectedPalettedContainer$target.set(injectedObject, container);
|
||||
}
|
||||
injectedObject.ceChunk(chunk);
|
||||
injectedObject.ceSection(ceSection);
|
||||
injectedObject.cePos(pos);
|
||||
injectedObject.setActive(true);
|
||||
Reflections.varHandle$PalettedContainer$data.setVolatile(injectedObject, Reflections.varHandle$PalettedContainer$data.get(container));
|
||||
Reflections.field$LevelChunkSection$states.set(targetSection, injectedObject);
|
||||
} else {
|
||||
injectedObject = (InjectedPalettedContainerHolder) Reflections.UNSAFE.allocateInstance(clazz$InjectedPalettedContainer);
|
||||
varHandle$InjectedPalettedContainer$target.set(injectedObject, container);
|
||||
holder.ceChunk(chunk);
|
||||
holder.ceSection(ceSection);
|
||||
holder.cePos(pos);
|
||||
holder.setActive(true);
|
||||
}
|
||||
} else {
|
||||
if (!(targetSection instanceof InjectedHolder.Section holder)) {
|
||||
InjectedHolder.Section injectedObject;
|
||||
if (Config.fastInjection()) {
|
||||
injectedObject = FastNMS.INSTANCE.createInjectedLevelChunkSectionHolder(targetSection);
|
||||
} else {
|
||||
injectedObject = (InjectedHolder.Section) constructor$InjectedLevelChunkSection.invoke(
|
||||
FastNMS.INSTANCE.field$LevelChunkSection$states(targetSection), FastNMS.INSTANCE.field$LevelChunkSection$biomes(targetSection));
|
||||
}
|
||||
injectedObject.ceChunk(chunk);
|
||||
injectedObject.ceSection(ceSection);
|
||||
injectedObject.cePos(pos);
|
||||
injectedObject.setActive(true);
|
||||
callback.accept(injectedObject);
|
||||
} else {
|
||||
holder.ceChunk(chunk);
|
||||
holder.ceSection(ceSection);
|
||||
holder.cePos(pos);
|
||||
holder.setActive(true);
|
||||
}
|
||||
injectedObject.ceWorld(ceWorld);
|
||||
injectedObject.ceChunk(chunk);
|
||||
injectedObject.ceSection(ceSection);
|
||||
injectedObject.cePos(pos);
|
||||
Reflections.varHandle$PalettedContainer$data.setVolatile(injectedObject, Reflections.varHandle$PalettedContainer$data.get(container));
|
||||
Reflections.field$LevelChunkSection$states.set(targetSection, injectedObject);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().severe("Failed to inject chunk section", e);
|
||||
} catch (Throwable e) {
|
||||
CraftEngine.instance().logger().severe("Failed to inject chunk section " + pos, e);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized static void uninjectLevelChunkSection(Object section) {
|
||||
try {
|
||||
Object states = FastNMS.INSTANCE.field$LevelChunkSection$states(section);
|
||||
if (states instanceof InjectedPalettedContainerHolder holder) {
|
||||
Reflections.field$LevelChunkSection$states.set(section, holder.target());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().severe("Failed to inject chunk section", e);
|
||||
public static boolean isSectionInjected(Object section) {
|
||||
if (Config.injectionTarget()) {
|
||||
Object container = FastNMS.INSTANCE.field$LevelChunkSection$states(section);
|
||||
return container instanceof InjectedHolder.Palette;
|
||||
} else {
|
||||
return section instanceof InjectedHolder.Section;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized static Object uninjectLevelChunkSection(Object section) {
|
||||
if (Config.injectionTarget()) {
|
||||
Object states = FastNMS.INSTANCE.field$LevelChunkSection$states(section);
|
||||
if (states instanceof InjectedHolder.Palette holder) {
|
||||
holder.setActive(false);
|
||||
// try {
|
||||
// Reflections.field$LevelChunkSection$states.set(section, holder.target());
|
||||
// } catch (ReflectiveOperationException e) {
|
||||
// CraftEngine.instance().logger().severe("Failed to uninject palette", e);
|
||||
// }
|
||||
}
|
||||
} else {
|
||||
if (section instanceof InjectedHolder.Section holder) {
|
||||
holder.setActive(false);
|
||||
//return FastNMS.INSTANCE.constructor$LevelChunkSection(holder);
|
||||
}
|
||||
}
|
||||
return section;
|
||||
}
|
||||
|
||||
public static class GetRecipeForMethodInterceptor1_20 {
|
||||
public static final GetRecipeForMethodInterceptor1_20 INSTANCE = new GetRecipeForMethodInterceptor1_20();
|
||||
|
||||
@@ -677,58 +753,82 @@ public class BukkitInjector {
|
||||
}
|
||||
}
|
||||
|
||||
public static class SetBlockStateInterceptor {
|
||||
public static final SetBlockStateInterceptor INSTANCE = new SetBlockStateInterceptor();
|
||||
|
||||
@RuntimeType
|
||||
public Object intercept(@This Object thisObj, @AllArguments Object[] args, @SuperCall Callable<Object> superMethod) throws Exception {
|
||||
InjectedHolder.Section holder = (InjectedHolder.Section) thisObj;
|
||||
int x = (int) args[0];
|
||||
int y = (int) args[1];
|
||||
int z = (int) args[2];
|
||||
Object newState = args[3];
|
||||
Object previousState = superMethod.call();
|
||||
if (holder.isActive()) {
|
||||
compareAndUpdateBlockState(x, y, z, newState, previousState, holder);
|
||||
}
|
||||
return previousState;
|
||||
}
|
||||
}
|
||||
|
||||
public static class GetAndSetInterceptor {
|
||||
public static final GetAndSetInterceptor INSTANCE = new GetAndSetInterceptor();
|
||||
|
||||
@RuntimeType
|
||||
public Object intercept(@This Object thisObj, @AllArguments Object[] args) {
|
||||
InjectedPalettedContainerHolder holder = (InjectedPalettedContainerHolder) thisObj;
|
||||
InjectedHolder.Palette holder = (InjectedHolder.Palette) thisObj;
|
||||
Object targetStates = holder.target();
|
||||
int x = (int) args[0];
|
||||
int y = (int) args[1];
|
||||
int z = (int) args[2];
|
||||
Object previousState = FastNMS.INSTANCE.method$PalettedContainer$getAndSet(targetStates, x, y, z, args[3]);
|
||||
try {
|
||||
Object newState = args[3];
|
||||
int stateId = BlockStateUtils.blockStateToId(newState);
|
||||
CESection section = holder.ceSection();
|
||||
// 如果是原版方块
|
||||
if (BlockStateUtils.isVanillaBlock(stateId)) {
|
||||
// 那么应该情况自定义块
|
||||
ImmutableBlockState previous = section.setBlockState(x, y, z, EmptyBlock.STATE);
|
||||
// 如果先前不是空气则标记
|
||||
if (!previous.isEmpty()) {
|
||||
holder.ceChunk().setDirty(true);
|
||||
}
|
||||
if (Config.enableLightSystem() && Config.forceUpdateLight()) {
|
||||
updateLightIfChanged(holder, previousState, newState, null, y, z, x);
|
||||
}
|
||||
} else {
|
||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockStateUnsafe(stateId);
|
||||
ImmutableBlockState previousImmutableBlockState = section.setBlockState(x, y, z, immutableBlockState);
|
||||
// 如果之前的自定义块(空气)和当前自定义块不同
|
||||
if (previousImmutableBlockState != immutableBlockState) {
|
||||
holder.ceChunk().setDirty(true);
|
||||
if (Config.enableLightSystem() && !immutableBlockState.isEmpty()) {
|
||||
updateLightIfChanged(holder, previousState, newState, immutableBlockState.vanillaBlockState().handle(), y, z, x);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to intercept setBlockState", e);
|
||||
Object newState = args[3];
|
||||
Object previousState = FastNMS.INSTANCE.method$PalettedContainer$getAndSet(targetStates, x, y, z, newState);
|
||||
if (holder.isActive()) {
|
||||
compareAndUpdateBlockState(x, y, z, newState, previousState, holder);
|
||||
}
|
||||
return previousState;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateLightIfChanged(@This InjectedPalettedContainerHolder thisObj, Object previousBlockState, Object newState, @Nullable Object clientSideNewState, int y, int z, int x) throws ReflectiveOperationException {
|
||||
int previousLight = BlockStateUtils.getLightEmission(previousBlockState);
|
||||
int newLight = BlockStateUtils.getLightEmission(newState);
|
||||
if (previousLight != newLight || (clientSideNewState != null && (BlockStateUtils.isOcclude(newState) != BlockStateUtils.isOcclude(clientSideNewState)))) {
|
||||
CEWorld world = thisObj.ceWorld();
|
||||
SectionPos sectionPos = thisObj.cePos();
|
||||
Set<SectionPos> posSet = SectionPosUtils.calculateAffectedRegions((sectionPos.x() << 4) + x, (sectionPos.y() << 4) + y, (sectionPos.z() << 4) + z, Math.max(newLight, previousLight));
|
||||
world.sectionLightUpdated(posSet);
|
||||
protected static void compareAndUpdateBlockState(int x, int y, int z, Object newState, Object previousState, InjectedHolder holder) {
|
||||
try {
|
||||
int stateId = BlockStateUtils.blockStateToId(newState);
|
||||
CESection section = holder.ceSection();
|
||||
// 如果是原版方块
|
||||
if (BlockStateUtils.isVanillaBlock(stateId)) {
|
||||
// 那么应该情况自定义块
|
||||
ImmutableBlockState previous = section.setBlockState(x, y, z, EmptyBlock.STATE);
|
||||
// 如果先前不是空气则标记
|
||||
if (!previous.isEmpty()) {
|
||||
holder.ceChunk().setDirty(true);
|
||||
}
|
||||
if (Config.enableLightSystem() && Config.forceUpdateLight()) {
|
||||
updateLightIfChanged(holder, previousState, newState, null, y, z, x);
|
||||
}
|
||||
} else {
|
||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockStateUnsafe(stateId);
|
||||
ImmutableBlockState previousImmutableBlockState = section.setBlockState(x, y, z, immutableBlockState);
|
||||
// 如果之前的自定义块(空气)和当前自定义块不同
|
||||
if (previousImmutableBlockState != immutableBlockState) {
|
||||
holder.ceChunk().setDirty(true);
|
||||
if (Config.enableLightSystem() && !immutableBlockState.isEmpty()) {
|
||||
updateLightIfChanged(holder, previousState, newState, immutableBlockState.vanillaBlockState().handle(), y, z, x);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to intercept setBlockState", e);
|
||||
}
|
||||
}
|
||||
|
||||
protected static void updateLightIfChanged(@This InjectedHolder thisObj, Object previousBlockState, Object newState, @Nullable Object clientSideNewState, int y, int z, int x) throws ReflectiveOperationException {
|
||||
int previousLight = BlockStateUtils.getLightEmission(previousBlockState);
|
||||
int newLight = BlockStateUtils.getLightEmission(newState);
|
||||
if (previousLight != newLight || (clientSideNewState != null && (BlockStateUtils.isOcclude(newState) != BlockStateUtils.isOcclude(clientSideNewState)))) {
|
||||
CEWorld world = thisObj.ceChunk().world();
|
||||
SectionPos sectionPos = thisObj.cePos();
|
||||
Set<SectionPos> posSet = SectionPosUtils.calculateAffectedRegions((sectionPos.x() << 4) + x, (sectionPos.y() << 4) + y, (sectionPos.z() << 4) + z, Math.max(newLight, previousLight));
|
||||
world.sectionLightUpdated(posSet);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.network;
|
||||
|
||||
import com.mojang.datafixers.util.Either;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
@@ -33,6 +34,7 @@ import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.plugin.network.ConnectionState;
|
||||
import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
|
||||
import net.momirealms.craftengine.core.plugin.network.NetworkManager;
|
||||
import net.momirealms.craftengine.core.plugin.network.ProtocolVersion;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import net.momirealms.craftengine.core.world.BlockHitResult;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
@@ -52,6 +54,7 @@ import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.util.RayTraceResult;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@@ -198,7 +201,6 @@ public class PacketConsumers {
|
||||
buf.writeInt(chunkZ);
|
||||
if (VersionHelper.isOrAbove1_21_5()) {
|
||||
buf.writeVarInt(heightmapsCount);
|
||||
assert heightmapsMap != null;
|
||||
for (Map.Entry<Integer, long[]> entry : heightmapsMap.entrySet()) {
|
||||
buf.writeVarInt(entry.getKey());
|
||||
buf.writeLongArray(entry.getValue());
|
||||
@@ -331,8 +333,17 @@ public class PacketConsumers {
|
||||
Tag displayName = buf.readNbt(false);
|
||||
if (displayName == null) return;
|
||||
byte friendlyFlags = buf.readByte();
|
||||
String nameTagVisibility = buf.readUtf(40);
|
||||
String collisionRule = buf.readUtf(40);
|
||||
|
||||
Either<String, Integer> eitherVisibility;
|
||||
Either<String, Integer> eitherCollisionRule;
|
||||
|
||||
if (VersionHelper.isOrAbove1_21_5()) {
|
||||
eitherVisibility = Either.right(buf.readVarInt());
|
||||
eitherCollisionRule = Either.right(buf.readVarInt());
|
||||
} else {
|
||||
eitherVisibility = Either.left(buf.readUtf(40));
|
||||
eitherCollisionRule = Either.left(buf.readUtf(40));
|
||||
}
|
||||
int color = buf.readVarInt();
|
||||
Tag prefix = buf.readNbt(false);
|
||||
if (prefix == null) return;
|
||||
@@ -368,8 +379,8 @@ public class PacketConsumers {
|
||||
}
|
||||
|
||||
buf.writeByte(friendlyFlags);
|
||||
buf.writeUtf(nameTagVisibility);
|
||||
buf.writeUtf(collisionRule);
|
||||
eitherVisibility.ifLeft(buf::writeUtf).ifRight(buf::writeVarInt);
|
||||
eitherCollisionRule.ifLeft(buf::writeUtf).ifRight(buf::writeVarInt);
|
||||
buf.writeVarInt(color);
|
||||
|
||||
if (!tokens2.isEmpty()) {
|
||||
@@ -1339,7 +1350,7 @@ public class PacketConsumers {
|
||||
// When the hotbar is full, the latest creative mode inventory can only be accessed when the player opens the inventory screen. Currently, it is not worth further handling this issue.
|
||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> SET_CREATIVE_SLOT = (user, event, packet) -> {
|
||||
try {
|
||||
if (VersionHelper.isOrAbove1_21_4()) return;
|
||||
if (user.protocolVersion().isVersionNewerThan(ProtocolVersion.V1_21_4)) return;
|
||||
if (!user.isOnline()) return;
|
||||
BukkitServerPlayer player = (BukkitServerPlayer) user;
|
||||
if (VersionHelper.isFolia()) {
|
||||
@@ -1349,7 +1360,7 @@ public class PacketConsumers {
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundSetCreativeModeSlotPacket", e);
|
||||
}
|
||||
}, (World) player.level().platformWorld(), (MCUtils.fastFloor(player.x())) >> 4, (MCUtils.fastFloor(player.z())) >> 4);
|
||||
}, (World) player.world().platformWorld(), (MCUtils.fastFloor(player.x())) >> 4, (MCUtils.fastFloor(player.z())) >> 4);
|
||||
} else {
|
||||
handleSetCreativeSlotPacketOnMainThread(player, packet);
|
||||
}
|
||||
@@ -1469,7 +1480,7 @@ public class PacketConsumers {
|
||||
if (state == null) return;
|
||||
Key itemId = state.settings().itemId();
|
||||
if (itemId == null) return;
|
||||
pickItem(player, itemId);
|
||||
pickItem(player, itemId, pos, null);
|
||||
}
|
||||
|
||||
// 1.21.4+
|
||||
@@ -1508,18 +1519,24 @@ public class PacketConsumers {
|
||||
private static void handlePickItemFromEntityOnMainThread(Player player, LoadedFurniture furniture) throws Exception {
|
||||
Key itemId = furniture.config().settings().itemId();
|
||||
if (itemId == null) return;
|
||||
pickItem(player, itemId);
|
||||
pickItem(player, itemId, null, FastNMS.INSTANCE.method$CraftEntity$getHandle(furniture.baseEntity()));
|
||||
}
|
||||
|
||||
private static void pickItem(Player player, Key itemId) throws IllegalAccessException, InvocationTargetException {
|
||||
private static void pickItem(Player player, Key itemId, @Nullable Object blockPos, @Nullable Object entity) throws IllegalAccessException, InvocationTargetException {
|
||||
ItemStack itemStack = BukkitCraftEngine.instance().itemManager().buildCustomItemStack(itemId, BukkitCraftEngine.instance().adapt(player));
|
||||
if (itemStack == null) {
|
||||
CraftEngine.instance().logger().warn("Item: " + itemId + " is not a valid item");
|
||||
return;
|
||||
}
|
||||
assert Reflections.method$ServerGamePacketListenerImpl$tryPickItem != null;
|
||||
Reflections.method$ServerGamePacketListenerImpl$tryPickItem.invoke(
|
||||
Reflections.field$ServerPlayer$connection.get(FastNMS.INSTANCE.method$CraftPlayer$getHandle(player)), FastNMS.INSTANCE.method$CraftItemStack$asNMSCopy(itemStack));
|
||||
if (VersionHelper.isOrAbove1_21_5()) {
|
||||
Reflections.method$ServerGamePacketListenerImpl$tryPickItem.invoke(
|
||||
Reflections.field$ServerPlayer$connection.get(FastNMS.INSTANCE.method$CraftPlayer$getHandle(player)),
|
||||
FastNMS.INSTANCE.method$CraftItemStack$asNMSCopy(itemStack), blockPos, entity, true);
|
||||
} else {
|
||||
Reflections.method$ServerGamePacketListenerImpl$tryPickItem.invoke(
|
||||
Reflections.field$ServerPlayer$connection.get(FastNMS.INSTANCE.method$CraftPlayer$getHandle(player)), FastNMS.INSTANCE.method$CraftItemStack$asNMSCopy(itemStack));
|
||||
}
|
||||
}
|
||||
|
||||
public static final BiConsumer<NetWorkUser, ByteBufPacketEvent> ADD_ENTITY_BYTEBUFFER = (user, event) -> {
|
||||
|
||||
@@ -26,6 +26,8 @@ import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import net.momirealms.craftengine.core.world.WorldEvents;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.attribute.AttributeInstance;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@@ -427,8 +429,8 @@ public class BukkitServerPlayer extends Player {
|
||||
} else {
|
||||
if (VersionHelper.isOrAbove1_20_5()) {
|
||||
Object attributeModifier = VersionHelper.isOrAbove1_21() ?
|
||||
Reflections.constructor$AttributeModifier.newInstance(KeyUtils.toResourceLocation("craftengine", "custom_hardness"), -9999d, Reflections.instance$AttributeModifier$Operation$ADD_VALUE) :
|
||||
Reflections.constructor$AttributeModifier.newInstance(UUID.randomUUID(), "craftengine:custom_hardness", -9999d, Reflections.instance$AttributeModifier$Operation$ADD_VALUE);
|
||||
Reflections.constructor$AttributeModifier.newInstance(KeyUtils.toResourceLocation(Key.DEFAULT_NAMESPACE, "custom_hardness"), -9999d, Reflections.instance$AttributeModifier$Operation$ADD_VALUE) :
|
||||
Reflections.constructor$AttributeModifier.newInstance(UUID.randomUUID(), Key.DEFAULT_NAMESPACE + ":custom_hardness", -9999d, Reflections.instance$AttributeModifier$Operation$ADD_VALUE);
|
||||
Object attributeSnapshot = Reflections.constructor$ClientboundUpdateAttributesPacket$AttributeSnapshot.newInstance(Reflections.instance$Holder$Attribute$block_break_speed, 1d, Lists.newArrayList(attributeModifier));
|
||||
Object newPacket = Reflections.constructor$ClientboundUpdateAttributesPacket1.newInstance(entityID(), Lists.newArrayList(attributeSnapshot));
|
||||
sendPacket(newPacket, true);
|
||||
@@ -677,7 +679,7 @@ public class BukkitServerPlayer extends Player {
|
||||
}
|
||||
|
||||
@Override
|
||||
public World level() {
|
||||
public World world() {
|
||||
return new BukkitWorld(platformPlayer().getWorld());
|
||||
}
|
||||
|
||||
@@ -800,4 +802,18 @@ public class BukkitServerPlayer extends Player {
|
||||
this.resourcePackUUID.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performCommand(String command) {
|
||||
platformPlayer().performCommand(command);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double luck() {
|
||||
if (VersionHelper.isOrAbove1_21_3()) {
|
||||
return Optional.ofNullable(platformPlayer().getAttribute(Attribute.LUCK)).map(AttributeInstance::getValue).orElse(1d);
|
||||
} else {
|
||||
return LegacyAttributeUtils.getLuck(platformPlayer());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ public class ParticleUtils {
|
||||
} catch (IllegalArgumentException e) {
|
||||
return switch (particle) {
|
||||
case "REDSTONE" -> Particle.valueOf("DUST");
|
||||
case "VILLAGER_HAPPY" -> Particle.valueOf(VersionHelper.isOrAbove1_20_5() ? "HAPPY_VILLAGER" : "VILLAGER_HAPPY");
|
||||
case "VILLAGER_HAPPY", "HAPPY_VILLAGER" -> Particle.valueOf(VersionHelper.isOrAbove1_20_5() ? "HAPPY_VILLAGER" : "VILLAGER_HAPPY");
|
||||
default -> Particle.valueOf(particle);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1928,7 +1928,6 @@ public class Reflections {
|
||||
// field$ChunkAccess$blockEntities = targetField;
|
||||
// }
|
||||
|
||||
@Deprecated
|
||||
public static final Method method$LevelChunkSection$setBlockState = requireNonNull(
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$LevelChunkSection, clazz$BlockState, int.class, int.class, int.class, clazz$BlockState, boolean.class
|
||||
@@ -4963,10 +4962,10 @@ public class Reflections {
|
||||
|
||||
public static final Method method$BonemealableBlock$isValidBonemealTarget = requireNonNull(
|
||||
VersionHelper.isOrAbove1_20_2() ?
|
||||
ReflectionUtils.getMethod(
|
||||
ReflectionUtils.getInstanceMethod(
|
||||
clazz$BonemealableBlock, boolean.class, clazz$LevelReader, clazz$BlockPos, clazz$BlockState
|
||||
) :
|
||||
ReflectionUtils.getMethod(
|
||||
ReflectionUtils.getInstanceMethod(
|
||||
clazz$BonemealableBlock, boolean.class, clazz$LevelReader, clazz$BlockPos, clazz$BlockState, boolean.class
|
||||
)
|
||||
);
|
||||
@@ -5030,6 +5029,10 @@ public class Reflections {
|
||||
);
|
||||
|
||||
public static final Method method$ServerGamePacketListenerImpl$tryPickItem =
|
||||
VersionHelper.isOrAbove1_21_5() ?
|
||||
ReflectionUtils.getDeclaredMethod(
|
||||
clazz$ServerGamePacketListenerImpl, void.class, clazz$ItemStack, clazz$BlockPos, clazz$Entity, boolean.class
|
||||
) :
|
||||
ReflectionUtils.getDeclaredMethod(
|
||||
clazz$ServerGamePacketListenerImpl, void.class, clazz$ItemStack
|
||||
);
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package net.momirealms.craftengine.bukkit.world;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks;
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.item.behavior.BlockItemBehavior;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
@@ -13,24 +15,25 @@ import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.context.BlockPlaceContext;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.world.WorldBlock;
|
||||
import net.momirealms.craftengine.core.world.BlockInWorld;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class BukkitWorldBlock implements WorldBlock {
|
||||
public class BukkitBlockInWorld implements BlockInWorld {
|
||||
private final Block block;
|
||||
|
||||
public BukkitWorldBlock(Block block) {
|
||||
public BukkitBlockInWorld(Block block) {
|
||||
this.block = block;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public boolean canBeReplaced(BlockPlaceContext context) {
|
||||
ImmutableBlockState customState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockDataToId(block.getBlockData()));
|
||||
ImmutableBlockState customState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockDataToId(this.block.getBlockData()));
|
||||
if (customState != null && !customState.isEmpty()) {
|
||||
Key clickedBlockId = customState.owner().value().id();
|
||||
Item<ItemStack> item = (Item<ItemStack>) context.getPlayer().getItemInHand(context.getHand());
|
||||
@@ -45,14 +48,14 @@ public class BukkitWorldBlock implements WorldBlock {
|
||||
}
|
||||
}
|
||||
}
|
||||
return block.isReplaceable();
|
||||
return this.block.isReplaceable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWaterSource(BlockPlaceContext blockPlaceContext) {
|
||||
try {
|
||||
Location location = block.getLocation();
|
||||
Object serverLevel = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(block.getWorld());
|
||||
Location location = this.block.getLocation();
|
||||
Object serverLevel = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(this.block.getWorld());
|
||||
Object fluidData = Reflections.method$Level$getFluidState.invoke(serverLevel, LocationUtils.toBlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()));
|
||||
if (fluidData == null) return false;
|
||||
return Reflections.method$FluidState$getType.invoke(fluidData) == Reflections.instance$Fluids$WATER;
|
||||
@@ -62,7 +65,45 @@ public class BukkitWorldBlock implements WorldBlock {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int x() {
|
||||
return this.block.getX();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int y() {
|
||||
return this.block.getY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int z() {
|
||||
return this.block.getZ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public World world() {
|
||||
return new BukkitWorld(this.block.getWorld());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsString() {
|
||||
ImmutableBlockState state = CraftEngineBlocks.getCustomBlockState(this.block);
|
||||
if (state != null) {
|
||||
return state.toString();
|
||||
}
|
||||
return this.block.getBlockData().getAsString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key owner() {
|
||||
ImmutableBlockState state = CraftEngineBlocks.getCustomBlockState(this.block);
|
||||
if (state != null) {
|
||||
return state.owner().value().id();
|
||||
}
|
||||
return KeyUtils.namespacedKey2Key(this.block.getType().getKey());
|
||||
}
|
||||
|
||||
public Block block() {
|
||||
return block;
|
||||
return this.block;
|
||||
}
|
||||
}
|
||||
@@ -6,9 +6,9 @@ import net.momirealms.craftengine.bukkit.util.ItemUtils;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.craftengine.core.world.BlockInWorld;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import net.momirealms.craftengine.core.world.WorldBlock;
|
||||
import net.momirealms.craftengine.core.world.WorldHeight;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.SoundCategory;
|
||||
@@ -51,8 +51,8 @@ public class BukkitWorld implements World {
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldBlock getBlockAt(int x, int y, int z) {
|
||||
return new BukkitWorldBlock(platformWorld().getBlockAt(x, y, z));
|
||||
public BlockInWorld getBlockAt(int x, int y, int z) {
|
||||
return new BukkitBlockInWorld(platformWorld().getBlockAt(x, y, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -266,23 +266,24 @@ public class BukkitWorldManager implements WorldManager, Listener {
|
||||
if (ceChunk != null) {
|
||||
if (ceChunk.dirty()) {
|
||||
try {
|
||||
world.worldDataStorage().writeChunkAt(pos, ceChunk, false);
|
||||
this.plugin.debug(() -> "[Dirty Chunk]" + pos + " unloaded");
|
||||
world.worldDataStorage().writeChunkAt(pos, ceChunk);
|
||||
ceChunk.setDirty(false);
|
||||
} catch (IOException e) {
|
||||
this.plugin.logger().warn("Failed to write chunk tag at " + chunk.getX() + " " + chunk.getZ(), e);
|
||||
}
|
||||
}
|
||||
if (Config.restoreVanillaBlocks()) {
|
||||
boolean unsaved = false;
|
||||
CESection[] ceSections = ceChunk.sections();
|
||||
Object worldServer = FastNMS.INSTANCE.field$CraftChunk$worldServer(chunk);
|
||||
Object chunkSource = FastNMS.INSTANCE.method$ServerLevel$getChunkSource(worldServer);
|
||||
Object levelChunk = FastNMS.INSTANCE.method$ServerChunkCache$getChunkAtIfLoadedMainThread(chunkSource, chunk.getX(), chunk.getZ());
|
||||
Object[] sections = FastNMS.INSTANCE.method$ChunkAccess$getSections(levelChunk);
|
||||
for (int i = 0; i < ceSections.length; i++) {
|
||||
CESection ceSection = ceSections[i];
|
||||
Object section = sections[i];
|
||||
BukkitInjector.uninjectLevelChunkSection(section);
|
||||
boolean unsaved = false;
|
||||
CESection[] ceSections = ceChunk.sections();
|
||||
Object worldServer = FastNMS.INSTANCE.field$CraftChunk$worldServer(chunk);
|
||||
Object chunkSource = FastNMS.INSTANCE.method$ServerLevel$getChunkSource(worldServer);
|
||||
Object levelChunk = FastNMS.INSTANCE.method$ServerChunkCache$getChunkAtIfLoadedMainThread(chunkSource, chunk.getX(), chunk.getZ());
|
||||
Object[] sections = FastNMS.INSTANCE.method$ChunkAccess$getSections(levelChunk);
|
||||
for (int i = 0; i < ceSections.length; i++) {
|
||||
CESection ceSection = ceSections[i];
|
||||
Object section = sections[i];
|
||||
BukkitInjector.uninjectLevelChunkSection(section);
|
||||
if (Config.restoreVanillaBlocks()) {
|
||||
if (!ceSection.statesContainer().isEmpty()) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
@@ -297,9 +298,9 @@ public class BukkitWorldManager implements WorldManager, Listener {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (unsaved && !FastNMS.INSTANCE.method$LevelChunk$isUnsaved(levelChunk)) {
|
||||
FastNMS.INSTANCE.method$LevelChunk$markUnsaved(levelChunk);
|
||||
}
|
||||
}
|
||||
if (unsaved && !FastNMS.INSTANCE.method$LevelChunk$isUnsaved(levelChunk)) {
|
||||
FastNMS.INSTANCE.method$LevelChunk$markUnsaved(levelChunk);
|
||||
}
|
||||
ceChunk.unload();
|
||||
}
|
||||
@@ -383,7 +384,9 @@ public class BukkitWorldManager implements WorldManager, Listener {
|
||||
}
|
||||
}
|
||||
}
|
||||
BukkitInjector.injectLevelChunkSection(section, ceSection, ceWorld, ceChunk, new SectionPos(pos.x, ceChunk.sectionY(i), pos.z));
|
||||
int finalI = i;
|
||||
BukkitInjector.injectLevelChunkSection(section, ceSection, ceChunk, new SectionPos(pos.x, ceChunk.sectionY(i), pos.z),
|
||||
(injected) -> sections[finalI] = injected);
|
||||
}
|
||||
if (Config.enableRecipeSystem()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
@@ -52,8 +52,12 @@ dependencies {
|
||||
// Aho-Corasick java implementation
|
||||
compileOnly("org.ahocorasick:ahocorasick:${rootProject.properties["ahocorasick_version"]}")
|
||||
// Amazon S3
|
||||
compileOnly("software.amazon.awssdk:s3:${rootProject.properties["amazon_awssdk_version"]}")
|
||||
compileOnly("software.amazon.awssdk:s3:${rootProject.properties["amazon_awssdk_version"]}") {
|
||||
|
||||
}
|
||||
compileOnly("software.amazon.awssdk:netty-nio-client:${rootProject.properties["amazon_awssdk_version"]}")
|
||||
// EvalEx
|
||||
compileOnly("com.ezylang:EvalEx:${rootProject.properties["evalex_version"]}")
|
||||
}
|
||||
|
||||
java {
|
||||
@@ -85,6 +89,7 @@ tasks {
|
||||
relocate("net.jpountz", "net.momirealms.craftengine.libraries.jpountz") // lz4
|
||||
relocate("software.amazon.awssdk", "net.momirealms.craftengine.libraries.awssdk") // awssdk
|
||||
relocate("software.amazon.eventstream", "net.momirealms.craftengine.libraries.eventstream") // awssdk
|
||||
relocate("com.ezylang.evalex", "net.momirealms.craftengine.libraries.evalex")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,16 +2,18 @@ package net.momirealms.craftengine.core.block;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.loot.LootTable;
|
||||
import net.momirealms.craftengine.core.loot.parameter.LootParameters;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.CommonParameters;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.util.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import net.momirealms.craftengine.shared.block.BlockBehavior;
|
||||
import net.momirealms.sparrow.nbt.CompoundTag;
|
||||
import net.momirealms.sparrow.nbt.NBT;
|
||||
import net.momirealms.sparrow.nbt.Tag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
@@ -138,12 +140,16 @@ public class ImmutableBlockState extends BlockStateHolder {
|
||||
return state.with(property, (T) value);
|
||||
}
|
||||
|
||||
public List<Item<Object>> getDrops(@NotNull ContextHolder.Builder builder, @NotNull World world) {
|
||||
return this.getDrops(builder, world, null);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Item<Object>> getDrops(ContextHolder.Builder builder, World world) {
|
||||
public List<Item<Object>> getDrops(@NotNull ContextHolder.Builder builder, @NotNull World world, @Nullable Player player) {
|
||||
CustomBlock block = owner.value();
|
||||
if (block == null) return List.of();
|
||||
LootTable<Object> lootTable = (LootTable<Object>) block.lootTable();
|
||||
if (lootTable == null) return List.of();
|
||||
return lootTable.getRandomItems(builder.withParameter(LootParameters.BLOCK_STATE, this).build(), world);
|
||||
return lootTable.getRandomItems(builder.withParameter(CommonParameters.BLOCK_STATE, this).build(), world, player);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,10 @@ public class UpdateOption {
|
||||
return flags;
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private int flags;
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ public class BlockBehaviors {
|
||||
public static BlockBehavior fromMap(CustomBlock block, @Nullable Map<String, Object> map) {
|
||||
if (map == null || map.isEmpty()) return EmptyBlockBehavior.INSTANCE;
|
||||
String type = ResourceConfigUtils.requireNonEmptyStringOrThrow(map.get("type"), "warning.config.block.behavior.missing_type");
|
||||
Key key = Key.withDefaultNamespace(type, "craftengine");
|
||||
Key key = Key.withDefaultNamespace(type, Key.DEFAULT_NAMESPACE);
|
||||
BlockBehaviorFactory factory = BuiltInRegistries.BLOCK_BEHAVIOR_FACTORY.getValue(key);
|
||||
if (factory == null) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.behavior.invalid_type", type.toString());
|
||||
|
||||
@@ -33,7 +33,7 @@ public class Properties {
|
||||
|
||||
public static Property<?> fromMap(String name, Map<String, Object> map) {
|
||||
String type = ResourceConfigUtils.requireNonEmptyStringOrThrow(map.get("type"), "warning.config.block.state.property.missing_type");
|
||||
Key key = Key.withDefaultNamespace(type, "craftengine");
|
||||
Key key = Key.withDefaultNamespace(type, Key.DEFAULT_NAMESPACE);
|
||||
PropertyFactory factory = BuiltInRegistries.PROPERTY_FACTORY.getValue(key);
|
||||
if (factory == null) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.property.invalid_type", key.toString(), name);
|
||||
|
||||
@@ -1,16 +1,24 @@
|
||||
package net.momirealms.craftengine.core.entity;
|
||||
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
|
||||
public abstract class Entity {
|
||||
|
||||
public abstract Key type();
|
||||
|
||||
public abstract double x();
|
||||
|
||||
public abstract double y();
|
||||
|
||||
public abstract double z();
|
||||
|
||||
public Vec3d position() {
|
||||
return new Vec3d(x(), y(), z());
|
||||
}
|
||||
|
||||
public abstract void tick();
|
||||
|
||||
public abstract int entityID();
|
||||
@@ -19,7 +27,7 @@ public abstract class Entity {
|
||||
|
||||
public abstract float getYRot();
|
||||
|
||||
public abstract World level();
|
||||
public abstract World world();
|
||||
|
||||
public abstract Direction getDirection();
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class Player extends Entity implements NetWorkUser {
|
||||
private static final Key TYPE = Key.of("minecraft:player");
|
||||
|
||||
public abstract boolean isSecondaryUseActive();
|
||||
|
||||
@@ -84,4 +85,13 @@ public abstract class Player extends Entity implements NetWorkUser {
|
||||
public abstract void clearView();
|
||||
|
||||
public abstract void unloadCurrentResourcePack();
|
||||
|
||||
public abstract void performCommand(String command);
|
||||
|
||||
public abstract double luck();
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,11 +7,11 @@ import net.momirealms.craftengine.core.pack.Pack;
|
||||
import net.momirealms.craftengine.core.pack.ResourceLocation;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.craftengine.core.plugin.locale.TranslationManager;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import net.momirealms.craftengine.core.util.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.util.context.PlayerContext;
|
||||
import org.ahocorasick.trie.Token;
|
||||
import org.ahocorasick.trie.Trie;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -121,10 +121,10 @@ public abstract class AbstractFontManager implements FontManager {
|
||||
continue;
|
||||
Component content = AdventureHelper.miniMessage().deserialize(
|
||||
emoji.content(),
|
||||
PlayerContext.of(player, ContextHolder.builder()
|
||||
PlayerOptionalContext.of(player, ContextHolder.builder()
|
||||
.withOptionalParameter(EmojiParameters.EMOJI, emoji.emojiImage())
|
||||
.withParameter(EmojiParameters.KEYWORD, emoji.keywords().get(0))
|
||||
.build()).tagResolvers()
|
||||
).tagResolvers()
|
||||
);
|
||||
replacements.put(fragment, AdventureHelper.componentToMiniMessage(content));
|
||||
}
|
||||
@@ -167,10 +167,10 @@ public abstract class AbstractFontManager implements FontManager {
|
||||
continue;
|
||||
emojis.put(fragment, AdventureHelper.miniMessage().deserialize(
|
||||
emoji.content(),
|
||||
PlayerContext.of(player, ContextHolder.builder()
|
||||
PlayerOptionalContext.of(player, ContextHolder.builder()
|
||||
.withOptionalParameter(EmojiParameters.EMOJI, emoji.emojiImage())
|
||||
.withParameter(EmojiParameters.KEYWORD, emoji.keywords().get(0))
|
||||
.build()).tagResolvers())
|
||||
).tagResolvers())
|
||||
);
|
||||
if (emojis.size() >= maxTimes) break;
|
||||
}
|
||||
@@ -199,11 +199,9 @@ public abstract class AbstractFontManager implements FontManager {
|
||||
continue;
|
||||
emojis.put(fragment, AdventureHelper.miniMessage().deserialize(
|
||||
emoji.content(),
|
||||
PlayerContext.of(player,
|
||||
ContextHolder.builder()
|
||||
.withOptionalParameter(EmojiParameters.EMOJI, emoji.emojiImage())
|
||||
.withParameter(EmojiParameters.KEYWORD, emoji.keywords().get(0))
|
||||
.build()
|
||||
PlayerOptionalContext.of(player, ContextHolder.builder()
|
||||
.withOptionalParameter(EmojiParameters.EMOJI, emoji.emojiImage())
|
||||
.withParameter(EmojiParameters.KEYWORD, emoji.keywords().get(0))
|
||||
).tagResolvers()
|
||||
));
|
||||
if (emojis.size() >= maxTimes) break;
|
||||
@@ -454,15 +452,32 @@ public abstract class AbstractFontManager implements FontManager {
|
||||
return it.toCharArray();
|
||||
}
|
||||
}).toList();
|
||||
if (chars.isEmpty()) {
|
||||
throw new LocalizedResourceConfigException("warning.config.image.missing_char", path, id);
|
||||
}
|
||||
} else {
|
||||
if (charsObj instanceof Integer integer) {
|
||||
chars = List.of(new char[]{(char) integer.intValue()});
|
||||
} else {
|
||||
String character = charsObj.toString();
|
||||
if (character.isEmpty()) {
|
||||
throw new LocalizedResourceConfigException("warning.config.image.missing_char", path, id);
|
||||
}
|
||||
if (character.length() == 1) {
|
||||
chars = List.of(character.toCharArray());
|
||||
} else {
|
||||
chars = List.of(CharacterUtils.decodeUnicodeToChars(character));
|
||||
if (character.startsWith("\\u")) {
|
||||
chars = List.of(CharacterUtils.decodeUnicodeToChars(character));
|
||||
} else {
|
||||
if (CharacterUtils.containsCombinedCharacter(character)) {
|
||||
TranslationManager.instance().log("warning.config.image.invalid_char", path.toString(), id.toString());
|
||||
}
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
for (char c : character.toCharArray()) {
|
||||
stringBuilder.append(String.format("\\u%04x", (int) c));
|
||||
}
|
||||
chars = List.of(CharacterUtils.decodeUnicodeToChars(stringBuilder.toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package net.momirealms.craftengine.core.font;
|
||||
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.context.ContextKey;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextKey;
|
||||
|
||||
public class EmojiParameters {
|
||||
public static final ContextKey<String> KEYWORD = new ContextKey<>(Key.of("keyword"));
|
||||
public static final ContextKey<String> EMOJI = new ContextKey<>(Key.of("emoji"));
|
||||
public final class EmojiParameters {
|
||||
private EmojiParameters() {}
|
||||
|
||||
public static final ContextKey<String> KEYWORD = ContextKey.of("keyword");
|
||||
public static final ContextKey<String> EMOJI = ContextKey.of("emoji");
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package net.momirealms.craftengine.core.item;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.context.ContextHolder;
|
||||
|
||||
public interface BuildableItem<I> {
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
||||
import net.momirealms.craftengine.core.item.modifier.ItemDataModifier;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.context.ContextHolder;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
@@ -35,7 +34,7 @@ public interface CustomItem<I> extends BuildableItem<I> {
|
||||
}
|
||||
|
||||
default Item<I> buildItem(Player player) {
|
||||
return buildItem(ItemBuildContext.of(player, ContextHolder.EMPTY));
|
||||
return buildItem(ItemBuildContext.of(player));
|
||||
}
|
||||
|
||||
Item<I> buildItem(ItemBuildContext context);
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
package net.momirealms.craftengine.core.item;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.util.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.util.context.PlayerContext;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.CommonParameters;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class ItemBuildContext extends PlayerContext {
|
||||
import java.util.Map;
|
||||
|
||||
public class ItemBuildContext extends PlayerOptionalContext {
|
||||
public static final ItemBuildContext EMPTY = new ItemBuildContext(null, ContextHolder.EMPTY);
|
||||
|
||||
public ItemBuildContext(@Nullable Player player, @NotNull ContextHolder contexts) {
|
||||
@@ -17,4 +20,16 @@ public class ItemBuildContext extends PlayerContext {
|
||||
public static ItemBuildContext of(@Nullable Player player, @NotNull ContextHolder contexts) {
|
||||
return new ItemBuildContext(player, contexts);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ItemBuildContext of(@Nullable Player player, @NotNull ContextHolder.Builder builder) {
|
||||
if (player != null) builder.withParameter(CommonParameters.PLAYER, player);
|
||||
return new ItemBuildContext(player, builder.build());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ItemBuildContext of(@Nullable Player player) {
|
||||
if (player == null) return new ItemBuildContext(null, ContextHolder.EMPTY);
|
||||
return new ItemBuildContext(player, new ContextHolder(Map.of(CommonParameters.PLAYER, () -> player)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
|
||||
public class ItemBehaviors {
|
||||
public static final Key EMPTY = Key.from("craftengine:empty");
|
||||
public static final Key EMPTY = Key.withDefaultNamespace("empty", Key.DEFAULT_NAMESPACE);
|
||||
|
||||
public static void register(Key key, ItemBehaviorFactory factory) {
|
||||
Holder.Reference<ItemBehaviorFactory> holder = ((WritableRegistry<ItemBehaviorFactory>) BuiltInRegistries.ITEM_BEHAVIOR_FACTORY)
|
||||
@@ -25,7 +25,7 @@ public class ItemBehaviors {
|
||||
public static ItemBehavior fromMap(Pack pack, Path path, Key id, Map<String, Object> map) {
|
||||
if (map == null || map.isEmpty()) return EmptyItemBehavior.INSTANCE;
|
||||
String type = ResourceConfigUtils.requireNonEmptyStringOrThrow(map.get("type"), "warning.config.item.behavior.missing_type");
|
||||
Key key = Key.withDefaultNamespace(type, "craftengine");
|
||||
Key key = Key.withDefaultNamespace(type, Key.DEFAULT_NAMESPACE);
|
||||
ItemBehaviorFactory factory = BuiltInRegistries.ITEM_BEHAVIOR_FACTORY.getValue(key);
|
||||
if (factory == null) {
|
||||
throw new LocalizedResourceConfigException("warning.config.item.behavior.invalid_type", type.toString());
|
||||
|
||||
@@ -17,7 +17,7 @@ public class UseOnContext {
|
||||
private final Item<?> itemStack;
|
||||
|
||||
public UseOnContext(Player player, InteractionHand hand, BlockHitResult hit) {
|
||||
this(player.level(), player, hand, player.getItemInHand(hand), hit);
|
||||
this(player.world(), player, hand, player.getItemInHand(hand), hit);
|
||||
}
|
||||
|
||||
public UseOnContext(World world, Player player, InteractionHand hand, Item<?> stack, BlockHitResult hit) {
|
||||
|
||||
@@ -184,16 +184,16 @@ public class CustomSmithingTransformRecipe<T> implements Recipe<T> {
|
||||
if (type == null) {
|
||||
throw new LocalizedResourceConfigException("warning.config.recipe.smithing_transform.post_processor.missing_type");
|
||||
}
|
||||
Key key = Key.withDefaultNamespace(type, "craftengine");
|
||||
ItemDataProcessor.Factory factory = BuiltInRegistries.SMITHING_RESULT_PROCESSOR_FACTORY.getValue(key);
|
||||
Key key = Key.withDefaultNamespace(type, Key.DEFAULT_NAMESPACE);
|
||||
ItemDataProcessor.ProcessorFactory factory = BuiltInRegistries.SMITHING_RESULT_PROCESSOR_FACTORY.getValue(key);
|
||||
if (factory == null) {
|
||||
throw new LocalizedResourceConfigException("warning.config.recipe.smithing_transform.post_processor.invalid_type", type);
|
||||
}
|
||||
return factory.create(map);
|
||||
}
|
||||
|
||||
public static void register(Key key, ItemDataProcessor.Factory factory) {
|
||||
Holder.Reference<ItemDataProcessor.Factory> holder = ((WritableRegistry<ItemDataProcessor.Factory>) BuiltInRegistries.SMITHING_RESULT_PROCESSOR_FACTORY)
|
||||
public static void register(Key key, ItemDataProcessor.ProcessorFactory factory) {
|
||||
Holder.Reference<ItemDataProcessor.ProcessorFactory> holder = ((WritableRegistry<ItemDataProcessor.ProcessorFactory>) BuiltInRegistries.SMITHING_RESULT_PROCESSOR_FACTORY)
|
||||
.registerForHolder(new ResourceKey<>(Registries.SMITHING_RESULT_PROCESSOR_FACTORY.location(), key));
|
||||
holder.bindValue(factory);
|
||||
}
|
||||
@@ -203,7 +203,7 @@ public class CustomSmithingTransformRecipe<T> implements Recipe<T> {
|
||||
|
||||
Key type();
|
||||
|
||||
interface Factory {
|
||||
interface ProcessorFactory {
|
||||
ItemDataProcessor create(Map<String, Object> arguments);
|
||||
}
|
||||
}
|
||||
@@ -231,7 +231,7 @@ public class CustomSmithingTransformRecipe<T> implements Recipe<T> {
|
||||
return ItemDataProcessors.KEEP_COMPONENTS;
|
||||
}
|
||||
|
||||
public static class Factory implements ItemDataProcessor.Factory {
|
||||
public static class Factory implements ProcessorFactory {
|
||||
|
||||
@Override
|
||||
public ItemDataProcessor create(Map<String, Object> arguments) {
|
||||
@@ -268,7 +268,7 @@ public class CustomSmithingTransformRecipe<T> implements Recipe<T> {
|
||||
return ItemDataProcessors.KEEP_TAGS;
|
||||
}
|
||||
|
||||
public static class Factory implements ItemDataProcessor.Factory {
|
||||
public static class Factory implements ProcessorFactory {
|
||||
|
||||
@Override
|
||||
public ItemDataProcessor create(Map<String, Object> arguments) {
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
package net.momirealms.craftengine.core.loot;
|
||||
|
||||
import net.momirealms.craftengine.core.plugin.context.Condition;
|
||||
import net.momirealms.craftengine.core.plugin.context.condition.*;
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.registry.Registries;
|
||||
import net.momirealms.craftengine.core.registry.WritableRegistry;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
import net.momirealms.craftengine.core.util.ResourceKey;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class LootConditions {
|
||||
|
||||
static {
|
||||
register(CommonConditions.MATCH_ITEM, new MatchItemCondition.FactoryImpl<>());
|
||||
register(CommonConditions.MATCH_BLOCK_PROPERTY, new MatchBlockPropertyCondition.FactoryImpl<>());
|
||||
register(CommonConditions.TABLE_BONUS, new TableBonusCondition.FactoryImpl<>());
|
||||
register(CommonConditions.SURVIVES_EXPLOSION, new SurvivesExplosionCondition.FactoryImpl<>());
|
||||
register(CommonConditions.ANY_OF, new AnyOfCondition.FactoryImpl<>(LootConditions::fromMap));
|
||||
register(CommonConditions.ALL_OF, new AllOfCondition.FactoryImpl<>(LootConditions::fromMap));
|
||||
register(CommonConditions.ENCHANTMENT, new EnchantmentCondition.FactoryImpl<>());
|
||||
register(CommonConditions.INVERTED, new InvertedCondition.FactoryImpl<>(LootConditions::fromMap));
|
||||
register(CommonConditions.FALLING_BLOCK, new FallingBlockCondition.FactoryImpl<>());
|
||||
register(CommonConditions.RANDOM, new RandomCondition.FactoryImpl<>());
|
||||
register(CommonConditions.DISTANCE, new DistanceCondition.FactoryImpl<>());
|
||||
}
|
||||
|
||||
public static void register(Key key, ConditionFactory<LootContext> factory) {
|
||||
Holder.Reference<ConditionFactory<LootContext>> holder = ((WritableRegistry<ConditionFactory<LootContext>>) BuiltInRegistries.LOOT_CONDITION_FACTORY)
|
||||
.registerForHolder(new ResourceKey<>(Registries.LOOT_CONDITION_FACTORY.location(), key));
|
||||
holder.bindValue(factory);
|
||||
}
|
||||
|
||||
public static <T> Predicate<T> andConditions(List<? extends Predicate<T>> predicates) {
|
||||
List<Predicate<T>> list = List.copyOf(predicates);
|
||||
return switch (list.size()) {
|
||||
case 0 -> ctx -> true;
|
||||
case 1 -> list.get(0);
|
||||
case 2 -> list.get(0).and(list.get(1));
|
||||
default -> (ctx -> {
|
||||
for (Predicate<T> predicate : list) {
|
||||
if (!predicate.test(ctx)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
public static <T> Predicate<T> orConditions(List<? extends Predicate<T>> predicates) {
|
||||
List<Predicate<T>> list = List.copyOf(predicates);
|
||||
return switch (list.size()) {
|
||||
case 0 -> ctx -> false;
|
||||
case 1 -> list.get(0);
|
||||
case 2 -> list.get(0).or(list.get(1));
|
||||
default -> (ctx -> {
|
||||
for (Predicate<T> predicate : list) {
|
||||
if (predicate.test(ctx)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
public static List<Condition<LootContext>> fromMapList(List<Map<String, Object>> mapList) {
|
||||
if (mapList == null || mapList.isEmpty()) return List.of();
|
||||
List<Condition<LootContext>> functions = new ArrayList<>();
|
||||
for (Map<String, Object> map : mapList) {
|
||||
functions.add(fromMap(map));
|
||||
}
|
||||
return functions;
|
||||
}
|
||||
|
||||
public static Condition<LootContext> fromMap(Map<String, Object> map) {
|
||||
String type = ResourceConfigUtils.requireNonEmptyStringOrThrow(map.get("type"), "warning.config.loot_table.condition.missing_type");
|
||||
Key key = Key.withDefaultNamespace(type, Key.DEFAULT_NAMESPACE);
|
||||
if (key.value().charAt(0) == '!') {
|
||||
ConditionFactory<LootContext> factory = BuiltInRegistries.LOOT_CONDITION_FACTORY.getValue(new Key(key.namespace(), key.value().substring(1)));
|
||||
if (factory == null) {
|
||||
throw new LocalizedResourceConfigException("warning.config.loot_table.condition.invalid_type", type);
|
||||
}
|
||||
return new InvertedCondition<>(factory.create(map));
|
||||
} else {
|
||||
ConditionFactory<LootContext> factory = BuiltInRegistries.LOOT_CONDITION_FACTORY.getValue(key);
|
||||
if (factory == null) {
|
||||
throw new LocalizedResourceConfigException("warning.config.loot_table.condition.invalid_type", type);
|
||||
}
|
||||
return factory.create(map);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,50 +1,38 @@
|
||||
package net.momirealms.craftengine.core.loot;
|
||||
|
||||
import net.momirealms.craftengine.core.util.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.util.context.ContextKey;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class LootContext {
|
||||
public class LootContext extends PlayerOptionalContext {
|
||||
private final World world;
|
||||
private final ContextHolder contexts;
|
||||
private final Random randomSource;
|
||||
private final float luck;
|
||||
private Item<?> tempLoot;
|
||||
|
||||
public LootContext(World world, ContextHolder contexts, Random randomSource, float luck) {
|
||||
this.randomSource = randomSource;
|
||||
this.contexts = contexts;
|
||||
public LootContext(@NotNull World world, @Nullable Player player, float luck, @NotNull ContextHolder contexts) {
|
||||
super(player, contexts);
|
||||
this.world = world;
|
||||
this.luck = luck;
|
||||
}
|
||||
|
||||
public Random randomSource() {
|
||||
return randomSource;
|
||||
}
|
||||
|
||||
public <T> Optional<T> getOptionalParameter(ContextKey<T> parameter) {
|
||||
return this.contexts.getOptional(parameter);
|
||||
}
|
||||
|
||||
public boolean hasParameter(ContextKey<?> parameter) {
|
||||
return this.contexts.has(parameter);
|
||||
}
|
||||
|
||||
public <T> T getParameterOrThrow(ContextKey<T> parameter) {
|
||||
return this.contexts.getOrThrow(parameter);
|
||||
}
|
||||
|
||||
public float luck() {
|
||||
return luck;
|
||||
}
|
||||
|
||||
public ContextHolder contexts() {
|
||||
return contexts;
|
||||
return this.luck;
|
||||
}
|
||||
|
||||
public World world() {
|
||||
return world;
|
||||
return this.world;
|
||||
}
|
||||
|
||||
public Item<?> tempLoot() {
|
||||
return this.tempLoot;
|
||||
}
|
||||
|
||||
public void setTempLoot(Item<?> tempLoot) {
|
||||
this.tempLoot = tempLoot;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,32 +2,31 @@ package net.momirealms.craftengine.core.loot;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.loot.condition.LootCondition;
|
||||
import net.momirealms.craftengine.core.loot.condition.LootConditions;
|
||||
import net.momirealms.craftengine.core.loot.entry.LootEntry;
|
||||
import net.momirealms.craftengine.core.loot.entry.LootEntryContainer;
|
||||
import net.momirealms.craftengine.core.loot.function.LootFunction;
|
||||
import net.momirealms.craftengine.core.loot.function.LootFunctions;
|
||||
import net.momirealms.craftengine.core.loot.number.NumberProvider;
|
||||
import net.momirealms.craftengine.core.plugin.context.Condition;
|
||||
import net.momirealms.craftengine.core.plugin.context.number.NumberProvider;
|
||||
import net.momirealms.craftengine.core.util.MCUtils;
|
||||
import net.momirealms.craftengine.core.util.MutableInt;
|
||||
import net.momirealms.craftengine.core.util.RandomUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class LootPool<T> {
|
||||
private final List<LootEntryContainer<T>> entryContainers;
|
||||
private final List<LootCondition> conditions;
|
||||
private final List<Condition<LootContext>> conditions;
|
||||
private final Predicate<LootContext> compositeCondition;
|
||||
private final List<LootFunction<T>> functions;
|
||||
private final BiFunction<Item<T>, LootContext, Item<T>> compositeFunction;
|
||||
private final NumberProvider rolls;
|
||||
private final NumberProvider bonusRolls;
|
||||
|
||||
public LootPool(List<LootEntryContainer<T>> entryContainers, List<LootCondition> conditions, List<LootFunction<T>> functions, NumberProvider rolls, NumberProvider bonusRolls) {
|
||||
public LootPool(List<LootEntryContainer<T>> entryContainers, List<Condition<LootContext>> conditions, List<LootFunction<T>> functions, NumberProvider rolls, NumberProvider bonusRolls) {
|
||||
this.entryContainers = entryContainers;
|
||||
this.conditions = conditions;
|
||||
this.functions = functions;
|
||||
@@ -38,7 +37,7 @@ public class LootPool<T> {
|
||||
}
|
||||
|
||||
public void addRandomItems(Consumer<Item<T>> lootConsumer, LootContext context) {
|
||||
for (LootCondition condition : this.conditions) {
|
||||
for (Condition<LootContext> condition : this.conditions) {
|
||||
if (!condition.test(context)) {
|
||||
return;
|
||||
}
|
||||
@@ -62,7 +61,6 @@ public class LootPool<T> {
|
||||
}
|
||||
|
||||
private void addRandomItem(Consumer<Item<T>> lootConsumer, LootContext context) {
|
||||
Random randomSource = context.randomSource();
|
||||
List<LootEntry<T>> list = Lists.newArrayList();
|
||||
MutableInt mutableInt = new MutableInt(0);
|
||||
for (LootEntryContainer<T> lootPoolEntryContainer : this.entryContainers) {
|
||||
@@ -79,7 +77,7 @@ public class LootPool<T> {
|
||||
if (i == 1) {
|
||||
list.get(0).createItem(lootConsumer, context);
|
||||
} else {
|
||||
int j = randomSource.nextInt(mutableInt.intValue());
|
||||
int j = RandomUtils.generateRandomInt(0, mutableInt.intValue());
|
||||
for (LootEntry<T> loot : list) {
|
||||
j -= loot.getWeight(context.luck());
|
||||
if (j < 0) {
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
package net.momirealms.craftengine.core.loot;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.loot.condition.LootCondition;
|
||||
import net.momirealms.craftengine.core.loot.condition.LootConditions;
|
||||
import net.momirealms.craftengine.core.loot.entry.LootEntryContainer;
|
||||
import net.momirealms.craftengine.core.loot.entry.LootEntryContainers;
|
||||
import net.momirealms.craftengine.core.loot.function.LootFunction;
|
||||
import net.momirealms.craftengine.core.loot.function.LootFunctions;
|
||||
import net.momirealms.craftengine.core.loot.number.NumberProvider;
|
||||
import net.momirealms.craftengine.core.loot.number.NumberProviders;
|
||||
import net.momirealms.craftengine.core.plugin.context.Condition;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.number.NumberProvider;
|
||||
import net.momirealms.craftengine.core.plugin.context.number.NumberProviders;
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
import net.momirealms.craftengine.core.util.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -21,7 +21,6 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
@@ -52,7 +51,7 @@ public class LootTable<T> {
|
||||
Map<String, Object> pool = MiscUtils.castToMap(rawPoolMap, false);
|
||||
NumberProvider rolls = NumberProviders.fromObject(pool.getOrDefault("rolls", 1));
|
||||
NumberProvider bonus_rolls = NumberProviders.fromObject(pool.getOrDefault("bonus_rolls", 0));
|
||||
List<LootCondition> conditions = Optional.ofNullable(pool.get("conditions"))
|
||||
List<Condition<LootContext>> conditions = Optional.ofNullable(pool.get("conditions"))
|
||||
.map(it -> LootConditions.fromMapList(castToMapListOrThrow(it,
|
||||
() -> new LocalizedResourceConfigException("warning.config.loot_table.invalid_conditions_type", it.getClass().getSimpleName()))))
|
||||
.orElse(Lists.newArrayList());
|
||||
@@ -80,7 +79,11 @@ public class LootTable<T> {
|
||||
}
|
||||
|
||||
public ArrayList<Item<T>> getRandomItems(ContextHolder parameters, World world) {
|
||||
return this.getRandomItems(new LootContext(world, parameters, ThreadLocalRandom.current(), 1));
|
||||
return this.getRandomItems(parameters, world, null);
|
||||
}
|
||||
|
||||
public ArrayList<Item<T>> getRandomItems(ContextHolder parameters, World world, @Nullable Player player) {
|
||||
return this.getRandomItems(new LootContext(world, player, player == null ? 1f : (float) player.luck(), parameters));
|
||||
}
|
||||
|
||||
private ArrayList<Item<T>> getRandomItems(LootContext context) {
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
package net.momirealms.craftengine.core.loot.condition;
|
||||
|
||||
import net.momirealms.craftengine.core.loot.LootContext;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class AllOfCondition implements LootCondition {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private final List<LootCondition> conditions;
|
||||
|
||||
public AllOfCondition(List<LootCondition> conditions) {
|
||||
this.conditions = conditions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return LootConditions.ALL_OF;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(LootContext lootContext) {
|
||||
for (LootCondition condition : conditions) {
|
||||
if (!condition.test(lootContext)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static class Factory implements LootConditionFactory {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public LootCondition create(Map<String, Object> arguments) {
|
||||
List<Map<String, Object>> terms = (List<Map<String, Object>>) arguments.get("terms");
|
||||
return new AllOfCondition(LootConditions.fromMapList(terms));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package net.momirealms.craftengine.core.loot.condition;
|
||||
|
||||
import net.momirealms.craftengine.core.loot.LootContext;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class AnyOfCondition implements LootCondition {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private final List<LootCondition> conditions;
|
||||
|
||||
public AnyOfCondition(List<LootCondition> conditions) {
|
||||
this.conditions = conditions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return LootConditions.ANY_OF;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(LootContext lootContext) {
|
||||
for (LootCondition condition : conditions) {
|
||||
if (condition.test(lootContext)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static class Factory implements LootConditionFactory {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public LootCondition create(Map<String, Object> arguments) {
|
||||
List<Map<String, Object>> terms = (List<Map<String, Object>>) arguments.get("terms");
|
||||
return new AnyOfCondition(LootConditions.fromMapList(terms));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
package net.momirealms.craftengine.core.loot.condition;
|
||||
|
||||
import net.momirealms.craftengine.core.item.Enchantment;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.loot.LootContext;
|
||||
import net.momirealms.craftengine.core.loot.parameter.LootParameters;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class EnchantmentCondition implements LootCondition {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private final Key id;
|
||||
private final Function<Integer, Boolean> expression;
|
||||
|
||||
public EnchantmentCondition(Key id, Function<Integer, Boolean> expression) {
|
||||
this.id = id;
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return LootConditions.ENCHANTMENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(LootContext lootContext) {
|
||||
Optional<Item<?>> item = lootContext.getOptionalParameter(LootParameters.TOOL);
|
||||
if (item.isEmpty()) return false;
|
||||
Optional<Enchantment> enchantment = item.get().getEnchantment(id);
|
||||
int level = enchantment.map(Enchantment::level).orElse(0);
|
||||
return this.expression.apply(level);
|
||||
}
|
||||
|
||||
public static class Factory implements LootConditionFactory {
|
||||
@Override
|
||||
public LootCondition create(Map<String, Object> arguments) {
|
||||
String predicate = (String) arguments.get("predicate");
|
||||
String[] split = predicate.split("(<=|>=|<|>|==|=)", 2);
|
||||
int level = Integer.parseInt(split[1]);
|
||||
String operator = predicate.substring(split[0].length(), predicate.length() - split[1].length());
|
||||
Function<Integer, Boolean> expression;
|
||||
switch (operator) {
|
||||
case "<" -> expression = (i -> i < level);
|
||||
case ">" -> expression = (i -> i > level);
|
||||
case "==", "=" -> expression = (i -> i == level);
|
||||
case "<=" -> expression = (i -> i <= level);
|
||||
case ">=" -> expression = (i -> i >= level);
|
||||
default -> throw new IllegalArgumentException("Unknown operator: " + operator);
|
||||
}
|
||||
return new EnchantmentCondition(Key.of(split[0]), expression);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package net.momirealms.craftengine.core.loot.condition;
|
||||
|
||||
import net.momirealms.craftengine.core.loot.LootContext;
|
||||
import net.momirealms.craftengine.core.loot.parameter.LootParameters;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class FallingCondition implements LootCondition {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
public static final FallingCondition INSTANCE = new FallingCondition();
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return LootConditions.FALLING_BLOCK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(LootContext lootContext) {
|
||||
return lootContext.getOptionalParameter(LootParameters.FALLING_BLOCK).orElse(false);
|
||||
}
|
||||
|
||||
public static class Factory implements LootConditionFactory {
|
||||
@Override
|
||||
public LootCondition create(Map<String, Object> arguments) {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package net.momirealms.craftengine.core.loot.condition;
|
||||
|
||||
import net.momirealms.craftengine.core.loot.LootContext;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class InvertedCondition implements LootCondition {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private final LootCondition condition;
|
||||
|
||||
public InvertedCondition(LootCondition condition) {
|
||||
this.condition = condition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return LootConditions.INVERTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(LootContext lootContext) {
|
||||
return !condition.test(lootContext);
|
||||
}
|
||||
|
||||
public static class Factory implements LootConditionFactory {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public LootCondition create(Map<String, Object> arguments) {
|
||||
Map<String, Object> term = (Map<String, Object>) arguments.get("term");
|
||||
return new InvertedCondition(LootConditions.fromMap(term));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package net.momirealms.craftengine.core.loot.condition;
|
||||
|
||||
import net.momirealms.craftengine.core.loot.LootContext;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public interface LootCondition extends Predicate<LootContext> {
|
||||
|
||||
Key type();
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package net.momirealms.craftengine.core.loot.condition;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface LootConditionFactory {
|
||||
|
||||
LootCondition create(Map<String, Object> arguments);
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
package net.momirealms.craftengine.core.loot.condition;
|
||||
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.registry.Registries;
|
||||
import net.momirealms.craftengine.core.registry.WritableRegistry;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.ResourceKey;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class LootConditions {
|
||||
public static final Key MATCH_ITEM = Key.from("craftengine:match_item");
|
||||
public static final Key MATCH_BLOCK_PROPERTY = Key.from("craftengine:match_block_property");
|
||||
public static final Key TABLE_BONUS = Key.from("craftengine:table_bonus");
|
||||
public static final Key SURVIVES_EXPLOSION = Key.from("craftengine:survives_explosion");
|
||||
public static final Key RANDOM = Key.from("craftengine:random");
|
||||
public static final Key ANY_OF = Key.from("craftengine:any_of");
|
||||
public static final Key ALL_OF = Key.from("craftengine:all_of");
|
||||
public static final Key ENCHANTMENT = Key.from("craftengine:enchantment");
|
||||
public static final Key INVERTED = Key.from("craftengine:inverted");
|
||||
public static final Key FALLING_BLOCK = Key.from("craftengine:falling_block");
|
||||
|
||||
static {
|
||||
register(MATCH_ITEM, MatchItemCondition.FACTORY);
|
||||
register(MATCH_BLOCK_PROPERTY, MatchBlockPropertyCondition.FACTORY);
|
||||
register(TABLE_BONUS, TableBonusCondition.FACTORY);
|
||||
register(SURVIVES_EXPLOSION, SurvivesExplosionCondition.FACTORY);
|
||||
register(ANY_OF, AnyOfCondition.FACTORY);
|
||||
register(ALL_OF, AllOfCondition.FACTORY);
|
||||
register(ENCHANTMENT, EnchantmentCondition.FACTORY);
|
||||
register(INVERTED, InvertedCondition.FACTORY);
|
||||
register(FALLING_BLOCK, FallingCondition.FACTORY);
|
||||
register(RANDOM, RandomCondition.FACTORY);
|
||||
}
|
||||
|
||||
public static void register(Key key, LootConditionFactory factory) {
|
||||
Holder.Reference<LootConditionFactory> holder = ((WritableRegistry<LootConditionFactory>) BuiltInRegistries.LOOT_CONDITION_FACTORY)
|
||||
.registerForHolder(new ResourceKey<>(Registries.LOOT_CONDITION_FACTORY.location(), key));
|
||||
holder.bindValue(factory);
|
||||
}
|
||||
|
||||
public static <T> Predicate<T> andConditions(List<? extends Predicate<T>> predicates) {
|
||||
List<Predicate<T>> list = List.copyOf(predicates);
|
||||
return switch (list.size()) {
|
||||
case 0 -> ctx -> true;
|
||||
case 1 -> list.get(0);
|
||||
case 2 -> list.get(0).and(list.get(1));
|
||||
default -> (ctx -> {
|
||||
for (Predicate<T> predicate : list) {
|
||||
if (!predicate.test(ctx)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
public static <T> Predicate<T> orConditions(List<? extends Predicate<T>> predicates) {
|
||||
List<Predicate<T>> list = List.copyOf(predicates);
|
||||
return switch (list.size()) {
|
||||
case 0 -> ctx -> false;
|
||||
case 1 -> list.get(0);
|
||||
case 2 -> list.get(0).or(list.get(1));
|
||||
default -> (ctx -> {
|
||||
for (Predicate<T> predicate : list) {
|
||||
if (predicate.test(ctx)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
public static List<LootCondition> fromMapList(List<Map<String, Object>> mapList) {
|
||||
if (mapList == null || mapList.isEmpty()) return List.of();
|
||||
List<LootCondition> functions = new ArrayList<>();
|
||||
for (Map<String, Object> map : mapList) {
|
||||
functions.add(fromMap(map));
|
||||
}
|
||||
return functions;
|
||||
}
|
||||
|
||||
public static LootCondition fromMap(Map<String, Object> map) {
|
||||
String type = (String) map.get("type");
|
||||
if (type == null) {
|
||||
throw new LocalizedResourceConfigException("warning.config.loot_table.condition.missing_type");
|
||||
}
|
||||
Key key = Key.withDefaultNamespace(type, "craftengine");
|
||||
LootConditionFactory factory = BuiltInRegistries.LOOT_CONDITION_FACTORY.getValue(key);
|
||||
if (factory == null) {
|
||||
throw new LocalizedResourceConfigException("warning.config.loot_table.condition.invalid_type", type);
|
||||
}
|
||||
return factory.create(map);
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package net.momirealms.craftengine.core.loot.condition;
|
||||
|
||||
import net.momirealms.craftengine.core.loot.LootContext;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.RandomUtils;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class RandomCondition implements LootCondition {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private final float chance;
|
||||
|
||||
public RandomCondition(float chance) {
|
||||
this.chance = chance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return LootConditions.RANDOM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(LootContext lootContext) {
|
||||
return RandomUtils.generateRandomFloat(0, 1) < this.chance;
|
||||
}
|
||||
|
||||
public static class Factory implements LootConditionFactory {
|
||||
@Override
|
||||
public LootCondition create(Map<String, Object> arguments) {
|
||||
float chance = ResourceConfigUtils.getAsFloat(arguments.getOrDefault("value", 0.5f), "value");
|
||||
return new RandomCondition(chance);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package net.momirealms.craftengine.core.loot.condition;
|
||||
|
||||
import net.momirealms.craftengine.core.loot.LootContext;
|
||||
import net.momirealms.craftengine.core.loot.parameter.LootParameters;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class SurvivesExplosionCondition implements LootCondition {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private static final SurvivesExplosionCondition INSTANCE = new SurvivesExplosionCondition();
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return LootConditions.SURVIVES_EXPLOSION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(LootContext lootContext) {
|
||||
Optional<Float> radius = lootContext.getOptionalParameter(LootParameters.EXPLOSION_RADIUS);
|
||||
if (radius.isPresent()) {
|
||||
float f = 1f / radius.get();
|
||||
return lootContext.randomSource().nextFloat() < f;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static class Factory implements LootConditionFactory {
|
||||
@Override
|
||||
public LootCondition create(Map<String, Object> arguments) {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package net.momirealms.craftengine.core.loot.entry;
|
||||
|
||||
import net.momirealms.craftengine.core.loot.LootContext;
|
||||
import net.momirealms.craftengine.core.loot.condition.LootCondition;
|
||||
import net.momirealms.craftengine.core.plugin.context.Condition;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
@@ -10,7 +10,7 @@ public abstract class AbstractCompositeLootEntryContainer<T> extends AbstractLoo
|
||||
protected final List<LootEntryContainer<T>> children;
|
||||
private final LootEntryContainer<T> composedChildren;
|
||||
|
||||
protected AbstractCompositeLootEntryContainer(List<LootCondition> conditions, List<LootEntryContainer<T>> children) {
|
||||
protected AbstractCompositeLootEntryContainer(List<Condition<LootContext>> conditions, List<LootEntryContainer<T>> children) {
|
||||
super(conditions);
|
||||
this.children = children;
|
||||
this.composedChildren = compose(children);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package net.momirealms.craftengine.core.loot.entry;
|
||||
|
||||
import net.momirealms.craftengine.core.loot.LootContext;
|
||||
import net.momirealms.craftengine.core.loot.condition.LootCondition;
|
||||
import net.momirealms.craftengine.core.plugin.context.Condition;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MCUtils;
|
||||
|
||||
@@ -9,10 +9,10 @@ import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public abstract class AbstractLootEntryContainer<T> implements LootEntryContainer<T>, Predicate<LootContext> {
|
||||
protected final List<LootCondition> conditions;
|
||||
protected final List<Condition<LootContext>> conditions;
|
||||
private final Predicate<LootContext> compositeCondition;
|
||||
|
||||
protected AbstractLootEntryContainer(List<LootCondition> conditions) {
|
||||
protected AbstractLootEntryContainer(List<Condition<LootContext>> conditions) {
|
||||
this.conditions = conditions;
|
||||
this.compositeCondition = MCUtils.allOf(conditions);
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@ package net.momirealms.craftengine.core.loot.entry;
|
||||
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.loot.LootContext;
|
||||
import net.momirealms.craftengine.core.loot.condition.LootCondition;
|
||||
import net.momirealms.craftengine.core.loot.function.LootFunction;
|
||||
import net.momirealms.craftengine.core.loot.function.LootFunctions;
|
||||
import net.momirealms.craftengine.core.plugin.context.Condition;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
@@ -24,7 +24,7 @@ public abstract class AbstractSingleLootEntryContainer<T> extends AbstractLootEn
|
||||
}
|
||||
};
|
||||
|
||||
protected AbstractSingleLootEntryContainer(List<LootCondition> conditions, List<LootFunction<T>> functions, int weight, int quality) {
|
||||
protected AbstractSingleLootEntryContainer(List<Condition<LootContext>> conditions, List<LootFunction<T>> functions, int weight, int quality) {
|
||||
super(conditions);
|
||||
this.weight = weight;
|
||||
this.quality = quality;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package net.momirealms.craftengine.core.loot.entry;
|
||||
|
||||
import net.momirealms.craftengine.core.loot.condition.LootCondition;
|
||||
import net.momirealms.craftengine.core.loot.condition.LootConditions;
|
||||
import net.momirealms.craftengine.core.loot.LootConditions;
|
||||
import net.momirealms.craftengine.core.loot.LootContext;
|
||||
import net.momirealms.craftengine.core.plugin.context.Condition;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.util.*;
|
||||
@@ -9,7 +10,7 @@ import java.util.*;
|
||||
public class AlternativesLootEntryContainer<T> extends AbstractCompositeLootEntryContainer<T> {
|
||||
public static final Factory<?> FACTORY = new Factory<>();
|
||||
|
||||
protected AlternativesLootEntryContainer(List<LootCondition> conditions, List<LootEntryContainer<T>> children) {
|
||||
protected AlternativesLootEntryContainer(List<Condition<LootContext>> conditions, List<LootEntryContainer<T>> children) {
|
||||
super(conditions, children);
|
||||
}
|
||||
|
||||
@@ -42,7 +43,7 @@ public class AlternativesLootEntryContainer<T> extends AbstractCompositeLootEntr
|
||||
List<LootEntryContainer<A>> containers = Optional.ofNullable(arguments.get("children"))
|
||||
.map(it -> (List<LootEntryContainer<A>>) new ArrayList<LootEntryContainer<A>>(LootEntryContainers.fromMapList((List<Map<String, Object>>) it)))
|
||||
.orElse(Collections.emptyList());
|
||||
List<LootCondition> conditions = Optional.ofNullable(arguments.get("conditions"))
|
||||
List<Condition<LootContext>> conditions = Optional.ofNullable(arguments.get("conditions"))
|
||||
.map(it -> LootConditions.fromMapList((List<Map<String, Object>>) it))
|
||||
.orElse(Collections.emptyList());
|
||||
return new AlternativesLootEntryContainer<>(conditions, containers);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package net.momirealms.craftengine.core.loot.entry;
|
||||
|
||||
import net.momirealms.craftengine.core.loot.LootConditions;
|
||||
import net.momirealms.craftengine.core.loot.LootContext;
|
||||
import net.momirealms.craftengine.core.loot.condition.LootCondition;
|
||||
import net.momirealms.craftengine.core.loot.condition.LootConditions;
|
||||
import net.momirealms.craftengine.core.loot.number.NumberProvider;
|
||||
import net.momirealms.craftengine.core.loot.number.NumberProviders;
|
||||
import net.momirealms.craftengine.core.loot.parameter.LootParameters;
|
||||
import net.momirealms.craftengine.core.plugin.context.Condition;
|
||||
import net.momirealms.craftengine.core.plugin.context.number.NumberProvider;
|
||||
import net.momirealms.craftengine.core.plugin.context.number.NumberProviders;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.CommonParameters;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
|
||||
@@ -19,7 +19,7 @@ public class ExpLootEntryContainer<T> extends AbstractLootEntryContainer<T> {
|
||||
public static final Factory<?> FACTORY = new Factory<>();
|
||||
private final NumberProvider value;
|
||||
|
||||
protected ExpLootEntryContainer(NumberProvider value, List<LootCondition> conditions) {
|
||||
protected ExpLootEntryContainer(NumberProvider value, List<Condition<LootContext>> conditions) {
|
||||
super(conditions);
|
||||
this.value = value;
|
||||
}
|
||||
@@ -32,8 +32,8 @@ public class ExpLootEntryContainer<T> extends AbstractLootEntryContainer<T> {
|
||||
@Override
|
||||
public boolean expand(LootContext context, Consumer<LootEntry<T>> choiceConsumer) {
|
||||
if (super.test(context)) {
|
||||
context.getOptionalParameter(LootParameters.WORLD)
|
||||
.ifPresent(it -> context.getOptionalParameter(LootParameters.LOCATION).ifPresent(loc -> it.dropExp(loc.toCenter(), value.getInt(context))));
|
||||
context.getOptionalParameter(CommonParameters.WORLD)
|
||||
.ifPresent(it -> context.getOptionalParameter(CommonParameters.LOCATION).ifPresent(loc -> it.dropExp(loc.toCenter(), value.getInt(context))));
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -45,7 +45,7 @@ public class ExpLootEntryContainer<T> extends AbstractLootEntryContainer<T> {
|
||||
@Override
|
||||
public LootEntryContainer<A> create(Map<String, Object> arguments) {
|
||||
Object value = ResourceConfigUtils.requireNonNullOrThrow(arguments.get("count"), "warning.config.loot_table.entry.exp.missing_count");
|
||||
List<LootCondition> conditions = Optional.ofNullable(arguments.get("conditions"))
|
||||
List<Condition<LootContext>> conditions = Optional.ofNullable(arguments.get("conditions"))
|
||||
.map(it -> LootConditions.fromMapList((List<Map<String, Object>>) it))
|
||||
.orElse(Collections.emptyList());
|
||||
return new ExpLootEntryContainer<>(NumberProviders.fromObject(value), conditions);
|
||||
|
||||
@@ -42,7 +42,7 @@ public class LootEntryContainers {
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> LootEntryContainer<T> fromMap(Map<String, Object> map) {
|
||||
String type = ResourceConfigUtils.requireNonEmptyStringOrThrow(map.get("type"), "warning.config.loot_table.entry.missing_type");
|
||||
Key key = Key.withDefaultNamespace(type, "craftengine");
|
||||
Key key = Key.withDefaultNamespace(type, Key.DEFAULT_NAMESPACE);
|
||||
LootEntryContainerFactory<T> factory = (LootEntryContainerFactory<T>) BuiltInRegistries.LOOT_ENTRY_CONTAINER_FACTORY.getValue(key);
|
||||
if (factory == null) {
|
||||
throw new LocalizedResourceConfigException("warning.config.loot_table.entry.invalid_type", type);
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package net.momirealms.craftengine.core.loot.entry;
|
||||
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.loot.LootConditions;
|
||||
import net.momirealms.craftengine.core.loot.LootContext;
|
||||
import net.momirealms.craftengine.core.loot.condition.LootCondition;
|
||||
import net.momirealms.craftengine.core.loot.condition.LootConditions;
|
||||
import net.momirealms.craftengine.core.loot.function.LootFunction;
|
||||
import net.momirealms.craftengine.core.loot.function.LootFunctions;
|
||||
import net.momirealms.craftengine.core.loot.parameter.LootParameters;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.context.Condition;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.CommonParameters;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
|
||||
@@ -18,7 +18,7 @@ public class SingleItemLootEntryContainer<T> extends AbstractSingleLootEntryCont
|
||||
public static final Factory<?> FACTORY = new Factory<>();
|
||||
private final Key item;
|
||||
|
||||
protected SingleItemLootEntryContainer(Key item, List<LootCondition> conditions, List<LootFunction<T>> lootFunctions, int weight, int quality) {
|
||||
protected SingleItemLootEntryContainer(Key item, List<Condition<LootContext>> conditions, List<LootFunction<T>> lootFunctions, int weight, int quality) {
|
||||
super(conditions, lootFunctions, weight, quality);
|
||||
this.item = item;
|
||||
}
|
||||
@@ -31,7 +31,7 @@ public class SingleItemLootEntryContainer<T> extends AbstractSingleLootEntryCont
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected void createItem(Consumer<Item<T>> lootConsumer, LootContext context) {
|
||||
Item<T> tItem = (Item<T>) CraftEngine.instance().itemManager().createWrappedItem(this.item, context.getOptionalParameter(LootParameters.PLAYER).orElse(null));
|
||||
Item<T> tItem = (Item<T>) CraftEngine.instance().itemManager().createWrappedItem(this.item, context.getOptionalParameter(CommonParameters.PLAYER).orElse(null));
|
||||
if (tItem != null) {
|
||||
lootConsumer.accept(tItem);
|
||||
} else {
|
||||
@@ -47,7 +47,7 @@ public class SingleItemLootEntryContainer<T> extends AbstractSingleLootEntryCont
|
||||
Key item = Key.from(itemObj);
|
||||
int weight = ResourceConfigUtils.getAsInt(arguments.getOrDefault("weight", 1), "weight");
|
||||
int quality = ResourceConfigUtils.getAsInt(arguments.getOrDefault("quality", 0), "quality");
|
||||
List<LootCondition> conditions = Optional.ofNullable(arguments.get("conditions"))
|
||||
List<Condition<LootContext>> conditions = Optional.ofNullable(arguments.get("conditions"))
|
||||
.map(it -> LootConditions.fromMapList((List<Map<String, Object>>) it))
|
||||
.orElse(Collections.emptyList());
|
||||
List<LootFunction<A>> functions = Optional.ofNullable(arguments.get("functions"))
|
||||
|
||||
@@ -2,17 +2,17 @@ package net.momirealms.craftengine.core.loot.function;
|
||||
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.loot.LootContext;
|
||||
import net.momirealms.craftengine.core.loot.condition.LootCondition;
|
||||
import net.momirealms.craftengine.core.plugin.context.Condition;
|
||||
import net.momirealms.craftengine.core.util.MCUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public abstract class AbstractLootConditionalFunction<T> implements LootFunction<T> {
|
||||
protected final List<LootCondition> predicates;
|
||||
protected final List<Condition<LootContext>> predicates;
|
||||
private final Predicate<LootContext> compositePredicates;
|
||||
|
||||
public AbstractLootConditionalFunction(List<LootCondition> predicates) {
|
||||
public AbstractLootConditionalFunction(List<Condition<LootContext>> predicates) {
|
||||
this.predicates = predicates;
|
||||
this.compositePredicates = MCUtils.allOf(predicates);
|
||||
}
|
||||
|
||||
@@ -2,10 +2,10 @@ package net.momirealms.craftengine.core.loot.function;
|
||||
|
||||
import net.momirealms.craftengine.core.item.Enchantment;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.loot.LootConditions;
|
||||
import net.momirealms.craftengine.core.loot.LootContext;
|
||||
import net.momirealms.craftengine.core.loot.condition.LootCondition;
|
||||
import net.momirealms.craftengine.core.loot.condition.LootConditions;
|
||||
import net.momirealms.craftengine.core.loot.parameter.LootParameters;
|
||||
import net.momirealms.craftengine.core.plugin.context.Condition;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.PlayerParameters;
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
@@ -17,14 +17,13 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class ApplyBonusCountFunction<T> extends AbstractLootConditionalFunction<T> {
|
||||
public static final Factory<?> FACTORY = new Factory<>();
|
||||
private final Key enchantment;
|
||||
private final Formula formula;
|
||||
|
||||
public ApplyBonusCountFunction(List<LootCondition> predicates, Key enchantment, Formula formula) {
|
||||
public ApplyBonusCountFunction(List<Condition<LootContext>> predicates, Key enchantment, Formula formula) {
|
||||
super(predicates);
|
||||
this.enchantment = enchantment;
|
||||
this.formula = formula;
|
||||
@@ -32,7 +31,7 @@ public class ApplyBonusCountFunction<T> extends AbstractLootConditionalFunction<
|
||||
|
||||
@Override
|
||||
protected Item<T> applyInternal(Item<T> item, LootContext context) {
|
||||
Optional<Item<?>> itemInHand = context.getOptionalParameter(LootParameters.TOOL);
|
||||
Optional<Item<?>> itemInHand = context.getOptionalParameter(PlayerParameters.MAIN_HAND_ITEM);
|
||||
int level = itemInHand.map(value -> value.getEnchantment(this.enchantment).map(Enchantment::level).orElse(0)).orElse(0);
|
||||
int newCount = this.formula.apply(item.count(), level);
|
||||
item.count(newCount);
|
||||
@@ -54,7 +53,7 @@ public class ApplyBonusCountFunction<T> extends AbstractLootConditionalFunction<
|
||||
if (formulaMap == null) {
|
||||
throw new LocalizedResourceConfigException("warning.config.loot_table.function.apply_bonus.missing_formula");
|
||||
}
|
||||
List<LootCondition> conditions = Optional.ofNullable(arguments.get("conditions"))
|
||||
List<Condition<LootContext>> conditions = Optional.ofNullable(arguments.get("conditions"))
|
||||
.map(it -> LootConditions.fromMapList((List<Map<String, Object>>) it))
|
||||
.orElse(Collections.emptyList());
|
||||
return new ApplyBonusCountFunction<>(conditions, Key.from(enchantment), Formulas.fromMap(formulaMap));
|
||||
@@ -92,7 +91,7 @@ public class ApplyBonusCountFunction<T> extends AbstractLootConditionalFunction<
|
||||
if (type == null) {
|
||||
throw new NullPointerException("number type cannot be null");
|
||||
}
|
||||
Key key = Key.withDefaultNamespace(type, "craftengine");
|
||||
Key key = Key.withDefaultNamespace(type, Key.DEFAULT_NAMESPACE);
|
||||
FormulaFactory factory = BuiltInRegistries.FORMULA_FACTORY.getValue(key);
|
||||
if (factory == null) {
|
||||
throw new IllegalArgumentException("Unknown formula type: " + type);
|
||||
@@ -108,7 +107,7 @@ public class ApplyBonusCountFunction<T> extends AbstractLootConditionalFunction<
|
||||
@Override
|
||||
public int apply(int initialCount, int enchantmentLevel) {
|
||||
if (enchantmentLevel > 0) {
|
||||
int i = ThreadLocalRandom.current().nextInt(enchantmentLevel + 2) - 1;
|
||||
int i = RandomUtils.generateRandomInt(0, enchantmentLevel + 2) - 1;
|
||||
if (i < 0) {
|
||||
i = 0;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package net.momirealms.craftengine.core.loot.function;
|
||||
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.loot.LootConditions;
|
||||
import net.momirealms.craftengine.core.loot.LootContext;
|
||||
import net.momirealms.craftengine.core.loot.condition.LootCondition;
|
||||
import net.momirealms.craftengine.core.loot.condition.LootConditions;
|
||||
import net.momirealms.craftengine.core.loot.number.NumberProvider;
|
||||
import net.momirealms.craftengine.core.loot.number.NumberProviders;
|
||||
import net.momirealms.craftengine.core.loot.parameter.LootParameters;
|
||||
import net.momirealms.craftengine.core.plugin.context.Condition;
|
||||
import net.momirealms.craftengine.core.plugin.context.number.NumberProvider;
|
||||
import net.momirealms.craftengine.core.plugin.context.number.NumberProviders;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.CommonParameters;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
|
||||
@@ -19,15 +19,15 @@ public class DropExpFunction<T> extends AbstractLootConditionalFunction<T> {
|
||||
public static final Factory<?> FACTORY = new Factory<>();
|
||||
private final NumberProvider value;
|
||||
|
||||
public DropExpFunction(NumberProvider value, List<LootCondition> predicates) {
|
||||
public DropExpFunction(NumberProvider value, List<Condition<LootContext>> predicates) {
|
||||
super(predicates);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Item<T> applyInternal(Item<T> item, LootContext context) {
|
||||
context.getOptionalParameter(LootParameters.WORLD)
|
||||
.ifPresent(it -> context.getOptionalParameter(LootParameters.LOCATION).ifPresent(loc -> it.dropExp(loc.toCenter(), value.getInt(context))));
|
||||
context.getOptionalParameter(CommonParameters.WORLD)
|
||||
.ifPresent(it -> context.getOptionalParameter(CommonParameters.LOCATION).ifPresent(loc -> it.dropExp(loc.toCenter(), value.getInt(context))));
|
||||
return item;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ public class DropExpFunction<T> extends AbstractLootConditionalFunction<T> {
|
||||
@Override
|
||||
public LootFunction<T> create(Map<String, Object> arguments) {
|
||||
Object value = ResourceConfigUtils.requireNonNullOrThrow(arguments.get("count"), "warning.config.loot_table.function.drop_exp.missing_count");
|
||||
List<LootCondition> conditions = Optional.ofNullable(arguments.get("conditions"))
|
||||
List<Condition<LootContext>> conditions = Optional.ofNullable(arguments.get("conditions"))
|
||||
.map(it -> LootConditions.fromMapList((List<Map<String, Object>>) it))
|
||||
.orElse(Collections.emptyList());
|
||||
return new DropExpFunction<>(NumberProviders.fromObject(value), conditions);
|
||||
|
||||
@@ -1,31 +1,34 @@
|
||||
package net.momirealms.craftengine.core.loot.function;
|
||||
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.loot.LootConditions;
|
||||
import net.momirealms.craftengine.core.loot.LootContext;
|
||||
import net.momirealms.craftengine.core.loot.condition.LootCondition;
|
||||
import net.momirealms.craftengine.core.loot.condition.LootConditions;
|
||||
import net.momirealms.craftengine.core.loot.parameter.LootParameters;
|
||||
import net.momirealms.craftengine.core.plugin.context.Condition;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.CommonParameters;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.RandomUtils;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class ExplosionDecayFunction<T> extends AbstractLootConditionalFunction<T> {
|
||||
public static final Factory<?> FACTORY = new Factory<>();
|
||||
|
||||
public ExplosionDecayFunction(List<LootCondition> predicates) {
|
||||
public ExplosionDecayFunction(List<Condition<LootContext>> predicates) {
|
||||
super(predicates);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Item<T> applyInternal(Item<T> item, LootContext context) {
|
||||
Optional<Float> radius = context.getOptionalParameter(LootParameters.EXPLOSION_RADIUS);
|
||||
Optional<Float> radius = context.getOptionalParameter(CommonParameters.EXPLOSION_RADIUS);
|
||||
if (radius.isPresent()) {
|
||||
Random random = context.randomSource();
|
||||
float f = 1f / radius.get();
|
||||
int amount = item.count();
|
||||
int survive = 0;
|
||||
for (int j = 0; j < amount; j++) {
|
||||
if (random.nextFloat() <= f) {
|
||||
if (RandomUtils.generateRandomFloat(0, 1) <= f) {
|
||||
survive++;
|
||||
}
|
||||
}
|
||||
@@ -43,7 +46,7 @@ public class ExplosionDecayFunction<T> extends AbstractLootConditionalFunction<T
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public LootFunction<T> create(Map<String, Object> arguments) {
|
||||
List<LootCondition> conditions = Optional.ofNullable(arguments.get("conditions"))
|
||||
List<Condition<LootContext>> conditions = Optional.ofNullable(arguments.get("conditions"))
|
||||
.map(it -> LootConditions.fromMapList((List<Map<String, Object>>) it))
|
||||
.orElse(Collections.emptyList());
|
||||
return new ExplosionDecayFunction<>(conditions);
|
||||
|
||||
@@ -70,7 +70,7 @@ public class LootFunctions {
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> LootFunction<T> fromMap(Map<String, Object> map) {
|
||||
String type = ResourceConfigUtils.requireNonEmptyStringOrThrow(map.get("type"), "warning.config.loot_table.function.missing_type");
|
||||
Key key = Key.withDefaultNamespace(type, "craftengine");
|
||||
Key key = Key.withDefaultNamespace(type, Key.DEFAULT_NAMESPACE);
|
||||
LootFunctionFactory<T> factory = (LootFunctionFactory<T>) BuiltInRegistries.LOOT_FUNCTION_FACTORY.getValue(key);
|
||||
if (factory == null) {
|
||||
throw new LocalizedResourceConfigException("warning.config.loot_table.function.invalid_type", type);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package net.momirealms.craftengine.core.loot.function;
|
||||
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.loot.LootConditions;
|
||||
import net.momirealms.craftengine.core.loot.LootContext;
|
||||
import net.momirealms.craftengine.core.loot.condition.LootCondition;
|
||||
import net.momirealms.craftengine.core.loot.condition.LootConditions;
|
||||
import net.momirealms.craftengine.core.loot.number.NumberProvider;
|
||||
import net.momirealms.craftengine.core.loot.number.NumberProviders;
|
||||
import net.momirealms.craftengine.core.plugin.context.Condition;
|
||||
import net.momirealms.craftengine.core.plugin.context.number.NumberProvider;
|
||||
import net.momirealms.craftengine.core.plugin.context.number.NumberProviders;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
|
||||
@@ -20,7 +20,7 @@ public class SetCountFunction<T> extends AbstractLootConditionalFunction<T> {
|
||||
private final NumberProvider value;
|
||||
private final boolean add;
|
||||
|
||||
public SetCountFunction(List<LootCondition> conditions, NumberProvider value, boolean add) {
|
||||
public SetCountFunction(List<Condition<LootContext>> conditions, NumberProvider value, boolean add) {
|
||||
super(conditions);
|
||||
this.value = value;
|
||||
this.add = add;
|
||||
@@ -44,7 +44,7 @@ public class SetCountFunction<T> extends AbstractLootConditionalFunction<T> {
|
||||
public LootFunction<A> create(Map<String, Object> arguments) {
|
||||
Object value = ResourceConfigUtils.requireNonNullOrThrow(arguments.get("count"), "warning.config.loot_table.function.set_count.missing_count");
|
||||
boolean add = (boolean) arguments.getOrDefault("add", false);
|
||||
List<LootCondition> conditions = Optional.ofNullable(arguments.get("conditions"))
|
||||
List<Condition<LootContext>> conditions = Optional.ofNullable(arguments.get("conditions"))
|
||||
.map(it -> LootConditions.fromMapList((List<Map<String, Object>>) it))
|
||||
.orElse(Collections.emptyList());
|
||||
return new SetCountFunction<>(conditions, NumberProviders.fromObject(value), add);
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
package net.momirealms.craftengine.core.loot.number;
|
||||
|
||||
import net.momirealms.craftengine.core.loot.LootContext;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class FixedNumberProvider implements NumberProvider {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private final float value;
|
||||
|
||||
public FixedNumberProvider(float value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFloat(LootContext context) {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return NumberProviders.FIXED;
|
||||
}
|
||||
|
||||
public static class Factory implements NumberProviderFactory {
|
||||
@Override
|
||||
public NumberProvider create(Map<String, Object> arguments) {
|
||||
Number value = (Number) arguments.get("value");
|
||||
return new FixedNumberProvider(value.floatValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package net.momirealms.craftengine.core.loot.number;
|
||||
|
||||
import net.momirealms.craftengine.core.loot.LootContext;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
public interface NumberProvider {
|
||||
|
||||
float getFloat(LootContext context);
|
||||
|
||||
default int getInt(LootContext context) {
|
||||
return Math.round(this.getFloat(context));
|
||||
}
|
||||
|
||||
Key type();
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package net.momirealms.craftengine.core.loot.number;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface NumberProviderFactory {
|
||||
|
||||
NumberProvider create(Map<String, Object> arguments);
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
package net.momirealms.craftengine.core.loot.number;
|
||||
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.registry.Registries;
|
||||
import net.momirealms.craftengine.core.registry.WritableRegistry;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
import net.momirealms.craftengine.core.util.ResourceKey;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class NumberProviders {
|
||||
public static final Key FIXED = Key.of("craftengine:constant");
|
||||
public static final Key UNIFORM = Key.of("craftengine:uniform");
|
||||
|
||||
static {
|
||||
register(FIXED, FixedNumberProvider.FACTORY);
|
||||
register(UNIFORM, UniformNumberProvider.FACTORY);
|
||||
}
|
||||
|
||||
public static void register(Key key, NumberProviderFactory factory) {
|
||||
Holder.Reference<NumberProviderFactory> holder = ((WritableRegistry<NumberProviderFactory>) BuiltInRegistries.NUMBER_PROVIDER_FACTORY)
|
||||
.registerForHolder(new ResourceKey<>(Registries.NUMBER_PROVIDER_FACTORY.location(), key));
|
||||
holder.bindValue(factory);
|
||||
}
|
||||
|
||||
public static List<NumberProvider> fromMapList(List<Map<String, Object>> mapList) {
|
||||
if (mapList == null || mapList.isEmpty()) return List.of();
|
||||
List<NumberProvider> functions = new ArrayList<>();
|
||||
for (Map<String, Object> map : mapList) {
|
||||
functions.add(fromMap(map));
|
||||
}
|
||||
return functions;
|
||||
}
|
||||
|
||||
public static NumberProvider fromMap(Map<String, Object> map) {
|
||||
String type = ResourceConfigUtils.requireNonEmptyStringOrThrow(map.get("type"), "warning.config.loot_table.number.missing_type");
|
||||
Key key = Key.withDefaultNamespace(type, "craftengine");
|
||||
NumberProviderFactory factory = BuiltInRegistries.NUMBER_PROVIDER_FACTORY.getValue(key);
|
||||
if (factory == null) {
|
||||
throw new LocalizedResourceConfigException("warning.config.loot_table.number.invalid_type", type);
|
||||
}
|
||||
return factory.create(map);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static NumberProvider fromObject(Object object) {
|
||||
if (object == null) {
|
||||
throw new NullPointerException("number argument is null");
|
||||
}
|
||||
if (object instanceof Number number) {
|
||||
return new FixedNumberProvider(number.floatValue());
|
||||
} else if (object instanceof String string) {
|
||||
return new FixedNumberProvider(Float.parseFloat(string));
|
||||
} else if (object instanceof Map<?,?> map) {
|
||||
return fromMap((Map<String, Object>) map);
|
||||
}
|
||||
throw new IllegalArgumentException("Can't convert " + object + " to " + NumberProvider.class.getSimpleName());
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package net.momirealms.craftengine.core.loot.number;
|
||||
|
||||
import net.momirealms.craftengine.core.loot.LootContext;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class UniformNumberProvider implements NumberProvider {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private final NumberProvider min;
|
||||
private final NumberProvider max;
|
||||
|
||||
public UniformNumberProvider(NumberProvider min, NumberProvider max) {
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(LootContext context) {
|
||||
return context.randomSource().nextInt(this.min.getInt(context), this.max.getInt(context) + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFloat(LootContext context) {
|
||||
return context.randomSource().nextFloat(this.min.getFloat(context), this.max.getFloat(context));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return NumberProviders.UNIFORM;
|
||||
}
|
||||
|
||||
public static class Factory implements NumberProviderFactory {
|
||||
@Override
|
||||
public NumberProvider create(Map<String, Object> arguments) {
|
||||
Object min = arguments.getOrDefault("min", 1);
|
||||
Object max = arguments.getOrDefault("max", 1);
|
||||
return new UniformNumberProvider(NumberProviders.fromObject(min), NumberProviders.fromObject(max));
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user