forked from public/foundryvtt-reve-de-dragon
129 lines
3.9 KiB
JavaScript
129 lines
3.9 KiB
JavaScript
|
|
/**
|
|
* class designed to store actor modification instructions, to apply them in a single operation, and have the ability to revert these
|
|
*/
|
|
export class ActorImpacts {
|
|
constructor(actorToken) {
|
|
this.actorToken = actorToken
|
|
this.updates = []
|
|
this.deltas = []
|
|
this.itemCreates = []
|
|
this.itemUpdates = []
|
|
this.itemDeletes = []
|
|
}
|
|
|
|
addActorUpdate(path, value) {
|
|
this.updates.push([path, value])
|
|
}
|
|
|
|
addActorDelta(path, value) {
|
|
const intValue = Number.parseInt(value)
|
|
if (Number.isInteger(intValue) && intValue != 0) {
|
|
const delta = [path, intValue]
|
|
this.deltas.push(delta)
|
|
}
|
|
else {
|
|
console.error('Cannot use non integer value {} for delta update', value)
|
|
}
|
|
}
|
|
|
|
addDeletedItem(item) {
|
|
this.itemDeletes.push(item)
|
|
}
|
|
addCreatedItem(item) {
|
|
this.itemCreates.push(item)
|
|
}
|
|
|
|
addItemUpdate(item, path, value) {
|
|
const existing = this.itemUpdates.find(it => it.id == item.id)
|
|
const update = [path, value]
|
|
if (existing) {
|
|
existing.updates.push(update)
|
|
}
|
|
else {
|
|
this.itemUpdates.push({ id: item.id, updates: [update], deltas: [] })
|
|
}
|
|
}
|
|
|
|
addItemDelta(item, path, value) {
|
|
const intValue = Number.parseInt(value)
|
|
if (Number.isInteger(intValue) && intValue != 0) {
|
|
const delta = [path, intValue]
|
|
const existing = this.itemUpdates.find(it => it.id == item.id)
|
|
if (existing) {
|
|
existing.deltas.push(delta)
|
|
}
|
|
else {
|
|
this.itemUpdates.push({ id: item.id, updates: [], deltas: [delta] })
|
|
}
|
|
}
|
|
else {
|
|
console.error('Cannot use non integer value {} for delta update', value)
|
|
}
|
|
}
|
|
|
|
reverseImpacts() {
|
|
const reverse = ActorImpacts.$computeReverts(new ActorImpacts(this.actorToken), this, __ => this.actorToken.actor)
|
|
reverse.itemCreates = this.itemDeletes.map(it => foundry.utils.duplicate(it))
|
|
reverse.itemDeletes = this.itemCreates.map(it => { return { id: it.id } })
|
|
reverse.itemUpdates = this.itemUpdates.map(it => ActorImpacts.$computeReverts({ id: it.id }, it, id => this.$getActorItem(id)))
|
|
return reverse
|
|
}
|
|
|
|
toStorable() {
|
|
delete this.actorToken
|
|
return this
|
|
}
|
|
|
|
async applyImpacts() {
|
|
const actor = this.actorToken.actor
|
|
const isItemsDelete = this.itemDeletes.length > 0
|
|
const isItemsCreate = this.itemCreates.length > 0
|
|
const isItemsUpdate = this.itemUpdates.length > 0
|
|
const isActorUpdate = this.updates.length > 0 || this.deltas.length > 0
|
|
|
|
if (isItemsDelete) {
|
|
const deletes = this.itemDeletes.map(it => it.id)
|
|
await actor.deleteEmbeddedDocuments('Item', deletes, { render: !(isItemsCreate || isItemsUpdate || isActorUpdate) })
|
|
}
|
|
|
|
if (isItemsCreate) {
|
|
const creates = this.itemCreates
|
|
const created = await actor.createEmbeddedDocuments('Item', creates, { render: !(isItemsUpdate || isActorUpdate)})
|
|
for (let i=0; i<creates.length; i++){
|
|
creates[i].createdId = created[i].id
|
|
}
|
|
}
|
|
|
|
if (isItemsUpdate) {
|
|
const updates = this.itemUpdates.map(u => ActorImpacts.$computeUpdates(u, id => this.$getActorItem(id)))
|
|
await actor.updateEmbeddedDocuments('Item', updates, { render: !isActorUpdate })
|
|
}
|
|
|
|
if (isActorUpdate) {
|
|
const updates = ActorImpacts.$computeUpdates(this, id => actor)
|
|
await actor.update(updates, { render: true })
|
|
}
|
|
}
|
|
|
|
$getActorItem(id) {
|
|
return this.actorToken.actor.items.get(id)
|
|
}
|
|
|
|
static $computeUpdates(u, getSource) {
|
|
const source = getSource(u.id)
|
|
const instruction = { _id: u.id }
|
|
u.updates.forEach(u => instruction[u[0]] = u[1])
|
|
u.deltas.forEach(u => instruction[u[0]] = foundry.utils.getProperty(source, u[0]) + u[1])
|
|
return instruction
|
|
}
|
|
|
|
static $computeReverts(target, u, getSource) {
|
|
const source = getSource(u.id)
|
|
target.updates = u.updates.map(u => [u[0], foundry.utils.getProperty(source, u[0])])
|
|
target.deltas = u.deltas.map(d => [d[0], -d[1]])
|
|
return target
|
|
}
|
|
|
|
}
|