Dropt

Dropt

3M Downloads

How to replace drop without changing the amount of drop

Fireztonez opened this issue ยท 17 comments

commented

Hello,
In my modpack, I try to replace all Gems Ores drops, question to drop uncut version of the same gem. Basically, what I need is just changing each diamond drop by uncut Diamond.

For now, the only way I see, is to recreate completly the item drop count, and this is anoying, because of the fact I don't only have 3 level of fortune in my modpack, but 10, so, adding a rule for each level, for all gems type I have in the pack (With silent Gems install, so like 50 type of gems), I think my script will have about 5000 lines...

So I want to know if you have a better way possible right now or if not, do you think this is possible to add something for me question to do what I need easily...

Thank's
Fireztonez

commented

I don't know of a better way to do what you want with the current features of Dropt. As far as adding something to do this, I'm sure it's possible, but I may not get to it for a while.

commented

ok, thank's for the information.
I saw the IRandomFortuneInt, I will possibly try to do the way with the calculation method if I can understand how it work...

commented

I test the second mod availiable in curse forge for changing the drop for blocks and the issue there have the same problem, I will have to set manually heach level of fortune, but the JSON syntax is a total mess and look like it give less control at the end than Dropt and the docs is just completly absents, question of the JSON syntax, so, if you are able to work question to add the possibility of changing the item drop, but keeping the fortune quantity, it will be really nice!!

Unless, I think I will have to find a mod dev to do something costum for me, but, not sure if I will be able to find one...

Thank's again Codetaylor for your great work! Continue like that
Fireztonez

commented

I would really like this feature as well. I'm trying to replace the drops of Dynamic Trees trees, and there's no way to determine the tree size within Dropt. It would probably be easy to add an option that just copies the stacksize of matching items to the stacksize of the new items.

commented

The approach of just copying the stack size of matching items to the stack size of the new items is pretty straightforward if the rule is a 1:1, meaning the rule is replacing one item with one other item. It starts to break down a bit when the rule becomes more complex and deserves attention to how the feature would play out given different use cases.

For example, what is the behavior when more than one item match is defined in the rule and more than one drop is also defined?

Here's a case:

  • a block can drop saplings and sticks, sometimes separately, sometimes together, and
  • the rule is set to match both sticks and saplings, and
  • the rule uses a REPLACE_ITEMS strategy indicating that all defined items (sticks and saplings) should be replaced with the drops, and
  • the rule indicates that it should use the quantities of the dropped items, and
  • the rule has two defined drops, dirt and cobblestone, and is configured to always drop both items

Now let's say the block in the case is broken and it drops 5 sticks and 1 sapling.

The rule will match the first drop it encounters in the list of drops that is also defined in the rule.
Let's say that in this case it matches on the 5 sticks.

Which quantity is selected and how is it mapped to the two new item drops?

The rule would remove the 5 sticks and 1 sapling. At this point, it would be fairly easy to tally the quantities of the removed items, but how should the tallied quantities be mapped to the new output?

Should it drop 5 dirt and 1 cobblestone?
Should it drop 1 dirt and 5 cobblestone?
Should it drop 6 dirt and 6 cobblestone?
Should it drop 5 dirt and 5 cobblestone?
Should it drop 1 dirt and 1 cobblestone?

After giving it some serious thought, this is my first proposed solution:

{
  "rules": [
    {
      "match": {
        "drops": {
          "drops": [
            "minecraft:stick",
            "minecraft:sapling"
          ]
        }
      },
      "dropCount": {
        "fixed": 2
      },
      "dropStrategy": "UNIQUE",
      "replaceStrategy": "REPLACE_ITEMS",
      "drops": [
        {
          "item": {
            "items" : [
              "minecraft:dirt"
            ],
            "matchQuantity": {
              "drops": [
                "minecraft:stick"
              ]
            }
          }
        },
        {
          "item": {
            "items" : [
              "minecraft:cobblestone"
            ],
            "matchQuantity": {
              "drops": [
                "minecraft:sapling"
              ]
            }
          }
        }
      ]
    }
  ]
}

Item entries in the drops list would be given an additional parameter, matchQuantity.

If a drop is selected, its quantity would depend on the total quantities of all items defined in the list. If no matching item was found in the dropped items, the drop would first default to a defined quantity, then the default quantity of one.

Using this solution for the case above, Dropt now knows exactly how to derive each item's quantity from dropped items.

Additionally, thought must be given to the syntax of the new feature.

"matchQuantity": {
  "drops": [
    "minecraft:sapling"
  ]
}

Defining the matchQuantity as an object allows for the easy addition of future parameters without breaking existing scripts. For example, adding a parameter in the future might look like this:

"matchQuantity": {
  "type": "RANDOM",
  "drops": [
    "minecraft:sapling"
  ]
}

Defining the drops as a list of items rather than a single item will allow for more flexibility in the future.

