~jadedctrl/gem-xwx-moe

~jadedctrl/gem-xwx-moe/gemujo_ludo/mods.niaj/fasado/subtitles/util.lua
 ..
0 --[[
1 Subtitles — adds subtitles to Minetest.
2
3 Copyright © 2022‒2023, Silver Sandstone <@SilverSandstone@craftodon.social>
4
5 Permission is hereby granted, free of charge, to any person obtaining a
6 copy of this software and associated documentation files (the "Software"),
7 to deal in the Software without restriction, including without limitation
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 and/or sell copies of the Software, and to permit persons to whom the
10 Software is furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included
13 in all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 DEALINGS IN THE SOFTWARE.
22 ]]
23
24
25 --- Generic utility functions.
26
27
28 local S = subtitles.S;
29
30
31 subtitles.util = {};
32
33
34 --- An enumerator of HUD directions.
35 subtitles.util.HUDDirection =
36 {
37 LEFT_TO_RIGHT = 0;
38 RIGHT_TO_LEFT = 1;
39 TOP_TO_BOTTOM = 2;
40 BOTTOM_TO_TOP = 3;
41 };
42
43 --- A bitfield of HUD text styles.
44 subtitles.util.TextStyle =
45 {
46 REGULAR = 0;
47 BOLD = 1;
48 ITALIC = 2;
49 MONOSPACE = 4;
50 };
51
52
53 local NODE_SOUND_DEFAULTS = {dig = '__group'};
54 local DIG_GROUPS = {'cracky', 'choppy', 'crumbly', 'snappy', 'fleshy', 'oddly_breakable_by_hand', 'dig_immediate'};
55
56
57 --- Returns the sound spec for a particular action on a node.
58 -- @param name The name of the node.
59 -- @param keys A key in the sounds table, such as 'dig' or 'footstep', or a list of such keys.
60 -- @return A SimpleSoundSpec or `nil`.
61 function subtitles.util.get_node_sound(name, keys)
62 if type(keys) == 'string' then
63 keys = {keys};
64 end;
65
66 local def = minetest.registered_nodes[name] or {};
67 local sounds = def.sounds or {};
68
69 for __, key in ipairs(keys) do
70 local sound = sounds[key] or NODE_SOUND_DEFAULTS[key];
71 if sound == '__group' then
72 sound = subtitles.util.get_dig_sound_for_groups(def.groups or {});
73 end;
74 if sound then
75 return sound;
76 end;
77 end;
78
79 return nil;
80 end;
81
82
83 --- Decides which sounds to use for a node with the specified groups.
84 -- @param groups A group table.
85 -- @return A SimpleSoundSpec or `nil`.
86 function subtitles.util.get_dig_sound_for_groups(groups)
87 local best_group = nil;
88 local best_score = 0;
89 for __, group in ipairs(DIG_GROUPS) do
90 local score = groups[group] or 0;
91 if score > best_score then
92 best_group = group;
93 best_score = score;
94 end;
95 end;
96
97 if best_score <= 0 or not best_group then
98 return nil;
99 end;
100
101 return {name = 'default_dig_' .. best_group, gain = 0.5};
102 end;
103
104
105 --- Describes how a player was damaged.
106 -- @param reason A damage reason table, as passed to on_player_hp_change callbacks.
107 -- @return A human-readabable description
108 function subtitles.util.describe_damage(reason)
109 if reason.type == 'fall' then
110 return S('Hits ground');
111 elseif reason.type == 'punch' then
112 return S('Punched');
113 elseif reason.type == 'drown' then
114 return S('Drowning');
115 else
116 return S('Person hurts');
117 end;
118 end;
119
120
121 --- Updates a table, overriding existing keys.
122 -- @param tbl The table to update.
123 -- @param ... Any number of additional tables to update from.
124 -- @return A reference to the original table.
125 function subtitles.util.update(tbl, ...)
126 for __, updates in ipairs{...} do
127 for key, value in pairs(updates) do
128 tbl[key] = value;
129 end;
130 end;
131 return tbl;
132 end;
133
134
135 --- Checks if a player or entity is moving at walking speed.
136 -- This function does not check if the object is on ground.
137 -- @param objref An ObjectRef.
138 -- @return true if the object is moving at walking speed.
139 function subtitles.util.object_is_walking(objref)
140 -- Check controls:
141 local controls = objref:get_player_control();
142 if controls.sneak then
143 return false;
144 elseif (not minetest.features.direct_velocity_on_players) and (controls.up or controls.down or controls.left or controls.right) then
145 return true;
146 end;
147
148 -- Check velocity:
149 local velocity = objref:get_velocity();
150 return velocity and vector.length(velocity) >= 0.99;
151 end;
152
153
154 --- Returns the position of an object's feet based on its collision box.
155 -- @param objref A player or entity.
156 -- @return An absolute position vector.
157 function subtitles.util.get_feet_pos(objref)
158 local pos = objref:get_pos();
159 local properties = objref:get_properties();
160 return vector.add(pos, vector.new(0, properties.collisionbox[2], 0));
161 end;
162
163
164 --- Updates a HUD, only settings attributes that have changed.
165 -- @param player A player ObjectRef.
166 -- @param hud_id The id of the HUD to update.
167 -- @param old_def The old HUD definition table.
168 -- @param new_def The new HUD definition table.
169 function subtitles.util.update_hud(player, hud_id, old_def, new_def)
170 local function _compare(old, new)
171 if type(new) == 'table' then
172 for key, value in pairs(new) do
173 if value ~= old[key] then
174 return false;
175 end;
176 end;
177 return true;
178 else
179 return old == new;
180 end;
181 end;
182
183 for key, value in pairs(new_def) do
184 if not _compare(value, old_def[key]) then
185 player:hud_change(hud_id, key, value);
186 end;
187 end;
188 end;
189
190
191 --- Clamps a number to within a specified range.
192 -- @param value The value to clamp.
193 -- @param min The lower bound.
194 -- @param max The upper bound.
195 -- @return min, max, or value.
196 function subtitles.util.clamp(value, min, max)
197 if value < min then
198 return min;
199 elseif value > max then
200 return max;
201 else
202 return value;
203 end;
204 end;
205
206
207 --- Reads a boolean value from metadata.
208 -- @param meta The MetaDataRef to read from.
209 -- @param key The name of the metadata entry to read.
210 -- @param default The default value. Not necessarily a boolean.
211 -- @return A boolean value or the default.
212 function subtitles.util.get_meta_bool(meta, key, default)
213 local value = meta:get_string(key):lower();
214 if value == 'true' then
215 return true;
216 elseif value == 'false' then
217 return false;
218 else
219 return default;
220 end;
221 end;
222
223
224 --- Writes a boolean value to metadata.
225 -- @param meta The MetaDataRef to write to.
226 -- @param key The name of the metadata entry to write.
227 -- @param value The boolean value to write.
228 function subtitles.util.set_meta_bool(meta, key, value)
229 meta:set_string(key, value and 'true' or 'false');
230 end;
231
232
233 --- Converts a colour from RGB to a number for HUDs.
234 -- @param red The red component, from 0 to 255.
235 -- @param green The green component, from 0 to 255.
236 -- @param blue The blue component, from 0 to 255.
237 -- @return An integer in the form 0xRRGGBB.
238 function subtitles.util.rgb_to_number(red, green, blue)
239 red = subtitles.util.clamp(math.floor(red), 0, 255);
240 green = subtitles.util.clamp(math.floor(green), 0, 255);
241 blue = subtitles.util.clamp(math.floor(blue), 0, 255);
242 return red * 65536 + green * 256 + blue;
243 end;