Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[1.9] Loot table hooking #2540

Closed
williewillus opened this issue Mar 13, 2016 · 1 comment
Closed

[1.9] Loot table hooking #2540

williewillus opened this issue Mar 13, 2016 · 1 comment

Comments

@williewillus
Copy link
Contributor

I thought I'd start off the discussion for this, since it's one of the parts I'm most interested in in 1.9.

Some terminology

Ctrl+F "Loot tables" in this for some basic terminology
https://gist.github.com/williewillus/e37edde85dc78d2e138c

Adding pieces to the looting system

  • All the abovementioned classes are easy to add to in code. Each class has its own registry where you can register your object to a name, e.g. I can register a LootFunction "botania:add_mana" that takes a stack and adds mana to it simply by calling LootFunctionManager.registerFunction(Serializer). For all of these, you have to pass in a serializer describing how it'll be (de)serialized from JSON form.

Activation of the looting system

  • For living entities: The entire loot table system is only queried for subclasses of EntityLiving. EntityLivingBase#onDeath calls dropLoot, which is fully overriden by EntityLiving. dropFewItems doesn't do anything anymore (except for slimes which still use it for some reason.
    • The loot table to use is an NBT tag in the entity, "DeathLootTable". Falls back to a default for vanilla mobs.
    • The forge hook to capture drops is in EntityLivingBase#onDeath and should still capture all loot dropped. Perhaps we should provide the loot context in LivingDropsEvent, though that would require us to move the event. A more viable alternative is to expose the LootContext in an event, allowing others to modify the Loot Tables in code?
  • For TE's and things like minecarts. These implement ILootableContainer, which contains a single method returning the ResourceLocation of the loot table to generate. TE's and carts have a field/NBT tag that holds this ResourceLocation. Upon the first opening of the container, the loot table is queried and then the loot table field in the object is set to null. It's possible in code for the loot table to be re-set so that it regenerates again whenever the container is opened next. I don't think this requires any hooking/modification.

Loading of loot tables

Probably the most difficulty piece to figure out currently.
Although loot tables in the vanilla jar are in the "/assets/" directory, they are far from being part of the powerful cascading resource pack / clientside asset system. What vanilla does currently in LootTableManager.Loader.load(ResourceLocation) is look for loot jsons in the world directory (new File(LootTableManager#baseFolder, ...)), a vanilla feature allowing mappers to override tables, and then fall back directly to the jar if the former is missing (LootTableManager.class.getResource(URL)), then to an empty table if it's still missing.
The easiest solution is simply to place a hook directly below the loading from world folder call, that loads from mod jars, but still lets mappers' world-specific tables have top priority
The question arises is that with this, we don't know what jar to look in. Looking at the resource domain of the resource location to determine which jar to search would be a fallback but it would prevent an addon for example from changing its parent mod's tables. Or we could scan through all jars to look for any loot json, but that implicitly enforces an ordering in the case of conflicting jsons.
(Or we could find a way to bring that whole cascading resource system to the serverside? I don't know that system well enough to say if that's feasible)

Alternatively we could just forego this entirely, use the vanilla registries, and just have mods "figure it out" how to get an instance of LootTable to the registry. (i.e. they handle deserialization themselves). But that's meh.

Thoughts?

What would get obsoleted

  • ChestGenHooks and FishingHooks are both going to go away
    • This requires us to determine a way to inject mod entries into the main loot tables. Can't replace the tables because then mods would conflict. Would using the events proposed above be suitable?
@williewillus
Copy link
Contributor Author

Moving discussion to the PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant