9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-21 16:09:26 +00:00

添加一些基础条件和函数

还需要对vanilla-loots系统进行重构
This commit is contained in:
XiaoMoMi
2025-05-14 21:44:56 +08:00
parent f7016bacdf
commit c047e5a83c
32 changed files with 608 additions and 74 deletions

View File

@@ -90,7 +90,10 @@ warning.config.condition.match_block_property.missing_properties: "<yellow>Issue
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.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_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.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.condition.click_type.missing_click_type: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'click-type' argument for 'click_type' condition.</yellow>" warning.config.condition.permission.missing_permission: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'permission' argument for 'permission' condition.</yellow>"
warning.config.condition.equals.missing_value1: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'value1' argument for 'equals' condition.</yellow>"
warning.config.condition.equals.missing_value2: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'value2' argument for 'equals' condition.</yellow>"
warning.config.condition.expression.missing_expression: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'expression' argument for 'expression' 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.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.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>" warning.config.image.missing_height: "<yellow>Issue found in file <arg:0> - The image '<arg:1>' is missing the required 'height' argument.</yellow>"
@@ -303,3 +306,8 @@ warning.config.event.condition.invalid_type: "<yellow>Issue found in file <arg:0
warning.config.function.missing_type: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'type' argument for function.</yellow>" warning.config.function.missing_type: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'type' argument for function.</yellow>"
warning.config.function.invalid_type: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is using an invalid function type '<arg:2>'.</yellow>" warning.config.function.invalid_type: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is using an invalid function type '<arg:2>'.</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>" 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>"
warning.config.function.actionbar.missing_actionbar: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'actionbar' argument for 'actionbar' function.</yellow>"
warning.config.function.message.missing_message: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'message' argument for 'message' function.</yellow>"
warning.config.selector.missing_type: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'type' argument for selector.</yellow>"
warning.config.selector.invalid_type: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is using an invalid selector type '<arg:2>'.</yellow>"
warning.config.selector.invalid_target: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is using an invalid selector target '<arg:2>'.</yellow>"

View File

@@ -90,7 +90,8 @@ warning.config.condition.match_block_property.missing_properties: "<yellow>在
warning.config.condition.match_item.missing_id: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 缺少 'match_item' 条件所需的 'id' 参数</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_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.condition.table_bonus.missing_chances: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 缺少 'table_bonus' 条件所需的 'chances' 参数</yellow>"
warning.config.condition.click_type.missing_click_type: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'click-type' argument for 'click_type' condition.</yellow>"
warning.config.structure.not_section: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 应为配置段落 但实际类型为 '<arg:2>'</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.duplicate: "<yellow>在文件 <arg:0> 发现问题 - 重复的图片配置 '<arg:1>' 请检查其他文件中是否存在相同配置</yellow>"
warning.config.image.missing_height: "<yellow>在文件 <arg:0> 发现问题 - 图片 '<arg:1>' 缺少必需的 'height' 参数</yellow>" warning.config.image.missing_height: "<yellow>在文件 <arg:0> 发现问题 - 图片 '<arg:1>' 缺少必需的 'height' 参数</yellow>"

View File

