diff --git a/app/imports/api/creature/log/CreatureLogs.js b/app/imports/api/creature/log/CreatureLogs.js
index a37569bd..453012e4 100644
--- a/app/imports/api/creature/log/CreatureLogs.js
+++ b/app/imports/api/creature/log/CreatureLogs.js
@@ -137,26 +137,7 @@ const insertCreatureLog = new ValidatedMethod({
},
});
-const insertTabletopLog = new ValidatedMethod({
- name: 'creatureLogs.methods.insertTabletopLog',
- mixins: [RateLimiterMixin],
- rateLimit: {
- numRequests: 5,
- timeInterval: 5000,
- },
- validate: new SimpleSchema({
- log: CreatureLogSchema.omit('date'),
- }).validator(),
- run({ log }) {
- const tabletopId = log.tabletopId;
- assertUserInTabletop(tabletopId, this.userId);
- // Build the new log
- let id = insertCreatureLogWork({ log, method: this })
- return id;
- },
-});
-
-export function insertCreatureLogWork({ log, creature, method }) {
+export function insertCreatureLogWork({ log, creature, tabletopId, method }) {
// Build the new log
if (typeof log === 'string') {
log = { content: [{ value: log }] };
@@ -170,8 +151,8 @@ export function insertCreatureLogWork({ log, creature, method }) {
}
});
log.date = new Date();
- if (creature) log.tabletopId = creature.tabletop;
-
+ if (tabletopId) log.tabletopId = tabletopId;
+ if (creature && creature.tabletop) log.tabletopId = creature.tabletop;
// Insert it
let id = CreatureLogs.insert(log);
if (Meteor.isServer) {
@@ -205,24 +186,39 @@ const logRoll = new ValidatedMethod({
roll: {
type: String,
},
+ tabletopId: {
+ type: String,
+ regEx: SimpleSchema.RegEx.Id,
+ optional: true,
+ },
creatureId: {
type: String,
regEx: SimpleSchema.RegEx.Id,
+ optional: true,
},
}).validator(),
- run({ roll, creatureId }) {
- const creature = Creatures.findOne(creatureId, {
- fields: {
- readers: 1,
- writers: 1,
- owner: 1,
- 'settings.discordWebhook': 1,
- name: 1,
- avatarPicture: 1,
- }
- });
- assertEditPermission(creature, this.userId);
- const variables = CreatureVariables.findOne({ _creatureId: creatureId });
+ run({ roll, tabletopId, creatureId }) {
+ if (!creatureId && !tabletopId) throw new Meteor.Error('no-id',
+ 'A creature id or tabletop id must be given'
+ );
+ let creature;
+ if (creatureId) {
+ creature = Creatures.findOne(creatureId, {
+ fields: {
+ readers: 1,
+ writers: 1,
+ owner: 1,
+ 'settings.discordWebhook': 1,
+ name: 1,
+ avatarPicture: 1,
+ }
+ });
+ assertEditPermission(creature, this.userId);
+ }
+ if (tabletopId) {
+ assertUserInTabletop(tabletopId, this.userId);
+ }
+ const variables = CreatureVariables.findOne({ _creatureId: creatureId }) || {};
let logContent = []
let parsedResult = undefined;
try {
@@ -263,11 +259,11 @@ const logRoll = new ValidatedMethod({
date: new Date(),
};
- let id = insertCreatureLogWork({ log, creature, method: this });
+ let id = insertCreatureLogWork({ log, creature, tabletopId, method: this });
return id;
},
});
export default CreatureLogs;
-export { CreatureLogSchema, insertCreatureLog, logRoll, insertTabletopLog, PER_CREATURE_LOG_LIMIT };
+export { CreatureLogSchema, insertCreatureLog, logRoll, PER_CREATURE_LOG_LIMIT };
diff --git a/app/imports/api/engine/computation/computeComputation/computeByType/computeAction.js b/app/imports/api/engine/computation/computeComputation/computeByType/computeAction.js
index 663922a5..86d23e80 100644
--- a/app/imports/api/engine/computation/computeComputation/computeByType/computeAction.js
+++ b/app/imports/api/engine/computation/computeComputation/computeByType/computeAction.js
@@ -9,8 +9,7 @@ export default function computeAction(computation, node) {
computeResources(computation, node);
if (!prop.resources) return;
prop.resources.itemsConsumed.forEach(itemConsumed => {
- if (!itemConsumed.itemId) return;
- if (itemConsumed.available < itemConsumed.quantity?.value) {
+ if (!itemConsumed.itemId || itemConsumed.available < itemConsumed.quantity?.value) {
prop.insufficientResources = true;
}
});
diff --git a/app/imports/api/engine/loadCreatures.js b/app/imports/api/engine/loadCreatures.js
index aa036a37..829033cb 100644
--- a/app/imports/api/engine/loadCreatures.js
+++ b/app/imports/api/engine/loadCreatures.js
@@ -10,15 +10,17 @@ export const loadedCreatures = new Map(); // creatureId => {creature, properties
export function loadCreature(creatureId, subscription) {
if (!creatureId) throw 'creatureId is required';
let creature = loadedCreatures.get(creatureId);
+ if (!creature || !creature.subs.has(subscription)) {
+ subscription.onStop(() => {
+ unloadCreature(creatureId, subscription);
+ });
+ }
if (loadedCreatures.has(creatureId)) {
creature.subs.add(subscription);
} else {
creature = new LoadedCreature(subscription, creatureId);
loadedCreatures.set(creatureId, creature);
}
- subscription.onStop(() => {
- unloadCreature(creatureId, subscription);
- });
}
function unloadCreature(creatureId, subscription) {
@@ -43,7 +45,7 @@ export function getSingleProperty(creatureId, propertyId) {
const prop = CreatureProperties.findOne({
_id: propertyId,
'ancestors.id': creatureId,
- 'removed': {$ne: true},
+ 'removed': { $ne: true },
}, {
sort: { order: 1 },
});
@@ -61,7 +63,7 @@ export function getProperties(creatureId) {
// console.time(`Cache miss on creature properties: ${creatureId}`)
const props = CreatureProperties.find({
'ancestors.id': creatureId,
- 'removed': {$ne: true},
+ 'removed': { $ne: true },
}, {
sort: { order: 1 },
}).fetch();
@@ -73,7 +75,7 @@ export function getPropertiesOfType(creatureId, propType) {
if (loadedCreatures.has(creatureId)) {
const creature = loadedCreatures.get(creatureId);
const props = []
- for (const prop of creature.properties.values()){
+ for (const prop of creature.properties.values()) {
if (prop.type === propType) {
props.push(prop);
}
@@ -97,7 +99,7 @@ export function getCreature(creatureId) {
if (loadedCreatures.has(creatureId)) {
const loadedCreature = loadedCreatures.get(creatureId);
const creature = loadedCreature.creature;
- if (creature) {
+ if (creature) {
const cloneCreature = EJSON.clone(creature);
return cloneCreature;
}
@@ -118,7 +120,7 @@ export function getVariables(creatureId) {
}
}
// console.time(`Cache miss on variables: ${creatureId}`);
- const variables = CreatureVariables.findOne({_creatureId: creatureId});
+ const variables = CreatureVariables.findOne({ _creatureId: creatureId });
// console.timeEnd(`Cache miss on variables: ${creatureId}`);
return variables;
}
@@ -148,7 +150,7 @@ export function getProperyAncestors(creatureId, propertyId) {
// Fetch from database
return CreatureProperties.find({
_id: { $in: ancestorIds },
- removed: {$ne: true},
+ removed: { $ne: true },
}, {
sort: { order: 1 },
}).fetch();
@@ -164,7 +166,7 @@ export function getPropertyDecendants(creatureId, propertyId) {
if (loadedCreatures.has(creatureId)) {
const creature = loadedCreatures.get(creatureId);
const props = [];
- for(const prop of creature.properties.values()){
+ for (const prop of creature.properties.values()) {
if (prop.ancestors[expectedAncestorPostition]?.id === propertyId) {
props.push(prop);
}
@@ -216,7 +218,7 @@ class LoadedCreature {
compute();
},
});
-
+
// Observe the creature itself
self.creatureObserver = Creatures.find({
_id: creatureId,
@@ -239,7 +241,7 @@ class LoadedCreature {
self.variablesObserver = CreatureVariables.find({
_creatureId: creatureId,
}, {
- fields: { _creatureId: 0},
+ fields: { _creatureId: 0 },
}).observeChanges({
added(id, fields) {
fields._id = id;
diff --git a/app/imports/api/log/LogComponent.vue b/app/imports/api/log/LogComponent.vue
deleted file mode 100644
index d3036749..00000000
--- a/app/imports/api/log/LogComponent.vue
+++ /dev/null
@@ -1,98 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/imports/api/tabletop/map/TabletopMap.vue b/app/imports/api/tabletop/map/TabletopMap.vue
deleted file mode 100644
index 0c87c5ae..00000000
--- a/app/imports/api/tabletop/map/TabletopMap.vue
+++ /dev/null
@@ -1,89 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/imports/client/ui/components/RollPopup.vue b/app/imports/client/ui/components/RollPopup.vue
index d7cb25b8..0aaca754 100644
--- a/app/imports/client/ui/components/RollPopup.vue
+++ b/app/imports/client/ui/components/RollPopup.vue
@@ -12,8 +12,8 @@
{ if (!noClick) e.stopPropagation(); }"
>
@@ -90,6 +90,7 @@ export default {
type: Number,
default: undefined,
},
+ noClick: Boolean,
},
data(){return {
open: false,
diff --git a/app/imports/client/ui/creature/character/CharacterSheet.vue b/app/imports/client/ui/creature/character/CharacterSheet.vue
index 75f4cbd8..568ebe79 100644
--- a/app/imports/client/ui/creature/character/CharacterSheet.vue
+++ b/app/imports/client/ui/creature/character/CharacterSheet.vue
@@ -30,17 +30,17 @@
$store.commit(
'setTabForCharacterSheet',
- {id: $route.params.id, tab: e}
+ {id: creatureId, tab: e}
)"
>
@@ -68,11 +68,10 @@
-
$store.commit(
'setTabForCharacterSheet',
- {id: $route.params.id, tab: e}
+ {id: creatureId, tab: e}
)"
>
@@ -164,7 +163,9 @@ export default {
type: String,
required: true,
},
+ embedded: Boolean,
},
+ // @ts-ignore
reactiveProvide: {
name: 'context',
include: ['creatureId', 'editPermission'],
@@ -250,7 +251,11 @@ export default {
diff --git a/app/imports/client/ui/dialogStack/DialogComponentIndex.js b/app/imports/client/ui/dialogStack/DialogComponentIndex.js
index 471d3b6a..bf084614 100644
--- a/app/imports/client/ui/dialogStack/DialogComponentIndex.js
+++ b/app/imports/client/ui/dialogStack/DialogComponentIndex.js
@@ -1,6 +1,7 @@
// Load commonly used dialogs immediately
import InsertPropertyDialog from '/imports/client/ui/properties/InsertPropertyDialog.vue';
import CharacterCreationDialog from '/imports/client/ui/creature/character/CharacterCreationDialog.vue';
+import CharacterSheetDialog from '/imports/client/ui/tabletop/CharacterSheetDialog.vue';
import CastSpellWithSlotDialog from '/imports/client/ui/properties/components/spells/CastSpellWithSlotDialog.vue';
import CreatureFormDialog from '/imports/client/ui/creature/CreatureFormDialog.vue';
import CreaturePropertyDialog from '/imports/client/ui/creature/creatureProperties/CreaturePropertyDialog.vue';
@@ -37,6 +38,7 @@ export default {
ArchiveDialog,
CastSpellWithSlotDialog,
CharacterCreationDialog,
+ CharacterSheetDialog,
CreatureFormDialog,
CreaturePropertyDialog,
CreaturePropertyFromLibraryDialog,
diff --git a/app/imports/client/ui/layouts/Sidebar.vue b/app/imports/client/ui/layouts/Sidebar.vue
index 9037b346..e8bfe92c 100644
--- a/app/imports/client/ui/layouts/Sidebar.vue
+++ b/app/imports/client/ui/layouts/Sidebar.vue
@@ -80,6 +80,7 @@ export default {
components: {
CreatureFolderList
},
+ // @ts-ignore
meteor: {
$subscribe: {
'characterList': [],
diff --git a/app/imports/client/ui/log/CharacterLog.vue b/app/imports/client/ui/log/CharacterLog.vue
index f4e9582a..6f32d184 100644
--- a/app/imports/client/ui/log/CharacterLog.vue
+++ b/app/imports/client/ui/log/CharacterLog.vue
@@ -25,8 +25,11 @@
:hint="inputHint"
:error-messages="inputError"
:disabled="!editPermission"
+ :loading="submitLoading"
@click:append-outer="submit"
@keyup.enter="submit"
+ @keyup.up="decrementHistory"
+ @keyup.down="incrementHistory"
/>
@@ -40,6 +43,7 @@ import { assertEditPermission } from '/imports/api/creature/creatures/creaturePe
import { parse, prettifyParseError } from '/imports/parser/parser.js';
import resolve, { toString } from '/imports/parser/resolve.js';
import LogEntry from '/imports/client/ui/log/LogEntry.vue';
+import { Tracker } from 'meteor/tracker'
export default {
components: {
@@ -48,22 +52,70 @@ export default {
props: {
creatureId: {
type: String,
- required: true,
+ default: undefined,
+ },
+ tabletopId: {
+ type: String,
+ default: undefined,
},
},
data(){return {
inputHint: undefined,
inputError: undefined,
input: undefined,
+ history: [],
+ historyIndex: 1,
+ submitLoading: false,
}},
watch: {
input(value){
this.input = value;
+ this.recalculate();
+ },
+ creatureId() {
+ Tracker.afterFlush(() => this.recalculate())
+ },
+ historyIndex(i) {
+ if (typeof this.history[i] === 'string') {
+ this.input = this.history[i];
+ }
+ }
+ },
+ methods: {
+ submit() {
+ if (!this.input) return;
+ if (this.submitLoading) return;
+ const log = {
+ roll: this.input,
+ };
+ if (this.tabletopId) log.tabletopId = this.tabletopId;
+ if (this.creatureId) log.creatureId = this.creatureId;
+ this.submitLoading = true;
+ logRoll.call(log, (error) => {
+ this.submitLoading = false;
+ if (!error) {
+ this.addHistory(this.input);
+ this.input = '';
+ this.inputError = undefined;
+ return;
+ }
+ this.inputError = error.message || error.toString();
+ console.error(error);
+ });
+ },
+ addHistory(string) {
+ // Don't add duplicates back to back in history
+ if (string === this.history[this.history.length - 1]) return;
+ this.history.push(string);
+ if (this.history.length > 50) this.history.shift();
+ this.historyIndex = this.history.length;
+ },
+ recalculate() {
this.inputHint = this.inputError = undefined;
if (!this.input) return;
let result;
try {
- result = parse(value);
+ result = parse(this.input);
} catch (e){
if (e.constructor.name === 'EndOfInputError'){
this.inputError = '...';
@@ -83,24 +135,29 @@ export default {
return;
}
},
- },
- methods: {
- submit(input){
- logRoll.call({
- roll: input,
- creatureId: this.creatureId,
- }, (error) => {
- if (error) console.error(error);
- });
+ incrementHistory() {
+ if (this.historyIndex < this.history.length) {
+ this.historyIndex += 1;
+ }
},
+ decrementHistory() {
+ if (this.historyIndex > 0) {
+ this.historyIndex -= 1;
+ }
+ }
},
+ // @ts-ignore
meteor: {
- logs(){
- return CreatureLogs.find({
- creatureId: this.creatureId,
- }, {
+ logs() {
+ const filter = {};
+ if (this.tabletopId) {
+ filter.tabletopId = this.tabletopId;
+ } else if (this.creatureId) {
+ filter.creatureId = this.creatureId;
+ }
+ return CreatureLogs.find(filter, {
sort: {date: -1},
- limit: 20
+ limit: 100
});
},
creature(){
diff --git a/app/imports/client/ui/properties/components/actions/AttributeConsumedView.vue b/app/imports/client/ui/properties/components/actions/AttributeConsumedView.vue
index 26571332..9ae84918 100644
--- a/app/imports/client/ui/properties/components/actions/AttributeConsumedView.vue
+++ b/app/imports/client/ui/properties/components/actions/AttributeConsumedView.vue
@@ -4,16 +4,23 @@
:class="insufficient && 'error--text'"
>
- {{ model.quantity && model.quantity.value }}
+ {{ model.quantity.value }}
{{ model.statName || model.variableName }}
+
+ ({{ model.available }})
+
diff --git a/app/imports/client/ui/properties/components/actions/ItemConsumedView.vue b/app/imports/client/ui/properties/components/actions/ItemConsumedView.vue
index f0eae75a..11be31fb 100644
--- a/app/imports/client/ui/properties/components/actions/ItemConsumedView.vue
+++ b/app/imports/client/ui/properties/components/actions/ItemConsumedView.vue
@@ -27,28 +27,30 @@
:color="model.itemColor"
/>
-
- {{ model.available }} / {{ quantity }}
-
-
- {{ model.available }}
-
+ {{ quantity }}
-
-
- {{ model.itemName }}
-
-
+
- Select item
-
+ {{ model.itemName }}
+
+
+ ({{ model.available }})
+
+
+
+ Select item
-
+
$store.commit(
+ 'setTabForCharacterSheet',
+ {id: creatureId, tab: e}
+ )"
>
Stats
- Features
-
-
- Inventory
+ Actions
Spells
- Character
+ Inventory
+
+
+ Features
+
+
+ Journal
+
+
+ Build
Tree
-
+
+
+
+
+
+
+
diff --git a/app/imports/client/ui/tabletop/TabletopActionCards.vue b/app/imports/client/ui/tabletop/TabletopActionCards.vue
deleted file mode 100644
index 5fe2efd8..00000000
--- a/app/imports/client/ui/tabletop/TabletopActionCards.vue
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
-
-
-
-
diff --git a/app/imports/client/ui/tabletop/TabletopComponent.vue b/app/imports/client/ui/tabletop/TabletopComponent.vue
index 603c8fbd..1e9bbf0a 100644
--- a/app/imports/client/ui/tabletop/TabletopComponent.vue
+++ b/app/imports/client/ui/tabletop/TabletopComponent.vue
@@ -19,16 +19,31 @@
@@ -67,22 +82,24 @@
@@ -95,9 +112,29 @@ import addCreaturesToTabletop from '/imports/api/tabletop/methods/addCreaturesTo
import TabletopCreatureCard from '/imports/client/ui/tabletop/TabletopCreatureCard.vue';
import TabletopMap from '/imports/client/ui/tabletop/TabletopMap.vue';
import Creatures from '/imports/api/creature/creatures/Creatures.js';
-import TabletopActionCards from '/imports/client/ui/tabletop/TabletopActionCards.vue';
import MiniCharacterSheet from '/imports/client/ui/creature/character/MiniCharacterSheet.vue';
import { snackbar } from '/imports/client/ui/components/snackbars/SnackbarQueue.js';
+import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
+import { assertEditPermission } from '/imports/api/creature/creatures/creaturePermissions.js';
+import ActionCard from '/imports/client/ui/tabletop/TabletopActionCard.vue';
+
+const getProperties = function (creatureId, selector = {}) {
+ return CreatureProperties.find({
+ 'ancestors.id': {
+ $eq: creatureId,
+ },
+ inactive: { $ne: true },
+ removed: { $ne: true },
+ overridden: { $ne: true },
+ $nor: [
+ { hideWhenTotalZero: true, total: 0 },
+ { hideWhenValueZero: true, value: 0 },
+ ],
+ ...selector,
+ }, {
+ sort: { order: 1 }
+ });
+}
export default {
components: {
@@ -118,8 +155,14 @@ export default {
},
data() {
return {
- activeCreature: undefined,
- targets: [],
+ activeCreatureId: undefined,
+ activeActionId: undefined,
+ targets: [],
+ }
+ },
+ watch: {
+ activeCreatureId(id) {
+ this.$root.$emit('active-tabletop-character-change', id);
}
},
meteor: {
@@ -132,28 +175,20 @@ export default {
return Creatures.find({ tabletop: this.model._id });
},
actions(){
- return getProperties(this.activeCreature, 'action').map(a => {
- delete a.summary;
- return a;
- });
+ return getProperties(this.activeCreatureId, { type: 'action', actionType: { $ne: 'event'} });
},
- editPermission(){
- try {
- assertEditPermission(this.activeCreature, Meteor.userId());
+ moreTargets(){
+ const activeAction = CreatureProperties.findOne(this.activeActionId);
+ if (!activeAction) return;
+ if (activeAction.target === 'singleTarget') {
+ return this.targets.length === 0;
+ } else if (activeAction.target === 'multipleTargets') {
return true;
- } catch (e) {
- return false;
}
},
- actions(){
- return getProperties(this.activeCreature, 'action').map(a => {
- delete a.summary;
- return a;
- });
- },
editPermission(){
try {
- assertEditPermission(this.activeCreature, Meteor.userId());
+ assertEditPermission(this.activeCreatureId, Meteor.userId());
return true;
} catch (e) {
return false;
@@ -184,7 +219,7 @@ export default {
component: 'character-sheet-dialog',
elementId: 'mini-character-sheet',
data: {
- creatureId: this.activeCreature,
+ creatureId: this.activeCreatureId,
},
});
},
@@ -199,7 +234,7 @@ export default {
if (!event.deltaY) {
return;
}
- event.currentTarget.scrollLeft += event.deltaY + event.deltaX;
+ event.currentTarget.scrollLeft += event.deltaY;
event.preventDefault();
},
untarget(id){
@@ -208,7 +243,7 @@ export default {
this.targets.splice(index, 1);
}
}
- }
+ },
}
@@ -220,12 +255,11 @@ export default {
width: 100px;
margin: 4px;
}
-.action-row > .v-card {
+.action-row > div {
flex-grow: 0;
flex-shrink: 0;
- max-height: 320px;
+ height: 120px;
width: 200px;
margin: 4px;
- overflow-y: hidden;
}
diff --git a/app/imports/client/ui/tabletop/TabletopCreatureCard.vue b/app/imports/client/ui/tabletop/TabletopCreatureCard.vue
index 656249e6..76e5c3d7 100644
--- a/app/imports/client/ui/tabletop/TabletopCreatureCard.vue
+++ b/app/imports/client/ui/tabletop/TabletopCreatureCard.vue
@@ -1,15 +1,17 @@
{ if (hasClickListener) hover = true; }"
@mouseleave="hover = false"
- @click="$emit('click')"
+ v-on="hasClickListener ? {click: () => $emit('click')} : {}"
>
-
- {{ targeted ? 'mdi-target' : 'mdi-target' }}
-
+
+
+
+ {{ targeted ? 'mdi-target' : 'mdi-target' }}
+
+
+
@@ -63,3 +85,9 @@ export default {
text-overflow: ellipsis;
}
+
+
diff --git a/app/imports/client/ui/tabletop/TabletopLog.vue b/app/imports/client/ui/tabletop/TabletopLog.vue
index 2dcd16ea..7f077e31 100644
--- a/app/imports/client/ui/tabletop/TabletopLog.vue
+++ b/app/imports/client/ui/tabletop/TabletopLog.vue
@@ -1,20 +1,17 @@
-
diff --git a/app/imports/client/ui/tabletop/TabletopMap.vue b/app/imports/client/ui/tabletop/TabletopMap.vue
index 605da292..37546d7e 100644
--- a/app/imports/client/ui/tabletop/TabletopMap.vue
+++ b/app/imports/client/ui/tabletop/TabletopMap.vue
@@ -1,11 +1,89 @@
-
-
+
+
+
+
-
+
\ No newline at end of file
diff --git a/app/imports/server/publications/tabletops.js b/app/imports/server/publications/tabletops.js
index 83bc84c1..58f10a48 100644
--- a/app/imports/server/publications/tabletops.js
+++ b/app/imports/server/publications/tabletops.js
@@ -2,37 +2,41 @@ import Tabletops from '/imports/api/tabletop/Tabletops.js';
import Creatures from '/imports/api/creature/creatures/Creatures.js';
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
import CreatureLogs from '/imports/api/creature/log/CreatureLogs.js';
+import CreatureVariables from '/imports/api/creature/creatures/CreatureVariables.js';
+import { loadCreature } from '/imports/api/engine/loadCreatures.js';
-Meteor.publish('tabletops', function(){
+Meteor.publish('tabletops', function () {
var userId = this.userId;
if (!userId) {
return [];
}
return Tabletops.find({
$or: [
- {players: userId},
- {gameMaster: userId},
+ { players: userId },
+ { gameMaster: userId },
],
});
});
-Meteor.publish('tabletop', function(tabletopId){
+Meteor.publish('tabletop', function (tabletopId) {
var userId = this.userId;
if (!userId) {
return [];
}
- this.autorun(function (){
+ this.autorun(function () {
+ const self = this;
let tabletopCursor = Tabletops.find({
_id: tabletopId,
$or: [
- {players: userId},
- {gameMaster: userId},
+ { players: userId },
+ { gameMaster: userId },
]
});
let tabletop = tabletopCursor.fetch()[0];
- if (!tabletop){
+ if (!tabletop) {
return [];
}
+
// Warning, this leaks data to users of the same tabletop who may not have
// read permission of this specific creature, so publish as few fields as
// possible
@@ -40,25 +44,31 @@ Meteor.publish('tabletop', function(tabletopId){
tabletop: tabletopId,
}, {
fields: {
+ _id: 1,
name: 1,
picture: 1,
avatarPicture: 1,
- variables: 1,
tabletop: 1,
initiativeRoll: 1,
},
});
const creatureIds = creatureSummaries.map(c => c._id);
+ creatureIds.forEach(creatureId => {
+ loadCreature(creatureId, self);
+ });
+ const variables = CreatureVariables.find({
+ _creatureId: { $in: creatureIds }
+ });
let properties = CreatureProperties.find({
- 'ancestors.0.id': {$in: creatureIds},
- removed: {$ne: true},
+ 'ancestors.id': { $in: creatureIds },
+ removed: { $ne: true },
});
const logs = CreatureLogs.find({
tabletopId,
}, {
- limit: 50,
- sort: {date: -1},
+ limit: 100,
+ sort: { date: -1 },
});
- return [ tabletopCursor, creatureSummaries, properties, logs]
+ return [tabletopCursor, creatureSummaries, properties, logs, variables]
})
});
diff --git a/app/package-lock.json b/app/package-lock.json
index ae7c0414..daf70f03 100644
--- a/app/package-lock.json
+++ b/app/package-lock.json
@@ -3426,15 +3426,9 @@
"dev": true
},
"signal-exit": {
-<<<<<<< HEAD
- "version": "3.0.2",
- "resolved": "",
- "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
-=======
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
->>>>>>> version-2
},
"simpl-schema": {
"version": "1.13.1",
@@ -3748,9 +3742,9 @@
"dev": true
},
"three": {
- "version": "0.139.2",
- "resolved": "https://registry.npmjs.org/three/-/three-0.139.2.tgz",
- "integrity": "sha512-gV7q7QY8rogu7HLFZR9cWnOQAUedUhu2WXAnpr2kdXZP9YDKsG/0ychwQvWkZN5PlNw9mv5MoCTin6zNTXoONg=="
+ "version": "0.148.0",
+ "resolved": "https://registry.npmjs.org/three/-/three-0.148.0.tgz",
+ "integrity": "sha512-8uzVV+qhTPi0bOFs/3te3RW6hb3urL8jYEl6irjCWo/l6sr8MPNMcClFev/MMYeIxr0gmDcoXTy/8LXh/LXkfw=="
},
"to-regex-range": {
"version": "5.0.1",
diff --git a/app/package.json b/app/package.json
index 463be480..75f76649 100644
--- a/app/package.json
+++ b/app/package.json
@@ -52,8 +52,9 @@
"simpl-schema": "^1.13.1",
"source-map-support": "^0.5.21",
"speakingurl": "^14.0.1",
+ "three": "^0.148.0",
"vivagraphjs": "^0.12.0",
- "vue": "2.6.14",
+ "vue": "2.6.10",
"vue-meteor-tracker": "^2.0.0",
"vue-reactive-provide": "^0.3.0",
"vue-router": "^3.6.5",