Overhaul: Maven migration, variant support, bug fixes, and updated docs#10
Overhaul: Maven migration, variant support, bug fixes, and updated docs#10RhythmicSys wants to merge 11 commits intomainfrom
Conversation
- add support for variants
- Config should now be more dynamic - default rules for bucketing mobs - Moved style configs under 'bucket-style' - Adjusted handling to use new formats
- getItemModel now returns the actual key - validation of the string happens in the Texture class now - Started work on making capture items and captured items more customizable
…dling bugs ConfigHandler was reading from bucket-style.* keys that never existed in config.yml; the correct section is captured-item-style.*. This silently ignored every style setting (name, glint, material, item model, resource pack toggle) and fell back to Java-side defaults. Fixed all key paths. config.yml had item-model: default, which is not a valid NamespacedKey and logged a warning on every reload. Changed to minecraft:bucket. Entity release now uses NMS Entity.setPos() via reflection before addEntity() is called, so mobs spawn at the release location directly. The previous approach (teleport before/after addEntity) broke when the capture chunk was unloaded, because teleport() requires the entity to already be in a world, and addEntity() always used the stored NBT position. Additional fixes: - Enchantment glint config option was always hardcoded to true; now reads isEnchantmentGlint() from ConfigHandler - Dead-code loop in setupTypes() added disallowed types to entityRules then immediately cleared them; removed the loop - onBucketMob and onUnbucketMob now guard on EquipmentSlot.HAND to avoid processing off-hand duplicate events - Event is now cancelled before world mutations in onBucketMob so other listeners do not see a half-removed entity - Debucket command: added null check for empty main hand, and now handles both the legacy string tag and the new byte-array tag - Texture config load error now goes through the SLF4J logger instead of printStackTrace()
| // These can already be bucketed, we don't wanna double-bucket lol | ||
| private final Set<EntityType> generalDisallowedTypes = Set.of( | ||
| EntityType.TROPICAL_FISH, EntityType.SALMON, EntityType.COD, | ||
| EntityType.AXOLOTL, EntityType.PUFFERFISH, EntityType.TADPOLE); |
There was a problem hiding this comment.
TODO: Add Sulfur Cube when 26.2 releases.
| @SuppressWarnings("SameParameterValue") | ||
| private Material validateMaterial(String materialName, Material defaultMaterial, String path) { | ||
| if (materialName == null) { | ||
| logger.warn("No material found for {}, using default material: {}", path, defaultMaterial); | ||
| return defaultMaterial; | ||
| } | ||
| Material material = Material.getMaterial(materialName); | ||
| if (material == null) { | ||
| logger.warn("Invalid material in '{}': {} - using default material: {}", path, materialName, defaultMaterial); | ||
| return defaultMaterial; | ||
| } | ||
| return material; | ||
| } |
There was a problem hiding this comment.
Either the caller should determine the defaultMaterial or the defaultMaterial should be known at this point without passing it in as a parameter.
In this case, the defaultMaterial should be a field and should be known without passing it in as a parameter.
There was a problem hiding this comment.
Requires additional testing with a new version of the Bucket Mobs Resource Pack.
| public boolean isAllowed() { | ||
| return allow; | ||
| } | ||
|
|
||
| public boolean isSneakRequired() { | ||
| return sneakRequired; | ||
| } | ||
|
|
||
| public boolean canPickupWhenAggro() { | ||
| return pickupWhenAggro; | ||
| } | ||
|
|
||
| public boolean shouldRequirePermission() { | ||
| return requiresPermission; | ||
| } |
There was a problem hiding this comment.
If the fields are final, they can just be public without getters.
| public String getItemName() { | ||
| return itemName; | ||
| } | ||
|
|
||
| public String getItemLore() { | ||
| return itemLore; | ||
| } | ||
|
|
||
| public boolean isEnchantGlint() { | ||
| return enchantGlint; | ||
| } | ||
|
|
||
| public NamespacedKey getItemModel() { | ||
| return itemModel; | ||
| } | ||
|
|
||
| public Material getItemType() { | ||
| return itemType; | ||
| } |
There was a problem hiding this comment.
If the fields are final, they can just be public without getters.
| public String getItemName() { | ||
| return itemName; | ||
| } | ||
|
|
||
| public boolean isEnchantGlint() { | ||
| return enchantGlint; | ||
| } | ||
|
|
||
| public NamespacedKey getItemModel() { | ||
| return itemModel; | ||
| } | ||
|
|
||
| public Material getItemType() { | ||
| return itemType; | ||
| } | ||
|
|
||
| public Integer getStackSize() { | ||
| return stackSize; | ||
| } |
There was a problem hiding this comment.
If the fields are final, they can just be public without getters.
| capture-item-style: | ||
| default: | ||
| name: default | ||
| enchantment-glint: false | ||
| item-model: "minecraft:bucket" | ||
| item-type: BUCKET | ||
| stack-size: default | ||
| captured-item-style: | ||
| use-resource-pack: false | ||
| default: | ||
| item-type: BUCKET | ||
| item-model: "minecraft:bucket" | ||
| name: "<aqua><display_name> in a Bucket" | ||
| lore: | ||
| - "<gray>A <type_name_cased> sits in the bucket</gray>" | ||
| enchantment-glint: true |
There was a problem hiding this comment.
This seems like a confusing name set: capture and captured are very easy to miss and confuse. Perhaps choose another name?
| default: op | ||
| simplebucketmobs.debucket: | ||
| description: "Dump saved mob NBT data from Mob Bucket to chat." No newline at end of file | ||
| description: "Dump saved mob NBT data from Mob Bucket to chat." |
There was a problem hiding this comment.
Does this accurately reflect debucket now? It shows the number of bytes for the new format.
There was a problem hiding this comment.
What is this file?
Should this file even be being committed?
There was a problem hiding this comment.
oh this shouldn't have been committed, no, this was just a reference from earlier in my testing to look at the format of a mob's data
Peashooter101
left a comment
There was a problem hiding this comment.
Mostly non-blocking, I think you're good to go after addressing the issues shown.
There was a problem hiding this comment.
Tested on 1.21.11
Functional Problems
- Fresh startup generates warnings:
[06:28:12 INFO]: [SimpleBucketMobs] Enabling SimpleBucketMobs v2.0.0-DEV
[06:28:12 WARN]: [SimpleBucketMobs] Invalid locale key: LOGGER_INVALID_LOCALE_KEY
[06:28:12 WARN]: [SimpleBucketMobs] Invalid locale key: LOGGER_INVALID_MOB_TYPE
[06:28:12 WARN]: [SimpleBucketMobs] Invalid locale key: LOGGER_INVALID_LOCALE_KEY
[06:28:12 WARN]: [SimpleBucketMobs] Invalid locale key: LOGGER_INVALID_MOB_TYPE
-
Bucketing has no default audio from interaction. There also does not appear to be any configuration option to set the sound if you wanted to.
-
Cow milking audio plays in spite of not milking cow. May be client sided and does not appear to be cancellable? Requires investigation.
-
Slimes and Spiders when aggro is placed on the player are bucketable with
pickup-when-aggro: false. These should not just work on Hostiles but on Neutral mobs as well.
Testing Problems
-
Cannot confirm
/sbm debucketwith legacy mob bucket, I do not have access to a legacy mob bucket. -
Testing
use-resource-pack: truerequires updated Simple Bucket Mobs resource pack.
General Issues
- Should we allow the user to specify what permission they would like to use when bucketing mobs? For an example use case, allow a player to bucket hostiles at a specific rank, but only bucket Villagers at a later rank?
| interactEvent.setCancelled(true); | ||
| ItemStack bucketItem = BucketHandler.getMobBucket(livingEntity); | ||
| BucketHandler.addMobBucketToInventory(player, bucketItem); | ||
| player.playSound(Sound.sound(Key.key("minecraft", "item.bucket.fill_fish"), Sound.Source.PLAYER, 1.0f, 1.0f)); |
There was a problem hiding this comment.
May be a good idea to make this sound configurable.
Peashooter101
left a comment
There was a problem hiding this comment.
No more blocking issues, testing was either done by you or me for confirmed issues.
Overhaul: Maven migration, variant support, bug fixes, and updated docs
Summary
BucketMoblistener with a split architecture (BucketHandler,EntityHandler,InteractListeners,BucketRule)texture.ymlusing NamespacedKey item models instead of the old integer custom model data systemapi-versionfrom1.20to1.21.6and updated Paper API dependency to matchBug fixes
Config keys were completely wrong
ConfigHandlerread frombucket-style.*keys that have never existed inconfig.yml. The correct section iscaptured-item-style.*. Every style setting (item name, glint, material, item model, resource pack toggle) was silently ignored and fell back to hardcoded Java defaults. All key paths corrected.config.ymlhaditem-model: default"default"is not a validNamespacedKeyand produced a logged warning on every reload. Changed to"minecraft:bucket".Entity release spawned at the capture location
addEntity()always reads the entity's stored NBT position. The previousteleport()-before/after approach broke when the capture chunk was unloaded becauseteleport()requires the entity to already be in a world and cannot reposition an unspawned entity. Fixed by callingEntity.setPos()via reflection (Paper 1.21+ uses Mojang mappings at runtime, so the method name is stable) beforeaddEntity(), so the mob spawns directly at the release location without touching the old chunk.Enchantment glint config was hardcoded
BucketHandleralways setENCHANTMENT_GLINT_OVERRIDEtotrueregardless of the config value. Now readsConfigHandler.isEnchantmentGlint().Dead-code loop in
setupTypes()A loop that added disallowed entity types to
entityRulesran immediately beforeentityRules.clear(), making it a no-op. Removed.Both hands triggered bucketing/unbucketing
PlayerInteractEntityEventandPlayerInteractEventboth fire once per hand. Neither handler checkedEquipmentSlot.HAND, so off-hand interactions caused duplicate processing. Added hand guards to both.Event cancelled too late in
onBucketMobThe entity was removed and the bucket given before
setCancelled(true), so other listeners received the event referencing an already-removed entity. Cancellation now happens first.Debucketcommand NPE and wrong tagCalling
.getItemMeta()on a null item (empty hand) caused a NullPointerException. The command also only checked the legacy string tag; buckets created by the current plugin version use the byte-array tag and would always return "not a bucket mob". Added null guard and both-tag support.Textureusede.printStackTrace()Replaced with
logger.error().Test plan
config.ymlsneak-required: truerequires-permission: truepickup-when-aggro: false/sbm reloadand confirm changes apply without restart/sbm debucketwith an empty hand, a regular item, a legacy bucket mob, and a current bucket mobuse-resource-pack: trueThis should close both Don't work #8 and Placing mob from bucket location issue #9