@@ -11,6 +11,7 @@ import net.momirealms.craftengine.bukkit.world.BukkitWorld;
import net.momirealms.craftengine.core.block.ImmutableBlockState; import net.momirealms.craftengine.core.block.ImmutableBlockState;
import net.momirealms.craftengine.core.block.properties.Property; import net.momirealms.craftengine.core.block.properties.Property;
import net.momirealms.craftengine.core.entity.player.InteractionHand; import net.momirealms.craftengine.core.entity.player.InteractionHand;
import net.momirealms.craftengine.core.item.CustomItem;
import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.loot.LootTable; import net.momirealms.craftengine.core.loot.LootTable;
import net.momirealms.craftengine.core.plugin.config.Config; import net.momirealms.craftengine.core.plugin.config.Config;
@@ -42,6 +43,7 @@ import org.bukkit.event.world.GenericGameEvent;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import java.util.List; import java.util.List;
import java.util.Optional;
public class BlockEventListener implements Listener { public class BlockEventListener implements Listener {
private final BukkitCraftEngine plugin; private final BukkitCraftEngine plugin;
@@ -121,11 +123,35 @@ public class BlockEventListener implements Listener {
Object blockState = BlockStateUtils.blockDataToBlockState(block.getBlockData()); Object blockState = BlockStateUtils.blockDataToBlockState(block.getBlockData());
int stateId = BlockStateUtils.blockStateToId(blockState); int stateId = BlockStateUtils.blockStateToId(blockState);
Player player = event.getPlayer(); Player player = event.getPlayer();
Location location = block.getLocation();
BukkitServerPlayer serverPlayer = this.plugin.adapt(player);
net.momirealms.craftengine.core.world.World world = new BukkitWorld(player.getWorld());
WorldPosition position = new WorldPosition(world, location.getBlockX() + 0.5, location.getBlockY() + 0.5, location.getBlockZ() + 0.5);
Item<ItemStack> itemInHand = serverPlayer.getItemInHand(InteractionHand.MAIN_HAND);
if (itemInHand != null) {
Optional<CustomItem<ItemStack>> optionalCustomItem = itemInHand.getCustomItem();
if (optionalCustomItem.isPresent()) {
Cancellable dummy = Cancellable.dummy();
optionalCustomItem.get().execute(
PlayerOptionalContext.of(serverPlayer, ContextHolder.builder()
.withParameter(DirectContextParameters.BLOCK, new BukkitBlockInWorld(block))
.withParameter(DirectContextParameters.POSITION, position)
.withParameter(DirectContextParameters.PLAYER, serverPlayer)
.withParameter(DirectContextParameters.EVENT, dummy)
.withOptionalParameter(DirectContextParameters.ITEM_IN_HAND, itemInHand)
), EventTrigger.BREAK
);
if (dummy.isCancelled()) {
event.setCancelled(true);
return;
}
}
}
if (!BlockStateUtils.isVanillaBlock(stateId)) { if (!BlockStateUtils.isVanillaBlock(stateId)) {
ImmutableBlockState state = manager.getImmutableBlockStateUnsafe(stateId); ImmutableBlockState state = manager.getImmutableBlockStateUnsafe(stateId);
if (!state.isEmpty()) { if (!state.isEmpty()) {
Location location = block.getLocation();
BukkitServerPlayer serverPlayer = this.plugin.adapt(player);
// double check adventure mode to prevent dupe // double check adventure mode to prevent dupe
if (!FastNMS.INSTANCE.mayBuild(serverPlayer.serverPlayer()) && !serverPlayer.canBreak(LocationUtils.toBlockPos(location), null)) { if (!FastNMS.INSTANCE.mayBuild(serverPlayer.serverPlayer()) && !serverPlayer.canBreak(LocationUtils.toBlockPos(location), null)) {
return; return;
@@ -139,10 +165,6 @@ public class BlockEventListener implements Listener {
return; return;
} }
Item<ItemStack> itemInHand = serverPlayer.getItemInHand(InteractionHand.MAIN_HAND);
net.momirealms.craftengine.core.world.World world = new BukkitWorld(location.getWorld());
WorldPosition position = new WorldPosition(world, location.getBlockX() + 0.5, location.getBlockY() + 0.5, location.getBlockZ() + 0.5);
// execute functions // execute functions
Cancellable cancellable = Cancellable.dummy(); Cancellable cancellable = Cancellable.dummy();
PlayerOptionalContext context = PlayerOptionalContext.of(serverPlayer, ContextHolder.builder() PlayerOptionalContext context = PlayerOptionalContext.of(serverPlayer, ContextHolder.builder()
@@ -180,12 +202,12 @@ public class BlockEventListener implements Listener {
} }
// drop items // drop items
ContextHolder.Builder builder = ContextHolder.builder() ContextHolder.Builder lootContext = ContextHolder.builder()
.withParameter(DirectContextParameters.POSITION, position) .withParameter(DirectContextParameters.POSITION, position)
.withParameter(DirectContextParameters.PLAYER, serverPlayer) .withParameter(DirectContextParameters.PLAYER, serverPlayer)
.withParameter(DirectContextParameters.BLOCK, new BukkitBlockInWorld(block)) .withParameter(DirectContextParameters.BLOCK, new BukkitBlockInWorld(block))
.withOptionalParameter(DirectContextParameters.ITEM_IN_HAND, itemInHand); .withOptionalParameter(DirectContextParameters.ITEM_IN_HAND, itemInHand);
for (Item<Object> item : state.getDrops(builder, world, serverPlayer)) { for (Item<Object> item : state.getDrops(lootContext, world, serverPlayer)) {
world.dropItemNaturally(position, item); world.dropItemNaturally(position, item);
} }
} }
@@ -197,23 +219,19 @@ public class BlockEventListener implements Listener {
event.setDropItems(false); event.setDropItems(false);
event.setExpToDrop(0); event.setExpToDrop(0);
} }
Location location = block.getLocation(); ContextHolder lootContext = ContextHolder.builder()
BukkitServerPlayer serverPlayer = this.plugin.adapt(player);
net.momirealms.craftengine.core.world.World world = new BukkitWorld(player.getWorld());
WorldPosition position = new WorldPosition(world, location.getBlockX() + 0.5, location.getBlockY() + 0.5, location.getBlockZ() + 0.5);
ContextHolder.Builder builder = ContextHolder.builder()
.withParameter(DirectContextParameters.BLOCK, new BukkitBlockInWorld(block)) .withParameter(DirectContextParameters.BLOCK, new BukkitBlockInWorld(block))
.withParameter(DirectContextParameters.POSITION, position) .withParameter(DirectContextParameters.POSITION, position)
.withParameter(DirectContextParameters.PLAYER, serverPlayer) .withParameter(DirectContextParameters.PLAYER, serverPlayer)
.withOptionalParameter(DirectContextParameters.ITEM_IN_HAND, serverPlayer.getItemInHand(InteractionHand.MAIN_HAND)); .withOptionalParameter(DirectContextParameters.ITEM_IN_HAND, itemInHand).build();
ContextHolder contextHolder = builder.build();
for (LootTable<?> lootTable : it.lootTables()) { for (LootTable<?> lootTable : it.lootTables()) {
for (Item<?> item : lootTable.getRandomItems(contextHolder, world, serverPlayer)) { for (Item<?> item : lootTable.getRandomItems(lootContext, world, serverPlayer)) {
world.dropItemNaturally(position, item); world.dropItemNaturally(position, item);
} }
} }
}); });
} }
// sound system // sound system
if (Config.enableSoundSystem()) { if (Config.enableSoundSystem()) {
Object ownerBlock = BlockStateUtils.getBlockOwner(blockState); Object ownerBlock = BlockStateUtils.getBlockOwner(blockState);

View File

@@ -8,6 +8,7 @@ import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.world.World; import net.momirealms.craftengine.core.world.World;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.UUID;
public class BukkitEntity extends AbstractEntity { public class BukkitEntity extends AbstractEntity {
private final WeakReference<org.bukkit.entity.Entity> entity; private final WeakReference<org.bukkit.entity.Entity> entity;
@@ -69,4 +70,14 @@ public class BukkitEntity extends AbstractEntity {
public Key type() { public Key type() {
return KeyUtils.namespacedKey2Key(literalObject().getType().getKey()); return KeyUtils.namespacedKey2Key(literalObject().getType().getKey());
} }
@Override
public String name() {
return literalObject().getName();
}
@Override
public UUID uuid() {
return literalObject().getUniqueId();
}
} }

View File

@@ -13,6 +13,7 @@ import net.momirealms.craftengine.bukkit.world.BukkitWorld;
import net.momirealms.craftengine.core.block.BlockSettings; import net.momirealms.craftengine.core.block.BlockSettings;
import net.momirealms.craftengine.core.block.ImmutableBlockState; import net.momirealms.craftengine.core.block.ImmutableBlockState;
import net.momirealms.craftengine.core.block.PackedBlockState; import net.momirealms.craftengine.core.block.PackedBlockState;
import net.momirealms.craftengine.core.entity.player.GameMode;
import net.momirealms.craftengine.core.entity.player.InteractionHand; import net.momirealms.craftengine.core.entity.player.InteractionHand;
import net.momirealms.craftengine.core.entity.player.Player; import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.item.Item;
@@ -27,7 +28,10 @@ import net.momirealms.craftengine.core.util.VersionHelper;
import net.momirealms.craftengine.core.world.BlockPos; import net.momirealms.craftengine.core.world.BlockPos;
import net.momirealms.craftengine.core.world.World; import net.momirealms.craftengine.core.world.World;
import net.momirealms.craftengine.core.world.WorldEvents; import net.momirealms.craftengine.core.world.WorldEvents;
import org.bukkit.*; import org.bukkit.FluidCollisionMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.SoundCategory;
import org.bukkit.attribute.Attribute; import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeInstance; import org.bukkit.attribute.AttributeInstance;
import org.bukkit.block.Block; import org.bukkit.block.Block;
@@ -145,18 +149,18 @@ public class BukkitServerPlayer extends Player {
} }
@Override @Override
public boolean isCreativeMode() { public GameMode gameMode() {
return platformPlayer().getGameMode() == GameMode.CREATIVE; return switch (platformPlayer().getGameMode()) {
case CREATIVE -> GameMode.CREATIVE;
case SPECTATOR -> GameMode.SPECTATOR;
case ADVENTURE -> GameMode.ADVENTURE;
case SURVIVAL -> GameMode.SURVIVAL;
};
} }
@Override @Override
public boolean isSpectatorMode() { public void setGameMode(GameMode gameMode) {
return platformPlayer().getGameMode() == GameMode.SPECTATOR; platformPlayer().setGameMode(Objects.requireNonNull(org.bukkit.GameMode.getByValue(gameMode.id())));
}
@Override
public boolean isAdventureMode() {
return platformPlayer().getGameMode() == GameMode.ADVENTURE;
} }
@Override @Override
@@ -175,6 +179,14 @@ public class BukkitServerPlayer extends Player {
sendPacket(packet, false); sendPacket(packet, false);
} }
@Override
public void sendTitle(Component title, Component subtitle, int fadeIn, int stay, int fadeOut) {
Object titlePacket = FastNMS.INSTANCE.constructor$ClientboundSetTitleTextPacket(ComponentUtils.adventureToMinecraft(title));
Object subtitlePacket = FastNMS.INSTANCE.constructor$ClientboundSetSubtitleTextPacket(ComponentUtils.adventureToMinecraft(subtitle));
Object timePacket = FastNMS.INSTANCE.constructor$ClientboundSetTitlesAnimationPacket(fadeIn, stay, fadeOut);
sendPackets(List.of(titlePacket, subtitlePacket, timePacket), false);
}
@Override @Override
public void sendMessage(Component text, boolean overlay) { public void sendMessage(Component text, boolean overlay) {
Object packet = FastNMS.INSTANCE.constructor$ClientboundSystemChatPacket(ComponentUtils.adventureToMinecraft(text), overlay); Object packet = FastNMS.INSTANCE.constructor$ClientboundSystemChatPacket(ComponentUtils.adventureToMinecraft(text), overlay);
@@ -816,4 +828,9 @@ public class BukkitServerPlayer extends Player {
return LegacyAttributeUtils.getLuck(platformPlayer()); return LegacyAttributeUtils.getLuck(platformPlayer());
} }
} }
@Override
public boolean isFlying() {
return platformPlayer().isFlying();
}
} }

