Skip to content

Commit e5bae83

Browse files
committed
initial work towards script-based model loading
1 parent 06d31cb commit e5bae83

File tree

2 files changed

+205
-0
lines changed

2 files changed

+205
-0
lines changed

scripts/dmodels_loader.dsc

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
###########################
2+
# This file is part of dModels / Denizen Models.
3+
# Refer to the header of "dmodels_main.dsc" for more information.
4+
###########################
5+
6+
7+
dmodels_load_bbmodel:
8+
type: task
9+
debug: false
10+
definitions: model_name
11+
script:
12+
# =============== Prep ===============
13+
- define pack_root data/dmodels/res_pack
14+
- define models_root <[pack_root]>/assets/minecraft/models/item/dmodels/<[model_name]>
15+
- define textures_root <[pack_root]>/assets/minecraft/textures/dmodels/<[model_name]>
16+
- define override_item_filepath <[pack_root]>/assets/minecraft/models/item/<script[dmodels_config].data_key[item]>.json
17+
- define file data/dmodels/<[model_name]>.bbmodel
18+
- define scale_factor <element[2.285].div[4]>
19+
- define mc_texture_data <map>
20+
- flag server dmodels_data.temp_<[model_name]>:!
21+
# =============== BBModel loading and validation ===============
22+
- if !<server.has_file[<[file]>]>:
23+
- debug error "Cannot load model '<[model_name]>' because file '<[file]>' does not exist."
24+
- stop
25+
- ~fileread path:<[file]> save:filedata
26+
- define data <util.parse_yaml[<entry[filedata].data.utf8_decode||>]||>
27+
- if !<[data].is_truthy>:
28+
- debug error "Something went wrong trying to load BBModel data for model '<[model_name]>' - fileread invalid."
29+
- stop
30+
- define meta <[data.meta]||>
31+
- define resolution <[data.resolution]||>
32+
- if !<[meta].is_truthy> || !<[resolution].is_truthy>:
33+
- debug error "Something went wrong trying to load BBModel data for model '<[model_name]>' - possibly not a valid BBModel file?"
34+
- stop
35+
- if !<[data.elements].exists>:
36+
- debug error "Can't load bbmodel for '<[model_name]>' - file has no elements?"
37+
- stop
38+
# =============== Pack validation ===============
39+
- if !<server.has_flag[data/dmodels/res_pack/pack.mcmeta]>:
40+
- filewrite path:data/dmodels/res_pack/pack.mcmeta data:<map.with[pack].as[<map[pack_format=8;description=dModels_AutoPack_Default]>].to_json[native_types=true;indent=4].utf8_encode>
41+
# =============== Textures loading ===============
42+
- define tex_id 0
43+
- foreach <[data.textures]||<list>> as:texture:
44+
- define texname <[texture.name]>
45+
- if <[texname].ends_with[.png]>:
46+
- define texname <[texname].before[.png]>
47+
- define raw_source <[texture.source]||>
48+
- if !<[raw_source].starts_with[data:image/png;base64,]>:
49+
- debug error "Can't load bbmodel for '<[model_name]>': invalid texture source data."
50+
- stop
51+
- define texture_output_path <[textures_root]>/<[texname]>.png
52+
- ~filewrite path:<[texture_output_path]> data:<[raw_source].after[,].base64_to_binary>
53+
- define proper_path dmodels/<[model_name]>/<[texname]>
54+
- define mc_texture_data.<[tex_id]> <[proper_path]>
55+
- if <[texture.particle]||false>:
56+
- define mc_texture_data.particle <[proper_path]>
57+
- define tex_id:++
58+
# =============== Elements loading ===============
59+
- foreach <[data.elements]> as:element:
60+
- if <[element.type]> != cube:
61+
- foreach next
62+
- define element.origin <[element.origin].separated_by[,]||0,0,0>
63+
- define element.rotation <[element.rotation].separated_by[,]||0,0,0>
64+
- define flagname dmodels_data.model_<[model_name]>.namecounter_element.<[element.name]>
65+
- flag server <[flagname]>:++
66+
- if <server.flag[<[flagname]>]> > 1:
67+
- define element.name <[element.name]><server.flag[<[flagname]>]>
68+
- flag server dmodels_data.temp_<[model_name]>.raw_elements.<[element.uuid]>:<[element]>
69+
# =============== Outlines loading ===============
70+
- define root_outline null
71+
- foreach <[data.outliner]||<list>> as:outliner:
72+
- if <[outliner].matches_character_set[abcdef0123456789-]>:
73+
- if <[root_outline]> == null:
74+
- definemap root_outline name:__root__ origin:0,0,0 rotation:0,0,0 uuid:<util.random_uuid>
75+
- flag server dmodels_data.temp_<[model_name]>.raw_outlines.<[root_outline.uuid]>:<[root_outline]>
76+
- run dmodels_loader_addchild def.model_name:<[model_name]> def.parent:<[root_outline]> def.child:<[outliner]>
77+
- else:
78+
- define outliner.parent:none
79+
- run dmodels_loader_readoutline def.model_name:<[model_name]> def.outline:<[outliner]>
80+
# =============== Clear out pre-existing data ===============
81+
- flag server dmodels_data.model_<[model_name]>:!
82+
- flag server dmodels_data.animations_<[model_name]>:!
83+
# =============== Animations loading ===============
84+
- foreach <[data.animations]||<list>> as:animation:
85+
- narrate "TODO: Animation stuff <[animation.name]>"
86+
# TODO: Animation loading stuff
87+
# =============== Item model file generation ===============
88+
- if <server.has_flag[<[override_item_filepath]>]>:
89+
- ~fileread path:<[override_item_filepath]> save:override_item
90+
- define override_item_data <util.parse_yaml[<entry[override_item].utf8_decode>]>
91+
- else:
92+
- definemap override_item_data parent:minecraft:item/generated textures:<map[layer0=minecraft:item/leather_horse_armor]>
93+
- define overrides_changed false
94+
- foreach <server.flag[dmodels_data.temp_<[model_name]>.raw_outlines]> as:outline:
95+
- define outline_origin <location[<[outline.origin]>]>
96+
- define model_json.textures <[mc_texture_data]>
97+
- define model_json.elements <list>
98+
- define child_count 0
99+
#### Element building
100+
- foreach <server.flag[dmodels_data.temp_<[model_name]>.raw_elements]> as:element:
101+
- if <[outline.children].contains[<[element.uuid]>]||false>:
102+
- define child_count:++
103+
- define jsonelement.name <[element.name]>
104+
- define rot <location[<[element.rotation]>]>
105+
- define jsonelement.from <location[<[element.from].separated_by[,]>].sub[<[outline_origin]>].mul[<[scale_factor]>].xyz.split[,]>
106+
- define jsonelement.to <location[<[element.to].separated_by[,]>].sub[<[outline_origin]>].mul[<[scale_factor]>].xyz.split[,]>
107+
- define jsonelement.rotation.origin <location[<[element.origin]>].sub[<[outline_origin]>].mul[<[scale_factor]>].xyz.split[,]>
108+
- if <[rot].x> != 0:
109+
- define jsonelement.rotation.axis x
110+
- define jsonelement.rotation.angle <[rot].x>
111+
- else if <[rot].z> != 0:
112+
- define jsonelement.rotation.axis z
113+
- define jsonelement.rotation.angle <[rot].z>
114+
- else:
115+
- define jsonelement.rotation.axis y
116+
- define jsonelement.rotation.angle <[rot].y>
117+
- foreach <[element.faces]> key:faceid as:face:
118+
- define jsonelement.faces.<[faceid]> <[face].proc[dmodels_facefix].context[<[resolution]>]>
119+
- define model_json.elements:->:<[jsonelement]>
120+
- define outline.children:!
121+
- if <[child_count]> > 0:
122+
#### Item override building
123+
- definemap json_group name:<[outline.name]> color:0 children:<util.list_numbers[from=0;to=<[child_count]>]> origin:<[outline_origin].mul[<[scale_factor]>].xyz.split[,]>
124+
- define model_json.groups <list[<[json_group]>]>
125+
- define model_json.display.head.translation <list[32|25|32]>
126+
- define model_json.display.head.scale <list[4|4|4]>
127+
- define modelpath item/dmodels/<[model_name]>/<[outline.name]>
128+
- ~filewrite path:<[models_root]>/<[outline.name]>.json data:<[model_json].to_json[native_types=true;indent=4].utf8_encode>
129+
- define cmd 0
130+
- define min_cmd 1000
131+
- foreach <[override_item_data.overrides]||<list>> as:override:
132+
- if <[override.model]> == <[modelpath]>:
133+
- define cmd <[override.predicate.custom_model_data]>
134+
- define min_cmd <[min_cmd].max[<[override.predicate.custom_model_data].add[1]||1000>]>
135+
- if <[cmd]> == 0:
136+
- define cmd <[min_cmd]>
137+
- define override_item_data.overrides:->:<map[predicate=<map[custom_model_data=<[cmd]>]>].with[model].as[<[modelpath]>]>
138+
- define overrides_changed true
139+
- define outline.item <script[dmodels_config].data_key[item]>[custom_model_data=<[cmd]>]
140+
# This sets the actual live usage flag data
141+
- flag server dmodels_data.model_<[model_name]>.<[outline.uuid]>:<[outline]>
142+
- if <[overrides_changed]>:
143+
- ~filewrite path:<[override_item_filepath]> data:<[override_item_data].to_json[native_types=true;indent=4].utf8_encode>
144+
# Final clear of temp data
145+
- flag server dmodels_data.temp_<[model_name]>:!
146+
147+
dmodels_facefix:
148+
type: procedure
149+
debug: false
150+
definitions: facedata|resolution
151+
script:
152+
- define uv <[facedata.uv]>
153+
- define out.texture #<[facedata.texture]>
154+
- define mul_x <element[16].div[<[resolution.width]>]>
155+
- define mul_y <element[16].div[<[resolution.height]>]>
156+
- define out.uv <list[<[uv].get[1].mul[<[mul_x]>]>|<[uv].get[2].mul[<[mul_y]>]>|<[uv].get[3].mul[<[mul_x]>]>|<[uv].get[4].mul[<[mul_y]>]>]>
157+
- determine <[out]>
158+
159+
dmodels_loader_addchild:
160+
type: task
161+
debug: false
162+
definitions: model_name|parent|child
163+
script:
164+
- if <[child].matches_character_set[abcdef0123456789-]>:
165+
- define elementflag dmodels_data.temp_<[model_name]>.raw_elements.<[child]>
166+
- define element <server.flag[<[elementflag]>]||null>
167+
- if <[element]> == null:
168+
- stop
169+
- define valid_rots 0|22.5|45|-22.5|-45
170+
- define rot <location[<[element.rotation]>]>
171+
- define xz <[rot].x.equals[0].if_true[0].if_false[1]>
172+
- define yz <[rot].y.equals[0].if_true[0].if_false[1]>
173+
- define zz <[rot].z.equals[0].if_true[0].if_false[1]>
174+
- define count <[xz].add[<[yz]>].add[<[zz]>]>
175+
- if <[rot].x> in <[valid_rots]> && <[rot].y> in <[valid_rots]> && <[rot].z> in <[valid_rots]> && <[count]> < 2:
176+
- flag server dmodels_data.temp_<[model_name]>.raw_outlines.<[parent.uuid]>.children:->:<[child]>
177+
- else:
178+
- definemap new_outline name:<[parent.name]>_auto_<[element.name]> origin:<[element.origin]> rotation:<[element.rotation]> uuid:<util.random_uuid> parent:<[parent.uuid]> children:<list[<[child]>]>
179+
- flag server dmodels_data.temp_<[model_name]>.raw_outlines.<[new_outline.uuid]>:<[new_outline]>
180+
- flag server <[elementflag]>.rotation:0,0,0
181+
- flag server <[elementflag]>.origin:0,0,0
182+
- else:
183+
- define child.parent:<[parent.uuid]>
184+
- run dmodels_loader_readoutline def.model_name:<[model_name]> def.outline:<[child]>
185+
186+
dmodels_loader_readoutline:
187+
type: task
188+
debug: false
189+
definitions: model_name|outline
190+
script:
191+
- definemap new_outline name:<[outline.name]> uuid:<[outline.uuid]> origin:<[outline.origin].separated_by[,]||0,0,0> rotation:<[outline.rotation].separated_by[,]||0,0,0> parent:<[outline.parent]||none>
192+
- define flagname dmodels_data.model_<[model_name]>.namecounter_outline.<[outline.name]>
193+
- flag server <[flagname]>:++
194+
- if <server.flag[<[flagname]>]> > 1:
195+
- define new_outline.name <[new_outline.name]><server.flag[<[flagname]>]>
196+
- define raw_children <[outline.children]||<list>>
197+
- define outline.children:!
198+
- flag server dmodels_data.temp_<[model_name]>.raw_outlines.<[new_outline.uuid]>:<[new_outline]>
199+
- foreach <[raw_children]> as:child:
200+
- run dmodels_loader_addchild def.model_name:<[model_name]> def.parent:<[outline]> def.child:<[child]>

scripts/dmodels_main.dsc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
# Usage: Loads a model from source data by name into server memory (flags).
6565
# Input definitions:
6666
# model_name: The name of the model to load, must correspond to the relevant ".dmodel.yml" file.
67+
# This task should be ~waited for.
6768
# dmodels_spawn_model
6869
# Usage: Spawns a single instance of a model using real armor stand entities at a location.
6970
# Input definitions:
@@ -105,3 +106,7 @@ dmodels_config:
105106
# If set to 0, will use the server default for armor stands.
106107
# You can instead set to a value like 16 for only short range visibility, or 128 for super long range, or any other number.
107108
tracking_range: 0
109+
# You can choose which item is used to override for models.
110+
# Using a leather based item is recommended to allow for dynamically recoloring items.
111+
# Leather_Horse_Armor is ideal because other leather armors make noise when equipped.
112+
item: leather_horse_armor

0 commit comments

Comments
 (0)