Repository navigation
Expand file tree
/
Copy pathbox.schema.json
More file actions
279 lines (279 loc) · 13 KB
/
Copy pathbox.schema.json
File metadata and controls
279 lines (279 loc) · 13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://csgobox.reclizer.com/schemas/box.schema.json",
"title": "CS2-Box Box Definition",
"description": "Schema for a CS2-Box crate / terminal definition (config/csbox/<id>.json). The file name (minus .json) becomes the box id. Terminal prices are NOT part of box files anymore — they live in the central price table config/csbox/_prices.json (see prices.schema.json); a leftover 'price' field is rejected by the runtime validator. Runtime validation in-game is authoritative; this schema is an authoring aid for IDE autocomplete / offline checks.",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Display name shown on the box item and GUI. May start with a '#RRGGBB ' color prefix (e.g. \"#FF5555 神化宝石箱\")."
},
"type": {
"type": "string",
"enum": ["csbox", "terminal"],
"description": "csbox = regular crate (default), terminal = terminal machine. Terminals must NOT declare a key field."
},
"key": {
"type": "string",
"description": "Key item id required to open. Use minecraft:air for a keyless box. Terminals forbid this field."
},
"drop": {
"type": "number",
"minimum": 0.0,
"maximum": 1.0,
"description": "Default entity drop chance (0.0-1.0)."
},
"random": {
"type": "array",
"minItems": 5,
"maxItems": 5,
"items": { "type": "integer", "minimum": 0, "maximum": 10000 },
"description": "Five grade weights ordered grade1(common)..grade5(rare). An explicit 0 keeps that tier out of the roll; absent slots use the default weight; negative values fall back to the default with an error; >10000 clamps."
},
"entity": {
"type": "array",
"items": {
"oneOf": [
{ "type": "string" },
{ "type": "number", "minimum": 0.0, "maximum": 1.0 }
]
},
"description": "Entity ids that drop this box, or alternating id/rate pairs."
},
"enabled": {
"type": "boolean",
"default": true,
"description": "v2.0.1: false skips this box entirely (no error)."
},
"requires": {
"type": "array",
"items": { "type": "string" },
"description": "v2.0.1: list of mod ids that must be loaded; the box is skipped with an error when any is missing."
},
"icon": {
"oneOf": [
{ "type": "string", "description": "Item-model id (26.x renders directly; other versions warn)" },
{ "type": "integer", "minimum": 0, "description": "CustomModelData value (pair with a resource pack)" }
],
"description": "v2.0.1: per-box icon override."
},
"discount": {
"type": "number",
"minimum": 0.0,
"maximum": 1.0,
"default": 0.0,
"description": "v2.0.1: terminal price discount (0..1 off), e.g. 0.2 = 20% off."
},
"stock": {
"type": "integer",
"minimum": -1,
"default": -1,
"description": "v2.0.1: terminal stock limit; -1 = unlimited."
},
"format_version": {
"type": "integer",
"minimum": 1,
"description": "v2.0.2: config schema version marker. Optional today (absent = legacy); write 2 for current files. Unknown top-level/item fields are reported by the runtime validator, so version bumps should add themselves here."
},
"restock_minutes": {
"type": "integer",
"deprecated": true,
"description": "Removed in 2.0.2 — accepted silently for legacy files (the runtime validator whitelists it without a warning), but it has no effect."
},
"max_per_player": {
"type": "integer",
"minimum": -1,
"default": -1,
"description": "v2.0.1: per-player open cap; -1 = unlimited (in-memory, resets on restart)."
},
"cooldown_seconds": {
"type": "integer",
"minimum": 0,
"default": 0,
"description": "v2.0.1: per-box open cooldown; 0 = none."
},
"permission": {
"type": "string",
"description": "v2.0.1: permission node checked against the PERMISSION_GATE hook (default allow-all)."
},
"pity": {
"type": "object",
"properties": {
"grade": {
"type": "string",
"description": "v2.0.1: the tier that must eventually drop; forces a roll at/above it. A legacy box uses one of consumer/industrial/mil_spec/restricted/classified; a custom \"grades\" box uses one of its configured tier ids."
},
"every": {
"type": "integer",
"minimum": 2,
"description": "v2.0.1: after every-1 consecutive opens below the target grade, the next open is forced to roll the target grade or higher. In-memory per player+box, resets on restart."
},
"first_open": {
"type": "boolean",
"default": false,
"description": "v2.x: also force the target grade on the player's first-ever open of this box (never-opened players count; in-memory, resets on restart)."
}
},
"required": ["grade", "every"],
"additionalProperties": false,
"description": "v2.0.1: pity (保底) policy. Invalid grade ids or every < 2 degrade to no pity (schema validator reports the mistake)."
},
"grade1": { "$ref": "#/$defs/grade" },
"grade2": { "$ref": "#/$defs/grade" },
"grade3": { "$ref": "#/$defs/grade" },
"grade4": { "$ref": "#/$defs/grade" },
"grade5": { "$ref": "#/$defs/grade" },
"sound": {
"type": "string",
"pattern": "^[a-z0-9_.-]+:[a-z0-9_./-]+$",
"description": "v2.x: custom open sound event id (e.g. minecraft:block.note_block.pling) played instead of the default open sound; unknown ids fall back to the default at play time."
},
"hide_odds": { "type": "boolean", "default": false, "description": "v2.x: hide all probability lines (tooltips/JEI/REI/EMI) — mystery box." },
"allow_bulk": { "type": "boolean", "default": true, "description": "v2.x: false disables Shift+right-click bulk opening for this box." },
"keys": { "type": "array", "items": { "type": "string" }, "description": "v2.x: additional accepted key item ids (any-of together with 'key'). Max 8." },
"wear": { "type": "array", "minItems": 2, "maxItems": 2, "items": { "type": "number", "minimum": 0, "maximum": 1 }, "description": "v2.x: [min, max] wear fraction for damageable items (default [0,1])." },
"bonus": { "type": "object", "properties": { "chance": { "type": "number", "minimum": 0, "maximum": 1 }, "mode": { "type": "string", "enum": ["double", "box"] } }, "description": "v2.x: chance-gated extra grant on single opens — duplicate the winner or an extra box of the same id." },
"announce_above": { "type": "string", "description": "v2.x: tier id or 1-based level; opens at/above it are broadcast server-wide." },
"available_from": { "type": "string", "description": "v2.x: ISO-8601 date-time; opens before it are rejected." },
"available_until": { "type": "string", "description": "v2.x: ISO-8601 date-time; opens after it are rejected." },
"open_cost": { "type": "integer", "minimum": 0, "default": 0, "description": "v2.x: Armory Points charged per open (creative exempt)." },
"negotiation": {
"type": "object",
"properties": {
"rounds": { "type": "integer", "minimum": 1, "maximum": 5, "description": "v2.x: terminal negotiation rounds (1..5, default 5)." },
"timeout_minutes": { "type": "integer", "minimum": 1, "description": "v2.x: negotiation countdown in minutes (default 180)." },
"price_bias": { "type": "number", "minimum": -0.9, "maximum": 9.0, "description": "v2.x: terminal offer price multiplier offset (0 = table price; -0.5 = half price; 1 = double)." }
},
"additionalProperties": false,
"description": "v2.x: terminal negotiation tuning; absent = built-in defaults. Server-side only."
},
"upgrade": {
"type": "object",
"properties": {
"target": { "type": "string", "description": "v2.x: box id this box upgrades into (must be a loaded definition at command time)." },
"consume": { "type": "integer", "minimum": 1, "default": 1, "description": "v2.x: copies of this box consumed per upgrade." }
},
"required": ["target", "consume"],
"additionalProperties": false,
"description": "v2.x: enables /csbox upgrade with the held box (all players, no OP)."
},
"grades": {
"type": "array",
"minItems": 1,
"maxItems": 64,
"items": { "$ref": "#/$defs/tier" },
"description": "v2.x: custom tier list, LOWEST tier first (position 1 = most common). Replaces random/grade1..5 entirely when present (those keys are then ignored and reported); absent = the default 5 legacy tiers. Each tier: id (unique, referenced by pity.grade), optional name (defaults to id) and color (#RRGGBB, defaults to white), optional weight (default 1, 0 = tier never rolls), items."
}
},
"$defs": {
"grade": {
"type": "array",
"items": { "$ref": "#/$defs/item" },
"description": "Items in this grade tier (grade1 lowest rarity .. grade5 highest)."
},
"tier": {
"type": "object",
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "Unique tier id; pity.grade references it and /csbox info prints it."
},
"name": {
"type": "string",
"description": "Display name shown in tooltips/JEI/the terminal; defaults to the id."
},
"color": {
"type": "string",
"pattern": "^#[0-9A-Fa-f]{6}$",
"description": "Tier color #RRGGBB; defaults to white."
},
"weight": {
"type": "integer",
"minimum": 0,
"maximum": 10000,
"default": 1,
"description": "Relative drop weight vs the other tiers; 0 = tier never rolls (stays listed at 0%)."
},
"items": {
"type": "array",
"items": { "$ref": "#/$defs/item" },
"description": "Items in this tier. An empty tier falls back to lower tiers when rolled."
},
"stock": {
"type": "integer",
"minimum": 0,
"description": "v2.x: per-tier terminal stock (custom grades only); -1/absent = unlimited. In-memory, resets on restart."
}
},
"required": ["id", "items"],
"additionalProperties": false
},
"item": {
"type": "object",
"description": "One item pool entry. Exactly one source: id, '#tag' or loot_table. Terminal prices come from the central _prices.json table, never from this object.",
"properties": {
"id": {
"type": "string",
"description": "Item registry id, e.g. minecraft:diamond_sword."
},
"tag": {
"type": "string",
"description": "Dual-purpose (matches runtime BoxItemCodec): a string starting with '#' is an item tag reference expanded at load time (e.g. '#minecraft:swords'); any other value is parsed as an SNBT string applied to the stack (e.g. '{GunId:\"tacz:modern_kinetics_gun_57\"}')."
},
"loot_table": {
"type": "string",
"description": "Loot table reference, e.g. minecraft:chests/simple_dungeon. Rolled at open time."
},
"count": {
"oneOf": [
{ "type": "integer", "minimum": 1 },
{ "type": "array", "minItems": 2, "maxItems": 2, "items": { "type": "integer", "minimum": 1 } }
],
"description": "Item count, or [min,max] rolled at open time (v2.0.1)."
},
"weight": {
"type": "integer",
"minimum": 0,
"default": 1,
"description": "v2.0.1: intra-grade weight; 0 disables the entry."
},
"enchant": {
"oneOf": [
{ "type": "boolean" },
{
"type": "object",
"properties": {
"id": { "type": "string", "description": "Enchantment id, e.g. minecraft:sharpness" },
"level": {
"oneOf": [
{ "type": "integer", "minimum": 1 },
{ "type": "array", "minItems": 2, "maxItems": 2, "items": { "type": "integer", "minimum": 1 } }
],
"description": "Fixed level or [min,max] range."
}
},
"additionalProperties": false
}
],
"description": "v2.0.1: random-enchant shortcut (true = any enchant, or {id, level})."
},
"price": {
"not": {},
"description": "REMOVED — do not use. Terminal prices are centrally managed in config/csbox/_prices.json (see prices.schema.json). A leftover price here is reported by the in-game validator; the item is treated as unpriced (terminal never sells it, recycler pays 0) until migrated."
},
"components": {
"type": "object",
"description": "Data components (1.21+/26.x). Ignored on 1.20.1."
}
},
"oneOf": [
{ "required": ["id"] },
{ "required": ["tag"] },
{ "required": ["loot_table"] }
]
}
},
"additionalProperties": false
}