View File

@@ -5,6 +5,8 @@ import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.world.World; import net.momirealms.craftengine.core.world.World;
import net.momirealms.craftengine.core.world.WorldPosition; import net.momirealms.craftengine.core.world.WorldPosition;
import java.util.UUID;
public interface Entity { public interface Entity {
Key type(); Key type();
@@ -29,4 +31,8 @@ public interface Entity {
Direction getDirection(); Direction getDirection();
Object literalObject(); Object literalObject();
String name();
UUID uuid();
} }

View File

@@ -0,0 +1,18 @@
package net.momirealms.craftengine.core.entity.player;
public enum GameMode {
SURVIVAL(0),
CREATIVE(1),
ADVENTURE(2),
SPECTATOR(3);
private final int id;
GameMode(int id) {
this.id = id;
}
public int id() {
return id;
}
}

View File

@@ -46,11 +46,9 @@ public abstract class Player extends AbstractEntity implements NetWorkUser {
public abstract boolean isSneaking(); public abstract boolean isSneaking();
public abstract boolean isCreativeMode(); public abstract GameMode gameMode();
public abstract boolean isSpectatorMode(); public abstract void setGameMode(GameMode gameMode);
public abstract boolean isAdventureMode();
public abstract boolean canBreak(BlockPos pos, Object state); public abstract boolean canBreak(BlockPos pos, Object state);
@@ -60,6 +58,8 @@ public abstract class Player extends AbstractEntity implements NetWorkUser {
public abstract void sendMessage(Component text, boolean overlay); public abstract void sendMessage(Component text, boolean overlay);
public abstract void sendTitle(Component title, Component subtitle, int fadeIn, int stay, int fadeOut);
public abstract boolean updateLastSuccessfulInteractionTick(int tick); public abstract boolean updateLastSuccessfulInteractionTick(int tick);
public abstract int lastSuccessfulInteractionTick(); public abstract int lastSuccessfulInteractionTick();
@@ -75,7 +75,7 @@ public abstract class Player extends AbstractEntity implements NetWorkUser {
public abstract String name(); public abstract String name();
public void playSound(Key sound) { public void playSound(Key sound) {
playSound(sound, 1, 1); playSound(sound, 1f, 1f);
} }
public abstract void playSound(Key sound, float volume, float pitch); public abstract void playSound(Key sound, float volume, float pitch);
@@ -92,8 +92,26 @@ public abstract class Player extends AbstractEntity implements NetWorkUser {
public abstract double luck(); public abstract double luck();
public abstract boolean isFlying();
@Override @Override
public Key type() { public Key type() {
return TYPE; return TYPE;
} }
public boolean isCreativeMode() {
return gameMode() == GameMode.CREATIVE;
}
public boolean isSpectatorMode() {
return gameMode() == GameMode.SPECTATOR;
}
public boolean isSurvivalMode() {
return gameMode() == GameMode.SURVIVAL;
}
public boolean isAdventureMode() {
return gameMode() == GameMode.ADVENTURE;
}
} }

View File

@@ -30,6 +30,9 @@ public class LootConditions {
register(CommonConditions.FALLING_BLOCK, new FallingBlockCondition.FactoryImpl<>()); register(CommonConditions.FALLING_BLOCK, new FallingBlockCondition.FactoryImpl<>());
register(CommonConditions.RANDOM, new RandomCondition.FactoryImpl<>()); register(CommonConditions.RANDOM, new RandomCondition.FactoryImpl<>());
register(CommonConditions.DISTANCE, new DistanceCondition.FactoryImpl<>()); register(CommonConditions.DISTANCE, new DistanceCondition.FactoryImpl<>());
register(CommonConditions.PERMISSION, new PermissionCondition.FactoryImpl<>());
register(CommonConditions.EQUALS, new EqualsCondition.FactoryImpl<>());
register(CommonConditions.EXPRESSION, new ExpressionCondition.FactoryImpl<>());
} }
public static void register(Key key, ConditionFactory<LootContext> factory) { public static void register(Key key, ConditionFactory<LootContext> factory) {

View File

@@ -14,6 +14,8 @@ public abstract class AbstractChainParameterContext extends AbstractCommonContex
CHAIN_PARAMETERS.put(DirectContextParameters.WORLD, new WorldParameterProvider()); CHAIN_PARAMETERS.put(DirectContextParameters.WORLD, new WorldParameterProvider());
CHAIN_PARAMETERS.put(DirectContextParameters.BLOCK, new BlockParameterProvider()); CHAIN_PARAMETERS.put(DirectContextParameters.BLOCK, new BlockParameterProvider());
CHAIN_PARAMETERS.put(DirectContextParameters.POSITION, new PositionParameterProvider()); CHAIN_PARAMETERS.put(DirectContextParameters.POSITION, new PositionParameterProvider());
CHAIN_PARAMETERS.put(DirectContextParameters.FURNITURE, new FurnitureParameterProvider());
CHAIN_PARAMETERS.put(DirectContextParameters.ENTITY, new EntityParameterProvider());
ItemParameterProvider itemProvider = new ItemParameterProvider(); ItemParameterProvider itemProvider = new ItemParameterProvider();
CHAIN_PARAMETERS.put(DirectContextParameters.MAIN_HAND_ITEM, itemProvider); CHAIN_PARAMETERS.put(DirectContextParameters.MAIN_HAND_ITEM, itemProvider);
CHAIN_PARAMETERS.put(DirectContextParameters.OFF_HAND_ITEM, itemProvider); CHAIN_PARAMETERS.put(DirectContextParameters.OFF_HAND_ITEM, itemProvider);

View File

@@ -10,7 +10,6 @@ public final class CommonConditions {
public static final Key ANY_OF = Key.of("craftengine:any_of"); public static final Key ANY_OF = Key.of("craftengine:any_of");
public static final Key INVERTED = Key.of("craftengine:inverted"); public static final Key INVERTED = Key.of("craftengine:inverted");
public static final Key MATCH_ITEM = Key.of("craftengine:match_item"); public static final Key MATCH_ITEM = Key.of("craftengine:match_item");
public static final Key CLICK_TYPE = Key.of("craftengine:click_type");
public static final Key MATCH_BLOCK_PROPERTY = Key.from("craftengine:match_block_property"); 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 TABLE_BONUS = Key.from("craftengine:table_bonus");
public static final Key SURVIVES_EXPLOSION = Key.from("craftengine:survives_explosion"); public static final Key SURVIVES_EXPLOSION = Key.from("craftengine:survives_explosion");
@@ -19,4 +18,6 @@ public final class CommonConditions {
public static final Key FALLING_BLOCK = Key.from("craftengine:falling_block"); public static final Key FALLING_BLOCK = Key.from("craftengine:falling_block");
public static final Key DISTANCE = Key.from("craftengine:distance"); public static final Key DISTANCE = Key.from("craftengine:distance");
public static final Key PERMISSION = Key.from("craftengine:permission"); public static final Key PERMISSION = Key.from("craftengine:permission");
public static final Key EQUALS = Key.from("craftengine:equals");
public static final Key EXPRESSION = Key.from("craftengine:expression");
} }

View File

@@ -0,0 +1,40 @@
package net.momirealms.craftengine.core.plugin.context.condition;
import net.momirealms.craftengine.core.plugin.context.Condition;
import net.momirealms.craftengine.core.plugin.context.Context;
import net.momirealms.craftengine.core.plugin.context.text.TextProvider;
import net.momirealms.craftengine.core.plugin.context.text.TextProviders;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import java.util.Map;
public class EqualsCondition<CTX extends Context> implements Condition<CTX> {
private final TextProvider value1;
private final TextProvider value2;
public EqualsCondition(TextProvider value1, TextProvider value2) {
this.value1 = value1;
this.value2 = value2;
}
@Override
public Key type() {
return CommonConditions.EQUALS;
}
@Override
public boolean test(CTX ctx) {
return this.value1.get(ctx).equals(this.value2.get(ctx));
}
public static class FactoryImpl<CTX extends Context> implements ConditionFactory<CTX> {
@Override
public Condition<CTX> create(Map<String, Object> arguments) {
String value1 = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("value1"), "warning.config.condition.equals.missing_value1");
String value2 = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("value1"), "warning.config.condition.equals.missing_value2");
return new EqualsCondition<>(TextProviders.fromString(value1), TextProviders.fromString(value2));
}
}
}

View File

@@ -0,0 +1,48 @@
package net.momirealms.craftengine.core.plugin.context.condition;
import com.ezylang.evalex.EvaluationException;
import com.ezylang.evalex.Expression;
import com.ezylang.evalex.parser.ParseException;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.context.Condition;
import net.momirealms.craftengine.core.plugin.context.Context;
import net.momirealms.craftengine.core.plugin.context.text.TextProvider;
import net.momirealms.craftengine.core.plugin.context.text.TextProviders;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import java.util.Map;
public class ExpressionCondition<CTX extends Context> implements Condition<CTX> {
private final TextProvider expression;
public ExpressionCondition(TextProvider expression) {
this.expression = expression;
}
@Override
public Key type() {
return CommonConditions.EXPRESSION;
}
@Override
public boolean test(CTX ctx) {
String exp = expression.get(ctx);
Expression expr = new Expression(exp);
try {
return expr.evaluate().getBooleanValue();
} catch (ParseException | EvaluationException e) {
CraftEngine.instance().logger().warn("Invalid expression " + exp, e);
return false;
}
}
public static class FactoryImpl<CTX extends Context> implements ConditionFactory<CTX> {
@Override
public Condition<CTX> create(Map<String, Object> arguments) {
String value = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("expression"), "warning.config.condition.expression.missing_expression");
return new ExpressionCondition<>(TextProviders.fromString(value));
}
}
}

View File

@@ -0,0 +1,39 @@
package net.momirealms.craftengine.core.plugin.context.condition;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.plugin.context.Condition;
import net.momirealms.craftengine.core.plugin.context.Context;
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import java.util.Map;
import java.util.Optional;
public class PermissionCondition<CTX extends Context> implements Condition<CTX> {
private final String permission;
public PermissionCondition(String permission) {
this.permission = permission;
}
@Override
public Key type() {
return CommonConditions.PERMISSION;
}
@Override
public boolean test(CTX ctx) {
Optional<Player> player = ctx.getOptionalParameter(DirectContextParameters.PLAYER);
return player.map(value -> value.hasPermission(this.permission)).orElse(false);
}
public static class FactoryImpl<CTX extends Context> implements ConditionFactory<CTX> {
@Override
public Condition<CTX> create(Map<String, Object> arguments) {
String permission = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("permission"), "warning.config.condition.permission.missing_permission");
return new PermissionCondition<>(permission);
}
}
}

