9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-23 17:09:19 +00:00

refactor vanilla loots

This commit is contained in:
XiaoMoMi
2025-04-04 03:57:55 +08:00
parent 0385343b2a
commit 4e945f2af2
6 changed files with 105 additions and 66 deletions

View File

@@ -64,4 +64,7 @@ warning.config.image.codepoint_in_use: "<yellow>Issue found in file <arg:0> - Th
warning.config.image.invalid_codepoint_grid: "<yellow>Issue found in file <arg:0> - Image '<arg:1>' has an invalid 'chars' codepoint grind.</yellow>"
warning.config.image.file_not_exist: "<yellow>Issue found in file <arg:0> - PNG file <arg:2> not found for image '<arg:1>'.</yellow>"
warning.config.recipe.duplicated: "<yellow>Issue found in file <arg:0> - Duplicated recipe '<arg:1>'.</yellow>"
warning.config.i18n.unknown_locale: "<yellow>Issue found in file <arg:0> - Unknown locale '<arg:1>'.</yellow>"
warning.config.i18n.unknown_locale: "<yellow>Issue found in file <arg:0> - Unknown locale '<arg:1>'.</yellow>"
warning.config.template.duplicated: "<yellow>Issue found in file <arg:0> - Duplicated template '<arg:1>'.</yellow>"
warning.config.vanilla_loot.type_not_exist: "<yellow>Issue found in file <arg:0> - 'type' not set for vanilla loot '<arg:1>'.</yellow>"
warning.config.vanilla_loot.block.invalid_target: "<yellow>Issue found in file <arg:0> - Invalid block target [<arg:2>] in vanilla loot '<arg:1>'.</yellow>"

View File

