Jump to content

[1.15.2] GlobalLootModifier not working


Sinhika

Recommended Posts

After explanations from Draco18s (which, with his permission, I have documented for future use here: How to use Global Loot Modifiers ), I have tried to implement a loot_modifier that looks for the modded shears items defined in my SimpleOres mod, and then regenerates the loot table as if they were silk touch items (or real minecraft:shears, I have tried both). The goal is to implement modded shears in a other-mod-friendly fashion; overriding vanilla loot tables, the only way I was able to do it previously, is extremely unfriendly to other mods.

 

The mod source code in question is here: https://github.com/Sinhika/SimpleOres2

The loot modifier stuff is in https://github.com/Sinhika/SimpleOres2/blob/1.15/src/main/java/mod/alexndr/simpleores/helpers/SimpleOresLootModifiers.java

(Don't want to clutter up this post with lots of source code).

It is registered (along with everything else) in https://github.com/Sinhika/SimpleOres2/blob/1.15/src/main/java/mod/alexndr/simpleores/ModEventSubscriber.java

 

I've cut down the loot_modifier/mod_shears_harvest.json to a minimal test case, like so:

{
	"conditions": [
		{
			"condition": "minecraft:match_tool",
			"predicate": {
				"item": "simpleores:copper_shears"
			}
		}
	]
}

Based on the logs, or lack thereof, the function is being registered, but isn't being called when it ought to be.

Can anyone see any reason why, when I whack a leaf block with the copper shears, the loot modifier function isn't being called?

Edited by Sinhika
line breaks messed up looks
Link to comment
Share on other sites

Your code looks fine, my guess is that the tool predicate is returning false. Ie. that the item you're using doesn't match "simpleores:copper_shears"

 

Double check your registry names.

 

Scratch that, this file is in the wrong folder:

https://github.com/Sinhika/SimpleOres2/blob/1.15/src/main/resources/data/forge/global_loot_modifiers/global_loot_modifiers.json

Should be forge/loot_modifiers not forge/global_loot_modifiers.

Edited by Draco18s
  • Thanks 1

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

  • 6 months later...

Hi Sinhika! Thanks a lot for taking the time to make this very useful tutorial (https://dragoness-e.dreamwidth.org/136561.html), there isn't much practical info you can find besides that!!!

 

What it is not clear to me is how to inject custom loot pools into existing vanilla chests tables using this method. Did you find out how to, or you have any "pointer" I can follow? I am working on 1.16.3 version now.

 

Thx again!

Link to comment
Share on other sites

Thx for your reply!

 

I guess you mean here:

{
  "conditions": [
    {
      "condition": "minecraft:match_tool",
      "predicate": {
        "item": "minecraft:shears"
      }
    },
    {
      "condition": "block_state_property",
      "block":"minecraft:wheat"
    }
  ],
  "seedItem": "minecraft:wheat_seeds",
  "numSeeds": 3,
  "replacement": "minecraft:wheat"
}

I can see there is a "replacement" part which might be the key part (right?), but I don't want to replace it, I would like to add custom items to the vanilla chests loots without replacing it.

Link to comment
Share on other sites

Thanks again!

 

I see... may be you mean here? 

 

@Nonnull
    @Override
    public List<ItemStack> doApply(List<ItemStack> generatedLoot, LootContext context) {
        //
        // Additional conditions can be checked, though as much as possible should be parameterized via JSON data.
        // It is better to write a new ILootCondition implementation than to do things here.
        //
        int numSeeds = 0;
        for(ItemStack stack : generatedLoot) {
            if(stack.getItem() == itemToCheck)
                numSeeds+=stack.getCount();
        }
        if(numSeeds >= numSeedsToConvert) {
            generatedLoot.removeIf(x -> x.getItem() == itemToCheck);
            generatedLoot.add(new ItemStack(itemReward, (numSeeds/numSeedsToConvert)));
            numSeeds = numSeeds%numSeedsToConvert;
            if(numSeeds > 0)
                generatedLoot.add(new ItemStack(itemToCheck, numSeeds));
        }
        return generatedLoot;
    }

If so, where can I find some info about how to use all this stuff, specially adding or injecting custom loots into existing ones? There isn't anything similar I can search in vanilla classes as far as I know (if there is, sorry, I couldn't find it)

Link to comment
Share on other sites

See these lines?

3 hours ago, Kalma said:

generatedLoot.add(new ItemStack(itemToCheck, numSeeds));

3 hours ago, Kalma said:

generatedLoot.add(new ItemStack(itemReward, (numSeeds/numSeedsToConvert)));

That's how you add stuff.

The items and amounts in question are initialized by values stored in the json:

3 hours ago, Kalma said:

"seedItem": "minecraft:wheat_seeds",

"numSeeds": 3,

"replacement": "minecraft:wheat"

 

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

Hi again! I have been searching and testing a lot. I think I have everything in place (global_loot_modifier.json file, my custom .json file, the class which extends LootModifier class, and the registry stuff). What I still don't get to know is how to add my custom items to the vanilla chests.

 

I guess it is something related to the "conditions" or "type" part of my custom loot_modifier.json, right? I have tried to find out the right option, and I think it can be related to "table_bonus" (though inside the class seems to be related to enchantments) or "reference"...  but I am not able to find the "predicate" or whatever is needed to "hook" my items to the chests loot ... Am I missing anything?

 

My global_loot_modifier.json:

{
  "replace": false,
  "entries": [
    "lazybuilder:chests_lazy_builder"
  ]
}

My custom loot_modifier.json

 {
  "type": "lazybuilder:chests_lazy_builder",
  "conditions": [
    {
      "condition": "WHAT SHOULD GO HERE???: e.g. reference???",
      "name":"AND HERE?: e.g. minecraft:chests???"
    }
  ],
  "items": [
    {
      "item": "lazybuilder:start_block",
      "weight": 20
    },
    {
      "item": "lazybuilder:mid_block",
      "weight": 30
    },
    {
      "item": "lazybuilder:end_block",
      "weight": 20
    },
    {
      "item": "lazybuilder:copy_paste_block",
      "weight": 10
    }
  ]
}

My LootModifier class

public class ChestLootModifier extends LootModifier {
	
	@SuppressWarnings("unused")
	private static final Logger LOGGER = LogManager.getLogger();

    private final List<Item> itemToAdd;
    private final List<Integer> weights;
	private final String addTo = "minecraft:chests";
    ILootCondition[] conditions;
    
    public ChestLootModifier(ILootCondition[] conditionsIn, List<Item> itemLoot, List<Integer> itemWeights) {
        super(conditionsIn);
        itemToAdd = itemLoot;
        weights = itemWeights;
    }

    @Nonnull
    @Override
    public List<ItemStack> doApply(List<ItemStack> generatedLoot, LootContext context) {
    	
    	if (false) { // How do I hook to chests loot to add my stuff???
        	for (int i = 0; i < itemToAdd.size() && i < weights.size(); ++i) {
        		int randValue = new Random().nextInt(101);
        		int count = 0;
        		if (randValue <= weights.get(i)) {
        			count = 1;
        		}
        		generatedLoot.add(new ItemStack(itemToAdd.get(i), count));
        	}
    	}
        return generatedLoot;
    }
    
    public static class Serializer extends GlobalLootModifierSerializer<ChestLootModifier> {

        @Override
        public ChestLootModifier read(ResourceLocation name, JsonObject object, ILootCondition[] conditionsIn) {
        	
        	List<Item> blockStack = new ArrayList<Item>();
            List<Integer> weightList = new ArrayList<Integer>();
            
        	for (JsonElement item : JSONUtils.getJsonArray(object, "items")) {
        		blockStack.add(ForgeRegistries.ITEMS.getValue(new ResourceLocation(JSONUtils.getString(item.getAsJsonObject(), "item"))));
        		weightList.add(JSONUtils.getInt(item.getAsJsonObject(), "weight"));
        	}
        	return new ChestLootModifier(conditionsIn, blockStack, weightList);
        }

		@Override
		public JsonObject write(ChestLootModifier instance) {
			// TODO Auto-generated method stub
			return null;
		}
    }
}

 

Link to comment
Share on other sites

HAHAHAHA! Well... I learned a lot on the way!

 

So, I should stick to the "old" method, right?

    public class onLootTableLoadListener {
		
	@SubscribeEvent
	    public void LootTablesLoad(final LootTableLoadEvent event) {
		
		String prefix = "minecraft:chests/";
		String name = event.getName().toString();
			
		// Test: /loot give @p loot minecraft:chests/pillager_outpost
		if (name.startsWith(prefix)) {
                event.getTable().addPool(LootPool.builder()
    						.addEntry(TableLootEntry.builder(new ResourceLocation(Refs.MODID, "chests/lazy_builder"))
    						.weight(1))
    						.bonusRolls(0, 1)
    						.name(Refs.MODID)
    						.build()
    			);
			}
		}
	}

 

Thank you anyway!

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.