Skip to content

Commit

Permalink
Curios data generation
Browse files Browse the repository at this point in the history
  • Loading branch information
TheIllusiveC4 committed Jan 20, 2024
1 parent 91d8a71 commit 2b4cb3f
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 11 deletions.
159 changes: 159 additions & 0 deletions docs/curios/Developing with Curios/data-generation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
---
sidebar_position: 4
---

# Data Generation

A tutorial on how to programmatically generate the Curios data files.

## Prerequisites
---
The documentation on this page was written with the assumption that readers are already familiar with basic data
generation and its usages. If you are not, please prime yourself by learning about data generation on either [Forge](https://forge.gemwire.uk/wiki/Datageneration)
or [NeoForge](https://docs.neoforged.net/docs/datagen/) before proceeding further.

## Getting Started
---
Slots and entities can be generated for a mod by constructing a new implementation of the
`top.theillusivec4.curios.api.CuriosDataProvider` class, making sure to override the `generate` method to run the
generation code.

```java
public class CuriosTestProvider extends CuriosDataProvider {

public CuriosTestProvider(String modId, PackOutput output,
ExistingFileHelper fileHelper,
CompletableFuture<HolderLookup.Provider> registries) {
super(modId, output, fileHelper, registries);
}

@Override
public void generate(HolderLookup.Provider registries, ExistingFileHelper fileHelper) {
// Generation code here
}
}
```

A new instance of the implementation should be constructed in the `GatherDataEvent` event on the MOD event bus.

```java
// On the MOD event bus
@SubscribeEvent
public void gatherData(GatherDataEvent event) {
event.getGenerator().addProvider(
// Tell generator to run only when server data are generating
event.includeServer(),
new CuriosTestProvider(
"mod_id",
event.getGenerator().getPackOutput(),
event.getExistingFileHelper(),
event.getLookupProvider()
)
);
}
```

## Slot Generation
---
`CuriosDataProvider` has a `createSlot` method to facilitate easy data generation of slot types, by taking in an initial
`String` identifier/file name and allowing developers to chain additional parameters as needed.

```java
@Override
public void generate(HolderLookup.Provider registries, ExistingFileHelper fileHelper) {
this.createSlot("test_slot"); // Create a slot with the identifier and file name "test_slot"
}
```

Additional parameters can be added by calling methods on the `ISlotData` returned by the `createSlot` method call. Most
of these parameters are linked to fields for `ISlotType`, more information on how these fields are constructed and what
they represent can be found on the page for [slot registration](../slot-register.md#-syntax).

| Method | Parameters | Field |
|----------------|--------------------|------------------|
| `replace` | boolean | `replace` |
| `size` | integer | `size` |
| `operation` | string | `operation` |
| `order` | integer | `order` |
| `icon` | `ResourceLocation` | `icon` |
| `addCosmetic` | boolean | `add_cosmetic` |
| `useNativeGui` | boolean | `use_native_gui` |
| `renderToggle` | boolean | `render_toggle` |
| `dropRule` | `ICurio$DropRule` | `drop_rule` |
| `addCondition` | `ICondition` | N/A |

### Example

The following example creates a slot file with the file name and identifier `test_slot`, gives it a size of `4`, sets the
drop rule to `"ALWAYS_KEEP"` so that it is never dropped upon death, and gives it a cosmetic slot by setting `addCosmetic`
to `true`.

```java
@Override
public void generate(HolderLookup.Provider registries, ExistingFileHelper fileHelper) {
this.createSlot("test_slot")
.size(4)
.dropRule(ICurio.DropRule.ALWAYS_KEEP)
.addCosmetic(true);
}
```

## Entities Generation
---
`CuriosDataProvider` has a `createEntities` method to facilitate easy data generation of adding slot types to entities,
by taking in an initial `String` file name and allowing developers to chain additional parameters as needed.

```java
@Override
public void generate(HolderLookup.Provider registries, ExistingFileHelper fileHelper) {
this.createEntities("test_entities"); // Create an entities file with the name "test_entities"
}
```
Additional parameters can be added by calling methods on the `IEntitiesData` returned by the `createEntities` method
call. All of these parameters correspond to JSON fields, more information on these can be found on the page for
[entity registration](../entity-register.md#-syntax).

| Method | Parameters | Field | Notes |
|----------------|-------------------|--------------|------------------------------------------------------------|
| `replace` | boolean | `replace` | |
| `addPlayer` | N/A | `entities` | Adds `"minecraft:player"` to the `entities` array |
| `addEntities` | `EntityType<?>[]` | `entities` | |
| `addSlots` | string[] | `slots` | Adds each string as a slot identifier to the `slots` array |
| `addCondition` | `ICondition` | `conditions` | |

### Example

The following example creates an entities file with the file name `test_entities`, and assigns the `"head"`, `"ring"`,
and `"necklace"` slot types to the `"minecraft:player"` and `"minecraft:zombie"` entities.

```java
@Override
public void generate(HolderLookup.Provider registries, ExistingFileHelper fileHelper) {
this.createEntities("test_entities")
.addPlayer()
.addEntities(EntityType.ZOMBIE)
.addSlots("head", "ring", "necklace");
}
```

## Criterion Triggers

Curios provides several helper methods in the `top.theillusivec4.curios.api.CuriosTriggers` class to generate data
associated with criterion triggers used for advancements and other similar files.

Currently, the only triggers available are `equip` and `equipAtLocation` for triggering when a certain item is equipped
into a curio slot.

### Example

The following example will create an advancement file, `curiostest/test`, that adds a criteration called `"test"`, that
is triggered when a `"minecraft:diamond"` item is equipped in the Badlands biome.

```java
Advancement.Builder.advancement()
.addCriterion("test",
CuriosTriggers.equipAtLocation(
ItemPredicate.Builder.item().of(Items.DIAMOND),
LocationPredicate.Builder.location().setBiome(Biomes.BADLANDS)))
.save(saver, new ResourceLocation("curiostest", "test"), existingFileHelper);
```
6 changes: 5 additions & 1 deletion docs/curios/entity-register.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,17 @@ anything that is lowercased with no special characters.

## Syntax
---
The structure of the `.json` file for the entity configuration consists of a top-level JSON object that holds two
The structure of the `.json` file for the entity configuration consists of a top-level JSON object that holds several
potential fields.

* `entities`
* An array of registry names of entity types or entity type tags.
* `slots`
* An array of `identifier` names for registered slot types.
* `replace`
* A boolean, `true` if the values listed in this file should replace values in lower-priority datapacks
* `conditions`
* An array of `ICondition` implementations that must all pass before these slots are loaded into these entities

All the listed slots will be associated to all the listed entities.

Expand Down
21 changes: 11 additions & 10 deletions docs/curios/slot-register.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,17 @@ anything that is lowercased with no special characters.
The structure of the `.json` file for the slot type consists of a top-level JSON object that holds various fields
related to that slot type.

| Field | Type | Default | Required | Description | Merge Behavior |
|------------------|------------------------------|---------------------------------|----------|----------------------------------------------------------------------------------------------------------------------|---------------------------------------------|
| `replace` | boolean | `false` | `false` | When `true`, replaces data from lower-priority datapacks | N/A |
| `size` | integer | `1` | `false` | The number of slots of this slot type to give by default | The highest size will be used |
| `operation` | `"SET"`\|`"ADD"`\|`"REMOVE"` | `"SET"` | `false` | Whether to use `size` to set, add, or remove from the total number of slots | N/A |
| `order` | integer | `1000` | `false` | The order the slots will appear in the native Curios GUI, lower numbers appear higher | The lowest order will be used |
| `icon` | string | `curios:slot/empty_curios_slot` | `false` | The location of the icon to use for the slot type | The last icon will be used |
| `add_cosmetic` | boolean | `false` | `false` | When `true`, adds a cosmetic slot next to the original that does not provide function but still renders its contents | `true` if any add a cosmetic slot |
| `use_native_gui` | boolean | `true` | `false` | When `false`, does not add the slot type to the native Curios GUI | `false` if any do not use the native GUI |
| `render_toggle` | boolean | `true` | `false` | When `false`, does not allow the slot type to toggle its rendering | `false` if any do not allow render toggling |
| Field | Type | Default | Required | Description | Merge Behavior |
|------------------|------------------------------------------------------------|---------------------------------|----------|----------------------------------------------------------------------------------------------------------------------|---------------------------------------------|
| `replace` | boolean | `false` | `false` | When `true`, replaces data from lower-priority datapacks | N/A |
| `size` | integer | `1` | `false` | The number of slots of this slot type to give by default | The highest size will be used |
| `operation` | `"SET"`\|`"ADD"`\|`"REMOVE"` | `"SET"` | `false` | Whether to use `size` to set, add, or remove from the total number of slots | N/A |
| `order` | integer | `1000` | `false` | The order the slots will appear in the native Curios GUI, lower numbers appear higher | The lowest order will be used |
| `icon` | string | `curios:slot/empty_curios_slot` | `false` | The location of the icon to use for the slot type | The last icon will be used |
| `add_cosmetic` | boolean | `false` | `false` | When `true`, adds a cosmetic slot next to the original that does not provide function but still renders its contents | `true` if any add a cosmetic slot |
| `use_native_gui` | boolean | `true` | `false` | When `false`, does not add the slot type to the native Curios GUI | `false` if any do not use the native GUI |
| `render_toggle` | boolean | `true` | `false` | When `false`, does not allow the slot type to toggle its rendering | `false` if any do not allow render toggling |
| `drop_rule` | `"DEFAULT"`\|`"ALWAYS_DROP"`\|`"ALWAYS_KEEP"`\|`"DESTROY"` | `"DEFAULT"` | `false` | Whether to drop, keep, destroy, or follow the `keepCurios` configuration | N/A |

:::info
**Which `operation` value should I use?**
Expand Down

0 comments on commit 2b4cb3f

Please sign in to comment.