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

View File

@@ -142,7 +142,7 @@ public abstract class CraftEngine implements Plugin {
@Override @Override
public void enable() { public void enable() {
this.networkManager.enable(); this.networkManager.enable();
this.templateManager = new TemplateManagerImpl(this); this.templateManager = new TemplateManagerImpl();
this.itemBrowserManager = new ItemBrowserManagerImpl(this); this.itemBrowserManager = new ItemBrowserManagerImpl(this);
this.commandManager.registerDefaultFeatures(); this.commandManager.registerDefaultFeatures();
// delay the reload so other plugins can register some parsers // 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);
this.packManager.registerConfigSectionParser(this.soundManager.jukeboxSongManager()); this.packManager.registerConfigSectionParser(this.soundManager.jukeboxSongManager());
// register vanilla loot parser // register vanilla loot parser
this.packManager.registerConfigSectionParser(this.vanillaLootManager); this.packManager.registerConfigSectionParser(this.vanillaLootManager.parser());
} }
protected abstract void delayedEnable(); 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.pack.Pack;
import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser; 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.GsonHelper;
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;
@@ -19,13 +20,11 @@ import java.util.regex.Matcher;
import static net.momirealms.craftengine.core.util.MiscUtils.castToMap; import static net.momirealms.craftengine.core.util.MiscUtils.castToMap;
public class TemplateManagerImpl implements TemplateManager { public class TemplateManagerImpl implements TemplateManager {
private final CraftEngine plugin;
private final Map<Key, Object> templates = new HashMap<>(); 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 static Set<String> NON_TEMPLATE_KEY = new HashSet<>(Set.of(TEMPLATE, ARGUMENTS, OVERRIDES));
private final TemplateParser templateParser; private final TemplateParser templateParser;
public TemplateManagerImpl(CraftEngine plugin) { public TemplateManagerImpl() {
this.plugin = plugin;
this.templateParser = new TemplateParser(); this.templateParser = new TemplateParser();
} }
@@ -60,7 +59,10 @@ public class TemplateManagerImpl implements TemplateManager {
@Override @Override
public void addTemplate(Pack pack, Path path, Key id, Object obj) { 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); this.templates.put(id, obj);
} }