View File

@@ -0,0 +1,61 @@
package net.momirealms.craftengine.core.plugin.context.function;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.plugin.context.*;
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelector;
import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelectors;
import net.momirealms.craftengine.core.plugin.context.text.TextProvider;
import net.momirealms.craftengine.core.plugin.context.text.TextProviders;
import net.momirealms.craftengine.core.util.AdventureHelper;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Map;
import java.util.Optional;
public class ActionBarFunction<CTX extends Context> extends AbstractConditionalFunction<CTX> {
private final TextProvider message;
private final PlayerSelector<CTX> selector;
public ActionBarFunction(List<Condition<CTX>> predicates, @Nullable PlayerSelector<CTX> selector, TextProvider messages) {
super(predicates);
this.message = messages;
this.selector = selector;
}
@Override
public void runInternal(CTX ctx) {
Optional<Player> owner = ctx.getOptionalParameter(DirectContextParameters.PLAYER);
if (this.selector == null) {
owner.ifPresent(it -> {
it.sendActionBar(AdventureHelper.miniMessage().deserialize(this.message.get(ctx), ctx.tagResolvers()));
});
} else {
for (Player viewer : this.selector.get(ctx)) {
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(viewer, ContextHolder.EMPTY));
viewer.sendActionBar(AdventureHelper.miniMessage().deserialize(this.message.get(relationalContext), relationalContext.tagResolvers()));
}
}
}
@Override
public Key type() {
return CommonFunctions.ACTIONBAR;
}
public static class FactoryImpl<CTX extends Context> extends AbstractFactory<CTX> {
public FactoryImpl(java.util.function.Function<Map<String, Object>, Condition<CTX>> factory) {
super(factory);
}
@Override
public Function<CTX> create(Map<String, Object> arguments) {
String message = ResourceConfigUtils.requireNonEmptyStringOrThrow(ResourceConfigUtils.get(arguments, "actionbar", "message"), "warning.config.function.actionbar.missing_actionbar");
return new ActionBarFunction<>(getPredicates(arguments), PlayerSelectors.fromObject(arguments.get("target"), conditionFactory()), TextProviders.fromString(message));
}
}
}

View File

@@ -0,0 +1,41 @@
package net.momirealms.craftengine.core.plugin.context.function;
import net.momirealms.craftengine.core.plugin.context.Condition;
import net.momirealms.craftengine.core.plugin.context.Context;
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
import net.momirealms.craftengine.core.util.Cancellable;
import net.momirealms.craftengine.core.util.Key;
import java.util.List;
import java.util.Map;
import java.util.Optional;
public class CancelEventFunction<CTX extends Context> extends AbstractConditionalFunction<CTX> {
public CancelEventFunction(List<Condition<CTX>> predicates) {
super(predicates);
}
@Override
public void runInternal(CTX ctx) {
Optional<Cancellable> cancellable = ctx.getOptionalParameter(DirectContextParameters.EVENT);
cancellable.ifPresent(value -> value.setCancelled(true));
}
@Override
public Key type() {
return CommonFunctions.CANCEL_EVENT;
}
public static class FactoryImpl<CTX extends Context> extends AbstractFactory<CTX> {
public FactoryImpl(java.util.function.Function<Map<String, Object>, Condition<CTX>> factory) {
super(factory);
}
@Override
public Function<CTX> create(Map<String, Object> arguments) {
return new CancelEventFunction<>(getPredicates(arguments));
}
}
}

View File

