# KubeJS Support

Genetics: Resequenced has a KubeJS plugin. They go in `kubejs/server_scripts/`.

The plugin adds:

- `GeneticsEvents` - Events for Genes, temporary Genes, cooldowns, entity Gene weights, and Gene requirements
- `GeneticsJS` - Helper methods for adding, removing, querying, listing, and putting Genes on cooldown
- The `geneticsresequenced:gene` server registry, so Genes can be created with KubeJS

## Gene Events

Permanent Gene changes have four events:

- `GeneticsEvents.geneAddedPre`
- `GeneticsEvents.geneAdded`
- `GeneticsEvents.geneRemovedPre`
- `GeneticsEvents.geneRemoved`

The `Pre` events can be cancelled with `event.cancel()`. Every event can be targeted with a Gene id, or used without a target to listen to every Gene change.

Each event has:

- `entity` - The LivingEntity whose Genes are changing
- `gene` - The Gene holder being added or removed

```js
GeneticsEvents.geneAddedPre('geneticsresequenced:cringe', event => {
  const entity = event.entity

  if (entity.name.getString() == '1aaron5') {
    event.cancel()
  }
})
```

```js
GeneticsEvents.geneRemoved((event) => {
	const entity = event.entity;
	if (entity.level.isClientSide()) return;

	const gene = event.gene;

	entity.tell("You lost the gene " + gene.getKey().location());
});
```

## Temporary Gene Events

Temporary Gene changes have four events:

- `GeneticsEvents.temporaryGeneAddedPre`
- `GeneticsEvents.temporaryGeneAdded`
- `GeneticsEvents.temporaryGeneRemovedPre`
- `GeneticsEvents.temporaryGeneRemoved`

The `Pre` events can be cancelled with `event.cancel()`. These events are targetable by Gene id.

Each event has:

- `entity` - The LivingEntity whose temporary Genes are changing
- `gene` - The Gene holder being added or removed
- `duration` - The number of ticks the temporary Gene will last, only on the added events. Can be changed on `temporaryGeneAddedPre`.

```js
GeneticsEvents.temporaryGeneAddedPre('geneticsresequenced:flight', event => {
  if (event.duration > 20 * 60 * 5) {
    event.duration = 20 * 60 * 5
  }
})
```

## Gene Cooldown Events

Gene cooldowns have two events:

- `GeneticsEvents.geneCooldownAdded`
- `GeneticsEvents.geneCooldownRemoved`

`geneCooldownAdded` can be cancelled with `event.cancel()`. Both events are targetable by Gene id.

Each event has:

- `entity` - The LivingEntity whose cooldowns are changing
- `gene` - The Gene holder being put on or removed from cooldown
- `duration` - The number of ticks the cooldown will last, only on `geneCooldownAdded`. Can be changed before the cooldown is added.

```js
GeneticsEvents.geneCooldownAdded('geneticsresequenced:slimy_death', event => {
  if (event.duration > 20 * 60 * 10) {
    event.duration = 20 * 60 * 10
  }
})
```

## Modifying Entity Gene Weights

`GeneticsEvents.modifyGeneWeights` fires when the mod checks what Genes an entity type can have, such as when using a [Gene Checker](@geneticsresequenced:gene_checker) or when the [DNA Decryptor](@geneticsresequenced:dna_decryptor) reveals a Helix's Gene.

This event is targetable by entity type id.

The event has:

- `entityType` - The entity type ResourceKey being modified
- `weights` - The mutable Gene weight map
- `getWeight(gene)` - Gets the integer weight for a Gene
- `getTotalWeight()` - Gets the total weight of all Genes
- `setWeight(gene, weight)` - Sets the integer weight for a Gene
- `remove(gene)` - Removes a Gene from the entity type's possible Genes

```js
GeneticsEvents.modifyGeneWeights('minecraft:cow', event => {
  event.setWeight('geneticsresequenced:lay_egg', 999)
  event.remove('geneticsresequenced:milky')
})
```

## Modifying Gene Requirements

`GeneticsEvents.modifyGeneRequirements` fires when the mod checks which Genes are required before another Gene can stay on an entity.

This event is targetable by Gene id.

The event has:

- `gene` - The Gene holder whose requirements are being modified
- `requirements` - The mutable set of required Gene ids
- `add(gene)` - Adds a required Gene
- `remove(gene)` - Removes a required Gene
- `contains(gene)` - Checks whether the Gene is already required

