sandstone-mc / sandstone

Sandstone | Next Generation Framework for Minecraft
https://sandstone.dev/
MIT License
173 stars 16 forks source link

Added conflict handling #76

Closed TheMrZZ closed 3 years ago

TheMrZZ commented 3 years ago

Changelog:

Conflict strategies

Values

Conflict handling strategies define what Sandstone should do when two resources of the same type (MCFunctions, Advancements...) have the exact same name. All resources have the following available strategies:

MCFunctions have two additional strategies:

The default strategy for all resources is warn.

Changing the strategy

You can change the strategy:

Tag('name', ..., { onConflict: '...', })

Advancement('name', ..., { onConflict: '...', })


## 'append' and 'replace'

`append` and `replace` are uncommon strategies, but they can be very useful when used properly.
Let's say you want to summon entities with a specific UUID, and `/kill` them when uninstalling the data pack.

In the past, you would have done the following:
```ts
let uuids: string[] = []
MCFunction('first', () => {
  const uuid = generateUUID()
  uuids.push(uuid)
  summon('armor_stand', rel(0, 0, 0), { UUID: uuid })
})

MCFunction('second', () => {
  const uuid = generateUUID()
  uuids.push(uuid)
  summon('armor_stand', rel(0, 0, 0), { UUID: uuid })
})

MCFunction('uninstall', () => {
  for (const uuid of uuids) {
    kill(uuid)
  }
})

There is a big problem in this sample. If you put the definition of uninstall before first and second, the entities will never be killed, because the uninstall function will be created before first and second. This make function creation order-dependant, which can lead to unexpected bug.

With conflict strategies, we can refactor the previous snippet, and make it order-independant:

function killOnUninstall(const uuid: string) {
  MCFunction('uninstall', () => { 
    kill(uuid)
  }, { onConflict: 'append' })
}

MCFunction('first', () => {
  const uuid = generateUUID()
  killOnUninstall(uuid)
  summon('armor_stand', rel(0, 0, 0), { UUID: uuid })
})

MCFunction('second', () => {
  const uuid = generateUUID()
  killOnUninstall(uuid)
  summon('armor_stand', rel(0, 0, 0), { UUID: uuid })
})

Here, the order doesn't matter anymore. This behavior allows powerful patterns.