@@ -23,7 +23,7 @@ public class CommandFunction<CTX extends Context> extends AbstractConditionalFun
private final boolean asPlayer; private final boolean asPlayer;
private final PlayerSelector<CTX> selector; private final PlayerSelector<CTX> selector;
public CommandFunction(List<Condition<CTX>> predicates, List<TextProvider> command, boolean asPlayer, @Nullable PlayerSelector<CTX> selector) { public CommandFunction(List<Condition<CTX>> predicates, @Nullable PlayerSelector<CTX> selector, List<TextProvider> command, boolean asPlayer) {
super(predicates); super(predicates);
this.asPlayer = asPlayer; this.asPlayer = asPlayer;
this.command = command; this.command = command;
@@ -72,7 +72,7 @@ public class CommandFunction<CTX extends Context> extends AbstractConditionalFun
Object command = ResourceConfigUtils.requireNonNullOrThrow(ResourceConfigUtils.get(arguments, "command", "commands"), "warning.config.function.command.missing_command"); Object command = ResourceConfigUtils.requireNonNullOrThrow(ResourceConfigUtils.get(arguments, "command", "commands"), "warning.config.function.command.missing_command");
List<TextProvider> commands = MiscUtils.getAsStringList(command).stream().map(TextProviders::fromString).toList(); List<TextProvider> commands = MiscUtils.getAsStringList(command).stream().map(TextProviders::fromString).toList();
boolean asPlayer = (boolean) arguments.getOrDefault("as-player", false); boolean asPlayer = (boolean) arguments.getOrDefault("as-player", false);
return new CommandFunction<>(getPredicates(arguments), commands, asPlayer, PlayerSelectors.fromObject(arguments.get("target"), conditionFactory())); return new CommandFunction<>(getPredicates(arguments), PlayerSelectors.fromObject(arguments.get("target"), conditionFactory()), commands, asPlayer);
} }
} }
} }

View File

@@ -22,7 +22,7 @@ public class MessageFunction<CTX extends Context> extends AbstractConditionalFun
private final PlayerSelector<CTX> selector; private final PlayerSelector<CTX> selector;
private final boolean overlay; private final boolean overlay;
public MessageFunction(List<Condition<CTX>> predicates, List<TextProvider> messages, @Nullable PlayerSelector<CTX> selector, boolean overlay) { public MessageFunction(List<Condition<CTX>> predicates, @Nullable PlayerSelector<CTX> selector, List<TextProvider> messages, boolean overlay) {
super(predicates); super(predicates);
this.messages = messages; this.messages = messages;
this.selector = selector; this.selector = selector;
@@ -64,7 +64,7 @@ public class MessageFunction<CTX extends Context> extends AbstractConditionalFun
Object message = ResourceConfigUtils.requireNonNullOrThrow(ResourceConfigUtils.get(arguments, "messages", "message"), "warning.config.function.command.missing_message"); Object message = ResourceConfigUtils.requireNonNullOrThrow(ResourceConfigUtils.get(arguments, "messages", "message"), "warning.config.function.command.missing_message");
List<TextProvider> messages = MiscUtils.getAsStringList(message).stream().map(TextProviders::fromString).toList(); List<TextProvider> messages = MiscUtils.getAsStringList(message).stream().map(TextProviders::fromString).toList();
boolean overlay = (boolean) arguments.getOrDefault("overlay", false); boolean overlay = (boolean) arguments.getOrDefault("overlay", false);
return new MessageFunction<>(getPredicates(arguments), messages, PlayerSelectors.fromObject(arguments.get("target"), conditionFactory()), overlay); return new MessageFunction<>(getPredicates(arguments), PlayerSelectors.fromObject(arguments.get("target"), conditionFactory()), messages, overlay);
} }
} }
} }

View File

@@ -0,0 +1,82 @@
package net.momirealms.craftengine.core.plugin.context.function;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.plugin.context.*;
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.DirectContextParameters;
import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelector;
import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelectors;
import net.momirealms.craftengine.core.plugin.context.text.TextProvider;
import net.momirealms.craftengine.core.plugin.context.text.TextProviders;
import net.momirealms.craftengine.core.util.AdventureHelper;
import net.momirealms.craftengine.core.util.Key;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Map;
import java.util.Optional;
public class TitleFunction<CTX extends Context> extends AbstractConditionalFunction<CTX> {
private final PlayerSelector<CTX> selector;
private final TextProvider main;
private final TextProvider sub;
private final NumberProvider fadeIn;
private final NumberProvider stay;
private final NumberProvider fadeOut;
public TitleFunction(List<Condition<CTX>> predicates, @Nullable PlayerSelector<CTX> selector,
TextProvider main, TextProvider sub, NumberProvider fadeIn, NumberProvider stay, NumberProvider fadeOut) {
super(predicates);
this.selector = selector;
this.main = main;
this.sub = sub;
this.fadeIn = fadeIn;
this.stay = stay;
this.fadeOut = fadeOut;
}
@Override
public void runInternal(CTX ctx) {
Optional<Player> owner = ctx.getOptionalParameter(DirectContextParameters.PLAYER);
if (this.selector == null) {
owner.ifPresent(it -> it.sendTitle(
AdventureHelper.miniMessage().deserialize(this.main.get(ctx), ctx.tagResolvers()),
AdventureHelper.miniMessage().deserialize(this.sub.get(ctx), ctx.tagResolvers()),
this.fadeIn.getInt(ctx), this.stay.getInt(ctx), this.fadeOut.getInt(ctx)
));
} else {
for (Player viewer : this.selector.get(ctx)) {
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(viewer, ContextHolder.EMPTY));
viewer.sendTitle(
AdventureHelper.miniMessage().deserialize(this.main.get(relationalContext), relationalContext.tagResolvers()),
AdventureHelper.miniMessage().deserialize(this.sub.get(relationalContext), relationalContext.tagResolvers()),
this.fadeIn.getInt(relationalContext), this.stay.getInt(relationalContext), this.fadeOut.getInt(relationalContext)
);
}
}
}
@Override
public Key type() {
return CommonFunctions.TITLE;
}
public static class FactoryImpl<CTX extends Context> extends AbstractFactory<CTX> {
public FactoryImpl(java.util.function.Function<Map<String, Object>, Condition<CTX>> factory) {
super(factory);
}
@Override
public Function<CTX> create(Map<String, Object> arguments) {
String title = arguments.getOrDefault("title", "").toString();
String subtitle = arguments.getOrDefault("subtitle", "").toString();
NumberProvider fadeIn = NumberProviders.fromObject(arguments.getOrDefault("fade-in", 10));
NumberProvider stay = NumberProviders.fromObject(arguments.getOrDefault("stay", 20));
NumberProvider fadeOut = NumberProviders.fromObject(arguments.getOrDefault("fade-out", 5));
return new TitleFunction<>(getPredicates(arguments), PlayerSelectors.fromObject(arguments.get("target"), conditionFactory()),
TextProviders.fromString(title), TextProviders.fromString(subtitle), fadeIn, stay, fadeOut);
}
}
}

View File