```js
GeneticsEvents.modifyGeneRequirements('geneticsresequenced:cringe', event => {
  event.add('geneticsresequenced:cursed')
})
```

## Adding, Removing, and Querying Genes

Use the `GeneticsJS` binding to change Genes from your own KubeJS scripts.

```js
PlayerEvents.loggedIn(event => {
  const player = event.player

  if (!GeneticsJS.hasGene(player, 'geneticsresequenced:chatterbox')) {
    GeneticsJS.addGene(player, 'geneticsresequenced:chatterbox')
  }

  const hasPermanentChatterbox = GeneticsJS.hasPermanentGene(player, 'geneticsresequenced:chatterbox')
  const hasTemporaryFlight = GeneticsJS.hasTemporaryGene(player, 'geneticsresequenced:flight')

  GeneticsJS.removeGene(player, 'geneticsresequenced:lay_egg')
  GeneticsJS.addTemporaryGene(player, 'geneticsresequenced:slimy_death', 20 * 60)
  GeneticsJS.removeTemporaryGene(player, 'geneticsresequenced:flight')

  const permanentGenes = GeneticsJS.getPermanentGenes(player)
  const temporaryGenes = GeneticsJS.getTemporaryGenes(player)
  const activeGenes = GeneticsJS.getActiveGenes(player)
  const temporarySlimyDeathTicks = GeneticsJS.getTemporaryGeneTicks(player, 'geneticsresequenced:slimy_death')

  GeneticsJS.addCooldown(player, 'geneticsresequenced:slimy_death', 20 * 60 * 5, true)
  const onCooldown = GeneticsJS.isOnCooldown(player, 'geneticsresequenced:slimy_death')
  const cooldownTicks = GeneticsJS.getCooldownTicks(player, 'geneticsresequenced:slimy_death')
  GeneticsJS.removeCooldown(player, 'geneticsresequenced:slimy_death')
})
```

Mutation helper methods return `true` if they changed anything, and `false` if they did not.

Available helpers:

- `hasGene(entity, gene)` - Checks permanent and temporary Genes
- `hasPermanentGene(entity, gene)` - Checks only permanent Genes
- `hasTemporaryGene(entity, gene)` - Checks only temporary Genes
- `getPermanentGenes(entity)` - Gets permanent Gene ids
- `getTemporaryGenes(entity)` - Gets temporary Gene ids
- `getActiveGenes(entity)` - Gets permanent and temporary Gene ids
- `addGene(entity, gene)` - Adds a permanent Gene
- `removeGene(entity, gene)` - Removes a permanent Gene
- `addTemporaryGene(entity, gene, ticks)` - Adds or refreshes a temporary Gene
- `removeTemporaryGene(entity, gene)` - Removes a temporary Gene
- `getTemporaryGeneTicks(entity, gene)` - Gets remaining temporary Gene ticks, or `-1` if absent
- `isOnCooldown(entity, gene)` - Checks whether a Gene is on cooldown
- `getCooldownTicks(entity, gene)` - Gets remaining cooldown ticks, or `-1` if absent
- `addCooldown(entity, gene, ticks, notify)` - Adds a Gene cooldown
- `removeCooldown(entity, gene)` - Removes a Gene cooldown

## Creating Genes

The plugin registers the `geneticsresequenced:gene` server registry with KubeJS. Use `createFromJson` with the same fields described on the [Custom Genes](./custom_genes) page.

```js
ServerEvents.registry('geneticsresequenced:gene', event => {
  event.createFromJson('modpackname:example', {
    dna_points_required: 8,
    allowed_entities: 'minecraft:player',
    potion_details: [
      {
        effect: 'minecraft:speed',
        level: 2,
        show_icon: true
      }
    ],
    incompatible_genes: [
      'geneticsresequenced:slowness'
    ]
  })
})
```

The generated translation keys are `gene.namespace.path` and `info.gene.namespace.path`. For the example above, those are `gene.modpackname.example` and `info.gene.modpackname.example`.

## Gene Tags

Gene tags still use regular KubeJS tag events.

```js
ServerEvents.tags('geneticsresequenced:gene', event => {
  event.add('geneticsresequenced:disabled', 'geneticsresequenced:keep_inventory')
  event.add('geneticsresequenced:mutation', 'modpackname:example')
})
```