From 131cbbe586463a7232f332650af5f0b2c13dc7e9 Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Fri, 10 Jul 2026 20:37:29 -0400 Subject: feat(admin): remove unused fields from drop tables --- building_guide/drops.md | 57 +++++++++++++++++++++++------ data/.admin_history.json | 1 - data/drops/herb_table_high.yaml | 2 +- data/drops/herb_table_low.yaml | 2 +- data/drops/herb_table_mid.yaml | 2 +- data/mobs/flight_attendant.yaml | 47 ++++++++++++------------ internal/admin/static/dropeditor.js | 66 ++++++++++++++++++++++------------ internal/validate/checks.go | 72 ++++++++++++++++++++++++++++++++++++- 8 files changed, 190 insertions(+), 59 deletions(-) delete mode 100644 data/.admin_history.json diff --git a/building_guide/drops.md b/building_guide/drops.md index f71f712..edac103 100644 --- a/building_guide/drops.md +++ b/building_guide/drops.md @@ -4,7 +4,11 @@ (`gem_table.yaml` → `gem_table`); reference it from behaviors/mobs by that name. Do not put an `id:` field in the file — it is ignored. -Shared drop tables can be referenced by multiple behaviors: +### Shared drop table entries + +Shared drop tables in `data/drops/` are pure weighted pools of items. Each entry supports +only three fields (four with `table`): + ```yaml # data/drops/gem_table.yaml drops: @@ -18,6 +22,34 @@ drops: weight: 1 ``` +| Field | Required | Description | +|-------|----------|-------------| +| `item_id` | XOR with `table` | Item ID to drop | +| `table` | XOR with `item_id` | Reference to another shared drop table (can nest) | +| `weight` | yes | Relative drop weight | +| `quantity` | no | Amount to drop (default 1) | + +**`item_id` and `table` are mutually exclusive per entry.** The entry drops *either* the named +item *or* rolls on the referenced sub-table; never both. + +### What does NOT belong on a shared drop table + +The following fields are **meaningless on shared drop table entries** and are ignored by the +engine — they belong on the *referencing* gather entry in the object config instead: + +- `depletes` — controls whether the gatherable node depletes (per-drop; ore vs gem). Set on + the `gather.drops[]` entry in the object YAML that references this table. +- `level` — skill-level gate on a drop. Only meaningful on the outer gather entry. +- `xp` — skill XP for this drop. Only meaningful on the outer gather entry. +- `tool` — tool-type filter. Only meaningful on the outer gather entry. +- `success_message` — per-drop message. Overridden by the outer entry when referenced via + `table:`. + +The admin Drop Table editor intentionally shows only `item_id`/`table` (toggle), `weight`, +and `quantity`. Edit the raw YAML if you need niche overrides. + +### Examples + Bird's nest drop table: ```yaml # data/drops/birds_nest_drop.yaml @@ -39,16 +71,21 @@ drops: quantity: 10000 ``` -Referenced from a gather behavior: +Referenced from a gather behavior (note `depletes` lives on the **outer** entries here, +not inside `gem_table`): ```yaml -drops: - - item_id: copper_ore - weight: 90 - depletes: true - - table: gem_table # pulls from data/drops/gem_table.yaml - weight: 10 - depletes: false +gather: + drops: + - item_id: copper_ore + weight: 90 + level: 1 + xp: 17 + depletes: true + success_message: "You manage to mine some copper ore." + - table: gem_table # pulls from data/drops/gem_table.yaml + weight: 10 + depletes: false # gem drops don't deplete the rock + success_message: "You spot a glint of something valuable!" ``` --- - diff --git a/data/.admin_history.json b/data/.admin_history.json deleted file mode 100644 index 499b27d..0000000 --- a/data/.admin_history.json +++ /dev/null @@ -1 +0,0 @@ -{"history":[{"time":"2026-07-10T19:25:32-04:00","description":"update room 1008","file_path":"data/rooms/intro/1008.yaml","old_content":"block_transport: false\ncolor: D3\ndescription: []\nexits:\n east:\n room: 1009\n south:\n always_blocked: false\n blocked_message: \"\"\n condition: null\n hidden: false\n room: 1007\nhazard: \"\"\nid: 1008\nitem_spawns: []\nmobs: []\nname: 'Room #1008'\nobjects: []\non_enter:\n - condition:\n all_of: []\n steps: []\non_exit:\n - steps: []\n","new_content":"block_transport: false\ncolor: D3\ndescription: []\nexits:\n east:\n room: 1009\n south:\n always_blocked: false\n blocked_message: \"\"\n condition: null\n hidden: false\n room: 1007\nhazard: \"\"\nid: 1008\nitem_spawns: []\nmobs: []\nname: 'Room #1008'\nobjects: []\non_enter:\n - condition:\n all_of: []\n steps: []\n - steps: []\non_exit:\n - steps: []\n","is_delete":false,"is_create":false},{"time":"2026-07-10T19:25:35-04:00","description":"update room 1008","file_path":"data/rooms/intro/1008.yaml","old_content":"block_transport: false\ncolor: D3\ndescription: []\nexits:\n east:\n room: 1009\n south:\n always_blocked: false\n blocked_message: \"\"\n condition: null\n hidden: false\n room: 1007\nhazard: \"\"\nid: 1008\nitem_spawns: []\nmobs: []\nname: 'Room #1008'\nobjects: []\non_enter:\n - condition:\n all_of: []\n steps: []\n - steps: []\non_exit:\n - steps: []\n","new_content":"block_transport: false\ncolor: D3\ndescription: []\nexits:\n east:\n room: 1009\n south:\n always_blocked: false\n blocked_message: \"\"\n condition: null\n hidden: false\n room: 1007\nhazard: \"\"\nid: 1008\nitem_spawns: []\nmobs: []\nname: 'Room #1008'\nobjects: []\non_enter:\n - condition:\n all_of: []\n steps: []\n - steps: []\non_exit:\n - steps: []\n","is_delete":false,"is_create":false},{"time":"2026-07-10T19:25:38-04:00","description":"update room 1008","file_path":"data/rooms/intro/1008.yaml","old_content":"block_transport: false\ncolor: D3\ndescription: []\nexits:\n east:\n room: 1009\n south:\n always_blocked: false\n blocked_message: \"\"\n condition: null\n hidden: false\n room: 1007\nhazard: \"\"\nid: 1008\nitem_spawns: []\nmobs: []\nname: 'Room #1008'\nobjects: []\non_enter:\n - condition:\n all_of: []\n steps: []\n - steps: []\non_exit:\n - steps: []\n","new_content":"block_transport: false\ncolor: D3\ndescription: []\nexits:\n east:\n room: 1009\n south:\n always_blocked: false\n blocked_message: \"\"\n condition: null\n hidden: false\n room: 1007\nhazard: \"\"\nid: 1008\nitem_spawns: []\nmobs: []\nname: 'Room #1008'\nobjects: []\non_enter:\n - condition:\n all_of: []\n steps: []\n - steps: []\non_exit:\n - steps: []\n","is_delete":false,"is_create":false},{"time":"2026-07-10T19:25:41-04:00","description":"update room 1008","file_path":"data/rooms/intro/1008.yaml","old_content":"block_transport: false\ncolor: D3\ndescription: []\nexits:\n east:\n room: 1009\n south:\n always_blocked: false\n blocked_message: \"\"\n condition: null\n hidden: false\n room: 1007\nhazard: \"\"\nid: 1008\nitem_spawns: []\nmobs: []\nname: 'Room #1008'\nobjects: []\non_enter:\n - condition:\n all_of: []\n steps: []\n - steps: []\non_exit:\n - steps: []\n","new_content":"block_transport: false\ncolor: D3\ndescription: []\nexits:\n east:\n room: 1009\n south:\n always_blocked: false\n blocked_message: \"\"\n condition: null\n hidden: false\n room: 1007\nhazard: \"\"\nid: 1008\nitem_spawns: []\nmobs: []\nname: 'Room #1008'\nobjects: []\non_enter:\n - condition:\n all_of: []\n steps: []\n - steps: []\non_exit:\n - steps: []\n","is_delete":false,"is_create":false},{"time":"2026-07-10T19:25:42-04:00","description":"update room 1008","file_path":"data/rooms/intro/1008.yaml","old_content":"block_transport: false\ncolor: D3\ndescription: []\nexits:\n east:\n room: 1009\n south:\n always_blocked: false\n blocked_message: \"\"\n condition: null\n hidden: false\n room: 1007\nhazard: \"\"\nid: 1008\nitem_spawns: []\nmobs: []\nname: 'Room #1008'\nobjects: []\non_enter:\n - condition:\n all_of: []\n steps: []\n - steps: []\non_exit:\n - steps: []\n","new_content":"block_transport: false\ncolor: D3\ndescription: []\nexits:\n east:\n room: 1009\n south:\n always_blocked: false\n blocked_message: \"\"\n condition: null\n hidden: false\n room: 1007\nhazard: \"\"\nid: 1008\nitem_spawns: []\nmobs: []\nname: 'Room #1008'\nobjects: []\non_enter:\n - condition:\n all_of: []\n steps: []\n - steps: []\n - steps: []\non_exit:\n - steps: []\n","is_delete":false,"is_create":false},{"time":"2026-07-10T19:25:44-04:00","description":"update room 1008","file_path":"data/rooms/intro/1008.yaml","old_content":"block_transport: false\ncolor: D3\ndescription: []\nexits:\n east:\n room: 1009\n south:\n always_blocked: false\n blocked_message: \"\"\n condition: null\n hidden: false\n room: 1007\nhazard: \"\"\nid: 1008\nitem_spawns: []\nmobs: []\nname: 'Room #1008'\nobjects: []\non_enter:\n - condition:\n all_of: []\n steps: []\n - steps: []\n - steps: []\non_exit:\n - steps: []\n","new_content":"block_transport: false\ncolor: D3\ndescription: []\nexits:\n east:\n room: 1009\n south:\n always_blocked: false\n blocked_message: \"\"\n condition: null\n hidden: false\n room: 1007\nhazard: \"\"\nid: 1008\nitem_spawns: []\nmobs: []\nname: 'Room #1008'\nobjects: []\non_enter:\n - condition:\n all_of: []\n steps: []\n - steps: []\n - steps: []\non_exit:\n - steps: []\n","is_delete":false,"is_create":false},{"time":"2026-07-10T19:25:44-04:00","description":"update room 1008","file_path":"data/rooms/intro/1008.yaml","old_content":"block_transport: false\ncolor: D3\ndescription: []\nexits:\n east:\n room: 1009\n south:\n always_blocked: false\n blocked_message: \"\"\n condition: null\n hidden: false\n room: 1007\nhazard: \"\"\nid: 1008\nitem_spawns: []\nmobs: []\nname: 'Room #1008'\nobjects: []\non_enter:\n - condition:\n all_of: []\n steps: []\n - steps: []\n - steps: []\non_exit:\n - steps: []\n","new_content":"block_transport: false\ncolor: D3\ndescription: []\nexits:\n east:\n room: 1009\n south:\n always_blocked: false\n blocked_message: \"\"\n condition: null\n hidden: false\n room: 1007\nhazard: \"\"\nid: 1008\nitem_spawns: []\nmobs: []\nname: 'Room #1008'\nobjects: []\non_enter:\n - condition:\n all_of: []\n steps: []\n - steps: []\n - steps: []\non_exit:\n - steps: []\n","is_delete":false,"is_create":false},{"time":"2026-07-10T19:25:45-04:00","description":"update room 1008","file_path":"data/rooms/intro/1008.yaml","old_content":"block_transport: false\ncolor: D3\ndescription: []\nexits:\n east:\n room: 1009\n south:\n always_blocked: false\n blocked_message: \"\"\n condition: null\n hidden: false\n room: 1007\nhazard: \"\"\nid: 1008\nitem_spawns: []\nmobs: []\nname: 'Room #1008'\nobjects: []\non_enter:\n - condition:\n all_of: []\n steps: []\n - steps: []\n - steps: []\non_exit:\n - steps: []\n","new_content":"block_transport: false\ncolor: D3\ndescription: []\nexits:\n east:\n room: 1009\n south:\n always_blocked: false\n blocked_message: \"\"\n condition: null\n hidden: false\n room: 1007\nhazard: \"\"\nid: 1008\nitem_spawns: []\nmobs: []\nname: 'Room #1008'\nobjects: []\non_enter:\n - condition:\n all_of: []\n steps: []\n - steps: []\n - steps: []\non_exit:\n - steps: []\n","is_delete":false,"is_create":false},{"time":"2026-07-10T19:25:48-04:00","description":"update room 1008","file_path":"data/rooms/intro/1008.yaml","old_content":"block_transport: false\ncolor: D3\ndescription: []\nexits:\n east:\n room: 1009\n south:\n always_blocked: false\n blocked_message: \"\"\n condition: null\n hidden: false\n room: 1007\nhazard: \"\"\nid: 1008\nitem_spawns: []\nmobs: []\nname: 'Room #1008'\nobjects: []\non_enter:\n - condition:\n all_of: []\n steps: []\n - steps: []\n - steps: []\non_exit:\n - steps: []\n","new_content":"block_transport: false\ncolor: D3\ndescription: []\nexits:\n east:\n room: 1009\n south:\n always_blocked: false\n blocked_message: \"\"\n condition: null\n hidden: false\n room: 1007\nhazard: \"\"\nid: 1008\nitem_spawns: []\nmobs: []\nname: 'Room #1008'\nobjects: []\non_enter:\n - condition:\n all_of: []\n steps: []\n - steps: []\n - steps: []\non_exit:\n - steps: []\n - steps: []\n","is_delete":false,"is_create":false},{"time":"2026-07-10T19:25:48-04:00","description":"update room 1008","file_path":"data/rooms/intro/1008.yaml","old_content":"block_transport: false\ncolor: D3\ndescription: []\nexits:\n east:\n room: 1009\n south:\n always_blocked: false\n blocked_message: \"\"\n condition: null\n hidden: false\n room: 1007\nhazard: \"\"\nid: 1008\nitem_spawns: []\nmobs: []\nname: 'Room #1008'\nobjects: []\non_enter:\n - condition:\n all_of: []\n steps: []\n - steps: []\n - steps: []\non_exit:\n - steps: []\n - steps: []\n","new_content":"block_transport: false\ncolor: D3\ndescription: []\nexits:\n east:\n room: 1009\n south:\n always_blocked: false\n blocked_message: \"\"\n condition: null\n hidden: false\n room: 1007\nhazard: \"\"\nid: 1008\nitem_spawns: []\nmobs: []\nname: 'Room #1008'\nobjects: []\non_enter:\n - condition:\n all_of: []\n steps: []\n - steps: []\n - steps: []\non_exit:\n - steps: []\n - steps: []\n","is_delete":false,"is_create":false}],"redo":null} \ No newline at end of file diff --git a/data/drops/herb_table_high.yaml b/data/drops/herb_table_high.yaml index 8631a3c..25e96b2 100644 --- a/data/drops/herb_table_high.yaml +++ b/data/drops/herb_table_high.yaml @@ -1,4 +1,4 @@ -entries: +drops: - item_id: grimy_kwuarm weight: 7 - item_id: grimy_snapdragon diff --git a/data/drops/herb_table_low.yaml b/data/drops/herb_table_low.yaml index 7c20bb6..1cbbed8 100644 --- a/data/drops/herb_table_low.yaml +++ b/data/drops/herb_table_low.yaml @@ -1,4 +1,4 @@ -entries: +drops: - item_id: grimy_guam weight: 10 - item_id: grimy_marrentill diff --git a/data/drops/herb_table_mid.yaml b/data/drops/herb_table_mid.yaml index 17e3275..382f225 100644 --- a/data/drops/herb_table_mid.yaml +++ b/data/drops/herb_table_mid.yaml @@ -1,4 +1,4 @@ -entries: +drops: - item_id: grimy_harralander weight: 8 - item_id: grimy_ranarr diff --git a/data/mobs/flight_attendant.yaml b/data/mobs/flight_attendant.yaml index e595e67..a0be1e8 100644 --- a/data/mobs/flight_attendant.yaml +++ b/data/mobs/flight_attendant.yaml @@ -1,27 +1,30 @@ -name: flight attendant description: A smiling flight attendant in a crisp uniform, ready to assist passengers. -unique: false -protected: true +id: flight_attendant idle_descriptions: - adjusts her name badge - smiles politely at you +name: flight attendant +protected: true talk: - nodes: - start: - condition: - player_flag: 1001_look_sign - not: true - messages: ['"Hi there, how can I help?"'] - goto: thanks - options: - - text: '"Oh, nothing... Small crowd on this ship. Just looking for conversation."' - goto: sign_reminder - - text: '"Goodbye."' - thanks: - messages: ['"Thank for flying with Denali. Watch your step on the way out please."'] - options: - - text: '"Thank you."' - sign_reminder: - messages: - - '"Yeah, just us two! Not a lot of people heading into the belt these days."' - - '"But we''ll be landing shortly! Please be sure {0B bold}look{/} at the information {0B bold}sign{/} so you''ll be all set for your final destination."' + nodes: + sign_reminder: + messages: + - '"Yeah, just us two! Not a lot of people heading into the belt these days."' + - '"But we''ll be landing shortly! Please be sure {0B bold}look{/} at the information {0B bold}sign{/} so you''ll be all set for your final destination."' + start: + condition: + not: true + player_flag: 1001_look_sign + goto: thanks + messages: + - '"Hi there, how can I help?"' + options: + - goto: sign_reminder + text: '"Oh, nothing... Small crowd on this ship. Just looking for conversation."' + - text: '"Goodbye."' + thanks: + messages: + - '"Thank for flying with Denali. Watch your step on the way out please."' + options: + - text: '"Thank you."' +unique: false diff --git a/internal/admin/static/dropeditor.js b/internal/admin/static/dropeditor.js index 566d696..ac1df97 100644 --- a/internal/admin/static/dropeditor.js +++ b/internal/admin/static/dropeditor.js @@ -11,10 +11,6 @@ var DROP_SECTIONS = [ ['table', 'Table', 'search', 'e.g. gem_table', '', null, 'drops'], ['weight', 'Weight', 'number', '10', 'narrow'], ['quantity', 'Quantity', 'number', '1', 'narrow'], - ['level', 'Level', 'number', '1', 'narrow'], - ['xp', 'XP', 'number', '5', 'narrow'], - ['depletes', 'Depletes', 'checkbox'], - ['success_message', 'Success Message', 'text', 'You get some %n.', 'wide'], ] } ]; @@ -113,16 +109,37 @@ function renderArraySection(sec, data) { var arr = dropData[cardPath(sec)] || []; var h = ''; arr.forEach(function(item, idx) { + var isItem = item._type !== undefined ? item._type !== 't' : !item.table; + var showKey = isItem ? 'item_id' : 'table'; + var hideKey = isItem ? 'table' : 'item_id'; + h += '
'; + h += ''; h += '
'; - sec.fields.forEach(function(f) { - h += renderField(sec, f, data, idx); - }); + + h += '
' + + '.' + + '' + (isItem ? 'Item' : 'Table') + '' + + '
'; + + var showField = sec.fields.find(function(f) { return f[0] === showKey; }); + if (showField) { + h += renderField(sec, showField, data, idx); + } + + var weightField = sec.fields.find(function(f) { return f[0] === 'weight'; }); + var qtyField = sec.fields.find(function(f) { return f[0] === 'quantity'; }); + if (weightField) h += renderField(sec, weightField, data, idx); + if (qtyField) h += renderField(sec, qtyField, data, idx); + h += '
'; h += ''; h += '
'; }); - h += ''; + h += '
'; + h += ''; + h += ''; + h += '
'; return h; } @@ -130,6 +147,16 @@ function renderField(sec, f, data, idx) { return ced_renderField(sec, f, data, idx, null, null, cardPath, fieldID, getVal); } +function addDropRow(cardID, kind) { + var sec = DROP_SECTIONS.find(function(s) { return s.id === cardID; }); + if (!sec || !sec.isArray) return; + var arr = dropData[sec.path] || []; + var empty = { _type: (kind === 'table' ? 't' : 'i'), weight: 10, quantity: 0 }; + arr.push(empty); + dropData[sec.path] = arr; + renderCurrent(); +} + function toggleCard(id) { expandedCards[id] = expandedCards[id] === false ? true : false; renderCurrent(); @@ -140,19 +167,6 @@ function toggleCardWidth(id) { renderCurrent(); } -function addArrayItem(cardID) { - var sec = DROP_SECTIONS.find(function(s) { return s.id === cardID; }); - if (!sec || !sec.isArray) return; - var arr = dropData[sec.path] || []; - var empty = {}; - sec.fields.forEach(function(f) { - empty[f[0]] = f[2] === 'checkbox' ? false : (f[2] === 'number' ? 0 : ''); - }); - arr.push(empty); - dropData[sec.path] = arr; - renderCurrent(); -} - function removeArrayItem(cardID, idx) { var sec = DROP_SECTIONS.find(function(s) { return s.id === cardID; }); if (!sec || !sec.isArray) return; @@ -178,7 +192,12 @@ function saveDrop() { sec.fields.forEach(function(f) { var fid = fieldID(sec, f[0], idx); var el = document.getElementById(fid); - if (el) item[f[0]] = collectFieldValue(el, f[2]); + if (el) { + var val = collectFieldValue(el, f[2]); + if (val !== '' && val !== null && val !== undefined && val !== 0 && val !== false) { + item[f[0]] = val; + } + } }); if (Object.keys(item).length > 0) arr.push(item); }); @@ -246,6 +265,9 @@ function duplicateDrop() { delete copy._raw; delete copy._path; copy.id = newID; + if (copy.drops && Array.isArray(copy.drops)) { + copy.drops.forEach(function(e) { delete e._type; }); + } var dir = ''; if (dropData._path) { diff --git a/internal/validate/checks.go b/internal/validate/checks.go index f89e52d..bbcb820 100644 --- a/internal/validate/checks.go +++ b/internal/validate/checks.go @@ -2,6 +2,8 @@ package validate import ( "fmt" + "os" + "path/filepath" "sort" "strings" @@ -732,7 +734,24 @@ func validateDropTables(s Source) []Issue { }) continue } - for _, d := range dt.Drops { + + // Detect files that use "entries:" instead of "drops:" as the top-level list key. + // DropTableDef only reads "drops:", so "entries:" produces an empty list. + if len(dt.Drops) == 0 { + raw, rawErr := os.ReadFile(filepath.Join(s.DataDir, "drops", id+".yaml")) + if rawErr == nil { + content := string(raw) + if strings.Contains(content, "\nentries:") || strings.HasPrefix(content, "entries:") { + issues = append(issues, Issue{ + Level: "ERROR", + Type: "integrity", + Message: fmt.Sprintf("Drop table %q: uses key 'entries:' instead of 'drops:' — entries are not loaded; rename to 'drops:'", id), + }) + } + } + } + + for i, d := range dt.Drops { if d.ItemID != "" && !itemIDs[d.ItemID] { issues = append(issues, Issue{ Level: "ERROR", @@ -749,6 +768,57 @@ func validateDropTables(s Source) []Issue { id, d.Table), }) } + + if d.ItemID != "" && d.Table != "" { + issues = append(issues, Issue{ + Level: "WARN", + Type: "integrity", + Message: fmt.Sprintf("Drop table %q entry %d: both item_id and table set (only one is used per entry)", id, i+1), + }) + } + if d.ItemID == "" && d.Table == "" { + issues = append(issues, Issue{ + Level: "WARN", + Type: "integrity", + Message: fmt.Sprintf("Drop table %q entry %d: neither item_id nor table set (roll produces nothing)", id, i+1), + }) + } + + if d.Depletes { + issues = append(issues, Issue{ + Level: "WARN", + Type: "integrity", + Message: fmt.Sprintf("Drop table %q entry %d: 'depletes' is ignored on shared drop table entries; set it on the gather entry that references this table instead", id, i+1), + }) + } + if d.Level > 0 { + issues = append(issues, Issue{ + Level: "WARN", + Type: "integrity", + Message: fmt.Sprintf("Drop table %q entry %d: 'level' is ignored on shared drop table entries; set it on the gather entry that references this table", id, i+1), + }) + } + if d.XP > 0 { + issues = append(issues, Issue{ + Level: "WARN", + Type: "integrity", + Message: fmt.Sprintf("Drop table %q entry %d: 'xp' is ignored on shared drop table entries; set it on the gather entry that references this table", id, i+1), + }) + } + if d.Tool != "" { + issues = append(issues, Issue{ + Level: "WARN", + Type: "integrity", + Message: fmt.Sprintf("Drop table %q entry %d: 'tool' is ignored on shared drop table entries; set it on the gather entry that references this table", id, i+1), + }) + } + if d.SuccessMessage != "" { + issues = append(issues, Issue{ + Level: "WARN", + Type: "integrity", + Message: fmt.Sprintf("Drop table %q entry %d: 'success_message' is ignored on shared drop table entries; set it on the gather entry that references this table", id, i+1), + }) + } } } -- cgit v1.2.3