@@ -8,11 +8,15 @@ 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.VanillaLootManager;
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.locale.TranslationManager;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MiscUtils;
import net.momirealms.craftengine.core.util.PreConditions;
@@ -33,15 +37,13 @@ import java.nio.file.Path;
import java.util.*;
// note: block listeners are in BlockEventListener to reduce performance cost
public class BukkitVanillaLootManager implements VanillaLootManager, Listener {
public class BukkitVanillaLootManager extends AbstractVanillaLootManager implements Listener {
private final BukkitCraftEngine plugin;
private final Map<Integer, VanillaLoot> blockLoots;
private final Map<Key, VanillaLoot> entityLoots;
private final VanillaLootParser vanillaLootParser;
public BukkitVanillaLootManager(BukkitCraftEngine plugin) {
this.plugin = plugin;
this.blockLoots = new HashMap<>();
this.entityLoots = new HashMap<>();
this.vanillaLootParser = new VanillaLootParser();
}
@Override
@@ -54,17 +56,6 @@ public class BukkitVanillaLootManager implements VanillaLootManager, Listener {
HandlerList.unregisterAll(this);
}
@Override
public void unload() {
this.blockLoots.clear();
this.entityLoots.clear();
}
@Override
public Optional<VanillaLoot> getBlockLoot(int vanillaBlockState) {
return Optional.ofNullable(this.blockLoots.get(vanillaBlockState));
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void onEntityDeath(EntityDeathEvent event) {
Entity entity = event.getEntity();
@@ -97,45 +88,65 @@ public class BukkitVanillaLootManager implements VanillaLootManager, Listener {
}
@Override
public void parseSection(Pack pack, Path path, Key id, Map<String, Object> section) {
String type = (String) section.get("type");
if (PreConditions.isNull(type, () -> this.plugin.logger().warn(path, "`type` option is required for vanilla-loot " + id))) {
return;
public ConfigSectionParser parser() {
return this.vanillaLootParser;
}
public class VanillaLootParser implements ConfigSectionParser {
public static final String[] CONFIG_SECTION_NAME = new String[] {"vanilla-loots", "vanilla-loot", "loots", "loot"};
@Override
public int loadingSequence() {
return LoadingSequence.VANILLA_LOOTS;
}
VanillaLoot.Type typeEnum = VanillaLoot.Type.valueOf(type.toUpperCase(Locale.ENGLISH));
boolean override = (boolean) section.getOrDefault("override", false);
List<String> targets = MiscUtils.getAsStringList(section.getOrDefault("target", List.of()));
LootTable<?> lootTable = LootTable.fromMap(MiscUtils.castToMap(section.get("loot"), false));
switch (typeEnum) {
case BLOCK -> {
for (String target : targets) {
if (target.endsWith("]") && target.contains("[")) {
java.lang.Object blockState = BlockStateUtils.blockDataToBlockState(Bukkit.createBlockData(target));
if (blockState == Reflections.instance$Blocks$AIR$defaultState) {
this.plugin.logger().warn(path, "Failed to load " + id + ". Invalid target " + target);
return;
}
VanillaLoot vanillaLoot = this.blockLoots.computeIfAbsent(BlockStateUtils.blockStateToId(blockState), k -> new VanillaLoot(VanillaLoot.Type.BLOCK));
vanillaLoot.addLootTable(lootTable);
} else {
for (Object blockState : BlockStateUtils.getAllVanillaBlockStates(Key.of(target))) {
@Override
public String[] sectionId() {
return CONFIG_SECTION_NAME;
}
@Override
public void parseSection(Pack pack, Path path, Key id, Map<String, Object> section) {
String type = (String) section.get("type");
if (type == null) {
TranslationManager.instance().log("warning.config.vanilla_loot.type_not_exist", path.toString(), id.toString());
return;
}
VanillaLoot.Type typeEnum = VanillaLoot.Type.valueOf(type.toUpperCase(Locale.ENGLISH));
boolean override = (boolean) section.getOrDefault("override", false);
List<String> targets = MiscUtils.getAsStringList(section.getOrDefault("target", List.of()));
LootTable<?> lootTable = LootTable.fromMap(MiscUtils.castToMap(section.get("loot"), false));
switch (typeEnum) {
case BLOCK -> {
for (String target : targets) {
if (target.endsWith("]") && target.contains("[")) {
java.lang.Object blockState = BlockStateUtils.blockDataToBlockState(Bukkit.createBlockData(target));
if (blockState == Reflections.instance$Blocks$AIR$defaultState) {
this.plugin.logger().warn(path, "Failed to load " + id + ". Invalid target " + target);
TranslationManager.instance().log("warning.config.vanilla_loot.block.invalid_target", path.toString(), id.toString(), target);
return;
}
VanillaLoot vanillaLoot = this.blockLoots.computeIfAbsent(BlockStateUtils.blockStateToId(blockState), k -> new VanillaLoot(VanillaLoot.Type.BLOCK));
if (override) vanillaLoot.override(true);
VanillaLoot vanillaLoot = blockLoots.computeIfAbsent(BlockStateUtils.blockStateToId(blockState), k -> new VanillaLoot(VanillaLoot.Type.BLOCK));
vanillaLoot.addLootTable(lootTable);
} else {
for (Object blockState : BlockStateUtils.getAllVanillaBlockStates(Key.of(target))) {
if (blockState == Reflections.instance$Blocks$AIR$defaultState) {
TranslationManager.instance().log("warning.config.vanilla_loot.block.invalid_target", path.toString(), id.toString(), target);
return;
}
VanillaLoot vanillaLoot = blockLoots.computeIfAbsent(BlockStateUtils.blockStateToId(blockState), k -> new VanillaLoot(VanillaLoot.Type.BLOCK));
if (override) vanillaLoot.override(true);
vanillaLoot.addLootTable(lootTable);
}
}
}
}
}
case ENTITY -> {
for (String target : targets) {
Key key = Key.of(target);
VanillaLoot vanillaLoot = this.entityLoots.computeIfAbsent(key, k -> new VanillaLoot(VanillaLoot.Type.ENTITY));
vanillaLoot.addLootTable(lootTable);
if (override) vanillaLoot.override(true);
case ENTITY -> {
for (String target : targets) {
Key key = Key.of(target);
VanillaLoot vanillaLoot = entityLoots.computeIfAbsent(key, k -> new VanillaLoot(VanillaLoot.Type.ENTITY));
vanillaLoot.addLootTable(lootTable);
if (override) vanillaLoot.override(true);
}
}
}
}

View File

@@ -0,0 +1,30 @@
package net.momirealms.craftengine.core.loot;
import net.momirealms.craftengine.core.util.Key;
import java.util.*;
public abstract class AbstractVanillaLootManager implements VanillaLootManager {
protected final Map<Integer, VanillaLoot> blockLoots = new HashMap<>();
// TODO More entity NBT
protected final Map<Key, VanillaLoot> entityLoots = new HashMap<>();
public AbstractVanillaLootManager() {
}
@Override
public void unload() {
this.blockLoots.clear();
this.entityLoots.clear();
}
@Override
public Optional<VanillaLoot> getBlockLoot(int vanillaBlockState) {
return Optional.ofNullable(this.blockLoots.get(vanillaBlockState));
}
@Override
public Optional<VanillaLoot> getEntityLoot(Key entity) {
return Optional.ofNullable(this.entityLoots.get(entity));
}
}

View File

@@ -1,23 +1,16 @@
package net.momirealms.craftengine.core.loot;
import net.momirealms.craftengine.core.pack.LoadingSequence;
import net.momirealms.craftengine.core.plugin.Reloadable;
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
import net.momirealms.craftengine.core.util.Key;
import java.util.Optional;
public interface VanillaLootManager extends ConfigSectionParser, Reloadable {
String[] CONFIG_SECTION_NAME = new String[] {"vanilla-loots", "vanilla-loot", "loots", "loot"};
public interface VanillaLootManager extends Reloadable {
@Override
default int loadingSequence() {
return LoadingSequence.VANILLA_LOOTS;
}
@Override
default String[] sectionId() {
return CONFIG_SECTION_NAME;
}
ConfigSectionParser parser();
Optional<VanillaLoot> getBlockLoot(int blockState);
Optional<VanillaLoot> getEntityLoot(Key entity);
}

View File

@@ -142,7 +142,7 @@ public abstract class CraftEngine implements Plugin {
@Override
public void enable() {
this.networkManager.enable();
this.templateManager = new TemplateManagerImpl(this);
this.templateManager = new TemplateManagerImpl();
this.itemBrowserManager = new ItemBrowserManagerImpl(this);
this.commandManager.registerDefaultFeatures();
// delay the reload so other plugins can register some parsers
@@ -205,7 +205,7 @@ public abstract class CraftEngine implements Plugin {
this.packManager.registerConfigSectionParser(this.soundManager);
this.packManager.registerConfigSectionParser(this.soundManager.jukeboxSongManager());
// register vanilla loot parser
this.packManager.registerConfigSectionParser(this.vanillaLootManager);
this.packManager.registerConfigSectionParser(this.vanillaLootManager.parser());
}
protected abstract void delayedEnable();

View File

@@ -4,6 +4,7 @@ import net.momirealms.craftengine.core.pack.LoadingSequence;
import net.momirealms.craftengine.core.pack.Pack;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
import net.momirealms.craftengine.core.plugin.locale.TranslationManager;
import net.momirealms.craftengine.core.util.GsonHelper;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MiscUtils;
@@ -19,13 +20,11 @@ import java.util.regex.Matcher;
import static net.momirealms.craftengine.core.util.MiscUtils.castToMap;
public class TemplateManagerImpl implements TemplateManager {
private final CraftEngine plugin;
private final Map<Key, Object> templates = new HashMap<>();
private final static Set<String> NON_TEMPLATE_KEY = new HashSet<>(Set.of(TEMPLATE, ARGUMENTS, OVERRIDES));
private final TemplateParser templateParser;
public TemplateManagerImpl(CraftEngine plugin) {
this.plugin = plugin;
public TemplateManagerImpl() {
this.templateParser = new TemplateParser();
}
@@ -60,7 +59,10 @@ public class TemplateManagerImpl implements TemplateManager {
@Override
public void addTemplate(Pack pack, Path path, Key id, Object obj) {
if (PreConditions.runIfTrue(this.templates.containsKey(id), () -> this.plugin.logger().warn(path, "Template duplicates: " + id))) return;
if (this.templates.containsKey(id)) {
TranslationManager.instance().log("warning.config.template.duplicated", path.toString(), id.toString());
return;
}
this.templates.put(id, obj);
}