If this is the approach that we go with, then this is the work that needs to be done:

  • write a new pojo for matchQuantity
  • write a new parser for the matchQuantity pojo
  • write the new quantity logic in the drop logic
  • add new API method(s) to define the matchQuantity object
  • add new CrT method(s) to define the matchQuantity object
  • document the new json syntax and provide example
  • document the new CrT syntax and provide example
  • document the new API syntax and provide example
  • test all three new syntaxes

I wish it was as simple as just copying the stack sizes, but in the interest of designing a good feature, I believe it requires more attention.

What are your thoughts on this approach?

commented

It looks like a good design to me. I'm not part of the team really, but if you could explain the objects associated with each of those points I'd be willing to try and implement it. I can code Java decently, especially when most of the stuff will just be adding to existing objects based on existing code, I just need to know the process for making and registering the "pojo" and "parser" and where to put the quantity logic.

commented

@WolfieWaffle I planned to work on this in a week or two, but if you'd like to have a go, here is some information.

I would ask that you please:

  • understand if I am particular about certain things
  • try to do the work in very few commits, one if possible; maybe use a feature branch / interactive rebase to squash commits, etc.
  • adhere to the project's code style and conventions
  • do not make any changes outside the context of this feature
  • try not to introduce any regressions; there aren't any tests, so a good understanding of how it works before changing it is crucial
  • ensure logging where appropriate using the existing logging setup

The json data is modeled with data objects here:
https://github.com/codetaylor/dropt/tree/master/src/main/java/com/codetaylor/mc/dropt/modules/dropt/rule/data

All json data objects have public fields and default values.

Here is the drop object parser:
https://github.com/codetaylor/dropt/blob/master/src/main/java/com/codetaylor/mc/dropt/modules/dropt/rule/parse/ParserRuleDropItem.java

I think it would be ok to put the parsing logic in the existing drop parser. The quantity match items should be parsed as domain:path:meta using the existing recipe item parser. Each quantity match item should probably be parsed into an Ingredient to simply use ingredient matching when calculating the drop quantity later.

Here is the drop modification logic:
https://github.com/codetaylor/dropt/blob/master/src/main/java/com/codetaylor/mc/dropt/modules/dropt/rule/drop/DropModifier.java#L24

I think the quantity calculations would look something like this pseudo:

if matchQuantity._drops != null
  for each ingredient in matchQuantity._drops
    for each drop in drops
      if ingredient matches drop
        quantity += drop.count
else
  ... existing quantity behavior

The API package:
https://github.com/codetaylor/dropt/tree/master/src/main/java/com/codetaylor/mc/dropt/api

Here is the ZenScript class for the drop objects:
https://github.com/codetaylor/dropt/blob/master/src/main/java/com/codetaylor/mc/dropt/modules/dropt/compat/crafttweaker/ZenDrop.java

The docs folder:
https://github.com/codetaylor/dropt/tree/master/docs

The api, examples, and json folders must be manually edited.

Do not manually edit the zs files, they are exported with:
https://github.com/codetaylor/dropt/blob/master/src/main/java/com/codetaylor/mc/dropt/modules/dropt/compat/crafttweaker/ExportDocumentation.java

commented

Hm now I kind of feel bad for making you type all that, I don't really know what regressions are or how to prevent them. But I can always attempt to figure all this out, it would certainly be good for learning even if I don't get it done before you do. My biggest problem is usually figuring out how a project that isn't mine works. Maybe I could do this step by step though and ask you if what I'm doing is correct?

commented

Ohh, so JUnit tests basically? But you don't have any tests to run? How do I know what bugs I need to avoid then?

commented

Yeah, like JUnit tests.

How do I know what bugs I need to avoid then?

That's a hazard of not having any tests. I would approach it by studying the project, at least the parts that are changing, until I was confident in my understanding of how those parts worked. Then I would assess the changes to be made and how those changes will affect the parts around them. After implementing the changes, I would test the new feature with some common use cases.

commented

No worries. :)

Regressions are basically features that used to work correctly after an update; new bugs in existing features or old bugs returned. These are usually prevented by running tests that ensure things still work the way they should after making changes, but Dropt doesn't have any tests.

[...] it would certainly be good for learning [...]

Absolutely. You can reach me here or on discord: https://discord.gg/HY69E8X

I might not be immediately available, but I'm happy to answer questions as I can.

commented

I think it might just be best if someone else does it, maybe if it was my own project that I knew how it worked, but with the requirements and the regressions and a bunch of stuff I've never done before as well I think I'll just never get it done to be honest.

commented

@WolfieWaffle Please let me know if you want to make that project, because I really want something for that...

Sorry for my inactivity on that issue, I have other thing to do and doesn't have mutch time to reply of issues, but this is still something I really want and the faster I can get a dev version or something, the faster I will be able make the change I want for my modpack...

Thank'you very mutch for your reply!!

commented

@Fireztonez I plan to implement this feature by the end of the week. Should be available next week sometime.

commented

Confirmed, this feature will be available in 1.16.0.

commented

Nice @codetaylor you're the best!!
Continue your great job!!

commented

Thank you! XD