Skip to content

Alpha Release: Datapack Migration

Caltinor edited this page Feb 4, 2022 · 8 revisions

This is the third alpha and revolves around one key feature, Datapacks. All but three of the configs from config/pmmo/ have been removed. "skills", "perks", and "globals" (a feature of NBT Compat that's being merged) have all remained in the config/pmmo folder.

Here's the full breakdown of what's in this release:

  1. Datapacks for configuration
    1. datapack structure
    2. file formats
    3. datapack behavior
  2. Fireworks!! (yay! no text yet though)
  3. Block Place Event (officially)
  4. Tooltips!!!
  5. Technical Changes (fixes and backend work)

Datapacks for Configuration

As mentioned in the opening paragraph, datapacks are being used instead of json files in a config folder. There are a few reasons for this change:

  1. The rework introduced an even greater level of configurability, which caused an explosion of files under the current system. Since users were already intimidated by the current number of files, it made sense to find a way to trim down the total file count. Initially, the config/pmmo was still going to be used, but with fewer files. This turned out to be equally worse because the files themselves became enormous, which would have been a nightmare to troubleshoot. Since syntax errors can invalidate an entire file, this route was immediately impractical. So a hybrid was made, where content would still be merged (you'll see what that means in 1.ii), but we still had too many files. Keep the file count issue in mind through the next points.
  2. Certain features of PMMO were already moving to datapack. The extra chance, treasure, fishing loot, fishing enchant, and mob drops features were all custom implementations of Minecraft's loot table system. Currently, though, there is no loot predicate for skill level, so these configs make sense. But since this system reinvents the wheel, and MC already has a feature that handles this, the rework is going to implement a pmmo loot predicate allowing all drops to be handled by loot tables, which gives pack makers and players more consolidated control over mob drops. Another feature moving to datapack is the level-up commands. These will use MC Functions, which are more performant and more powerful than the current implementation. So with datapacks already being used, it made sense to have all configuration move to datapack.
  3. Datapacks themselves have two features that make them advantageous: 1. they have a load order. 2. they allow for compartmentalization. On the topic of load order, mod datapacks (those built into the mod itself) load first, then player datapacks load. This means that pmmo is going to load its defaults, then your player pack will load on top. So if your player pack has data that pmmo already adds, you will override the defaults, but only those which you define. So there is no need to pour through the pmmo config to find the setting you want. You now just set what you want in your datapack and if pmmo has a setting, it will be overwritten. Next, we have compartmentalization. Let's assume you play with a unique mod that you want to configure, you only need to build a datapack for the extra items from this mod. There is no need to modify the pmmo configuration at all, unless you want to override something. And you can have as many datapacks as you want, which is the point. Suppose you make a datapack for each mod in your pack. You can unload just that pack to make changes, or if you remove the mod, you don't need to go in and remove all the entries for that mod from you pack (you wouldn't need to anyways, but if you're like me and don't like clutter, you might). You only need to remove that pack. It also makes sharing configurations easier since datapacks can be hosted on CurseForge now.
  4. The last point is more for packmakers, but there are two technical reasons datapacks make sense. If you have a server, your datapack is not included in the modpack, which means players can't peek into your configuration to cheese your setup. Second, datapacks automatically sync to the client when they join, so there is no need for any settings to be present on the client beforehand, adding more exclusivity to your content. You can still use OpenLoader or Global Data and Resourcepacks to share your datapacks if you want.

onto the meat of the changes!

Datapack structure

pmmo's datapack path is pmmo/* where * is the folder name for the object type you are defining. For example you will have different behavior for dirt as an item versus dirt as a block. The below snippet shows all the different object folders in the datapack.

data/namespace/pmmo/
  items/
  blocks/
  entities/
  biomes/
  dimensions/
  players/
  enchantments/

when defining your configuration, each file represents an object in the type of the folder. The name of the file should match the item's registry name exactly. Registry names look like "namespace:path"(you may notice the folder structure uses "namespace" in a specific location. the path is the item's unique name for that mod. for example dirt in minecraft is "minecraft:dirt" but if I had dirt in my own mod it would be "caltmod:dirt". So make sure you have a folder for each mod if not compartmentalizing. Then only include file names for actual objects from that mod. eg. data/bop/pmmo/biomes/mangrove_forest.json

what follows is the format for each of the configs

Items, Blocks, and Entities

{
  "isTagFor":[],
  "xp_values": {},
  "bonuses": {},
  "requirements": {},
  "nbt_requirements": {},
  "nbt_xp_values":{},
  "salvage": {}
}

Note that every root key (eg. "xp_values", "salvage", etc) is optional. For example if you are not using NBT for this item, there is no need to have a blank "nbt_requirements": []. you can't salvage entities, so that section can be omitted. Each Key will be explained below:

"isTagFor":[] This optional key instructs the data loader to ignore the namespace/path relationship and instead apply the below settings to the members of this list. So if you wanted to emulate the stone tag, you could write "isTagFor":["minecraft:stone","minecraft:andesite","minecraft:granite","minecraft:diorite"]. This also means that you name the file whatever you want, since the filename won't be used as the path for this file. eg. mySpeicalConfigForStone.json

"xp_values":{} this optional key defines what XP to award the player for certain action. eg. "CRAFT" for items tells pmmo how much xp, in what skill(s), you want to award when this item is crafted. All available actions are listed here. Note that not all actions apply to all object types. You can't kill an item, or craft a block. Also note that in this release, not all events actually have an effect in-game (crafting being one of them). an example of this section might look like

"xp_values": {
  "CRAFT": {"crafting": 10},
  "ENCHANT": {"magic": 15},
  "SMELT": {"smithing": 30}
}

This format consolidated all of the xp_value_*.json files.

"requirements":{} this optional key defines what skills are required to perform an action. the structure is the same as xp_values above, but uses these values as keys. an example might look like

"requirements": {
  "TOOL": {"mining": 10},
  "WEAPON": {"combat": 0},
  "USE": {"smithing": 30}
}

"bonuses":{} this optional key defines how much xp should be modified when this object is applicable. valid values can be found here. This is one of the only configs that uses decimal values. note that this is a raw multiplier of xp. so 1.0 does nothing. 1.1 is a 10% bonus and 0.75 is a 25% penalty.

"bonuses": {
  "WORN": {
    "mining": 1.15,
    "combat": 0.8
  },
  "HELD": {"combat": 3.5}
}

"nbt_requirements":{} and "nbt_xp_vales":{} are not implemented yet. They will use the EventType and ReqType keys like their non-nbt counterparts, but will use an array of logic tiers which you can get a glimpse of from the addon which it is derived WIKI

"salvage":{} this optional tag only applies to items, but determines whether an item can be salvaged, and what the behavior is. example format

"salvage": {
    "modid:item": {
      "baseChance": 0.25,
      "chancePerLevel": {
        "skill": 0.01,
        "otherskill": 0.25
      },
      "levelReq": {
        "skill": 30
      }
      "maxChance": 1.0,
      "xpPerItem": {
        "skill": 10
      },
      "salvageMax": 1
    },
    "modid:otheritem": {}
  }

Biomes and Dimensions

{
  "isTagFor":[],
  "bonus": {},
  "positive_effect": {},
  "negative_effect": {},
  "vein_blacklist": [],
  "travel_req":{},
  "mob_multiplier": {}
}

Like the previous objects, all keys are optional.

"isTagFor":[] Functions identical it's counterpart above. use this to group similar biomes and dimensions with the same settings

"bonus":{} Identical section to the bonuses from items, and grants the player the modified experience gains when in the biome or dimension.

"positive_effect":{} and "negative_effect":{} Positive effect grants effects to players if they meet the travel_req requirement. Negative effect grants effects if the player does not. They follow the format of potionID:power. note that failing to declare a travel_req will make these settings do nothing.

"positive_effect": {
  "minecraft:strength":0,
  "someothermod:effect":1
}

"vein_blacklist":[] This is a list of block IDs that the vein miner is not permitted to break. it applies only in the dimension or biome for which this is set, so you can have biome-specific vein blacklists.

"vein_blacklist": [
  "minecraft:bedrock",
  "minecraft:obsidian",
  "someothermod:someblock"
]

"travel_req":{} This setting behaves differently when used on a biome vs a dimension. For biomes, it determines whether the player will be given positive or negative effects. For dimensions it determines if a player is permitted to travel to the dimension. The format is the same as any other skill requirement.

"travel_req": {
  "combat": 50,
  "mining": 25
}

"mob_multiplier":{} This setting determines how mobs should be altered in this dimension or biome. Mobs that spawn will have their attributes modified by the value times the base. This means that it will add to mob scaling, but won't compound with mob scaling. The actual settings have not yet been defined, so the following example is just for demonstration purposes.

"mob_multiplier": {
  "minecraft:zombie": {
    "health": 2.0,
    "speed": 1.6,
    "damage": 0.5
  },
  "iceandfire:fire_dragon": {
    "damage": 30.0,
    "health": 1000.0
  }
}

Players

This will expand over time but players are a simple map of settings. Each file is named according to the UUID for the player it should apply to. currently only "ignoreReq" is read from the file, even though it isn't used yet. More player-specific settings such as modifiers will be added later. An example of something for the future is included in the demonstration. All settings are optional.

{
  "ignoreReq": true
  "futureSetting1": 3.5,
  "futureSetting2": ["",""],
  "futureSetting3": {
    "oooooh":"aahhhh"
  }
}

Enchantments

Enchantments are defined by their namespace. The structure lets you set a requirement block for each level. for example

{
  "1":{ 
    "magic": 10
  },
  "2":{ 
    "magic": 30
  },
  "3":{ 
    "magic": 50,
    "enchanting": 25
  }
}

Fireworks

I'm not 100% happy with this implementation, but here it is. Fireworks are a Perk that you can fire whenever you want, though I recommend only doing it in the SKILL_UP event. It has one required parameter "skill" which you need to pass the same skill as you declare it under. for example:

"SKILL_UP": {
  "combat": [
    {"perk":"pmmo:fireworks",
     "skill":"combat"}
  ],
  "endurance": [ 
    {"perk":"pmmo:fireworks",
     "skill":"endurance"}
  ]
}

Another element is the fireworks color which controlled by the color defined in the skills.json

Block Place Event

It's just implemented. you can now declare XpGain, Req, and perk values for this event using the BLOCK_PLACE keyword.

Tooltips!!!

It's a very early implementation that just shows the stats for the item. This was implemented to make testing easier. colors of skills should conform to the skills.json.

Technical and Backend Changes

  • NBT compat was partially merged in this version. None of the features are enabled yet though because the configs haven't been set up, only the logic part.
  • Data syncing across sides was severely overhauled. Data will now sync to all players on join and on data reload. This means that more work can be done on the client side, freeing up server resources. Certain functions are still server-side only though such as event triggers and perks.
  • Trimmed the enums for ReqType and ModifierDataType to remove the redundant prefixes of REQ_ and BONUS_ respectively.

Testing Notes

If you have never used a datapack before they are simple. it's one folder and a file. The file is a pack.mcmeta which you can get a copy of here. Next you need a folder called "data". If you take these two objects and save them as a zip file, you have created a datapack. The next part is to fill your data folder with useful things.

Under the data folder you must create folders for the namespaces you are interested in. For example if you want to override vanilla recipes, you need a folder under data called "minecraft". If you want to do the same for Mekanism, you make a folder called "mekanism". Pmmo is "pmmo". the End Remastered mod is "endrem". you get the point.

Now under these folders you add paths relevant to what you want for example an item tag under vanilla would be minecraft/tags/items/ where you would eventually put a file (that's next). As you saw above, pmmo has a path pmmo/*/ where the asterisk is your object type.

when testing this version, make a datapack of your own choosing and do two things. One, override one of my silly presets. Two, set up a new setting (like for obsidian or the other tools).

If you have any questions about datapacks or the configuration, please reach out to me on discord with a ping. This is major change to PMMO and I want to make sure it works right before moving on.

Clone this wiki locally