@@ -2,8 +2,10 @@ package net.momirealms.craftengine.core.plugin.context.parameter;
import net.momirealms.craftengine.core.block.CustomBlock; import net.momirealms.craftengine.core.block.CustomBlock;
import net.momirealms.craftengine.core.block.ImmutableBlockState; import net.momirealms.craftengine.core.block.ImmutableBlockState;
import net.momirealms.craftengine.core.entity.Entity;
import net.momirealms.craftengine.core.entity.furniture.AnchorType; import net.momirealms.craftengine.core.entity.furniture.AnchorType;
import net.momirealms.craftengine.core.entity.furniture.Furniture; import net.momirealms.craftengine.core.entity.furniture.Furniture;
import net.momirealms.craftengine.core.entity.player.GameMode;
import net.momirealms.craftengine.core.entity.player.InteractionHand; import net.momirealms.craftengine.core.entity.player.InteractionHand;
import net.momirealms.craftengine.core.entity.player.Player; import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.item.Item;
@@ -29,6 +31,7 @@ public final class DirectContextParameters {
public static final ContextKey<Boolean> FALLING_BLOCK = ContextKey.direct("falling_block"); public static final ContextKey<Boolean> FALLING_BLOCK = ContextKey.direct("falling_block");
public static final ContextKey<Float> EXPLOSION_RADIUS = ContextKey.direct("explosion_radius"); public static final ContextKey<Float> EXPLOSION_RADIUS = ContextKey.direct("explosion_radius");
public static final ContextKey<Player> PLAYER = ContextKey.direct("player"); public static final ContextKey<Player> PLAYER = ContextKey.direct("player");
public static final ContextKey<Entity> ENTITY = ContextKey.direct("entity");
public static final ContextKey<ImmutableBlockState> BLOCK_STATE = ContextKey.direct("custom_block_state"); public static final ContextKey<ImmutableBlockState> BLOCK_STATE = ContextKey.direct("custom_block_state");
public static final ContextKey<Position> COORDINATE = ContextKey.direct("coordinate"); public static final ContextKey<Position> COORDINATE = ContextKey.direct("coordinate");
public static final ContextKey<WorldPosition> POSITION = ContextKey.direct("position"); public static final ContextKey<WorldPosition> POSITION = ContextKey.direct("position");
@@ -51,4 +54,8 @@ public final class DirectContextParameters {
public static final ContextKey<AnchorType> ANCHOR_TYPE = ContextKey.direct("anchor_type"); public static final ContextKey<AnchorType> ANCHOR_TYPE = ContextKey.direct("anchor_type");
public static final ContextKey<InteractionHand> HAND = ContextKey.direct("hand"); public static final ContextKey<InteractionHand> HAND = ContextKey.direct("hand");
public static final ContextKey<Cancellable> EVENT = ContextKey.direct("event"); public static final ContextKey<Cancellable> EVENT = ContextKey.direct("event");
public static final ContextKey<Boolean> IS_FLYING = ContextKey.direct("is_flying");
public static final ContextKey<Boolean> IS_SNEAKING = ContextKey.direct("is_sneaking");
public static final ContextKey<Boolean> IS_CUSTOM = ContextKey.direct("is_custom");
public static final ContextKey<GameMode> GAMEMODE = ContextKey.direct("gamemode");
} }

View File

@@ -0,0 +1,33 @@
package net.momirealms.craftengine.core.plugin.context.parameter;
import net.momirealms.craftengine.core.entity.Entity;
import net.momirealms.craftengine.core.plugin.context.ChainParameterProvider;
import net.momirealms.craftengine.core.plugin.context.ContextKey;
import net.momirealms.craftengine.core.util.MCUtils;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
public class EntityParameterProvider implements ChainParameterProvider<Entity> {
private static final Map<ContextKey<?>, Function<Entity, Object>> CONTEXT_FUNCTIONS = new HashMap<>();
static {
CONTEXT_FUNCTIONS.put(DirectContextParameters.X, Entity::x);
CONTEXT_FUNCTIONS.put(DirectContextParameters.Y, Entity::y);
CONTEXT_FUNCTIONS.put(DirectContextParameters.Z, Entity::z);
CONTEXT_FUNCTIONS.put(DirectContextParameters.POSITION, Entity::position);
CONTEXT_FUNCTIONS.put(DirectContextParameters.BLOCK_X, p -> MCUtils.fastFloor(p.x()));
CONTEXT_FUNCTIONS.put(DirectContextParameters.BLOCK_Y, p -> MCUtils.fastFloor(p.y()));
CONTEXT_FUNCTIONS.put(DirectContextParameters.BLOCK_Z, p -> MCUtils.fastFloor(p.z()));
CONTEXT_FUNCTIONS.put(DirectContextParameters.NAME, Entity::name);
CONTEXT_FUNCTIONS.put(DirectContextParameters.UUID, Entity::uuid);
CONTEXT_FUNCTIONS.put(DirectContextParameters.WORLD, Entity::world);
}
@SuppressWarnings("unchecked")
@Override
public <T> Optional<T> getOptionalParameter(ContextKey<T> parameter, Entity entity) {
return (Optional<T>) Optional.ofNullable(CONTEXT_FUNCTIONS.get(parameter)).map(f -> f.apply(entity));
}
}

View File

@@ -0,0 +1,25 @@
package net.momirealms.craftengine.core.plugin.context.parameter;
import net.momirealms.craftengine.core.entity.furniture.Furniture;
import net.momirealms.craftengine.core.plugin.context.ChainParameterProvider;
import net.momirealms.craftengine.core.plugin.context.ContextKey;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
public class FurnitureParameterProvider implements ChainParameterProvider<Furniture> {
private static final Map<ContextKey<?>, Function<Furniture, Object>> CONTEXT_FUNCTIONS = new HashMap<>();
static {
CONTEXT_FUNCTIONS.put(DirectContextParameters.ID, Furniture::id);
CONTEXT_FUNCTIONS.put(DirectContextParameters.UUID, Furniture::uuid);
CONTEXT_FUNCTIONS.put(DirectContextParameters.ANCHOR_TYPE, Furniture::anchorType);
}
@SuppressWarnings("unchecked")
@Override
public <T> Optional<T> getOptionalParameter(ContextKey<T> parameter, Furniture world) {
return (Optional<T>) Optional.ofNullable(CONTEXT_FUNCTIONS.get(parameter)).map(f -> f.apply(world));
}
}

View File

