> ## Documentation Index
> Fetch the complete documentation index at: https://nexohub.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Plugins that build their own assets

> BetterHUD, ModelEngine, BetterModel and the like, and how to run different HUDs and models on different servers.

BetterHUD, MythicHUD, ModelEngine, BetterModel and similar plugins build their own assets
and hand them to Nexo. On a network that causes a problem: if your lobby uses one HUD and
your PvP server uses another, each server only builds its own half of the assets, so you
end up with two different packs and a re-download every time a player switches.

NexoHub handles this for you. Install your plugins per server exactly as you want them.

## What you need to do

**Check two settings in your other plugins' configs.** They are the only thing that can
still break this, and they are covered [below](#two-settings-to-check).

**Keep each plugin's own config where it is.** Different servers can run different HUDs
and hold different models. That lives in the plugin's `config.yml`, which is never
shared.

**Do not copy generated output up to the proxy.** Folders like
`plugins/Nexo/pack/external_packs/BetterHud/` are rebuilt by the plugin on every boot.
NexoHub collects them automatically, and a stale copy in `nexo-data/` only causes
confusion.

**Set `packs.mixed_content: true` if your servers run different HUDs or models,** so
each one's assets reach the others. See
[below](#servers-running-different-huds-or-models).

That is all. No plugin's files are copied between backends, so each server keeps only what
you installed on it. You can still put a file centrally under `_shared/_plugins/`, and
that wins. See [managing your files](/guides/managing-files).

## Two settings to check

Both are a plugin obfuscating its own pack. Turning them off costs no protection, because
Nexo obfuscates the merged pack afterwards either way.

<Warning>
  Set **`pack.use-obfuscation: false`** in BetterModel's config. This one ships **on**, so
  every install starts in the configuration that breaks and you have to change it.
</Warning>

With it off, BetterModel names each part after its model and bone, and two backends
holding different models build packs that agree. With it on, the names come from how many
parts that server loaded first, so a wizard's torso on one server is a knight's hammer on
the other.

<Warning>
  Leave **`resourcepack-obfuscation: false`** in BetterHUD's config. It is the default, so
  this only matters if someone turned it on.
</Warning>

With it off, BetterHUD names its generated files after the HUD they belong to. With it on,
it names them `a`, `b`, `c` in load order, so your lobby's first HUD and your PvP server's
first HUD are both called `a` and one overwrites the other.

Each is reported, but in a different place. A backend warns about BetterModel at boot:

```
[NexoHubBridge] BetterModel's pack.use-obfuscation is on, so it names model parts by this
server's load order and backends holding different models disagree about what each name
means.
[NexoHubBridge] Set it in plugins/BetterModel/config.yml:  pack: { use-obfuscation: false }.
Nexo obfuscates the merged pack anyway, so this costs no protection.
```

That warning is your only notice for BetterModel, because it hands its folder straight to
Nexo rather than writing into `external_packs/`, so nothing on the proxy ever compares it.
If you cannot turn the setting off, set `support.bettermodel: true` on that backend to
share its sources instead.

BetterHUD's clash is caught on the proxy, which tells you rather than shipping a broken
pack:

```
[nexohub] Contributions lobby/betterhud and pvp/betterhud both define
assets/betterhud/font/a.json with different content. Nexo merges these into one
pack, so one will silently win.
```

The same check applies to any plugin. If you see it, either turn that plugin's own
obfuscation off or exclude the folder with `contribute_exclude`. `collision` is one of the
[webhook events](/reference/proxy-config#notifications), so you do not have to read it off a
console.

A second wording names two *plugins* rather than two backends. That one means one plugin
is burying another's file, and no NexoHub setting fixes it. Run only one of them, or ask
their authors which should own that file.

## Servers running different HUDs or models

Some of these plugins number things by whatever their own server happened to load, so the
same number means something different on each backend. NexoHub keeps those numbers on the
proxy instead and hands the same ones to everybody.

| Plugin | Numbers per server | What NexoHub does |
| - | - | - |
| BetterHUD | shader `case` ids and packed font `ascent` | holds the numbering on the hub |
| ModelEngine | `custom_model_data` on `leather_horse_armor` | holds the numbering on the hub |
| BetterModel | no, from 3.4.0, with its obfuscation off | warns at boot if it is on |
| MythicHUD | no | leaves it alone |
| Animotions | no | leaves it alone |
| Overdrive | not measured | leaves it alone |
| Tooltips | not measured | leaves it alone |

<Warning>
  BetterHUD's and ModelEngine's assets reach the other backends only as contributions, so
  running different HUDs on different servers needs `packs.mixed_content: true` on the
  proxy. On the default `SERVER` each backend gets a pack holding only its own.
</Warning>

A backend says which it is doing at startup, naming only the plugins it has installed:

```
[NexoHubBridge] Keeping BetterHud, ModelEngine numbered the way the network numbers it, so
every backend builds one shared pack. This server holds only its own files.
[NexoHubBridge] Leaving BetterModel to name its own output, which comes out the same on
every backend, so this server holds only what you installed and still agrees with the rest.
```

A BetterModel whose own obfuscation is still on does not get that second line. It is
reported as building a pack of its own instead, which is what it is doing.

If you run a version that behaves differently, the backend says so at startup and names
the [`generators`](/reference/proxy-config#settings) setting that puts the old
behaviour back, which you set on the proxy for one backend, a group, or all of them. Most
networks never need it.

## What your players see

Only what that server runs. If pvp has the diving HUD and lobby has the welcome HUD, that
is what players see on each. A server's BetterHUD holds only the HUDs you installed there,
so `/hud add` offers nothing another server runs, and a model exists only on the server you
put it on. Every server's assets are still in the one pack they all hand out.

<Note>
  This is unrelated to Nexo's own `Pack.obfuscation` setting, which runs later on the
  finished pack and is safe to leave on.
</Note>

## How it travels

Each backend publishes whatever its plugins generated, and the hub keeps it. It comes back
down as a folder directly under `plugins/Nexo/pack/external_packs/`, named
`_hub-<plugin>-<id>`, and Nexo folds it into the pack.

BetterHUD and BetterModel build that output as a folder or as a single `.zip`, depending
on their own `pack-type` setting, and both are published either way. You do not have to
change it: NexoHub reads each plugin's `build-folder-location` to learn the exact name it
writes, which is also how it knows to leave a pack of your own in that folder alone.
Tooltips and Overdrive are read the same way, from `copy-resource-pack.path` and
`resourcepack.nexo_integration.output_path`, as long as that copy is switched on.

`packs.mixed_content` decides whether it reaches the other backends.

| Setting | What each backend builds from |
| - | - |
| `SERVER` (default) | its own output. Backends generating the same thing still share one pack |
| `NETWORK` | every backend's output, merged. Needed when servers run different HUDs or models |
| `OFF` | its own output, and the hub never sees it |

The first time you add a server it publishes its assets and the others pick them up on
their next reload, within a few seconds. After that nothing is re-sent unless the
generated content changes, so a normal restart costs nothing.

## Any other plugin

NexoHub knows the plugins above by name. Any other plugin that lets you choose where it
unpacks its pack works too: point it at a folder under `plugins/Nexo/pack/external_packs/`
whose name starts with `generated-`.

```yaml theme={null}
# plugins/SomePlugin/config.yml, under whatever that plugin calls the setting
output: plugins/Nexo/pack/external_packs/generated-someplugin
```

That folder is then handled like BetterHUD's output. It is published under
`packs.mixed_content`, the backend drops its own copy once the hub hands the same files
back, and it leaves the network once the plugin stops writing it. Two things are yours to
check, because NexoHub cannot see inside that plugin:

* It has to write the folder again every time it starts. A plugin that writes it only once
  loses it after the first restart.
* Nothing keeps its ids in step across servers. If two backends publish the same folder
  with different content, the proxy reports a collision naming it.

The prefix is the `generated_prefixes` [setting](/reference/proxy-config#settings). It is a
list, matched regardless of case, and `[]` turns this off.

## Removing a pack

Stop the plugin generating it. A HUD you removed from BetterHUD's config, or a plugin you
uninstalled, is out of the network's pack after that backend's next reload.

Deleting the folder by hand does not do it on its own. The plugin writes it again on its
next run, and the backend publishes it again with it.

A pack you placed yourself works the other way round, because nothing regenerates it:
delete it from `_shared/pack/external_packs/` on the proxy and it is gone from every
backend on the next push. See [managing your files](/guides/managing-files).

A pack you put directly on one backend instead is never published, since no plugin there
claims to have written it. The backend says so once, naming the file, so an empty
`/nexohub contributions` is never left unexplained.

`/nexohub contributions` on the proxy shows what the hub currently holds, per backend:

```
[NexoHub] 3 contribution(s), from 2 backend(s):
  lobby
      betterhud  412 KiB  5e6f7a8b
      bettermodel  1204 KiB  c1d2e3f4
  pvp
      betterhud  388 KiB  9a0b1c2d
```

`/nexohub contributions drop <server> [name]` removes one by hand and pushes. You need it
for a backend that cannot withdraw its own: one you have decommissioned, one on an older
bridge, or one with `contribute: false`.

## Turning it off

If you would rather each server keep its assets entirely to itself, with the hub never
seeing them:

```yaml theme={null}
# proxy: plugins/nexohub/config.yml
packs:
  collect_generated: false
```

Or exclude one folder on a single backend:

```yaml theme={null}
# backend: plugins/NexoHubBridge/config.yml
sync:
  contribute_exclude:
    - eventpack
```

## Checking it worked

`/nexohub status` shows every backend on the same pack. In the backend logs you will see
each server publishing what it made and skipping the rest:

```
[NexoHubBridge] Published betterhud (412 KiB) for the rest of the network.
[NexoHubBridge] Hub already holds pack 5e6f7a8b, skipping upload.
```

<Note>
  A network upgrading from a version that shared these plugins' source files keeps the
  copies it was sent. NexoHub only deletes inside `plugins/Nexo/`, so it names them at boot
  rather than removing them. Nothing breaks if you keep them; delete them once per backend.
</Note>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.