@@ -14,6 +14,7 @@ public class ItemParameterProvider implements ChainParameterProvider<Item<?>> {
static { static {
CONTEXT_FUNCTIONS.put(DirectContextParameters.ID, Item::id); CONTEXT_FUNCTIONS.put(DirectContextParameters.ID, Item::id);
CONTEXT_FUNCTIONS.put(DirectContextParameters.CUSTOM_MODEL_DATA, i -> i.customModelData().orElse(null)); CONTEXT_FUNCTIONS.put(DirectContextParameters.CUSTOM_MODEL_DATA, i -> i.customModelData().orElse(null));
CONTEXT_FUNCTIONS.put(DirectContextParameters.IS_CUSTOM, Item::isCustomItem);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

View File

@@ -26,6 +26,9 @@ public class PlayerParameterProvider implements ChainParameterProvider<Player> {
CONTEXT_FUNCTIONS.put(DirectContextParameters.NAME, Player::name); CONTEXT_FUNCTIONS.put(DirectContextParameters.NAME, Player::name);
CONTEXT_FUNCTIONS.put(DirectContextParameters.UUID, Player::uuid); CONTEXT_FUNCTIONS.put(DirectContextParameters.UUID, Player::uuid);
CONTEXT_FUNCTIONS.put(DirectContextParameters.WORLD, Entity::world); CONTEXT_FUNCTIONS.put(DirectContextParameters.WORLD, Entity::world);
CONTEXT_FUNCTIONS.put(DirectContextParameters.IS_FLYING, Player::isFlying);
CONTEXT_FUNCTIONS.put(DirectContextParameters.IS_SNEAKING, Player::isSneaking);
CONTEXT_FUNCTIONS.put(DirectContextParameters.GAMEMODE, Player::gameMode);
CONTEXT_FUNCTIONS.put(DirectContextParameters.MAIN_HAND_ITEM, p -> p.getItemInHand(InteractionHand.MAIN_HAND)); CONTEXT_FUNCTIONS.put(DirectContextParameters.MAIN_HAND_ITEM, p -> p.getItemInHand(InteractionHand.MAIN_HAND));
CONTEXT_FUNCTIONS.put(DirectContextParameters.OFF_HAND_ITEM, p -> p.getItemInHand(InteractionHand.OFF_HAND)); CONTEXT_FUNCTIONS.put(DirectContextParameters.OFF_HAND_ITEM, p -> p.getItemInHand(InteractionHand.OFF_HAND));
} }

View File

@@ -13,6 +13,8 @@ import net.momirealms.craftengine.core.util.MCUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Predicate; import java.util.function.Predicate;
public class AllPlayerSelector<CTX extends Context> implements PlayerSelector<CTX> { public class AllPlayerSelector<CTX extends Context> implements PlayerSelector<CTX> {
@@ -50,4 +52,14 @@ public class AllPlayerSelector<CTX extends Context> implements PlayerSelector<CT
public Key type() { public Key type() {
return PlayerSelectors.ALL; return PlayerSelectors.ALL;
} }
public static class FactoryImpl<CTX extends Context> implements PlayerSelectorFactory<CTX> {
@Override
public PlayerSelector<CTX> create(Map<String, Object> args, Function<Map<String, Object>, Condition<CTX>> conditionFactory) {
return null;
}
}
} }

View File

@@ -0,0 +1,12 @@
package net.momirealms.craftengine.core.plugin.context.selector;
import net.momirealms.craftengine.core.plugin.context.Condition;
import net.momirealms.craftengine.core.plugin.context.Context;
import java.util.Map;
import java.util.function.Function;
public interface PlayerSelectorFactory<CTX extends Context> {
PlayerSelector<CTX> create(Map<String, Object> args, Function<Map<String, Object>, Condition<CTX>> conditionFactory);
}

View File

@@ -2,12 +2,17 @@ package net.momirealms.craftengine.core.plugin.context.selector;
import net.momirealms.craftengine.core.plugin.context.Condition; import net.momirealms.craftengine.core.plugin.context.Condition;
import net.momirealms.craftengine.core.plugin.context.Context; import net.momirealms.craftengine.core.plugin.context.Context;
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.Key;
import net.momirealms.craftengine.core.util.MiscUtils; import net.momirealms.craftengine.core.util.MiscUtils;
import net.momirealms.craftengine.core.util.ResourceConfigUtils; import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import net.momirealms.craftengine.core.util.ResourceKey;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Function; import java.util.function.Function;
@@ -15,37 +20,41 @@ public class PlayerSelectors {
public static final Key ALL = Key.of("craftengine:all"); public static final Key ALL = Key.of("craftengine:all");
public static final Key SELF = Key.of("craftengine:self"); public static final Key SELF = Key.of("craftengine:self");
static {
register(ALL, new AllPlayerSelector.FactoryImpl<>());
register(SELF, new SelfPlayerSelector.FactoryImpl<>());
}
public static void register(Key key, PlayerSelectorFactory<?> factory) {
Holder.Reference<PlayerSelectorFactory<?>> holder = ((WritableRegistry<PlayerSelectorFactory<?>>) BuiltInRegistries.PLAYER_SELECTOR_FACTORY)
.registerForHolder(new ResourceKey<>(Registries.PLAYER_SELECTOR_FACTORY.location(), key));
holder.bindValue(factory);
}
@Nullable
public static <CTX extends Context> PlayerSelector<CTX> fromObject(Object object, Function<Map<String, Object>, Condition<CTX>> conditionFactory) { public static <CTX extends Context> PlayerSelector<CTX> fromObject(Object object, Function<Map<String, Object>, Condition<CTX>> conditionFactory) {
if (object == null) return null; if (object == null) return null;
if (object instanceof String string) { if (object instanceof Map<?,?> map) {
if (string.equals("self") || string.equals("@self") || string.equals("@s")) {
return new SelfPlayerSelector<>();
} else if (string.equals("all") || string.equals("@all") || string.equals("@a")) {
return new AllPlayerSelector<>();
}
} else if (object instanceof Map<?,?> map) {
Map<String, Object> selectorMap = MiscUtils.castToMap(map, false); Map<String, Object> selectorMap = MiscUtils.castToMap(map, false);
Object typeObj = selectorMap.get("type"); return fromMap(selectorMap, conditionFactory);
Object conditionObj = ResourceConfigUtils.get(selectorMap, "conditions"); } else if (object instanceof String target) {
if (!(typeObj instanceof String typeString)) { if (target.equals("all") || target.equals("@a")) {
throw new UnsupportedOperationException("Not supported yet."); return new AllPlayerSelector<>();
} } else if (target.equals("self") || target.equals("@s")) {
if (typeString.equals("all") || typeString.equals("@all") || typeString.equals("@a")) { return new SelfPlayerSelector<>();
List<Condition<CTX>> conditions = new ArrayList<>();
if (conditionObj instanceof List<?> list) {
@SuppressWarnings("unchecked")
List<Map<String, Object>> conditionList = (List<Map<String, Object>>) list;
for (Map<String, Object> condition : conditionList) {
conditions.add(conditionFactory.apply(condition));
}
} else if (conditionObj instanceof Map<?,?>) {
conditions.add(conditionFactory.apply(MiscUtils.castToMap(conditionObj, false)));
} else {
return new AllPlayerSelector<>();
}
return new AllPlayerSelector<>(conditions);
} }
} }
throw new UnsupportedOperationException("Not supported yet."); throw new LocalizedResourceConfigException("warning.config.selector.invalid_target", object.toString());
}
public static <CTX extends Context> PlayerSelector<CTX> fromMap(Map<String, Object> map, Function<Map<String, Object>, Condition<CTX>> conditionFactory) {
String type = ResourceConfigUtils.requireNonEmptyStringOrThrow(map.get("type"), "warning.config.selector.missing_type");
Key key = Key.withDefaultNamespace(type, Key.DEFAULT_NAMESPACE);
@SuppressWarnings("unchecked")
PlayerSelectorFactory<CTX> factory = (PlayerSelectorFactory<CTX>) BuiltInRegistries.PLAYER_SELECTOR_FACTORY.getValue(key);
if (factory == null) {
throw new LocalizedResourceConfigException("warning.config.selector.invalid_type", type);
}
return factory.create(map, conditionFactory);
} }
} }

View File

@@ -1,11 +1,14 @@
package net.momirealms.craftengine.core.plugin.context.selector; package net.momirealms.craftengine.core.plugin.context.selector;
import net.momirealms.craftengine.core.entity.player.Player; import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.plugin.context.Condition;
import net.momirealms.craftengine.core.plugin.context.Context; import net.momirealms.craftengine.core.plugin.context.Context;
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.Key;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.function.Function;
public class SelfPlayerSelector<CTX extends Context> implements PlayerSelector<CTX> { public class SelfPlayerSelector<CTX extends Context> implements PlayerSelector<CTX> {
@@ -18,4 +21,11 @@ public class SelfPlayerSelector<CTX extends Context> implements PlayerSelector<C
public Key type() { public Key type() {
return PlayerSelectors.SELF; return PlayerSelectors.SELF;
} }
public static class FactoryImpl<CTX extends Context> implements PlayerSelectorFactory<CTX> {
@Override
public PlayerSelector<CTX> create(Map<String, Object> args, Function<Map<String, Object>, Condition<CTX>> conditionFactory) {
return new SelfPlayerSelector<>();
}
}
} }

View File

@@ -28,6 +28,9 @@ public class EventConditions {
register(CommonConditions.FALLING_BLOCK, new FallingBlockCondition.FactoryImpl<>()); register(CommonConditions.FALLING_BLOCK, new FallingBlockCondition.FactoryImpl<>());
register(CommonConditions.RANDOM, new RandomCondition.FactoryImpl<>()); register(CommonConditions.RANDOM, new RandomCondition.FactoryImpl<>());
register(CommonConditions.DISTANCE, new DistanceCondition.FactoryImpl<>()); register(CommonConditions.DISTANCE, new DistanceCondition.FactoryImpl<>());
register(CommonConditions.PERMISSION, new PermissionCondition.FactoryImpl<>());
register(CommonConditions.EQUALS, new EqualsCondition.FactoryImpl<>());
register(CommonConditions.EXPRESSION, new ExpressionCondition.FactoryImpl<>());
} }
public static void register(Key key, ConditionFactory<PlayerOptionalContext> factory) { public static void register(Key key, ConditionFactory<PlayerOptionalContext> factory) {

View File

@@ -1,10 +1,7 @@
package net.momirealms.craftengine.core.plugin.event; package net.momirealms.craftengine.core.plugin.event;
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
import net.momirealms.craftengine.core.plugin.context.function.CommandFunction; import net.momirealms.craftengine.core.plugin.context.function.*;
import net.momirealms.craftengine.core.plugin.context.function.CommonFunctions;
import net.momirealms.craftengine.core.plugin.context.function.Function;
import net.momirealms.craftengine.core.plugin.context.function.FunctionFactory;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.registry.BuiltInRegistries; import net.momirealms.craftengine.core.registry.BuiltInRegistries;
import net.momirealms.craftengine.core.registry.Holder; import net.momirealms.craftengine.core.registry.Holder;
@@ -24,6 +21,10 @@ public class EventFunctions {
static { static {
register(CommonFunctions.COMMAND, new CommandFunction.FactoryImpl<>(EventConditions::fromMap)); register(CommonFunctions.COMMAND, new CommandFunction.FactoryImpl<>(EventConditions::fromMap));
register(CommonFunctions.MESSAGE, new MessageFunction.FactoryImpl<>(EventConditions::fromMap));
register(CommonFunctions.ACTIONBAR, new ActionBarFunction.FactoryImpl<>(EventConditions::fromMap));
register(CommonFunctions.TITLE, new TitleFunction.FactoryImpl<>(EventConditions::fromMap));
register(CommonFunctions.CANCEL_EVENT, new CancelEventFunction.FactoryImpl<>(EventConditions::fromMap));
} }
public static void register(Key key, FunctionFactory<PlayerOptionalContext> factory) { public static void register(Key key, FunctionFactory<PlayerOptionalContext> factory) {

View File

@@ -25,6 +25,7 @@ import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
import net.momirealms.craftengine.core.plugin.context.condition.ConditionFactory; import net.momirealms.craftengine.core.plugin.context.condition.ConditionFactory;
import net.momirealms.craftengine.core.plugin.context.function.FunctionFactory; import net.momirealms.craftengine.core.plugin.context.function.FunctionFactory;
import net.momirealms.craftengine.core.plugin.context.number.NumberProviderFactory; import net.momirealms.craftengine.core.plugin.context.number.NumberProviderFactory;
import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelectorFactory;
import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.ResourceKey; import net.momirealms.craftengine.core.util.ResourceKey;
@@ -54,6 +55,7 @@ public class BuiltInRegistries {
public static final Registry<ResourcePackHostFactory> RESOURCE_PACK_HOST_FACTORY = createRegistry(Registries.RESOURCE_PACK_HOST_FACTORY); public static final Registry<ResourcePackHostFactory> RESOURCE_PACK_HOST_FACTORY = createRegistry(Registries.RESOURCE_PACK_HOST_FACTORY);
public static final Registry<FunctionFactory<PlayerOptionalContext>> EVENT_FUNCTION_FACTORY = createRegistry(Registries.EVENT_FUNCTION_FACTORY); public static final Registry<FunctionFactory<PlayerOptionalContext>> EVENT_FUNCTION_FACTORY = createRegistry(Registries.EVENT_FUNCTION_FACTORY);
public static final Registry<ConditionFactory<PlayerOptionalContext>> EVENT_CONDITION_FACTORY = createRegistry(Registries.EVENT_CONDITION_FACTORY); public static final Registry<ConditionFactory<PlayerOptionalContext>> EVENT_CONDITION_FACTORY = createRegistry(Registries.EVENT_CONDITION_FACTORY);
public static final Registry<PlayerSelectorFactory<?>> PLAYER_SELECTOR_FACTORY = createRegistry(Registries.PLAYER_SELECTOR_FACTORY);
private static <T> Registry<T> createRegistry(ResourceKey<? extends Registry<T>> key) { private static <T> Registry<T> createRegistry(ResourceKey<? extends Registry<T>> key) {
return new MappedRegistry<>(key); return new MappedRegistry<>(key);

View File

@@ -25,6 +25,7 @@ import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
import net.momirealms.craftengine.core.plugin.context.condition.ConditionFactory; import net.momirealms.craftengine.core.plugin.context.condition.ConditionFactory;
import net.momirealms.craftengine.core.plugin.context.function.FunctionFactory; import net.momirealms.craftengine.core.plugin.context.function.FunctionFactory;
import net.momirealms.craftengine.core.plugin.context.number.NumberProviderFactory; import net.momirealms.craftengine.core.plugin.context.number.NumberProviderFactory;
import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelectorFactory;
import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.ResourceKey; import net.momirealms.craftengine.core.util.ResourceKey;
@@ -53,6 +54,7 @@ public class Registries {
public static final ResourceKey<Registry<CustomSmithingTransformRecipe.ItemDataProcessor.ProcessorFactory>> SMITHING_RESULT_PROCESSOR_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("smithing_result_processor_factory")); public static final ResourceKey<Registry<CustomSmithingTransformRecipe.ItemDataProcessor.ProcessorFactory>> SMITHING_RESULT_PROCESSOR_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("smithing_result_processor_factory"));
public static final ResourceKey<Registry<HitBoxFactory>> HITBOX_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("hitbox_factory")); public static final ResourceKey<Registry<HitBoxFactory>> HITBOX_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("hitbox_factory"));
public static final ResourceKey<Registry<ResourcePackHostFactory>> RESOURCE_PACK_HOST_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("resource_pack_host_factory")); public static final ResourceKey<Registry<ResourcePackHostFactory>> RESOURCE_PACK_HOST_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("resource_pack_host_factory"));
public static final ResourceKey<Registry<FunctionFactory<PlayerOptionalContext>>> EVENT_FUNCTION_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("player_block_function_factory")); public static final ResourceKey<Registry<FunctionFactory<PlayerOptionalContext>>> EVENT_FUNCTION_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("event_function_factory"));
public static final ResourceKey<Registry<ConditionFactory<PlayerOptionalContext>>> EVENT_CONDITION_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("player_block_condition_factory")); public static final ResourceKey<Registry<ConditionFactory<PlayerOptionalContext>>> EVENT_CONDITION_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("event_condition_factory"));
public static final ResourceKey<Registry<PlayerSelectorFactory<?>>> PLAYER_SELECTOR_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("player_selector"));
} }