Comment: | we have always been at war with east minecraft |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | trunk |
Files: | files | file ages | folders |
SHA3-256: |
4732f8d454ad0b335f1bea1bc365f82e |
User & Date: | lexi on 2025-01-19 19:18:55 |
Other Links: | manifest | tags |
2025-01-19
| ||
19:18 | we have always been at war with east minecraft Leaf check-in: 4732f8d454 user: lexi tags: trunk | |
19:05 | add to lore, add weather data, etc check-in: caec179da9 user: lexi tags: trunk | |
Modified mods/starlit-building/init.lua from [cc61bb3736] to [33f1e7300a].
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 .. 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 ... 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 ... 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 ... 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
--[[ { part = { ['starlit_building:pipe'] = 'myMod:stage3'; }; tool = { ['starlit:screwdriver'] = 'myMod:otherThing_stage1'; ['starlit:saw'] = function(node, tool) minetest.replace_node(node, {name='myMod:stage1'}) minetest.drop_item(node, 'starlit_building:pipe') end; ['myMod:laserWrench'] = { allow = function(node, tool) ... end; handle = function(node, tool) ... end; }; }; } ]] ................................................................................ if e.fab then scmID = string.format('%s_schematic', id) rev = { sw = scmID; complexity = e.complexity or 1; } end minetest.register_craftitem(id, { short_description = e.name; description = starlit.ui.tooltip { title = e.name; desc = e.desc; props = props; }; stack_max = e.max or (e.mass and math.min(math.max(math.floor(500 / e.mass), 1), 500)) or 10; inventory_image = e.img; on_place = function(stack, luser, point) local node = minetest.get_node(point.under) local function tryBuild() local p = B.path[node.name] if not p then return nil end if (not p.part) or (not p.part[id]) then return nil end local n = p.part[id] local obj if type(n) == 'function' then ................................................................................ else obj = ItemStack(n) stack:take_item(1) end local pname = obj:get_name() local stg = B.stage.db[pname] node.name = pname minetest.swap_node(point.under, node) -- TODO make a noise if stg.onBuild then stg.onBuild(point.under, luser, stack) end return stack end ................................................................................ if not p then return nil end if type(p) == 'function' then p = p(stack, node, point) if p == nil then return nil end else stack:take_item(1) end minetest.rotate_and_place(ItemStack(p), luser, point, true) -- TODO make a noise return stack end return tryBuild() or tryBegin() or stack end; _starlit = { ................................................................................ local grp = e.groups and table.copy(e.groups) or {} grp.stage = 1 local meta = { stage = id; recover = e.recover; } for k,v in pairs(e.meta or {}) do meta[k] = v end minetest.register_node(id, { description = 'Construction'; drawtype = (e.box and 'nodebox') or (e.mesh and 'mesh') or 'regular'; paramtype = e.paramtype or (e.box or e.mesh or e.light) and 'light' or nil; paramtype2 = e.paramtype2 or 'none'; tiles = e.tex; |
| | | | | | | |
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 .. 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 ... 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 ... 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 ... 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
--[[ { part = { ['starlit_building:pipe'] = 'myMod:stage3'; }; tool = { ['starlit:screwdriver'] = 'myMod:otherThing_stage1'; ['starlit:saw'] = function(node, tool) core.replace_node(node, {name='myMod:stage1'}) core.drop_item(node, 'starlit_building:pipe') end; ['myMod:laserWrench'] = { allow = function(node, tool) ... end; handle = function(node, tool) ... end; }; }; } ]] ................................................................................ if e.fab then scmID = string.format('%s_schematic', id) rev = { sw = scmID; complexity = e.complexity or 1; } end core.register_craftitem(id, { short_description = e.name; description = starlit.ui.tooltip { title = e.name; desc = e.desc; props = props; }; stack_max = e.max or (e.mass and math.min(math.max(math.floor(500 / e.mass), 1), 500)) or 10; inventory_image = e.img; on_place = function(stack, luser, point) local node = core.get_node(point.under) local function tryBuild() local p = B.path[node.name] if not p then return nil end if (not p.part) or (not p.part[id]) then return nil end local n = p.part[id] local obj if type(n) == 'function' then ................................................................................ else obj = ItemStack(n) stack:take_item(1) end local pname = obj:get_name() local stg = B.stage.db[pname] node.name = pname core.swap_node(point.under, node) -- TODO make a noise if stg.onBuild then stg.onBuild(point.under, luser, stack) end return stack end ................................................................................ if not p then return nil end if type(p) == 'function' then p = p(stack, node, point) if p == nil then return nil end else stack:take_item(1) end core.rotate_and_place(ItemStack(p), luser, point, true) -- TODO make a noise return stack end return tryBuild() or tryBegin() or stack end; _starlit = { ................................................................................ local grp = e.groups and table.copy(e.groups) or {} grp.stage = 1 local meta = { stage = id; recover = e.recover; } for k,v in pairs(e.meta or {}) do meta[k] = v end core.register_node(id, { description = 'Construction'; drawtype = (e.box and 'nodebox') or (e.mesh and 'mesh') or 'regular'; paramtype = e.paramtype or (e.box or e.mesh or e.light) and 'light' or nil; paramtype2 = e.paramtype2 or 'none'; tiles = e.tex; |
Modified mods/starlit-eco/init.lua from [f0d21c2132] to [c892dab0f5].
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
{-0.100, 'starlit:clear'};
{ 0.300, 'starlit:cloudy'};
{ 0.600, 'starlit:precip'};
{ 0.850, 'starlit:storm'};
{ 0.900, 'starlit:tstorm'};
};
})
minetest.register_craftitem('starlit_eco:fiber', {
description = "Plant Fiber";
groups = {fiber = 1};
inventory_image = lib.image('starlit-eco-plant-fiber.png'):shift(lib.color(0,1,0)):render();
_starlit = {
recover_vary = function(rng, ctx)
return starlit.type.fab {
element = { carbon = rng:int(0,1) };
|
| |
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
{-0.100, 'starlit:clear'};
{ 0.300, 'starlit:cloudy'};
{ 0.600, 'starlit:precip'};
{ 0.850, 'starlit:storm'};
{ 0.900, 'starlit:tstorm'};
};
})
core.register_craftitem('starlit_eco:fiber', {
description = "Plant Fiber";
groups = {fiber = 1};
inventory_image = lib.image('starlit-eco-plant-fiber.png'):shift(lib.color(0,1,0)):render();
_starlit = {
recover_vary = function(rng, ctx)
return starlit.type.fab {
element = { carbon = rng:int(0,1) };
|
Modified mods/starlit-eco/trees.lua from [d43bf4970e] to [6da5b86eb1].
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 .. 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 ... 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 ... 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 ... 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 |
base.groups.wood = 1 base.groups.log = 1 base.groups.falling_node = 1 local live = table.copy(base) live.drop = id live.groups.alive = 1 minetest.register_node(id, base) minetest.register_node(id..'_live', live) end regLog('starlit_eco:lambent_pine_log', { description = 'Lambent Pine Log'; drawtype = 'normal'; tiles = { 'starlit-eco-tree-lambent-pine-trunk-top.png'; ................................................................................ starlit.item.seed.link('starlit_eco:lambent_pine_seed', { name = 'Lambent Pine Seed'; tex = lib.image('starlit-eco-plant-seeds.png'):shift{hue=150, sat=-.5, lum=.8}:render(); grow = {kind = 'tree', id = 'starlit_eco:lambent_pine'}; }) minetest.register_node('starlit_eco:lambent_pine_bulb', { description = 'Lambent Pine Bulb'; drawtype = 'nodebox'; connects_to = {'starlit_eco:lambent_pine_needles'}; node_box = { type = 'connected'; connect_top = { {-.1, .5, -.1, ................................................................................ groups = {plant=1, attached_node = 4}; tiles = { 'starlit-eco-tree-lambent-pine-bulb.png'; }; _starlit = woodProps{}; }) minetest.register_node('starlit_eco:lambent_pine_needles', { description = 'Lambent Pine Needles'; groups = {plant = 1;}; drop = ''; tiles = { 'starlit-eco-tree-lambent-pine-needles.png'; 'starlit-eco-tree-lambent-pine-needles.png'; }; ................................................................................ tiles = { 'starlit-eco-tree-starblossom-trunk-top.png'; 'starlit-eco-tree-starblossom-trunk.png'; }; _starlit = woodProps{}; }) minetest.register_node('starlit_eco:starblossom_leaves', { description = 'Starblossom Leaves'; groups = {plant = 1;}; drop = ''; tiles = { 'starlit-eco-tree-starblossom-leaves.png'; 'starlit-eco-tree-starblossom-leaves.png'; }; _starlit = leafProps{}; }); minetest.register_node('starlit_eco:starblossom_leaves_shine', { description = 'Shining Starblossom Leaves'; groups = {plant = 1;}; drop = ''; paramtype = 'light'; light_source = 4; tiles = { 'starlit-eco-tree-starblossom-leaves.png'; ................................................................................ fill_ratio = 0.001; y_min = 0, y_max = 512; }; }; }; } minetest.register_abm { label = "lambent pine fruiting"; nodenames = {'starlit_eco:lambent_pine_needles'}; neighbors = {'starlit_eco:lambent_pine_log_live'}; chance = 40; interval = 80; catch_up = true; action = function(pos, node) local po = pos:offset(0,-1,0) if minetest.get_node(po).name == "air" then minetest.add_node(po, {name='starlit_eco:lambent_pine_bulb'}) end end; } |
| | | | | | | | | |
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 .. 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 ... 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 ... 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 ... 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 |
base.groups.wood = 1 base.groups.log = 1 base.groups.falling_node = 1 local live = table.copy(base) live.drop = id live.groups.alive = 1 core.register_node(id, base) core.register_node(id..'_live', live) end regLog('starlit_eco:lambent_pine_log', { description = 'Lambent Pine Log'; drawtype = 'normal'; tiles = { 'starlit-eco-tree-lambent-pine-trunk-top.png'; ................................................................................ starlit.item.seed.link('starlit_eco:lambent_pine_seed', { name = 'Lambent Pine Seed'; tex = lib.image('starlit-eco-plant-seeds.png'):shift{hue=150, sat=-.5, lum=.8}:render(); grow = {kind = 'tree', id = 'starlit_eco:lambent_pine'}; }) core.register_node('starlit_eco:lambent_pine_bulb', { description = 'Lambent Pine Bulb'; drawtype = 'nodebox'; connects_to = {'starlit_eco:lambent_pine_needles'}; node_box = { type = 'connected'; connect_top = { {-.1, .5, -.1, ................................................................................ groups = {plant=1, attached_node = 4}; tiles = { 'starlit-eco-tree-lambent-pine-bulb.png'; }; _starlit = woodProps{}; }) core.register_node('starlit_eco:lambent_pine_needles', { description = 'Lambent Pine Needles'; groups = {plant = 1;}; drop = ''; tiles = { 'starlit-eco-tree-lambent-pine-needles.png'; 'starlit-eco-tree-lambent-pine-needles.png'; }; ................................................................................ tiles = { 'starlit-eco-tree-starblossom-trunk-top.png'; 'starlit-eco-tree-starblossom-trunk.png'; }; _starlit = woodProps{}; }) core.register_node('starlit_eco:starblossom_leaves', { description = 'Starblossom Leaves'; groups = {plant = 1;}; drop = ''; tiles = { 'starlit-eco-tree-starblossom-leaves.png'; 'starlit-eco-tree-starblossom-leaves.png'; }; _starlit = leafProps{}; }); core.register_node('starlit_eco:starblossom_leaves_shine', { description = 'Shining Starblossom Leaves'; groups = {plant = 1;}; drop = ''; paramtype = 'light'; light_source = 4; tiles = { 'starlit-eco-tree-starblossom-leaves.png'; ................................................................................ fill_ratio = 0.001; y_min = 0, y_max = 512; }; }; }; } core.register_abm { label = "lambent pine fruiting"; nodenames = {'starlit_eco:lambent_pine_needles'}; neighbors = {'starlit_eco:lambent_pine_log_live'}; chance = 40; interval = 80; catch_up = true; action = function(pos, node) local po = pos:offset(0,-1,0) if core.get_node(po).name == "air" then core.add_node(po, {name='starlit_eco:lambent_pine_bulb'}) end end; } |
Modified mods/starlit-electronics/init.lua from [668ccf7fa8] to [e24965a858].
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 ... 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 ... 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 ... 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 ... 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 ... 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 ... 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 |
return function(stack, ...) local function fail() error(string.format('object %q is not a %s', stack:get_name(), ty)) end if not stack or stack:is_empty() then fail() end if minetest.get_item_group(stack:get_name(), ty) == 0 then fail() end return fn(stack, stack:get_definition()._starlit[ty], stack:get_meta(), ...) end end ................................................................................ totalPower = E.battery.charge; initialPower = E.battery.capacity; dischargeRate = E.battery.dischargeRate; wasteHeat = function() return 0 end; }; starlit.item.battery.foreach('starlit_electronics:battery-gen', {}, function(id, def) minetest.register_tool(id, { short_description = def.name; groups = { battery = 1; dynamo = 1; electronic = 1; }; inventory_image = def.img or 'starlit-item-battery.png'; description = starlit.ui.tooltip { title = def.name; desc = def.desc; color = lib.color(0,.2,1); ................................................................................ ----------- -- chips -- ----------- E.sw = {} function E.sw.findSchematicFor(item) local id = ItemStack(item):get_name() local fm = minetest.registered_items[id]._starlit if not (fm and fm.reverseEngineer) then return nil end local id = fm.reverseEngineer.sw return id, starlit.item.sw.db[id] end E.chip = { file = {} } do local T,G = lib.marshal.t, lib.marshal.g ................................................................................ elseif file.kind == 'note' then local sz = 0x10 + #file.body.author for _, e in pairs(file.body.entries) do sz = sz + #e.title + #e.body + 0x10 -- header overhead end return sz elseif file.kind == 'research' then local re = assert(minetest.registered_items[file.body.itemId]._starlit.reverseEngineer) return starlit.item.sw.db[re.sw].size * file.body.progress elseif file.kind == 'sw' then return starlit.item.sw.db[file.body.pgmId].size elseif file.kind == 'genome' then return 0 -- TODO end end ................................................................................ end function E.chip.update(chip) chip:get_meta():set_string('description', E.chip.describe(chip)) end starlit.item.chip.foreach('starlit_electronics:chip-gen', {}, function(id, def) minetest.register_craftitem(id, { short_description = def.name; description = E.chip.describe(def, true); inventory_image = def.img or 'starlit-item-chip.png'; groups = {chip = 1}; _starlit = { fab = def.fab; chip = def; ................................................................................ compute = {name = 'Compute Chip', clockRate = 4e9, flash = 24e6, ram = 64e9, powerEfficiency = 1e9, size = 4}; data = {name = 'Data Chip', clockRate = 128e3, flash = 2e12, ram = 32e3, powerEfficiency = 1e6, size = 4}; lp = {name = 'Low-Power Chip', clockRate = 128e6, flash = 64e6, ram = 1e9, powerEfficiency = 1e11, size = 4}; carbon = {name = 'Carbon Chip', clockRate = 64e6, flash = 32e6, ram = 2e6, powerEfficiency = 2e10, size = 2, circ='carbon'}; } E.chip.tiers.foreach('starlit_electronics:genChips', {}, function(id, t) id = t.id or string.format('%s:chip_%s', minetest.get_current_modname(), id) local circMat = t.circ or 'silicon'; starlit.item.chip.link(id, { name = t.name; clockRate = t.clockRate; flash = t.flash; ram = t.ram; powerEfficiency = t.powerEfficiency; -- cycles per joule ................................................................................ pgm = {starlit.item.sw.db[pgm]} end sw = pgm else sw = {} for i, e in ipairs(chips) do if (not e:is_empty()) and minetest.get_item_group(e:get_name(), 'chip') ~= 0 then for fl, inode in E.chip.files(e) do if fl.kind == 'sw' then local s = starlit.item.sw.db[fl.body.pgmId] table.insert(sw, { sw = s, chip = e, chipSlot = i; file = fl, inode = inode; |
| | | | | | | |
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 ... 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 ... 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 ... 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 ... 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 ... 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 ... 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 |
return function(stack, ...) local function fail() error(string.format('object %q is not a %s', stack:get_name(), ty)) end if not stack or stack:is_empty() then fail() end if core.get_item_group(stack:get_name(), ty) == 0 then fail() end return fn(stack, stack:get_definition()._starlit[ty], stack:get_meta(), ...) end end ................................................................................ totalPower = E.battery.charge; initialPower = E.battery.capacity; dischargeRate = E.battery.dischargeRate; wasteHeat = function() return 0 end; }; starlit.item.battery.foreach('starlit_electronics:battery-gen', {}, function(id, def) core.register_tool(id, { short_description = def.name; groups = { battery = 1; dynamo = 1; electronic = 1; }; inventory_image = def.img or 'starlit-item-battery.png'; description = starlit.ui.tooltip { title = def.name; desc = def.desc; color = lib.color(0,.2,1); ................................................................................ ----------- -- chips -- ----------- E.sw = {} function E.sw.findSchematicFor(item) local id = ItemStack(item):get_name() local fm = core.registered_items[id]._starlit if not (fm and fm.reverseEngineer) then return nil end local id = fm.reverseEngineer.sw return id, starlit.item.sw.db[id] end E.chip = { file = {} } do local T,G = lib.marshal.t, lib.marshal.g ................................................................................ elseif file.kind == 'note' then local sz = 0x10 + #file.body.author for _, e in pairs(file.body.entries) do sz = sz + #e.title + #e.body + 0x10 -- header overhead end return sz elseif file.kind == 'research' then local re = assert(core.registered_items[file.body.itemId]._starlit.reverseEngineer) return starlit.item.sw.db[re.sw].size * file.body.progress elseif file.kind == 'sw' then return starlit.item.sw.db[file.body.pgmId].size elseif file.kind == 'genome' then return 0 -- TODO end end ................................................................................ end function E.chip.update(chip) chip:get_meta():set_string('description', E.chip.describe(chip)) end starlit.item.chip.foreach('starlit_electronics:chip-gen', {}, function(id, def) core.register_craftitem(id, { short_description = def.name; description = E.chip.describe(def, true); inventory_image = def.img or 'starlit-item-chip.png'; groups = {chip = 1}; _starlit = { fab = def.fab; chip = def; ................................................................................ compute = {name = 'Compute Chip', clockRate = 4e9, flash = 24e6, ram = 64e9, powerEfficiency = 1e9, size = 4}; data = {name = 'Data Chip', clockRate = 128e3, flash = 2e12, ram = 32e3, powerEfficiency = 1e6, size = 4}; lp = {name = 'Low-Power Chip', clockRate = 128e6, flash = 64e6, ram = 1e9, powerEfficiency = 1e11, size = 4}; carbon = {name = 'Carbon Chip', clockRate = 64e6, flash = 32e6, ram = 2e6, powerEfficiency = 2e10, size = 2, circ='carbon'}; } E.chip.tiers.foreach('starlit_electronics:genChips', {}, function(id, t) id = t.id or string.format('%s:chip_%s', core.get_current_modname(), id) local circMat = t.circ or 'silicon'; starlit.item.chip.link(id, { name = t.name; clockRate = t.clockRate; flash = t.flash; ram = t.ram; powerEfficiency = t.powerEfficiency; -- cycles per joule ................................................................................ pgm = {starlit.item.sw.db[pgm]} end sw = pgm else sw = {} for i, e in ipairs(chips) do if (not e:is_empty()) and core.get_item_group(e:get_name(), 'chip') ~= 0 then for fl, inode in E.chip.files(e) do if fl.kind == 'sw' then local s = starlit.item.sw.db[fl.body.pgmId] table.insert(sw, { sw = s, chip = e, chipSlot = i; file = fl, inode = inode; |
Modified mods/starlit-electronics/sw.lua from [1c1e9dd876] to [922972e287].
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 .. 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 .. 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 ... 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 |
return items, charges end return function(user, ctx) local function cleanup() user.action.prog.shred = nil if user.action.sfx.shred then minetest.sound_fade(user.action.sfx.shred, 1, 0) user.action.sfx.shred = nil end if user.action.fx.shred then user.action.fx.shred.abort() end end ................................................................................ cleanup() return false end local shredTime = 1.0 local soundPitch = 1.0 -- TODO local pdraw = prop.powerDraw or 0 if minetest.is_protected(what, user.entity:get_player_name()) then return end local node = minetest.get_node(what) local nd = minetest.registered_nodes[node.name] local elt, fab, vary if nd._starlit then fab = nd._starlit.recover or nd._starlit.fab vary = nd._starlit.recover_vary end if fab then if fab.flag then ................................................................................ if p < pdx then cleanup() return false elseif not user.action.prog.shred then cleanup() -- kill danglers -- begin user.action.prog.shred = 0 user.action.sfx.shred = minetest.sound_play('starlit-nano-shred', { object = user.entity; max_hear_distance = prop.range*2; loop = true; pitch = soundPitch; }) user.action.fx.shred = starlit.fx.nano.shred(user, what, prop, shredTime, node) else user.action.prog.shred = user.action.prog.shred + ctx.how.delta or 0 end --print('shred progress: ', user.action.prog.shred) if user.action.prog.shred >= shredTime then minetest.remove_node(what) minetest.check_for_falling(what) --print('shred complete') user:suitSound 'starlit-success' if fab then local vf = fab if vary then local rng = (starlit.world.seedbank+0xa891f62)[minetest.hash_node_position(what)] vf = vf + vary(rng, {}) end local items, charges = fabToItemsAndCharges(vf) for i, it in ipairs(items) do user:give(it) end -- TODO give gasses, liquids end cleanup() ................................................................................ run = function(user, ctx) end; --[[ bgProc = function(user, ctx, interval, runState) if runState.flags.compiled == true then return false end -- only so many nanides to go around runState.flags.compiled = true local time = minetest.get_gametime() local cyclesLeft = ctx.comp.cycles * interval for id, e in ipairs(ctx.file.body.conf) do if e.key == 'job' then local t = J.dec(e.value) local remove = false local r = starlit.item.sw.db[t.schematic] |
| | | | | | | | | |
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 .. 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 .. 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 ... 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 |
return items, charges end return function(user, ctx) local function cleanup() user.action.prog.shred = nil if user.action.sfx.shred then core.sound_fade(user.action.sfx.shred, 1, 0) user.action.sfx.shred = nil end if user.action.fx.shred then user.action.fx.shred.abort() end end ................................................................................ cleanup() return false end local shredTime = 1.0 local soundPitch = 1.0 -- TODO local pdraw = prop.powerDraw or 0 if core.is_protected(what, user.entity:get_player_name()) then return end local node = core.get_node(what) local nd = core.registered_nodes[node.name] local elt, fab, vary if nd._starlit then fab = nd._starlit.recover or nd._starlit.fab vary = nd._starlit.recover_vary end if fab then if fab.flag then ................................................................................ if p < pdx then cleanup() return false elseif not user.action.prog.shred then cleanup() -- kill danglers -- begin user.action.prog.shred = 0 user.action.sfx.shred = core.sound_play('starlit-nano-shred', { object = user.entity; max_hear_distance = prop.range*2; loop = true; pitch = soundPitch; }) user.action.fx.shred = starlit.fx.nano.shred(user, what, prop, shredTime, node) else user.action.prog.shred = user.action.prog.shred + ctx.how.delta or 0 end --print('shred progress: ', user.action.prog.shred) if user.action.prog.shred >= shredTime then core.remove_node(what) core.check_for_falling(what) --print('shred complete') user:suitSound 'starlit-success' if fab then local vf = fab if vary then local rng = (starlit.world.seedbank+0xa891f62)[core.hash_node_position(what)] vf = vf + vary(rng, {}) end local items, charges = fabToItemsAndCharges(vf) for i, it in ipairs(items) do user:give(it) end -- TODO give gasses, liquids end cleanup() ................................................................................ run = function(user, ctx) end; --[[ bgProc = function(user, ctx, interval, runState) if runState.flags.compiled == true then return false end -- only so many nanides to go around runState.flags.compiled = true local time = core.get_gametime() local cyclesLeft = ctx.comp.cycles * interval for id, e in ipairs(ctx.file.body.conf) do if e.key == 'job' then local t = J.dec(e.value) local remove = false local r = starlit.item.sw.db[t.schematic] |
Modified mods/starlit-material/init.lua from [158d4b1720] to [3f132c9f77].
1 2 3 4 5 6 7 8 9 10 11 12 13 |
local lib = starlit.mod.lib
local M = {
canisterSizes = lib.registry.mk 'starlit_material:canister-size';
}
M.canisterSizes.foreach('starlit_material:canister_link', {}, function(id, sz)
starlit.item.canister.link(minetest.get_current_modname() .. ':canister_' .. id, {
name = sz.name;
slots = sz.slots;
vol = sz.vol; -- too big for suit?
desc = sz.desc;
})
end)
M.canisterSizes.meld {
|
| |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
local lib = starlit.mod.lib
local M = {
canisterSizes = lib.registry.mk 'starlit_material:canister-size';
}
M.canisterSizes.foreach('starlit_material:canister_link', {}, function(id, sz)
starlit.item.canister.link(core.get_current_modname() .. ':canister_' .. id, {
name = sz.name;
slots = sz.slots;
vol = sz.vol; -- too big for suit?
desc = sz.desc;
})
end)
M.canisterSizes.meld {
|
Modified mods/starlit-tech/init.lua from [91056054d4] to [9e988e1fe2].
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 .. 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 ... 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 ... 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
local grp = { object = 1; attached_node = 1; } if def.group then for k,v in pairs(def.group((i/stages))) do grp[k]=v end end minetest.register_node(stID(i), { short_description = def.name; description = starlit.ui.tooltip { title = def.name; desc = def.desc; color = def.color; props = { {title = 'Burn Remaining', desc=lib.math.timespec(stageTimeout * i), affinity=i > (stages/2) and 'good' or 'bad'}; ................................................................................ }; tiles = def.tile((i/stages)); paramtype = 'light'; paramtype2 = 'wallmounted'; wallmounted_rotate_vertical = true; light_source = math.floor(lib.math.lerp(i/stages, 0, def.glow)); on_construct = i ~= 0 and function(pos) local t = minetest.get_node_timer(pos) t:start(stageTimeout) if def.ctor then def.ctor(pos, (i/stages)) end end or nil; on_destruct = def.dtor and function(pos) def.dtor(pos, (i/stages)) end or nil; on_timer = i ~= 0 and function(pos) local me = minetest.get_node(pos) minetest.swap_node(pos, {name=stID(i-1), param2=me.param2}) return i > 1 end or nil; _starlit = (function() local meta = { mass = def.mass; reverseEngineer = { complexity = 1; ................................................................................ radiate = function(rp, pos) return 15 * f end; }; } end; } minetest.register_node('starlit_tech:crate', { short_description = 'Crate'; description = starlit.ui.tooltip { title = 'Crate'; desc = 'A sturdy but lightweight aluminum storage crate.'; props = { {title='Mass', affinity='info', desc='100g'} }; }; drawtype = 'nodebox'; ................................................................................ time = { shred = 1; shredPower = 3; }; }; }; on_construct = function(pos) local m = minetest.get_meta(pos) local inv = m:get_inventory() inv:set_size('starlit:contents', 12) end; on_rightclick = function(pos, node, luser) if not luser then return end local user = starlit.activeUsers[luser:get_player_name()] user:openUI('starlit:box', 'index', { |
| | | | | | |
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 .. 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 ... 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 ... 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
local grp = { object = 1; attached_node = 1; } if def.group then for k,v in pairs(def.group((i/stages))) do grp[k]=v end end core.register_node(stID(i), { short_description = def.name; description = starlit.ui.tooltip { title = def.name; desc = def.desc; color = def.color; props = { {title = 'Burn Remaining', desc=lib.math.timespec(stageTimeout * i), affinity=i > (stages/2) and 'good' or 'bad'}; ................................................................................ }; tiles = def.tile((i/stages)); paramtype = 'light'; paramtype2 = 'wallmounted'; wallmounted_rotate_vertical = true; light_source = math.floor(lib.math.lerp(i/stages, 0, def.glow)); on_construct = i ~= 0 and function(pos) local t = core.get_node_timer(pos) t:start(stageTimeout) if def.ctor then def.ctor(pos, (i/stages)) end end or nil; on_destruct = def.dtor and function(pos) def.dtor(pos, (i/stages)) end or nil; on_timer = i ~= 0 and function(pos) local me = core.get_node(pos) core.swap_node(pos, {name=stID(i-1), param2=me.param2}) return i > 1 end or nil; _starlit = (function() local meta = { mass = def.mass; reverseEngineer = { complexity = 1; ................................................................................ radiate = function(rp, pos) return 15 * f end; }; } end; } core.register_node('starlit_tech:crate', { short_description = 'Crate'; description = starlit.ui.tooltip { title = 'Crate'; desc = 'A sturdy but lightweight aluminum storage crate.'; props = { {title='Mass', affinity='info', desc='100g'} }; }; drawtype = 'nodebox'; ................................................................................ time = { shred = 1; shredPower = 3; }; }; }; on_construct = function(pos) local m = core.get_meta(pos) local inv = m:get_inventory() inv:set_size('starlit:contents', 12) end; on_rightclick = function(pos, node, luser) if not luser then return end local user = starlit.activeUsers[luser:get_player_name()] user:openUI('starlit:box', 'index', { |
Modified mods/starlit/effect.lua from [9a580a99bf] to [ee92b6e11c].
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 ... 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 ... 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 ... 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 ... 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 ... 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 ... 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 ... 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 ... 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 |
elseif d.pos then -- find effects anchored here and people in range for id,effect in pairs(starlit.effect.active) do if not effect.anchor then goto skip end -- this intentionally excludes attached effects if ineffectrange(effect,d.pos,d.range) then effects[#effects+1] = {v=effect,i=id} end ::skip::end local ppl = minetest.get_objects_inside_radius(d.pos,d.range) if #targets == 0 then targets = ppl else for _,p in pairs(ppl) do targets[#targets+1] = p end end end -- iterate over targets to remove from any effect's influence for _,t in pairs(targets) do ................................................................................ if v == effect then starlit.effect.active[k] = nil break end end end end end starlit.effect.ensorcelled = function(player,effect) if type(player) == 'string' then player = minetest.get_player_by_name(player) end for _,s in pairs(starlit.effect.active) do if effect and (s.name ~= effect) then goto skip end for _,sub in pairs(s.subjects) do if sub.player == player then return s end end ::skip::end return false ................................................................................ end end until idx >= #starlit.effect.active end end -- when a new effect is created, we analyze it and make the appropriate calls -- to minetest.after to queue up the events. each job returned needs to be -- saved in 'jobs' so they can be canceled if the effect is disjoined. no polling -- necessary :D starlit.effect.cast = function(proto) local s = table.copy(proto) s.jobs = s.jobs or {} s.vfx = s.vfx or {} s.sfx = s.sfx or {} s.impacts = s.impacts or {} s.subjects = s.subjects or {} s.delay = s.delay or 0 s.visual = function(subj, def) s.vfx[#s.vfx + 1] = { handle = minetest.add_particlespawner(def); subject = subj; } end s.visual_caster = function(def) -- convenience function local d = table.copy(def) d.attached = s.caster s.visual(nil, d) ................................................................................ s.impacts[#s.impacts+1] = rec etbl[#etbl+1] = rec end return etbl end s.abort = function() for _,j in ipairs(s.jobs) do j:cancel() end for _,v in ipairs(s.vfx) do minetest.delete_particlespawner(v.handle) end for _,i in ipairs(s.sfx) do s.silence(i) end for _,i in ipairs(s.impacts) do i.effect:stop() end end s.release_subject = function(si) local t = s.subjects[si] for _,f in pairs(s.sfx) do if f.subject == t then s.silence(f) end end for _,f in pairs(s.impacts) do if f.subject == t then f.effect:stop() end end for _,f in pairs(s.vfx) do if f.subject == t then minetest.delete_particlespawner(f.handle) end end s.subjects[si] = nil end local interpret_timespec = function(when) if when == nil then return 0 end local t if type(when) == 'number' then t = s.duration * when ................................................................................ end if t then return math.min(s.duration,math.max(0,t)) end log.err('invalid timespec ' .. dump(when)) return 0 end s.queue = function(when,fn) local elapsed = s.starttime and minetest.get_server_uptime() - s.starttime or 0 local timepast = interpret_timespec(when) if not timepast then timepast = 0 end local timeleft = s.duration - timepast local howlong = (s.delay + timepast) - elapsed if howlong < 0 then log.err('cannot time-travel! queue() called with `when` specifying timepoint that has already passed') howlong = 0 end s.jobs[#s.jobs+1] = minetest.after(howlong, function() -- this is somewhat awkward. since we're using a non-polling approach, we -- need to find a way to account for a caster or subject walking into an -- existing antimagic field, or someone with an existing antimagic aura -- walking into range of the anchor. so every time a effect effect would -- take place, we first check to see if it's in range of something nasty if not s.disjunction and -- avoid self-disjunction ((s.caster and starlit.effect.probe(s.caster:get_pos()).disjunction) or ................................................................................ for _,sub in pairs(s.subjects) do addobj(sub.player,sub) end elseif spec.where == 'pos' then specs[#specs+1] = { spec = {pos = s.anchor} } else specs[#specs+1] = { spec = {pos = spec.where} } end for _,sp in pairs(specs) do sp.spec.gain = sp.spec.gain or spec.gain local so = { handle = minetest.sound_play(spec.sound, sp.spec, spec.ephemeral); ctl = spec; -- object = sp.obj; subject = sp.subject; } stbl[#stbl+1] = so s.sfx[#s.sfx+1] = so end ................................................................................ for _,snd in pairs(snds) do s.silence(snd) end end) end end) end s.silence = function(sound) if not sound.handle then return end if sound.ctl.fade == 0 then minetest.sound_stop(sound.handle) else minetest.sound_fade(sound.handle,sound.ctl.fade or 1,0) end end local startqueued, termqueued = false, false local myid = #starlit.effect.active+1 s.cancel = function() s.abort() starlit.effect.active[myid] = nil end ................................................................................ iteration = iteration; iterationcount = itercount; timeleft = timeleft; timeelapsed = s.duration - timeleft; lastreturn = lastreturn; } if nr ~= false and iteration < itercount then s.jobs[#s.jobs+1] = minetest.after(int.period, function() iterate(nr) end) end end if int.after then s.queue(int.after, iterate) else s.queue({whence=0, secs=s.period}, iterate) end ................................................................................ end end if s.sounds then for when,what in pairs(s.sounds) do s.play(when,what) end end starlit.effect.active[myid] = s if not termqueued then s.jobs[#s.jobs+1] = minetest.after(s.delay + s.duration, function() if s.terminate then s:terminate() end starlit.effect.active[myid] = nil end) end s.starttime = minetest.get_server_uptime() return s end minetest.register_on_dieplayer(function(player) starlit.effect.disjoin{target=player} end) |
| | | | | | | | | | | | | | | |
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 ... 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 ... 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 ... 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 ... 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 ... 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 ... 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 ... 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 ... 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 |
elseif d.pos then -- find effects anchored here and people in range for id,effect in pairs(starlit.effect.active) do if not effect.anchor then goto skip end -- this intentionally excludes attached effects if ineffectrange(effect,d.pos,d.range) then effects[#effects+1] = {v=effect,i=id} end ::skip::end local ppl = core.get_objects_inside_radius(d.pos,d.range) if #targets == 0 then targets = ppl else for _,p in pairs(ppl) do targets[#targets+1] = p end end end -- iterate over targets to remove from any effect's influence for _,t in pairs(targets) do ................................................................................ if v == effect then starlit.effect.active[k] = nil break end end end end end starlit.effect.ensorcelled = function(player,effect) if type(player) == 'string' then player = core.get_player_by_name(player) end for _,s in pairs(starlit.effect.active) do if effect and (s.name ~= effect) then goto skip end for _,sub in pairs(s.subjects) do if sub.player == player then return s end end ::skip::end return false ................................................................................ end end until idx >= #starlit.effect.active end end -- when a new effect is created, we analyze it and make the appropriate calls -- to core.after to queue up the events. each job returned needs to be -- saved in 'jobs' so they can be canceled if the effect is disjoined. no polling -- necessary :D starlit.effect.cast = function(proto) local s = table.copy(proto) s.jobs = s.jobs or {} s.vfx = s.vfx or {} s.sfx = s.sfx or {} s.impacts = s.impacts or {} s.subjects = s.subjects or {} s.delay = s.delay or 0 s.visual = function(subj, def) s.vfx[#s.vfx + 1] = { handle = core.add_particlespawner(def); subject = subj; } end s.visual_caster = function(def) -- convenience function local d = table.copy(def) d.attached = s.caster s.visual(nil, d) ................................................................................ s.impacts[#s.impacts+1] = rec etbl[#etbl+1] = rec end return etbl end s.abort = function() for _,j in ipairs(s.jobs) do j:cancel() end for _,v in ipairs(s.vfx) do core.delete_particlespawner(v.handle) end for _,i in ipairs(s.sfx) do s.silence(i) end for _,i in ipairs(s.impacts) do i.effect:stop() end end s.release_subject = function(si) local t = s.subjects[si] for _,f in pairs(s.sfx) do if f.subject == t then s.silence(f) end end for _,f in pairs(s.impacts) do if f.subject == t then f.effect:stop() end end for _,f in pairs(s.vfx) do if f.subject == t then core.delete_particlespawner(f.handle) end end s.subjects[si] = nil end local interpret_timespec = function(when) if when == nil then return 0 end local t if type(when) == 'number' then t = s.duration * when ................................................................................ end if t then return math.min(s.duration,math.max(0,t)) end log.err('invalid timespec ' .. dump(when)) return 0 end s.queue = function(when,fn) local elapsed = s.starttime and core.get_server_uptime() - s.starttime or 0 local timepast = interpret_timespec(when) if not timepast then timepast = 0 end local timeleft = s.duration - timepast local howlong = (s.delay + timepast) - elapsed if howlong < 0 then log.err('cannot time-travel! queue() called with `when` specifying timepoint that has already passed') howlong = 0 end s.jobs[#s.jobs+1] = core.after(howlong, function() -- this is somewhat awkward. since we're using a non-polling approach, we -- need to find a way to account for a caster or subject walking into an -- existing antimagic field, or someone with an existing antimagic aura -- walking into range of the anchor. so every time a effect effect would -- take place, we first check to see if it's in range of something nasty if not s.disjunction and -- avoid self-disjunction ((s.caster and starlit.effect.probe(s.caster:get_pos()).disjunction) or ................................................................................ for _,sub in pairs(s.subjects) do addobj(sub.player,sub) end elseif spec.where == 'pos' then specs[#specs+1] = { spec = {pos = s.anchor} } else specs[#specs+1] = { spec = {pos = spec.where} } end for _,sp in pairs(specs) do sp.spec.gain = sp.spec.gain or spec.gain local so = { handle = core.sound_play(spec.sound, sp.spec, spec.ephemeral); ctl = spec; -- object = sp.obj; subject = sp.subject; } stbl[#stbl+1] = so s.sfx[#s.sfx+1] = so end ................................................................................ for _,snd in pairs(snds) do s.silence(snd) end end) end end) end s.silence = function(sound) if not sound.handle then return end if sound.ctl.fade == 0 then core.sound_stop(sound.handle) else core.sound_fade(sound.handle,sound.ctl.fade or 1,0) end end local startqueued, termqueued = false, false local myid = #starlit.effect.active+1 s.cancel = function() s.abort() starlit.effect.active[myid] = nil end ................................................................................ iteration = iteration; iterationcount = itercount; timeleft = timeleft; timeelapsed = s.duration - timeleft; lastreturn = lastreturn; } if nr ~= false and iteration < itercount then s.jobs[#s.jobs+1] = core.after(int.period, function() iterate(nr) end) end end if int.after then s.queue(int.after, iterate) else s.queue({whence=0, secs=s.period}, iterate) end ................................................................................ end end if s.sounds then for when,what in pairs(s.sounds) do s.play(when,what) end end starlit.effect.active[myid] = s if not termqueued then s.jobs[#s.jobs+1] = core.after(s.delay + s.duration, function() if s.terminate then s:terminate() end starlit.effect.active[myid] = nil end) end s.starttime = core.get_server_uptime() return s end core.register_on_dieplayer(function(player) starlit.effect.disjoin{target=player} end) |
Modified mods/starlit/element.lua from [f0333e36f4] to [79d7647b1a].
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 .. 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 ... 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 ... 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 ... 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 ... 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
indsz, indsz, indsz, indsz, indicator); end end M.element.foreach('starlit:gen-forms', {}, function(id, m) local eltID = F('%s:element_%s', minetest.get_current_modname(), id) -- local eltName = F('Elemental %s', lib.str.capitalize(m.name)) local tt = function(t, d, g) return starlit.ui.tooltip { title = t, desc = d; color = lib.color(0.1,0.2,0.1); props = { {title = 'Mass', desc = lib.math.si('g', g), affinity='info'} ................................................................................ m.form = m.form or {} if not (m.gas or m.liquid) then local brickID = eltID .. '_brick' local brickName = F('%s Brick', lib.str.capitalize(m.name)) m.form.brick = brickID minetest.register_craftitem(brickID, { short_description = brickName; description = tt(brickName, F('A small brick of %s, ready to be worked by a matter compiler', m.name), 1); inventory_image = img(lib.image 'starlit-item-brick.png'); wield_image = lib.image 'starlit-item-brick.png':colorize(m.color):render(); stack_max = 500; groups = {element=1, brick=1}; _starlit = { ................................................................................ }; }; }); end --[[ local chunk = F('starlit-element-%s-powder.png', id); minetest.register_craftitem(eltID, { short_description = eltName; description = tt(eltName, F('A 1g chunk of elemental %s, ready to be worked by a cold matter compiler', m.name), 1); inventory_image = iblit(chunk); wield_image = powder; stack_max = 1000; -- 1kg groups = {element = 1, chunk = 1}; _starlit = { ................................................................................ end) M.metal.foreach('starlit:gen-forms', {}, function(id, m) if m.elemental then -- avoid multiple forms for same material m.form = M.element.db[m.elemental].form; else local baseID = F('%s:metal_%s_', minetest.get_current_modname(), id) local brickID = baseID .. 'brick' local brickName = F('%s Brick', lib.str.capitalize(m.name)) m.form = m.form or {} m.form.brick = brickID local tt = function(t, d, g) return starlit.ui.tooltip { title = t, desc = d; ................................................................................ end local iblit = mkEltIndicator(mcomp) local function img(s) return iblit(s:colorize(m.color):render()) end local mass = 1 minetest.register_craftitem(brickID, { short_description = brickName; description = tt(brickName, F('A small brick of %s, ready to be worked by a matter compiler', m.name), mass); inventory_image = img(lib.image('starlit-item-brick.png')); wield_image = lib.image 'starlit-item-brick.png':colorize(m.color):render(); groups = {metal = 1, brick = 1}; stack_max = 500; _starlit = { ................................................................................ color = lib.color(0.2,0.1,0.1); props = props; }; end starlit.item.canister = lib.registry.mk 'starlit:canister'; starlit.item.canister.foreach('starlit:item-gen', {}, function(id, c) minetest.register_craftitem(id, { short_description = c.name; description = canisterDesc(nil, c); inventory_image = c.image or 'starlit-item-element-canister.png'; groups = {canister = 1}; stack_max = 1; _starlit = { canister = c; |
| | | | | | |
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 .. 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 ... 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 ... 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 ... 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 ... 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
indsz, indsz, indsz, indsz, indicator); end end M.element.foreach('starlit:gen-forms', {}, function(id, m) local eltID = F('%s:element_%s', core.get_current_modname(), id) -- local eltName = F('Elemental %s', lib.str.capitalize(m.name)) local tt = function(t, d, g) return starlit.ui.tooltip { title = t, desc = d; color = lib.color(0.1,0.2,0.1); props = { {title = 'Mass', desc = lib.math.si('g', g), affinity='info'} ................................................................................ m.form = m.form or {} if not (m.gas or m.liquid) then local brickID = eltID .. '_brick' local brickName = F('%s Brick', lib.str.capitalize(m.name)) m.form.brick = brickID core.register_craftitem(brickID, { short_description = brickName; description = tt(brickName, F('A small brick of %s, ready to be worked by a matter compiler', m.name), 1); inventory_image = img(lib.image 'starlit-item-brick.png'); wield_image = lib.image 'starlit-item-brick.png':colorize(m.color):render(); stack_max = 500; groups = {element=1, brick=1}; _starlit = { ................................................................................ }; }; }); end --[[ local chunk = F('starlit-element-%s-powder.png', id); core.register_craftitem(eltID, { short_description = eltName; description = tt(eltName, F('A 1g chunk of elemental %s, ready to be worked by a cold matter compiler', m.name), 1); inventory_image = iblit(chunk); wield_image = powder; stack_max = 1000; -- 1kg groups = {element = 1, chunk = 1}; _starlit = { ................................................................................ end) M.metal.foreach('starlit:gen-forms', {}, function(id, m) if m.elemental then -- avoid multiple forms for same material m.form = M.element.db[m.elemental].form; else local baseID = F('%s:metal_%s_', core.get_current_modname(), id) local brickID = baseID .. 'brick' local brickName = F('%s Brick', lib.str.capitalize(m.name)) m.form = m.form or {} m.form.brick = brickID local tt = function(t, d, g) return starlit.ui.tooltip { title = t, desc = d; ................................................................................ end local iblit = mkEltIndicator(mcomp) local function img(s) return iblit(s:colorize(m.color):render()) end local mass = 1 core.register_craftitem(brickID, { short_description = brickName; description = tt(brickName, F('A small brick of %s, ready to be worked by a matter compiler', m.name), mass); inventory_image = img(lib.image('starlit-item-brick.png')); wield_image = lib.image 'starlit-item-brick.png':colorize(m.color):render(); groups = {metal = 1, brick = 1}; stack_max = 500; _starlit = { ................................................................................ color = lib.color(0.2,0.1,0.1); props = props; }; end starlit.item.canister = lib.registry.mk 'starlit:canister'; starlit.item.canister.foreach('starlit:item-gen', {}, function(id, c) core.register_craftitem(id, { short_description = c.name; description = canisterDesc(nil, c); inventory_image = c.image or 'starlit-item-element-canister.png'; groups = {canister = 1}; stack_max = 1; _starlit = { canister = c; |
Modified mods/starlit/fab.lua from [06631e46d8] to [7c2e295411].
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
};
-- crystal = {
-- op = fQuant;
-- };
item = {
name = {"item", "items"};
string = function(x, n)
local i = minetest.registered_items[x]
return tostring(n) .. 'x ' .. i.short_description
end;
image = function(x, n)
return ItemStack(x):get_definition().inventory_image
end;
inventory = function(x, n, stack)
x = ItemStack(x)
|
| |
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
};
-- crystal = {
-- op = fQuant;
-- };
item = {
name = {"item", "items"};
string = function(x, n)
local i = core.registered_items[x]
return tostring(n) .. 'x ' .. i.short_description
end;
image = function(x, n)
return ItemStack(x):get_definition().inventory_image
end;
inventory = function(x, n, stack)
x = ItemStack(x)
|
Modified mods/starlit/food.lua from [c58f501acb] to [09c96accb0].
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
..
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
desc = f.desc; props = props; color = f.color; }; end F.foreach('starlit:gen-food', {}, function(id, f) minetest.register_item(id, { type = f.itemType or 'none'; inventory_image = f.tex; short_description = f.name; description = foodTip(nil, f); on_use = function(st, luser) local user = starlit.activeUsers[luser:get_player_name()] st:take_item(1) ................................................................................ recover = f.recover; mass = f.mass; }; }) end) starlit.item.seed.foreach('starlit:gen-seed', {}, function(id, s) minetest.register_item(id, { type = 'none'; inventory_image = s.tex; short_description = s.name; description = starlit.ui.tooltip { title = s.name; color = s.color; desc = s.desc; |
|
|
|
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
..
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
desc = f.desc; props = props; color = f.color; }; end F.foreach('starlit:gen-food', {}, function(id, f) core.register_item(id, { type = f.itemType or 'none'; inventory_image = f.tex; short_description = f.name; description = foodTip(nil, f); on_use = function(st, luser) local user = starlit.activeUsers[luser:get_player_name()] st:take_item(1) ................................................................................ recover = f.recover; mass = f.mass; }; }) end) starlit.item.seed.foreach('starlit:gen-seed', {}, function(id, s) core.register_item(id, { type = 'none'; inventory_image = s.tex; short_description = s.name; description = starlit.ui.tooltip { title = s.name; color = s.color; desc = s.desc; |
Modified mods/starlit/init.lua from [277b90dbc5] to [ae90c8058c].
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 .. 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 .. 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 ... 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 ... 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 280 281 282 ... 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 ... 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 ... 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 ... 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 |
-- [ʞ] starlit/init.lua -- ~ lexi hale <lexi@hale.su> -- ? basic setup, game rules, terrain -- © EUPL v1.2 local T = minetest.get_translator 'starlit' -- TODO enforce latest engine version local mod = { -- subordinate mods register here lib = vtlib; -- vtlib should be accessed as starlit.mod.lib by starlit modules for the sake of proper encapsulation. vtlib should simply be a provider, not a hardcoded dependency } local lib = mod.lib starlit = { ident = minetest.get_current_modname(); mod = mod; translator = T; constant = { light = { --minetest units dim = 3; lamp = 7; bright = 10; brightest = 14; -- only sun and growlights }; heat = { -- celsius freezing = 0; ................................................................................ thermalConductivity = 0.05; -- κ }; rad = { }; phys = { --- HACK HACK HAAAAAAAAAAACK engineGravity = minetest.settings:get('movement_gravity') or 9.81 }; }; activeUsers = { -- map of username -> user object }; activeUI = { ................................................................................ -- standardized effects fx = {}; type = {}; world = { defaultScenario = 'starlit_scenario:imperialExpat'; seedbank = lib.math.seedbank(minetest.get_mapgen_setting 'seed'); mineral = lib.registry.mk 'starlit:mineral'; material = { -- raw materials element = lib.registry.mk 'starlit:element'; -- elements are automatically sorted into the following categories -- if they match. however, it's possible to have a metal/gas/liquid -- that *isn't* a pure element, so these need separate registries -- for alloys and mixtures like steel and water ................................................................................ }; jobs = {}; } -- TODO deal with core.DEFAULT_PHYSICS once it hits master starlit.cfgDir = minetest.get_worldpath() .. '/' .. starlit.ident local logger = function(module) local function argjoin(arg, nxt, ...) if arg and not nxt then return tostring(arg) end if not arg then return "(nil)" end return tostring(arg) .. ' ' .. argjoin(nxt, ...) end local lg = {} local setup = function(fn, lvl) lvl = lvl or fn local function emit(...) local call = (fn == 'fatal') and error or function(str) minetest.log(lvl, str) end if module then call(string.format('[%s :: %s] %s',starlit.ident,module,argjoin(...))) else call(string.format('[%s] %s',starlit.ident,argjoin(...))) end end lg[fn ] = function(...) emit(...) end lg[fn .. 'f'] = function(...) emit(string.format(...)) end -- convenience fn ................................................................................ end starlit.logger = logger local log = logger() function starlit.evaluate(name, ...) local path = minetest.get_modpath(minetest.get_current_modname()) local filename = string.format('%s/%s', path, name) log.info('loading', filename) local chunk, err = loadfile(filename, filename) if not chunk then error(err) end return chunk(...) end function starlit.include(name, ...) -- semantic variant used for loading modules return starlit.evaluate(name..'.lua', ...) end function starlit.region.radiator.scan(pos,node) local R = starlit.region local phash = minetest.hash_node_position(pos) if R.radiator.sources[phash] then return end -- already loaded node = node or minetest.get_node(pos) local def = minetest.registered_nodes[node.name] local cl = def._starlit and def._starlit.radiator if not cl then return nil end local min,max = cl.maxEffectArea and cl.maxEffectArea(pos) or nil if not min then assert(cl.radius, 'no radius callback for radiator') local r = cl.radius(pos) local vr = vector.new(r,r,r) min,max = pos-vr, pos+vr end local id = R.radiator.store:insert_area(min,max, minetest.pos_to_string(pos)) R.radiator.sources[phash] = id end function starlit.region.radiator.unload(pos) local R = starlit.region local phash = minetest.hash_node_position(pos) local id = R.radiator.sources[phash] R.radiator.store:remove_area(id) R.radiator.sources[phash] = nil end minetest.register_lbm { label = 'build radiator index'; name = 'starlit:loadradiatorboxes'; nodenames = {'group:radiator'}; run_at_every_load = true; action = function(pos, node, dt) starlit.region.radiator.scan(pos, node) end; ................................................................................ -- NOTE: temp emitter nodes are responsible for decaching themselves in their on_destruct cb } function starlit.startJob(id, interval, job) local lastRun local function start() starlit.jobs[id] = minetest.after(interval, function() local t = minetest.get_gametime() local d = lastRun and t - lastRun or nil lastRun = t local continue = job(d, interval) if continue == true or continue == nil then start() elseif continue ~= false then interval = continue ................................................................................ starlit.include 'element' starlit.include 'terrain' starlit.include 'interfaces' starlit.include 'compile' starlit.include 'suit' -- minetest.settings:set('movement_gravity', starlit.world.planet.gravity) -- ??? seriously??? -- THIS OVERRIDES THE GLOBAL SETTING *AND PERSISTS IT* WHAT IN THE SATANIC FUCK --------------- -- callbacks -- --------------- -- here we connect our types up to the minetest API local function userCB(fn) return function(luser, ...) local name = luser:get_player_name() local user = starlit.activeUsers[name] return fn(user, ...) end end minetest.register_on_joinplayer(function(luser, lastLogin) -- TODO check that necessary CSMs are installed local user = starlit.type.user(luser) if lastLogin == nil then user:onSignup() end user:onJoin() starlit.activeUsers[user.name] = user end) minetest.register_on_leaveplayer(function(luser) starlit.activeUsers[luser:get_player_name()]:onPart() end) minetest.register_on_player_receive_fields(function(luser, formid, fields) local name = luser:get_player_name() local user = starlit.activeUsers[name] if not user then return false end if formid == '' then -- main menu return starlit.ui.userMenuDispatch(user,fields) end local ui = starlit.interface.db[formid] ................................................................................ user:onRespond(ui, state, fields) if fields.quit then starlit.activeUI[name] = nil end return true end) minetest.register_on_respawnplayer(userCB(function(user) return user:onRespawn() end)) minetest.register_on_dieplayer(userCB(function(user, reason) return user:onDie(reason) end)) minetest.register_on_punchnode(function(pos,node,puncher,point) local user = starlit.activeUsers[puncher:get_player_name()] local oldTgt = user.action.tgt user.action.tgt = point if bit.band(user.action.bits, 0x80)==0 then user.action.bits = bit.bor(user.action.bits, 0x80) --user:trigger('primary', {state = 'init'}) else ................................................................................ user:trigger('retarget', {oldTgt = oldTgt}) end end -- sigh --[[ core.noneitemdef_default.on_place = function(...) if not triggerPower(...) then minetest.item_place(...) end end core.noneitemdef_default.on_use = function(...) triggerPower(...) end core.noneitemdef_default.on_secondary_use = function(...) triggerPower(...) end ]] minetest.register_item(":", { type = "none", wield_image = "wieldhand.png", wield_scale = {x=1,y=1,z=2.5}, on_secondary_use = function(...) triggerPower(...) end; -- on_use = function(...) print'base' end; after_use = function(i,u,n,p) if (u:is_player()) then triggerPower(i,u,p) end end; }) minetest.register_item("starlit:_hand_dig", { type = "none", wield_image = "wieldhand.png", wield_scale = {x=1,y=1,z=2.5}, tool_capabilities = { groupcaps = { object = {maxlevel=1, times = {.10,.20,.40}}; plant = {maxlevel=1, times = {.50}}; ................................................................................ -- sand, dirt, gravel looseClump = {maxlevel=1, times = {1.5, 2.5}}; }; } }) minetest.register_on_player_inventory_action(function(luser, act, inv, p) local name = luser:get_player_name() local user = starlit.activeUsers[name] -- allow UIs to update on UI changes local state = starlit.activeUI[name] if state then local ui = starlit.interface.db[state.form] ui:cb('onMoveItem', user, act, inv, p) end end) minetest.register_on_player_hpchange(function(luser, delta, cause) local user = starlit.activeUsers[luser:get_player_name()] if cause.type == 'fall' then delta = user:damageModifier('bluntForceTrauma', (delta * 50)) -- justification: a short fall can do around -- five points of damage, which is nearly 50% -- of the default hp_max. since we crank up -- hp by a factor of 50~40, damage should be -- cranked by similarly end return delta end, true) function minetest.handle_node_drops(pos, drops, digger) local function jitter(pos) local function r(x) return x+math.random(-0.01, 0.01) end return vector.new( r(pos.x), r(pos.y), r(pos.z) ) end for i, it in ipairs(drops) do if type(it) == 'string' then it = ItemStack(it) end if not it:is_empty() then local ent = minetest.add_item(jitter(pos), it) if ent ~= nil then -- avoid crash when dropping unknown item local dp = vector.new(0,0,0) if digger then dp = digger:get_pos() end local delta = dp - ent:get_pos() ent:add_velocity(vector.new(delta.x,0,delta.z)); end end end end -- TODO timer iterates live UI |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
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 .. 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 .. 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 ... 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 ... 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 280 281 282 ... 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 ... 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 ... 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 ... 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 |
-- [ʞ] starlit/init.lua -- ~ lexi hale <lexi@hale.su> -- ? basic setup, game rules, terrain -- © EUPL v1.2 local T = core.get_translator 'starlit' -- TODO enforce latest engine version local mod = { -- subordinate mods register here lib = vtlib; -- vtlib should be accessed as starlit.mod.lib by starlit modules for the sake of proper encapsulation. vtlib should simply be a provider, not a hardcoded dependency } local lib = mod.lib starlit = { ident = core.get_current_modname(); mod = mod; translator = T; constant = { light = { --luanti units dim = 3; lamp = 7; bright = 10; brightest = 14; -- only sun and growlights }; heat = { -- celsius freezing = 0; ................................................................................ thermalConductivity = 0.05; -- κ }; rad = { }; phys = { --- HACK HACK HAAAAAAAAAAACK engineGravity = core.settings:get('movement_gravity') or 9.81 }; }; activeUsers = { -- map of username -> user object }; activeUI = { ................................................................................ -- standardized effects fx = {}; type = {}; world = { defaultScenario = 'starlit_scenario:imperialExpat'; seedbank = lib.math.seedbank(core.get_mapgen_setting 'seed'); mineral = lib.registry.mk 'starlit:mineral'; material = { -- raw materials element = lib.registry.mk 'starlit:element'; -- elements are automatically sorted into the following categories -- if they match. however, it's possible to have a metal/gas/liquid -- that *isn't* a pure element, so these need separate registries -- for alloys and mixtures like steel and water ................................................................................ }; jobs = {}; } -- TODO deal with core.DEFAULT_PHYSICS once it hits master starlit.cfgDir = core.get_worldpath() .. '/' .. starlit.ident local logger = function(module) local function argjoin(arg, nxt, ...) if arg and not nxt then return tostring(arg) end if not arg then return "(nil)" end return tostring(arg) .. ' ' .. argjoin(nxt, ...) end local lg = {} local setup = function(fn, lvl) lvl = lvl or fn local function emit(...) local call = (fn == 'fatal') and error or function(str) core.log(lvl, str) end if module then call(string.format('[%s :: %s] %s',starlit.ident,module,argjoin(...))) else call(string.format('[%s] %s',starlit.ident,argjoin(...))) end end lg[fn ] = function(...) emit(...) end lg[fn .. 'f'] = function(...) emit(string.format(...)) end -- convenience fn ................................................................................ end starlit.logger = logger local log = logger() function starlit.evaluate(name, ...) local path = core.get_modpath(core.get_current_modname()) local filename = string.format('%s/%s', path, name) log.info('loading', filename) local chunk, err = loadfile(filename, filename) if not chunk then error(err) end return chunk(...) end function starlit.include(name, ...) -- semantic variant used for loading modules return starlit.evaluate(name..'.lua', ...) end function starlit.region.radiator.scan(pos,node) local R = starlit.region local phash = core.hash_node_position(pos) if R.radiator.sources[phash] then return end -- already loaded node = node or core.get_node(pos) local def = core.registered_nodes[node.name] local cl = def._starlit and def._starlit.radiator if not cl then return nil end local min,max = cl.maxEffectArea and cl.maxEffectArea(pos) or nil if not min then assert(cl.radius, 'no radius callback for radiator') local r = cl.radius(pos) local vr = vector.new(r,r,r) min,max = pos-vr, pos+vr end local id = R.radiator.store:insert_area(min,max, core.pos_to_string(pos)) R.radiator.sources[phash] = id end function starlit.region.radiator.unload(pos) local R = starlit.region local phash = core.hash_node_position(pos) local id = R.radiator.sources[phash] R.radiator.store:remove_area(id) R.radiator.sources[phash] = nil end core.register_lbm { label = 'build radiator index'; name = 'starlit:loadradiatorboxes'; nodenames = {'group:radiator'}; run_at_every_load = true; action = function(pos, node, dt) starlit.region.radiator.scan(pos, node) end; ................................................................................ -- NOTE: temp emitter nodes are responsible for decaching themselves in their on_destruct cb } function starlit.startJob(id, interval, job) local lastRun local function start() starlit.jobs[id] = core.after(interval, function() local t = core.get_gametime() local d = lastRun and t - lastRun or nil lastRun = t local continue = job(d, interval) if continue == true or continue == nil then start() elseif continue ~= false then interval = continue ................................................................................ starlit.include 'element' starlit.include 'terrain' starlit.include 'interfaces' starlit.include 'compile' starlit.include 'suit' -- core.settings:set('movement_gravity', starlit.world.planet.gravity) -- ??? seriously??? -- THIS OVERRIDES THE GLOBAL SETTING *AND PERSISTS IT* WHAT IN THE SATANIC FUCK --------------- -- callbacks -- --------------- -- here we connect our types up to the luanti API local function userCB(fn) return function(luser, ...) local name = luser:get_player_name() local user = starlit.activeUsers[name] return fn(user, ...) end end core.register_on_joinplayer(function(luser, lastLogin) -- TODO check that necessary CSMs are installed local user = starlit.type.user(luser) if lastLogin == nil then user:onSignup() end user:onJoin() starlit.activeUsers[user.name] = user end) core.register_on_leaveplayer(function(luser) starlit.activeUsers[luser:get_player_name()]:onPart() end) core.register_on_player_receive_fields(function(luser, formid, fields) local name = luser:get_player_name() local user = starlit.activeUsers[name] if not user then return false end if formid == '' then -- main menu return starlit.ui.userMenuDispatch(user,fields) end local ui = starlit.interface.db[formid] ................................................................................ user:onRespond(ui, state, fields) if fields.quit then starlit.activeUI[name] = nil end return true end) core.register_on_respawnplayer(userCB(function(user) return user:onRespawn() end)) core.register_on_dieplayer(userCB(function(user, reason) return user:onDie(reason) end)) core.register_on_punchnode(function(pos,node,puncher,point) local user = starlit.activeUsers[puncher:get_player_name()] local oldTgt = user.action.tgt user.action.tgt = point if bit.band(user.action.bits, 0x80)==0 then user.action.bits = bit.bor(user.action.bits, 0x80) --user:trigger('primary', {state = 'init'}) else ................................................................................ user:trigger('retarget', {oldTgt = oldTgt}) end end -- sigh --[[ core.noneitemdef_default.on_place = function(...) if not triggerPower(...) then core.item_place(...) end end core.noneitemdef_default.on_use = function(...) triggerPower(...) end core.noneitemdef_default.on_secondary_use = function(...) triggerPower(...) end ]] core.register_item(":", { type = "none", wield_image = "wieldhand.png", wield_scale = {x=1,y=1,z=2.5}, on_secondary_use = function(...) triggerPower(...) end; -- on_use = function(...) print'base' end; after_use = function(i,u,n,p) if (u:is_player()) then triggerPower(i,u,p) end end; }) core.register_item("starlit:_hand_dig", { type = "none", wield_image = "wieldhand.png", wield_scale = {x=1,y=1,z=2.5}, tool_capabilities = { groupcaps = { object = {maxlevel=1, times = {.10,.20,.40}}; plant = {maxlevel=1, times = {.50}}; ................................................................................ -- sand, dirt, gravel looseClump = {maxlevel=1, times = {1.5, 2.5}}; }; } }) core.register_on_player_inventory_action(function(luser, act, inv, p) local name = luser:get_player_name() local user = starlit.activeUsers[name] -- allow UIs to update on UI changes local state = starlit.activeUI[name] if state then local ui = starlit.interface.db[state.form] ui:cb('onMoveItem', user, act, inv, p) end end) core.register_on_player_hpchange(function(luser, delta, cause) local user = starlit.activeUsers[luser:get_player_name()] if cause.type == 'fall' then delta = user:damageModifier('bluntForceTrauma', (delta * 50)) -- justification: a short fall can do around -- five points of damage, which is nearly 50% -- of the default hp_max. since we crank up -- hp by a factor of 50~40, damage should be -- cranked by similarly end return delta end, true) function core.handle_node_drops(pos, drops, digger) local function jitter(pos) local function r(x) return x+math.random(-0.01, 0.01) end return vector.new( r(pos.x), r(pos.y), r(pos.z) ) end for i, it in ipairs(drops) do if type(it) == 'string' then it = ItemStack(it) end if not it:is_empty() then local ent = core.add_item(jitter(pos), it) if ent ~= nil then -- avoid crash when dropping unknown item local dp = vector.new(0,0,0) if digger then dp = digger:get_pos() end local delta = dp - ent:get_pos() ent:add_velocity(vector.new(delta.x,0,delta.z)); end end end end -- TODO timer iterates live UI |
Modified mods/starlit/interfaces.lua from [42263b381c] to [7199aa7738].
565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 |
if q.quit then
user:suitSound 'starlit-quit' -- TODO better sound
end
end;
render = function(state, user)
local body = {kind='vert', w=6; mode='hw', spacing=.5, padding=1 }
for i, l in ipairs(state.ctx.inv) do
local inv = minetest.get_meta(l.pos):get_inventory()
local w = l.w or 6
if l.label then
table.insert(body, {kind = 'hbar'; text = l.label, w=w+.5, h = .5})
end
table.insert(body, {kind = 'list';
w = w, h = inv:get_size(l.id)/w;
node = l.pos, inv = l.id;
|
| |
565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 |
if q.quit then
user:suitSound 'starlit-quit' -- TODO better sound
end
end;
render = function(state, user)
local body = {kind='vert', w=6; mode='hw', spacing=.5, padding=1 }
for i, l in ipairs(state.ctx.inv) do
local inv = core.get_meta(l.pos):get_inventory()
local w = l.w or 6
if l.label then
table.insert(body, {kind = 'hbar'; text = l.label, w=w+.5, h = .5})
end
table.insert(body, {kind = 'list';
w = w, h = inv:get_size(l.id)/w;
node = l.pos, inv = l.id;
|
Modified mods/starlit/species.lua from [e0959a01e2] to [236ca7459a].
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
end
elseif ctx.how.state == 'prog' then
local d = ctx.how.delta
local p = user.action.prog.sprint
-- is the player currently holding any of WASD
local isMoving = bit.band(0x0f, user.entity:get_player_control_bits()) ~= 0
if p and isMoving then
user.cooldownTimes.stamina = minetest.get_gametime()
p.cb = p.cb + cost*d
if p.cb >= 5 then
user:statDelta('stamina', -p.cb)
p.cb = 0
if user:effectiveStat 'stamina' < cost then halt() end
end
end
|
| |
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
end
elseif ctx.how.state == 'prog' then
local d = ctx.how.delta
local p = user.action.prog.sprint
-- is the player currently holding any of WASD
local isMoving = bit.band(0x0f, user.entity:get_player_control_bits()) ~= 0
if p and isMoving then
user.cooldownTimes.stamina = core.get_gametime()
p.cb = p.cb + cost*d
if p.cb >= 5 then
user:statDelta('stamina', -p.cb)
p.cb = 0
if user:effectiveStat 'stamina' < cost then halt() end
end
end
|
Modified mods/starlit/suit.lua from [963193f502] to [d40c92ebbb].
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 ... 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 ... 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 ... 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 |
end a.suit[name] = img end end end minetest.register_tool(id, { short_description = def.name; description = starlit.ui.tooltip { title = def.name; desc = def.desc; color = lib.color(.1, .7, 1); }; groups = { ................................................................................ }; starlit_suit_canisters = { suitSlot = true; itemClass = 'canister'; }; } minetest.register_allow_player_inventory_action(function(luser, act, inv, p) local user = starlit.activeUsers[luser:get_player_name()] local function grp(i,g) return minetest.get_item_group(i:get_name(), g) ~= 0 end local function checkBaseRestrictions(list) local restrictions = slotProps[list] if not restrictions then return nil, true end if restrictions.suitSlot then if user:naked() then return restrictions, false end end ................................................................................ return true end local function itemCanLeave(item, list) local rst, ok = checkBaseRestrictions(list) if not ok then return false end if rst == nil then return true end if minetest.get_item_group(item:get_name(), 'specialInventory') then end if rst.maintenanceNode then return false end return true end ................................................................................ if not itemFits(p.stack, p.listname) then return 0 end elseif act == 'take' then if not itemCanLeave(p.stack, p.listname) then return 0 end end return true end) minetest.register_on_player_inventory_action(function(luser, act, inv, p) local user = starlit.activeUsers[luser:get_player_name()] local function slotChange(slot,a,item) local s = slotProps[slot] if slot == 'starlit_suit' then user:updateSuit() if user:naked() then starlit.type.suit.purgeInventories(user.entity) |
| | | | | |
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 ... 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 ... 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 ... 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 |
end a.suit[name] = img end end end core.register_tool(id, { short_description = def.name; description = starlit.ui.tooltip { title = def.name; desc = def.desc; color = lib.color(.1, .7, 1); }; groups = { ................................................................................ }; starlit_suit_canisters = { suitSlot = true; itemClass = 'canister'; }; } core.register_allow_player_inventory_action(function(luser, act, inv, p) local user = starlit.activeUsers[luser:get_player_name()] local function grp(i,g) return core.get_item_group(i:get_name(), g) ~= 0 end local function checkBaseRestrictions(list) local restrictions = slotProps[list] if not restrictions then return nil, true end if restrictions.suitSlot then if user:naked() then return restrictions, false end end ................................................................................ return true end local function itemCanLeave(item, list) local rst, ok = checkBaseRestrictions(list) if not ok then return false end if rst == nil then return true end if core.get_item_group(item:get_name(), 'specialInventory') then end if rst.maintenanceNode then return false end return true end ................................................................................ if not itemFits(p.stack, p.listname) then return 0 end elseif act == 'take' then if not itemCanLeave(p.stack, p.listname) then return 0 end end return true end) core.register_on_player_inventory_action(function(luser, act, inv, p) local user = starlit.activeUsers[luser:get_player_name()] local function slotChange(slot,a,item) local s = slotProps[slot] if slot == 'starlit_suit' then user:updateSuit() if user:naked() then starlit.type.suit.purgeInventories(user.entity) |
Modified mods/starlit/terrain.lua from [eeb268d7fe] to [6e0c0d7cf5].
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 .. 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 ... 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 ... 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 ... 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 ... 303 304 305 306 307 308 309 310 311 312 313 |
max_items = 3; items = { {rarity = 2, items = {'starlit:soil_clump'}}; {rarity = 3, items = {'starlit:soil_clump'}}; {rarity = 4, items = {'starlit:soil_clump'}}; }; } minetest.register_node('starlit:soil', { description = T 'Soil'; tiles = {'starlit-terrain-soil.png'}; groups = {looseClump = 2, soil = 1}; drop = soilDrop; sounds = soilSounds; _starlit = { kind = 'block'; elements = {}; recover = soilRec; }; }) minetest.register_node('starlit:sand', { description = T 'Sand'; tiles = {'starlit-terrain-sand.png'}; groups = {looseClump = 1, sand = 1, falling_node = 1}; drop = ''; sounds = sandSounds; _starlit = { kind = 'block'; fab = starlit.type.fab { element = { silicon = 25 } }; }; }) minetest.register_node('starlit:lifesilt', { description = T 'Lifesilt'; tiles = {'starlit-terrain-lifesilt.png'}; groups = {looseClump = 1, lifesilt = 1, falling_node = 1}; drop = ''; sounds = sandSounds; _starlit = { kind = 'block'; recover = starlit.type.fab { element = { carbon = 16, silicon = 16, rubidium = 4 } }; }; }) minetest.register_craftitem('starlit:soil_clump', { short_description = T 'Soil'; description = starlit.ui.tooltip { title = T 'Soil'; desc = 'A handful of nutrient-packed soil, suitable for growing plants'; color = lib.color(0.3,0.2,0.1); }; inventory_image = 'starlit-item-soil.png'; groups = {looseClump = 2, soil = 1}; on_place = function(me, luser, point) if me:get_count() < 3 then return end if minetest.place_node(point.above, {name = 'starlit:soil'}, luser) then me:take_item(3) end return me end; _starlit = { recover = starlit.type.fab { element = { carbon = 25 / 4 } }; }; ................................................................................ items = { { items = {'starlit:soil'}, rarity = 2; tool_groups = { 'shovel', 'trowel' }; }; }; } minetest.register_node(def.name, { description = T 'Greengraze'; tiles = { def.img .. '.png'; 'starlit-terrain-soil.png'; { name = 'starlit-terrain-soil.png^' .. def.img ..'-overlay.png'; tileable_vertical = false; ................................................................................ desc = T 'Undergloam'; -- fungal carpet img = 'starlit-terrain-undergloam'; recover = soilRec; } for _, w in pairs {false,true} do minetest.register_node('starlit:liquid_water' .. (w and '_flowing' or ''), { description = T 'Water'; drawtype = 'liquid'; waving = 3; tiles = { { -- name = "default_water_source_animated.png"; name = "starlit-water.png"; ................................................................................ groups = {water = 3, liquid = 3}; }); end starlit.world.mineral.foreach('starlit:mineral-generate', {}, function(node,m) local grp = {mineral = 1} minetest.register_node(node, { short_description = m.name; description = starlit.ui.tooltip { title = m.name; desc = m.desc; color = m.tone; }; tiles = m.tiles or ................................................................................ }) if not m.excludeOre then local seed = 0 -- grp.ore = 1 for i = 1, #m.name do seed = seed*50 + string.byte(m.name, i) end minetest.register_ore { ore = node; ore_type = m.dist.kind; wherein = m.dist.among; clust_scarcity = m.dist.rare; clust_num_ores = m.dist.ores; clust_size = m.dist.clust; y_min = m.dist.height[1], y_max = m.dist.height[2]; ................................................................................ time = { shred = 3; }; cost = { shredPower = 3; }; }; }) -- map generation minetest.register_alias('mapgen_stone', 'starlit:mineral_feldspar') minetest.register_alias('mapgen_water_source', 'starlit:liquid_water') minetest.register_alias('mapgen_river_water_source', 'starlit:liquid_water') |
| | | | | | | | | | | | |
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 .. 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 ... 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 ... 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 ... 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 ... 303 304 305 306 307 308 309 310 311 312 313 |
max_items = 3; items = { {rarity = 2, items = {'starlit:soil_clump'}}; {rarity = 3, items = {'starlit:soil_clump'}}; {rarity = 4, items = {'starlit:soil_clump'}}; }; } core.register_node('starlit:soil', { description = T 'Soil'; tiles = {'starlit-terrain-soil.png'}; groups = {looseClump = 2, soil = 1}; drop = soilDrop; sounds = soilSounds; _starlit = { kind = 'block'; elements = {}; recover = soilRec; }; }) core.register_node('starlit:sand', { description = T 'Sand'; tiles = {'starlit-terrain-sand.png'}; groups = {looseClump = 1, sand = 1, falling_node = 1}; drop = ''; sounds = sandSounds; _starlit = { kind = 'block'; fab = starlit.type.fab { element = { silicon = 25 } }; }; }) core.register_node('starlit:lifesilt', { description = T 'Lifesilt'; tiles = {'starlit-terrain-lifesilt.png'}; groups = {looseClump = 1, lifesilt = 1, falling_node = 1}; drop = ''; sounds = sandSounds; _starlit = { kind = 'block'; recover = starlit.type.fab { element = { carbon = 16, silicon = 16, rubidium = 4 } }; }; }) core.register_craftitem('starlit:soil_clump', { short_description = T 'Soil'; description = starlit.ui.tooltip { title = T 'Soil'; desc = 'A handful of nutrient-packed soil, suitable for growing plants'; color = lib.color(0.3,0.2,0.1); }; inventory_image = 'starlit-item-soil.png'; groups = {looseClump = 2, soil = 1}; on_place = function(me, luser, point) if me:get_count() < 3 then return end if core.place_node(point.above, {name = 'starlit:soil'}, luser) then me:take_item(3) end return me end; _starlit = { recover = starlit.type.fab { element = { carbon = 25 / 4 } }; }; ................................................................................ items = { { items = {'starlit:soil'}, rarity = 2; tool_groups = { 'shovel', 'trowel' }; }; }; } core.register_node(def.name, { description = T 'Greengraze'; tiles = { def.img .. '.png'; 'starlit-terrain-soil.png'; { name = 'starlit-terrain-soil.png^' .. def.img ..'-overlay.png'; tileable_vertical = false; ................................................................................ desc = T 'Undergloam'; -- fungal carpet img = 'starlit-terrain-undergloam'; recover = soilRec; } for _, w in pairs {false,true} do core.register_node('starlit:liquid_water' .. (w and '_flowing' or ''), { description = T 'Water'; drawtype = 'liquid'; waving = 3; tiles = { { -- name = "default_water_source_animated.png"; name = "starlit-water.png"; ................................................................................ groups = {water = 3, liquid = 3}; }); end starlit.world.mineral.foreach('starlit:mineral-generate', {}, function(node,m) local grp = {mineral = 1} core.register_node(node, { short_description = m.name; description = starlit.ui.tooltip { title = m.name; desc = m.desc; color = m.tone; }; tiles = m.tiles or ................................................................................ }) if not m.excludeOre then local seed = 0 -- grp.ore = 1 for i = 1, #m.name do seed = seed*50 + string.byte(m.name, i) end core.register_ore { ore = node; ore_type = m.dist.kind; wherein = m.dist.among; clust_scarcity = m.dist.rare; clust_num_ores = m.dist.ores; clust_size = m.dist.clust; y_min = m.dist.height[1], y_max = m.dist.height[2]; ................................................................................ time = { shred = 3; }; cost = { shredPower = 3; }; }; }) -- map generation core.register_alias('mapgen_stone', 'starlit:mineral_feldspar') core.register_alias('mapgen_water_source', 'starlit:liquid_water') core.register_alias('mapgen_river_water_source', 'starlit:liquid_water') |
Modified mods/starlit/ui.lua from [01dfc2a3de] to [3ce8488360].
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
..
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
return state, created end; render = function(self, state, user) return self.pages[state.page].render(state, user) end; show = function(self, user) local state = self:begin(user) minetest.show_formspec(user.name, self.id,self:render(state, user)) end; open = function(self, user, page, ...) user:suitSound 'starlit-nav' self:begin(user, page, ...) self:show(user) end; close = function(self, user) local state = starlit.activeUI[user.name] if state and state.form == self.id then self:cb('onClose', user) starlit.activeUI[user.name] = nil minetest.close_formspec(user.name, self.id) end end; }; construct = function(p) if not p.id then error('UI missing id') end p.pages = p.pages or {} return p ................................................................................ hue = 260, sat = 0, lum = 0 }; } local lines = state.lines local cmod = string.format('^[hsl:%s:%s:%s', state.color.hue, state.color.sat*0xff, state.color.lum*0xff) local E = minetest.formspec_escape if state.padding/2 > state.x then state.x = state.padding/2 end if state.padding/2 > state.y then state.y = state.padding/2 end local function btnColorDef(sel) local function climg(state,img) local selstr if sel == nil then |
|
|
|
|
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
..
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
return state, created end; render = function(self, state, user) return self.pages[state.page].render(state, user) end; show = function(self, user) local state = self:begin(user) core.show_formspec(user.name, self.id,self:render(state, user)) end; open = function(self, user, page, ...) user:suitSound 'starlit-nav' self:begin(user, page, ...) self:show(user) end; close = function(self, user) local state = starlit.activeUI[user.name] if state and state.form == self.id then self:cb('onClose', user) starlit.activeUI[user.name] = nil core.close_formspec(user.name, self.id) end end; }; construct = function(p) if not p.id then error('UI missing id') end p.pages = p.pages or {} return p ................................................................................ hue = 260, sat = 0, lum = 0 }; } local lines = state.lines local cmod = string.format('^[hsl:%s:%s:%s', state.color.hue, state.color.sat*0xff, state.color.lum*0xff) local E = core.formspec_escape if state.padding/2 > state.x then state.x = state.padding/2 end if state.padding/2 > state.y then state.y = state.padding/2 end local function btnColorDef(sel) local function climg(state,img) local selstr if sel == nil then |
Modified mods/starlit/user.lua from [9accce5f34] to [1a0e392600].
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 .. 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 ... 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 ... 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 ... 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 ... 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 ... 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 ... 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 ... 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 .... 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 .... 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 .... 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 .... 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 .... 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 .... 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 .... 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 |
-- client. it provides for initial signup and join, -- managing the HUD, skinning the player model, -- effecting weather changes, etc. local lib = starlit.mod.lib local function hudAdjustBacklight(img) local night = math.abs(minetest.get_timeofday() - .5) * 2 local opacity = night*0.8 return img:fade(opacity) end local userStore = lib.marshal.metaStore { persona = { key = 'starlit:persona'; ................................................................................ starlit.type.user = lib.class { name = 'starlit:user'; leds = leds; construct = function(ident) local name, luser if type(ident) == 'string' then name = ident luser = minetest.get_player_by_name(name) else luser = ident name = luser:get_player_name() end return { entity = luser; name = name; ................................................................................ } end; __index = { -------------- -- overlays -- -------------- updateOverlays = function(self) -- minetest: because fuck you, that's why local engineGravity = starlit.constant.phys.engineGravity local targetGravity = starlit.world.planet.gravity local phys = { speed = self.pheno:trait('speed',1); jump = self.pheno:trait('jump',1); gravity = targetGravity / engineGravity; speed_climb = 1; ................................................................................ self.hud.elt.time = self:attachTextBox { name = 'time'; align = {x=0, y=1}; pos = {x=0.5, y=1}; ofs = {x=0,y=-95}; text = function(user) local cal = starlit.world.time.calendar[user.pref.calendar] return cal.time(minetest.get_timeofday()) end; } self.hud.elt.temp = self:attachMeter { name = 'temp'; align = {x=1, y=-1}; pos = {x=0, y=1}; ofs = {x=20, y=-20}; ................................................................................ updateHUD = function(self) for name, e in pairs(self.hud.elt) do if e.update then e.update() end end self:updateLEDs() end; updateLEDs = function(self) local time = minetest.get_gametime() local function updateSide(name, ofs, tx) local del = {} local idx = 0 for i, l in ipairs(self.hud.led[name]) do if time - l.origin > 3 then if l.elt then self.entity:hud_remove(l.elt.id) end self.hud.led.map[l.kind] = nil ................................................................................ inv:set_stack('hand', 1, hnd) end; --------------------- -- intel-gathering -- --------------------- clientInfo = function(self) return minetest.get_player_information(self.name) end; species = function(self) return starlit.world.species.index[self.persona.species] end; -- can the suit heater sustain its current internal temperature in an area of t°C tempCanSustain = function(self, t) if self:naked() then return false end ................................................................................ -- i feel like there has to be a better way local posrng = starlit.world.seedbank[0x13f19] -- TODO player-specific seed local cx = posrng:int(-500,500) --math.random(-500,500) local iter, startPoint = 1 repeat local temp = -100 local cz = posrng:int(-500,500) local cy = minetest.get_spawn_level(cx, cz) if cy then startPoint = vector.new(cx,cy,cz) temp = starlit.world.climate.eval(startPoint,.5,.5).surfaceTemp end iter = iter + 1 if iter > 100 then break end -- avoid infiniloop in pathological conditions until temp > -2 ................................................................................ onDie = function(self, reason) local inv = self.entity:get_inventory() local where = self.entity:get_pos() local function dropInv(lst) local l = inv:get_list(lst) for i, o in ipairs(l) do if o and not o:is_empty() then minetest.item_drop(o, self.entity, where) end end inv:set_list(lst, {}) end dropInv 'main' dropInv 'starlit_suit' self:updateSuit() ................................................................................ -- environment suit & body -- ----------------------------- suitStack = function(self) return self.entity:get_inventory():get_stack('starlit_suit', 1) end; suitSound = function(self, sfx) -- trigger a sound effect from the player's suit computer minetest.sound_play(sfx, {object=self.entity, max_hear_distance=4}, true) end; suitPowerStateSet = function(self, state, silent) -- necessary to enable reacting to power state changes -- e.g. to play sound effects, display warnings local os self:forSuit(function(s) os=s:powerState() ................................................................................ return true end return false end; alarm = function(self, urgency, kind, minFreq) minFreq = minFreq or 1.5 local time = minetest.get_gametime() local led = leds[kind] local ul = self.hud.led.map[kind] if ul then if time - ul.origin > minFreq then ul.origin = time else return end ................................................................................ --[[ freq = freq or 3 local urgencies = { [1] = {sound = 'starlit-alarm'}; [2] = {sound = 'starlit-alarm-urgent'}; } local gt = minetest.get_gametime() local urg = urgencies[urgency] or urgencies[#urgencies] if gt - self.cooldownTimes.alarm < freq then return end self.cooldownTimes.alarm = gt self:suitSound(urg.sound) ................................................................................ } elt.ofs.x = elt.ofs.x + where.ofs.x elt.ofs.y = elt.ofs.y + where.ofs.y local attached = self:attachImage(elt) table.insert(self.hud.alarm, attached) -- HATE. HATE. HAAAAAAAAAAATE minetest.after(freq/2, function() for k,v in pairs(self.hud.alarm) do self.entity:hud_remove(v.id) end self.hud.alarm={} end) end]] end; ................................................................................ --------------- -- inventory -- --------------- give = function(self, item) item = ItemStack(item) local inv = self.entity:get_inventory() local function is(grp) return minetest.get_item_group(item:get_name(), grp) ~= 0 end -- TODO notif popups if is 'specialInventory' then --[[ if is 'powder' then if self:naked() then return item end local cans = inv:get_list 'starlit_suit_canisters' ................................................................................ else return inv:add_item('main', item) end end; thrustUpon = function(self, item) local r = self:give(st) if not r:is_empty() then return minetest.add_item(self.entity:get_pos(), r) end end; consume = function(self, stack, n) n = n or 1 if n == 0 then n = stack:get_count() end local fd = stack:take_item(n) local stats = starlit.world.food.effectiveStats(fd) ................................................................................ u:statDelta('health', -5*biointerval) end if water == 0 then -- dying of thirst u:statDelta('health', -20*biointerval) end if sp < 1.0 and minetest.get_gametime() - u.cooldownTimes.stamina > 5.0 then u:statDelta('stamina', (u:phenoTrait('staminaRegen',1) * penaltyFromFatigue) / heatPenalty) -- print('stam', u:effectiveStat 'stamina', u:phenoTrait('staminaRegen',1) / heatPenalty, heatPenalty) end local morale, mp = u:effectiveStat 'morale' local pr = u:phenoTrait 'numinaRegen' u:statDelta('numina', pr * penaltyFromFatigue * mp) ................................................................................ manv = 0x020; snk = 0x040; dig = 0x080; put = 0x100; zoom = 0x200; } -- this is the painful part minetest.register_globalstep(function(delta) local doNothing,mustInit,mustHalt = 0,1,2 for id, user in pairs(starlit.activeUsers) do local ent = user.entity local bits = ent:get_player_control_bits() local function what(b) if bit.band(bits, b) ~= 0 and bit.band(user.action.bits, b) == 0 then |
| | | | | | | | | | | | | | | | |
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 .. 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 ... 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 ... 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 ... 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 ... 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 ... 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 ... 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 ... 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 .... 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 .... 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 .... 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 .... 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 .... 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 .... 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 .... 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 |
-- client. it provides for initial signup and join, -- managing the HUD, skinning the player model, -- effecting weather changes, etc. local lib = starlit.mod.lib local function hudAdjustBacklight(img) local night = math.abs(core.get_timeofday() - .5) * 2 local opacity = night*0.8 return img:fade(opacity) end local userStore = lib.marshal.metaStore { persona = { key = 'starlit:persona'; ................................................................................ starlit.type.user = lib.class { name = 'starlit:user'; leds = leds; construct = function(ident) local name, luser if type(ident) == 'string' then name = ident luser = core.get_player_by_name(name) else luser = ident name = luser:get_player_name() end return { entity = luser; name = name; ................................................................................ } end; __index = { -------------- -- overlays -- -------------- updateOverlays = function(self) -- luanti: because fuck you, that's why local engineGravity = starlit.constant.phys.engineGravity local targetGravity = starlit.world.planet.gravity local phys = { speed = self.pheno:trait('speed',1); jump = self.pheno:trait('jump',1); gravity = targetGravity / engineGravity; speed_climb = 1; ................................................................................ self.hud.elt.time = self:attachTextBox { name = 'time'; align = {x=0, y=1}; pos = {x=0.5, y=1}; ofs = {x=0,y=-95}; text = function(user) local cal = starlit.world.time.calendar[user.pref.calendar] return cal.time(core.get_timeofday()) end; } self.hud.elt.temp = self:attachMeter { name = 'temp'; align = {x=1, y=-1}; pos = {x=0, y=1}; ofs = {x=20, y=-20}; ................................................................................ updateHUD = function(self) for name, e in pairs(self.hud.elt) do if e.update then e.update() end end self:updateLEDs() end; updateLEDs = function(self) local time = core.get_gametime() local function updateSide(name, ofs, tx) local del = {} local idx = 0 for i, l in ipairs(self.hud.led[name]) do if time - l.origin > 3 then if l.elt then self.entity:hud_remove(l.elt.id) end self.hud.led.map[l.kind] = nil ................................................................................ inv:set_stack('hand', 1, hnd) end; --------------------- -- intel-gathering -- --------------------- clientInfo = function(self) return core.get_player_information(self.name) end; species = function(self) return starlit.world.species.index[self.persona.species] end; -- can the suit heater sustain its current internal temperature in an area of t°C tempCanSustain = function(self, t) if self:naked() then return false end ................................................................................ -- i feel like there has to be a better way local posrng = starlit.world.seedbank[0x13f19] -- TODO player-specific seed local cx = posrng:int(-500,500) --math.random(-500,500) local iter, startPoint = 1 repeat local temp = -100 local cz = posrng:int(-500,500) local cy = core.get_spawn_level(cx, cz) if cy then startPoint = vector.new(cx,cy,cz) temp = starlit.world.climate.eval(startPoint,.5,.5).surfaceTemp end iter = iter + 1 if iter > 100 then break end -- avoid infiniloop in pathological conditions until temp > -2 ................................................................................ onDie = function(self, reason) local inv = self.entity:get_inventory() local where = self.entity:get_pos() local function dropInv(lst) local l = inv:get_list(lst) for i, o in ipairs(l) do if o and not o:is_empty() then core.item_drop(o, self.entity, where) end end inv:set_list(lst, {}) end dropInv 'main' dropInv 'starlit_suit' self:updateSuit() ................................................................................ -- environment suit & body -- ----------------------------- suitStack = function(self) return self.entity:get_inventory():get_stack('starlit_suit', 1) end; suitSound = function(self, sfx) -- trigger a sound effect from the player's suit computer core.sound_play(sfx, {object=self.entity, max_hear_distance=4}, true) end; suitPowerStateSet = function(self, state, silent) -- necessary to enable reacting to power state changes -- e.g. to play sound effects, display warnings local os self:forSuit(function(s) os=s:powerState() ................................................................................ return true end return false end; alarm = function(self, urgency, kind, minFreq) minFreq = minFreq or 1.5 local time = core.get_gametime() local led = leds[kind] local ul = self.hud.led.map[kind] if ul then if time - ul.origin > minFreq then ul.origin = time else return end ................................................................................ --[[ freq = freq or 3 local urgencies = { [1] = {sound = 'starlit-alarm'}; [2] = {sound = 'starlit-alarm-urgent'}; } local gt = core.get_gametime() local urg = urgencies[urgency] or urgencies[#urgencies] if gt - self.cooldownTimes.alarm < freq then return end self.cooldownTimes.alarm = gt self:suitSound(urg.sound) ................................................................................ } elt.ofs.x = elt.ofs.x + where.ofs.x elt.ofs.y = elt.ofs.y + where.ofs.y local attached = self:attachImage(elt) table.insert(self.hud.alarm, attached) -- HATE. HATE. HAAAAAAAAAAATE core.after(freq/2, function() for k,v in pairs(self.hud.alarm) do self.entity:hud_remove(v.id) end self.hud.alarm={} end) end]] end; ................................................................................ --------------- -- inventory -- --------------- give = function(self, item) item = ItemStack(item) local inv = self.entity:get_inventory() local function is(grp) return core.get_item_group(item:get_name(), grp) ~= 0 end -- TODO notif popups if is 'specialInventory' then --[[ if is 'powder' then if self:naked() then return item end local cans = inv:get_list 'starlit_suit_canisters' ................................................................................ else return inv:add_item('main', item) end end; thrustUpon = function(self, item) local r = self:give(st) if not r:is_empty() then return core.add_item(self.entity:get_pos(), r) end end; consume = function(self, stack, n) n = n or 1 if n == 0 then n = stack:get_count() end local fd = stack:take_item(n) local stats = starlit.world.food.effectiveStats(fd) ................................................................................ u:statDelta('health', -5*biointerval) end if water == 0 then -- dying of thirst u:statDelta('health', -20*biointerval) end if sp < 1.0 and core.get_gametime() - u.cooldownTimes.stamina > 5.0 then u:statDelta('stamina', (u:phenoTrait('staminaRegen',1) * penaltyFromFatigue) / heatPenalty) -- print('stam', u:effectiveStat 'stamina', u:phenoTrait('staminaRegen',1) / heatPenalty, heatPenalty) end local morale, mp = u:effectiveStat 'morale' local pr = u:phenoTrait 'numinaRegen' u:statDelta('numina', pr * penaltyFromFatigue * mp) ................................................................................ manv = 0x020; snk = 0x040; dig = 0x080; put = 0x100; zoom = 0x200; } -- this is the painful part core.register_globalstep(function(delta) local doNothing,mustInit,mustHalt = 0,1,2 for id, user in pairs(starlit.activeUsers) do local ent = user.entity local bits = ent:get_player_control_bits() local function what(b) if bit.band(bits, b) ~= 0 and bit.band(user.action.bits, b) == 0 then |
Modified mods/starlit/world.lua from [de51a702a5] to [e94ad91b55].
1 2 3 4 5 6 7 8 9 10 11 12 .. 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 .. 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 .. 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 ... 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 ... 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 ... 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 ... 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 |
local lib = starlit.mod.lib local world = starlit.world function world.date() local days = minetest.get_day_count() local year = math.floor(days / world.planet.orbit); local day = days % world.planet.orbit; return { year = year, day = day; season = day / world.planet.orbit + 0.5; -- begin summer } end ................................................................................ local heatRange = {min = -50, max = 50} -- translate mt temps into real temps -- this function provides the basis for temperature calculation, -- which is performed by adding this value to the ambient temperature, -- determined by querying nearby group:heatSource items in accordance -- with the inverse-square law function world.climate.eval(pos, tod, season) local data = minetest.get_biome_data(pos) local biome = world.ecology.biomes.db[minetest.get_biome_name(data.biome)] -- print('climate:', dump(data)) local heat, humid = data.heat, data.humidity heat = lerp(heat/100, heatRange.min, heatRange.max) tod = tod or minetest.get_timeofday() heat = lerp(math.abs(tod - 0.5)*2, heat, heat + biome.nightTempDelta) -- print('base heat', heat) local td = world.date() heat = heat + gradient(biome.seasonalTemp, season or td.season) -- print('seasonal heat', heat) if pos.y > 0 then ................................................................................ local vdsq = lib.math.vdsq function world.climate.temp(pos, timeshift) --> irradiance at pos in W local cl = world.climate.eval(pos) local radCenters = starlit.region.radiator.store:get_areas_for_pos(pos, false, true) local irradiance = 0 for _,e in pairs(radCenters) do local rpos = minetest.string_to_pos(e.data) local rdef = assert(minetest.registered_nodes[assert(minetest.get_node(rpos)).name]) local rc = rdef._starlit.radiator local r_max = rc.radius(rpos) local dist_sq = vdsq(rpos,pos) if dist_sq <= r_max^2 then -- cheap bad way -- if minetest.line_of_sight(rpos,pos) then -- -- expensive way local obstruct = 0 local ray = Raycast(rpos, pos, true, true) for p in ray do if p.type == 'node' then obstruct = obstruct + 1 end end ................................................................................ end local w = world.climate.weatherAt(pos, timeshift) return irradiance + cl.surfaceTemp end function world.ecology.biomeAt(pos) return world.ecology.biomes.db[minetest.get_biome_name(minetest.get_biome_data(pos).biome)] end minetest.after(0, function() world.climate.weatherMap.kind = minetest.get_perlin { seed = 0x925afe; octaves = 2; spread = vector.new(256,256,120); }; world.climate.weatherMap.severity = minetest.get_perlin { seed = 0x39de1d; octaves = 1; spread = vector.new(256,256,60); }; end) function world.climate.weatherAt(pos, timeshift) timeshift = timeshift or 0 local wv = world.climate.weatherMap.kind:get_3d(vector.new(pos.x, pos.z, minetest.get_gametime() + timeshift)) local sev = world.climate.weatherMap.severity:get_3d(vector.new(pos.x, pos.z, minetest.get_gametime() + timeshift)) local b = world.ecology.biomeAt(pos) local w = 'starlit:clear' for i,v in ipairs(b.weather) do if wv < v[1] then w = v[2] break end ................................................................................ world.climate.weather.link('starlit:meteorShower', { name = 'Meteor Shower'; danger = 2; }) world.ecology.biomes.foreach('starlit:biome-gen', {}, function(id, b) b.def.name = id minetest.register_biome(b.def) end) world.ecology.plants.foreach('starlit:plant-gen', {}, function(id, b) local stageCt = #b.stages local function stageID(n) if n == stageCt then return id end return id .. string.format('_stage_%s', n) ................................................................................ end; }; } if st.swap then base.node_dig_prediction = "" function base.after_dig_node(pos, node, digger) node.name = stageID(st.swap) minetest.swap_node(pos, node) return true end end if st.biolum then base.light_source = st.biolum; end return base end for i, v in ipairs(b.stages) do local n = regStage(i, v) minetest.register_node(stageID(i), n) b.stageNodes[i] = stageID(i) end b.fullyGrown = stageID(stageCt) local dec = { deco_type = 'simple'; decoration = b.stageNodes; height = 1; param2 = b.meshOpt or 0; } for k,v in pairs(b.decoration) do dec[k] = v end b.decoration = minetest.register_decoration(dec) end) local toward = lib.math.toward local hfinterval = 1.5 starlit.startJob('starlit:temps', hfinterval, function(delta) -- our base thermal conductivity (κ) is measured in °C/°C/s. say the ................................................................................ -- d = Tₑ − Tₚ = -40°C -- ΔT = κ×d = -.4°C/s -- too cold: -- x = beginning of danger zone -- κ × (x - Tₚ) = y where y < Tₚ -- our final change in temperature is computed as tΔC where t is time local kappa = starlit.constant.heat.thermalConductivity local now = minetest.get_gametime() for name,user in pairs(starlit.activeUsers) do local tr = user:species().tempRange local t = starlit.world.climate.temp(user.entity:get_pos()) local weather,wsev = starlit.world.climate.weatherAt(user.entity:get_pos()) local wfac if user.env.weather == nil ................................................................................ world.ecology.trees.foreach('starlit:tree-gen', {}, function(id, t) for i,td in ipairs(t.decorate) do local dec = { deco_type = 'lsystem'; treedef = t.def; } for k,v in pairs(td) do dec[k]=v end minetest.register_decoration(dec) end end) minetest.register_abm { label = "plant growth"; nodenames = {'group:plant_grow'}; chance = 15; interval = 20; catch_up = true; action = function(pos, node) local def = minetest.registered_nodes[node.name]._starlit.plant -- 5 W: maximum power for UV lamps -- 7 W: maximum solar power local uv = (minetest.get_natural_light(pos) / 15) * 7 -- TODO compute artificial contribution local req = lib.tbl.defaults({ uv = 3; soil = 'soil'; temp = -10; humid = nil; }, def.growReq); -- TODO check other reqs if uv > req.uv then local plant = starlit.world.ecology.plants.db[def.id] local nextStage = plant.stageNodes[def.stage + 1] minetest.swap_node(pos, {name=nextStage}) end end; } |
| | | | | | | | | | | | | | | | | | | | | | | |
1 2 3 4 5 6 7 8 9 10 11 12 .. 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 .. 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 .. 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 ... 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 ... 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 ... 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 ... 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 |
local lib = starlit.mod.lib local world = starlit.world function world.date() local days = core.get_day_count() local year = math.floor(days / world.planet.orbit); local day = days % world.planet.orbit; return { year = year, day = day; season = day / world.planet.orbit + 0.5; -- begin summer } end ................................................................................ local heatRange = {min = -50, max = 50} -- translate mt temps into real temps -- this function provides the basis for temperature calculation, -- which is performed by adding this value to the ambient temperature, -- determined by querying nearby group:heatSource items in accordance -- with the inverse-square law function world.climate.eval(pos, tod, season) local data = core.get_biome_data(pos) local biome = world.ecology.biomes.db[core.get_biome_name(data.biome)] -- print('climate:', dump(data)) local heat, humid = data.heat, data.humidity heat = lerp(heat/100, heatRange.min, heatRange.max) tod = tod or core.get_timeofday() heat = lerp(math.abs(tod - 0.5)*2, heat, heat + biome.nightTempDelta) -- print('base heat', heat) local td = world.date() heat = heat + gradient(biome.seasonalTemp, season or td.season) -- print('seasonal heat', heat) if pos.y > 0 then ................................................................................ local vdsq = lib.math.vdsq function world.climate.temp(pos, timeshift) --> irradiance at pos in W local cl = world.climate.eval(pos) local radCenters = starlit.region.radiator.store:get_areas_for_pos(pos, false, true) local irradiance = 0 for _,e in pairs(radCenters) do local rpos = core.string_to_pos(e.data) local rdef = assert(core.registered_nodes[assert(core.get_node(rpos)).name]) local rc = rdef._starlit.radiator local r_max = rc.radius(rpos) local dist_sq = vdsq(rpos,pos) if dist_sq <= r_max^2 then -- cheap bad way -- if core.line_of_sight(rpos,pos) then -- -- expensive way local obstruct = 0 local ray = Raycast(rpos, pos, true, true) for p in ray do if p.type == 'node' then obstruct = obstruct + 1 end end ................................................................................ end local w = world.climate.weatherAt(pos, timeshift) return irradiance + cl.surfaceTemp end function world.ecology.biomeAt(pos) return world.ecology.biomes.db[core.get_biome_name(core.get_biome_data(pos).biome)] end core.after(0, function() world.climate.weatherMap.kind = core.get_perlin { seed = 0x925afe; octaves = 2; spread = vector.new(256,256,120); }; world.climate.weatherMap.severity = core.get_perlin { seed = 0x39de1d; octaves = 1; spread = vector.new(256,256,60); }; end) function world.climate.weatherAt(pos, timeshift) timeshift = timeshift or 0 local wv = world.climate.weatherMap.kind:get_3d(vector.new(pos.x, pos.z, core.get_gametime() + timeshift)) local sev = world.climate.weatherMap.severity:get_3d(vector.new(pos.x, pos.z, core.get_gametime() + timeshift)) local b = world.ecology.biomeAt(pos) local w = 'starlit:clear' for i,v in ipairs(b.weather) do if wv < v[1] then w = v[2] break end ................................................................................ world.climate.weather.link('starlit:meteorShower', { name = 'Meteor Shower'; danger = 2; }) world.ecology.biomes.foreach('starlit:biome-gen', {}, function(id, b) b.def.name = id core.register_biome(b.def) end) world.ecology.plants.foreach('starlit:plant-gen', {}, function(id, b) local stageCt = #b.stages local function stageID(n) if n == stageCt then return id end return id .. string.format('_stage_%s', n) ................................................................................ end; }; } if st.swap then base.node_dig_prediction = "" function base.after_dig_node(pos, node, digger) node.name = stageID(st.swap) core.swap_node(pos, node) return true end end if st.biolum then base.light_source = st.biolum; end return base end for i, v in ipairs(b.stages) do local n = regStage(i, v) core.register_node(stageID(i), n) b.stageNodes[i] = stageID(i) end b.fullyGrown = stageID(stageCt) local dec = { deco_type = 'simple'; decoration = b.stageNodes; height = 1; param2 = b.meshOpt or 0; } for k,v in pairs(b.decoration) do dec[k] = v end b.decoration = core.register_decoration(dec) end) local toward = lib.math.toward local hfinterval = 1.5 starlit.startJob('starlit:temps', hfinterval, function(delta) -- our base thermal conductivity (κ) is measured in °C/°C/s. say the ................................................................................ -- d = Tₑ − Tₚ = -40°C -- ΔT = κ×d = -.4°C/s -- too cold: -- x = beginning of danger zone -- κ × (x - Tₚ) = y where y < Tₚ -- our final change in temperature is computed as tΔC where t is time local kappa = starlit.constant.heat.thermalConductivity local now = core.get_gametime() for name,user in pairs(starlit.activeUsers) do local tr = user:species().tempRange local t = starlit.world.climate.temp(user.entity:get_pos()) local weather,wsev = starlit.world.climate.weatherAt(user.entity:get_pos()) local wfac if user.env.weather == nil ................................................................................ world.ecology.trees.foreach('starlit:tree-gen', {}, function(id, t) for i,td in ipairs(t.decorate) do local dec = { deco_type = 'lsystem'; treedef = t.def; } for k,v in pairs(td) do dec[k]=v end core.register_decoration(dec) end end) core.register_abm { label = "plant growth"; nodenames = {'group:plant_grow'}; chance = 15; interval = 20; catch_up = true; action = function(pos, node) local def = core.registered_nodes[node.name]._starlit.plant -- 5 W: maximum power for UV lamps -- 7 W: maximum solar power local uv = (core.get_natural_light(pos) / 15) * 7 -- TODO compute artificial contribution local req = lib.tbl.defaults({ uv = 3; soil = 'soil'; temp = -10; humid = nil; }, def.growReq); -- TODO check other reqs if uv > req.uv then local plant = starlit.world.ecology.plants.db[def.id] local nextStage = plant.stageNodes[def.stage + 1] core.swap_node(pos, {name=nextStage}) end end; } |
Modified mods/vtlib/color.lua from [d9e5a5527c] to [f14f6eaefb].
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
end; int = function(self) return bit.bor(bit.lshift(self:int24(), 8), math.floor(0xff*(self.alpha or 1.0))) end; fmt = function(self, text) return minetest.colorize(self:hex(), text) end; bg = function(self, text) return text .. minetest.get_background_escape_sequence(self:hex()) end; lum = function(self) return (self.red + self.green + self.blue) / 3 end; pair = function(self) --> bg, fg |
| | |
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
end; int = function(self) return bit.bor(bit.lshift(self:int24(), 8), math.floor(0xff*(self.alpha or 1.0))) end; fmt = function(self, text) return core.colorize(self:hex(), text) end; bg = function(self, text) return text .. core.get_background_escape_sequence(self:hex()) end; lum = function(self) return (self.red + self.green + self.blue) / 3 end; pair = function(self) --> bg, fg |
Modified mods/vtlib/dbg.lua from [3d3bef9b5d] to [8f550c074a].
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
local lastmod, lastarea
function dbg.debugger(area)
local depth = 0
local d = {}
function d.enter() depth = depth+1 end
function d.exit() depth = depth-1 end
local mod = minetest.get_current_modname()
if dbg.aloud then
function d.report(fmt, ...)
local where = debug.getinfo(2)
local caller = debug.getinfo(3)
if mod and (lastmod ~= mod or lastarea ~= area) then
local ms = mod or ''
if area then ms = ms .. '.' .. area end
|
| |
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
local lastmod, lastarea
function dbg.debugger(area)
local depth = 0
local d = {}
function d.enter() depth = depth+1 end
function d.exit() depth = depth-1 end
local mod = core.get_current_modname()
if dbg.aloud then
function d.report(fmt, ...)
local where = debug.getinfo(2)
local caller = debug.getinfo(3)
if mod and (lastmod ~= mod or lastarea ~= area) then
local ms = mod or ''
if area then ms = ms .. '.' .. area end
|
Modified mods/vtlib/init.lua from [d021d078eb] to [d81d22bdc5].
1 2 3 4 5 6 7 8 9 |
local ident = minetest.get_current_modname() local path = minetest.get_modpath(ident) local lib = {} _G[ident] = lib local function component(name) local p = string.format('%s/%s.lua', path, name) |
| | |
1 2 3 4 5 6 7 8 9 |
local ident = core.get_current_modname() local path = core.get_modpath(ident) local lib = {} _G[ident] = lib local function component(name) local p = string.format('%s/%s.lua', path, name) |
Modified mods/vtlib/item.lua from [29827ac7a0] to [3c399f0296].
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
..
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
count = b:get_count() - a:get_count(); } end end end -- it is extremely unfortunate this function needs to exist. -- minetest needs to export its matching capabilities already fn.groupmatch = function(identity,item,exact) if exact == nil then exact = true end local count if type(identity) == 'table' then count = identity.count identity = identity.name else ................................................................................ end if lib.str.beginswith(identity, 'group:') then local stack = ItemStack(item) local groups = lib.str.explode(string.sub(identity,7), ',') for _,g in pairs(groups) do local rn,rv = lib.tbl.split(g,'=') local gv = minetest.get_item_group(stack:get_name(), rn) if rv then if gv ~= tonumber(rv) then return false, stack end else if (not gv) or gv == 0 then return false, stack end end end |
|
|
|
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
..
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
count = b:get_count() - a:get_count(); } end end end -- it is extremely unfortunate this function needs to exist. -- luanti needs to export its matching capabilities already fn.groupmatch = function(identity,item,exact) if exact == nil then exact = true end local count if type(identity) == 'table' then count = identity.count identity = identity.name else ................................................................................ end if lib.str.beginswith(identity, 'group:') then local stack = ItemStack(item) local groups = lib.str.explode(string.sub(identity,7), ',') for _,g in pairs(groups) do local rn,rv = lib.tbl.split(g,'=') local gv = core.get_item_group(stack:get_name(), rn) if rv then if gv ~= tonumber(rv) then return false, stack end else if (not gv) or gv == 0 then return false, stack end end end |
Modified mods/vtlib/marshal.lua from [979397aff5] to [63566b8bdf].
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
end
return encoder
end
function m.metaStore(map, prefix)
report('generating metaStore for %s', dump(map))
if prefix == true then prefix = minetest.get_current_modname() end
local function keyFor(k)
k = map[k].key
if prefix then return prefix .. ':' .. k end
return k
end
return function(obj)
|
| |
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
end
return encoder
end
function m.metaStore(map, prefix)
report('generating metaStore for %s', dump(map))
if prefix == true then prefix = core.get_current_modname() end
local function keyFor(k)
k = map[k].key
if prefix then return prefix .. ':' .. k end
return k
end
return function(obj)
|
Modified mods/vtlib/math.lua from [65dcc21fc6] to [3b6ca155c9].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
local lib = ...
local fn = {}
fn.vsep = function(vec) -- separate a vector into a direction + magnitude
return vec:normalize(), vec:length()
end
-- minetest now only provides the version of this function that sqrts the result
-- which is pointlessly wasteful much of the time
fn.vdsq = function(a,b)
local d = vector.subtract(a,b)
return (d.x ^ 2) + (d.y ^ 2) + (d.z ^ 2)
end
fn.vdcomp = function(dist,v1,v2) -- compare the distance between two points
|
| |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
local lib = ...
local fn = {}
fn.vsep = function(vec) -- separate a vector into a direction + magnitude
return vec:normalize(), vec:length()
end
-- luanti now only provides the version of this function that sqrts the result
-- which is pointlessly wasteful much of the time
fn.vdsq = function(a,b)
local d = vector.subtract(a,b)
return (d.x ^ 2) + (d.y ^ 2) + (d.z ^ 2)
end
fn.vdcomp = function(dist,v1,v2) -- compare the distance between two points
|
Modified mods/vtlib/node.lua from [75e0d781d2] to [aa93f93a5c].
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 ... 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 ... 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 ... 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 ... 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 ... 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 |
z = pos.z + r(0 - range, range); } end for name, inv in pairs(meta.inventory) do if only and not lib.tbl.has(only,name) then goto skip end for _, item in pairs(inv) do if not item:is_empty() then minetest.add_item(offset(pos,0.4), item) end end ::skip::end end; local force = function(pos,preload_for) local n = minetest.get_node_or_nil(pos) if preload_for then lib.node.preload(pos,preload_for) end if n then return n end minetest.load_area(pos) return minetest.get_node(pos) end; local amass = function(startpoint,names,directions) if not directions then directions = ofs.neighbors end local check = function(n) return lib.tbl.has(names, n.name, function(check,against) return lib.item.groupmatch(against,check) ................................................................................ until i > #stack return nodes, positions end; local is_air = function(pos) local n = force(pos) if n.name == 'air' then return true end local d = minetest.registered_nodes[n.name] if not d then return false end return (d.walkable == false) and (d.drawtype == 'airlike' or d.buildable_to == true) end; local is_clear = function(pos) if not lib.node.is_air(pos) then return false end local ents = minetest.get_objects_inside_radius(pos,0.5) if #ents > 0 then return false end return true end; local function boxwarp(nb, mogrifier, par) if nb == nil then return ................................................................................ end end; is_air = is_air; is_clear = is_clear; insert = function(item, slot, npos, user, inv) inv = inv or minetest.get_meta(npos):get_inventory() if inv:room_for_item(slot,item) then inv:add_item(slot,item) else repeat if user then local ui = user:get_inventory() if ui:room_for_item('main', item) then ui:add_item('main', item) break end end minetest.add_item(npos, item) until true end end; install_bed = function(bed, where, dir) local bottom = bed .. '_bottom' local top = bed .. '_top' local d if type(dir) == 'number' then d = dir dir = minetest.facedir_to_dir(d) else d = minetest.dir_to_facedir(dir) end if not is_clear(where) and is_clear(where - dir) then return false end minetest.set_node(where, {name = top, param2 = d}) minetest.set_node(where - dir, {name = bottom, param2 = d}) return true end; get_arrival_point = function(pos) local try = function(p) local air = lib.node.is_clear if air(p) then ................................................................................ end end; forneighbor = function(pos, n, fn) for _,p in pairs(n) do local sum = vector.add(pos, p) local n = minetest.get_node(sum) if n.name == 'ignore' then minetest.load_area(sum) n = minetest.get_node(sum) end if fn(sum, n) == false then break end end end; amass = amass; ................................................................................ x = math.floor(pos.x / 16); y = math.floor(pos.y / 16); z = math.floor(pos.z / 16); } end; preload = function(pos, user) minetest.load_area(pos) user:send_mapblock(lib.node.blockpos(pos)) end; discharger = function(pos) local below = force(vector.subtract(pos,{x=0,y=1,z=0})) if below.name == 'hopper:hopper' or below.name == 'hopper:hopper_side' then local hopper = minetest.get_meta(below):get_inventory() return function(i) if hopper:room_for_item('main',i) then return hopper:add_item('main',i), true end return i, false end else ................................................................................ max_items = 1; items = { { items = {id} }; }; } local next_apn = tbl.after_place_node tbl.after_place_node = function(...) local pos, who, stack = ... minetest.get_meta(pos):from_table(stack:get_meta():to_table()) if next_apn then return next_apn(...) end end local next_pm = tbl.preserve_metadata tbl.preserve_metadata = function(...) local pos, node, meta, drops = ... drops[1]:get_meta():from_table({fields = meta}) if next_pm then return next_pm(...) end end return tbl end; reg_autopreserve = function(id, tbl) minetest.register_node(id, lib.node.autopreserve(id, tbl)) end; boxwarp = boxwarp; boxwarped = boxwarped; } |
| | | | | | | | | | | | | | | | | | | |
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 ... 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 ... 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 ... 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 ... 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 ... 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 |
z = pos.z + r(0 - range, range); } end for name, inv in pairs(meta.inventory) do if only and not lib.tbl.has(only,name) then goto skip end for _, item in pairs(inv) do if not item:is_empty() then core.add_item(offset(pos,0.4), item) end end ::skip::end end; local force = function(pos,preload_for) local n = core.get_node_or_nil(pos) if preload_for then lib.node.preload(pos,preload_for) end if n then return n end core.load_area(pos) return core.get_node(pos) end; local amass = function(startpoint,names,directions) if not directions then directions = ofs.neighbors end local check = function(n) return lib.tbl.has(names, n.name, function(check,against) return lib.item.groupmatch(against,check) ................................................................................ until i > #stack return nodes, positions end; local is_air = function(pos) local n = force(pos) if n.name == 'air' then return true end local d = core.registered_nodes[n.name] if not d then return false end return (d.walkable == false) and (d.drawtype == 'airlike' or d.buildable_to == true) end; local is_clear = function(pos) if not lib.node.is_air(pos) then return false end local ents = core.get_objects_inside_radius(pos,0.5) if #ents > 0 then return false end return true end; local function boxwarp(nb, mogrifier, par) if nb == nil then return ................................................................................ end end; is_air = is_air; is_clear = is_clear; insert = function(item, slot, npos, user, inv) inv = inv or core.get_meta(npos):get_inventory() if inv:room_for_item(slot,item) then inv:add_item(slot,item) else repeat if user then local ui = user:get_inventory() if ui:room_for_item('main', item) then ui:add_item('main', item) break end end core.add_item(npos, item) until true end end; install_bed = function(bed, where, dir) local bottom = bed .. '_bottom' local top = bed .. '_top' local d if type(dir) == 'number' then d = dir dir = core.facedir_to_dir(d) else d = core.dir_to_facedir(dir) end if not is_clear(where) and is_clear(where - dir) then return false end core.set_node(where, {name = top, param2 = d}) core.set_node(where - dir, {name = bottom, param2 = d}) return true end; get_arrival_point = function(pos) local try = function(p) local air = lib.node.is_clear if air(p) then ................................................................................ end end; forneighbor = function(pos, n, fn) for _,p in pairs(n) do local sum = vector.add(pos, p) local n = core.get_node(sum) if n.name == 'ignore' then core.load_area(sum) n = core.get_node(sum) end if fn(sum, n) == false then break end end end; amass = amass; ................................................................................ x = math.floor(pos.x / 16); y = math.floor(pos.y / 16); z = math.floor(pos.z / 16); } end; preload = function(pos, user) core.load_area(pos) user:send_mapblock(lib.node.blockpos(pos)) end; discharger = function(pos) local below = force(vector.subtract(pos,{x=0,y=1,z=0})) if below.name == 'hopper:hopper' or below.name == 'hopper:hopper_side' then local hopper = core.get_meta(below):get_inventory() return function(i) if hopper:room_for_item('main',i) then return hopper:add_item('main',i), true end return i, false end else ................................................................................ max_items = 1; items = { { items = {id} }; }; } local next_apn = tbl.after_place_node tbl.after_place_node = function(...) local pos, who, stack = ... core.get_meta(pos):from_table(stack:get_meta():to_table()) if next_apn then return next_apn(...) end end local next_pm = tbl.preserve_metadata tbl.preserve_metadata = function(...) local pos, node, meta, drops = ... drops[1]:get_meta():from_table({fields = meta}) if next_pm then return next_pm(...) end end return tbl end; reg_autopreserve = function(id, tbl) core.register_node(id, lib.node.autopreserve(id, tbl)) end; boxwarp = boxwarp; boxwarped = boxwarped; } |
Modified mods/vtlib/obj.lua from [7fd77150af] to [42f785b164].
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 .. 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 .. 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
-- from the game API local fn = {} local lib = ... -- WARNING: INEFFICIENT AS FUCK fn.identify = function(objref) --> objectid for _, o in pairs(minetest.get_connected_players()) do if objref == o then return o:get_player_name(), 'player' end end for id, le in pairs(minetest.luaentities) do if le.object == objref then return id, 'entity' end end end fn.handle = lib.class { __newindex = function(self,key,newval) local hnd if self.player then hnd = minetest.get_player_by_name(self._id) else hnd = minetest.luaentities[self._id] end if key == 'id' then if type(newval) == 'string' then local p = minetest.get_player_by_name(newval) if p then self._id = newval self.player = true return end end if minetest.luaentities[newval] then self._id = newval self.player = false else error('attempted to assign invalid ID to entity handle') end elseif key == 'obj' then local no, kind = fn.identify(newval) if no then self._id = no ................................................................................ else error('attempted to assign invalid ObjectRef to entity handle') end elseif key == 'stack' and self.kind == 'item' then hnd:set_item(newval) end end; __index = function(self,key) local hnd if self.player then hnd = minetest.get_player_by_name(self._id) else hnd = minetest.luaentities[self._id] end if key == 'online' then return hnd ~= nil elseif key == 'id' then if self.player then return nil else return self._id end elseif key == 'obj' then ................................................................................ return maxy-miny, miny else return 0 end end end end; construct = function(h) local kind, id if type(h) == 'string' and minetest.get_player_by_name(h) ~= nil then kind = 'player'; id = h elseif minetest.luaentities[h] then kind = 'entity'; id = h else id, kind = fn.identify(h) end if not id then error('attempted to construct object handle from invalid value') end |
| | | | | | | | | | |
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 .. 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 .. 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
-- from the game API local fn = {} local lib = ... -- WARNING: INEFFICIENT AS FUCK fn.identify = function(objref) --> objectid for _, o in pairs(core.get_connected_players()) do if objref == o then return o:get_player_name(), 'player' end end for id, le in pairs(core.luaentities) do if le.object == objref then return id, 'entity' end end end fn.handle = lib.class { __newindex = function(self,key,newval) local hnd if self.player then hnd = core.get_player_by_name(self._id) else hnd = core.luaentities[self._id] end if key == 'id' then if type(newval) == 'string' then local p = core.get_player_by_name(newval) if p then self._id = newval self.player = true return end end if core.luaentities[newval] then self._id = newval self.player = false else error('attempted to assign invalid ID to entity handle') end elseif key == 'obj' then local no, kind = fn.identify(newval) if no then self._id = no ................................................................................ else error('attempted to assign invalid ObjectRef to entity handle') end elseif key == 'stack' and self.kind == 'item' then hnd:set_item(newval) end end; __index = function(self,key) local hnd if self.player then hnd = core.get_player_by_name(self._id) else hnd = core.luaentities[self._id] end if key == 'online' then return hnd ~= nil elseif key == 'id' then if self.player then return nil else return self._id end elseif key == 'obj' then ................................................................................ return maxy-miny, miny else return 0 end end end end; construct = function(h) local kind, id if type(h) == 'string' and core.get_player_by_name(h) ~= nil then kind = 'player'; id = h elseif core.luaentities[h] then kind = 'entity'; id = h else id, kind = fn.identify(h) end if not id then error('attempted to construct object handle from invalid value') end |
Modified mods/vtlib/str.lua from [ded7121fc6] to [b2f5363bf4].
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
...
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
|
['\xf2'] = '\2'; ['\xf3'] = '\3'; ['\xf4'] = '\0'; }; } local utf8 if _G.minetest then if minetest.global_exists 'utf8' then utf8 = _G.utf8 end else utf8 = _G.utf8 end if not utf8 then -- sigh utf8 = {} ................................................................................ end return str end; meta_armor = function(str,mark_struct) -- binary values stored in metadata need to be sanitized so -- they don't contain values that will disrupt parsing of the -- KV store, as minetest (stupidly) uses in-band signalling local sanitized = string.gsub(str, '.', function(char) if sanitable.from[char] then return '\xfe' .. sanitable.from[char] else return char end end) if sanitized ~= str and mark_struct then -- use different type code to mark struct headers for |
|
|
|
|
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
...
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
|
['\xf2'] = '\2'; ['\xf3'] = '\3'; ['\xf4'] = '\0'; }; } local utf8 if _G.core then if core.global_exists 'utf8' then utf8 = _G.utf8 end else utf8 = _G.utf8 end if not utf8 then -- sigh utf8 = {} ................................................................................ end return str end; meta_armor = function(str,mark_struct) -- binary values stored in metadata need to be sanitized so -- they don't contain values that will disrupt parsing of the -- KV store, as luanti (stupidly) uses in-band signalling local sanitized = string.gsub(str, '.', function(char) if sanitable.from[char] then return '\xfe' .. sanitable.from[char] else return char end end) if sanitized ~= str and mark_struct then -- use different type code to mark struct headers for |
Modified mods/vtlib/ui.lua from [765cced2b5] to [77b0e87fc7].
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 .. 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 .. 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
self.curs.y = math.max(h, self.curs.y + self.curs.maxh) self.curs.maxh = 0 end; attach = function(self, elt, x, y, w, h, ...) local content = '' if self.width - self.curs.x < w then self:nl() end for _, v in pairs{...} do content = content .. ';' .. minetest.formspec_escape(tostring(v)) end self.src = self.src .. string.format('%s[%f,%f;%f,%f%s]', elt, x,y, w,h, content) if h > self.curs.maxh then self.curs.maxh = h end end; add = function(self, elt, w, h, ...) local ax, ay = self.curs.x, self.curs.y self:attach(elt, ax,ay, w,h, ...) ................................................................................ -- takes a configuration table mapping affinities to colors. -- 'neutral' is the only required affinity return function(a) local color = a.color and a.color:readable(0.65, 1.0) if color == nil then color = l.color(.5,.5,.5) end local str = a.title if a.desc then str = str .. '\n' .. color:fmt(minetest.wrap_text(a.desc,60)) end if a.props then -- str = str .. '\n' for _,prop in pairs(a.props) do local c if prop.color and l.color.id(prop.color) then c = prop.color:readable(0.6, 1.0) ................................................................................ str = str .. '\n ' .. c:fmt('* ') if prop.title then str = str .. c:brighten(1.2):fmt(prop.title) .. ': ' end local lines = minetest.wrap_text(prop.desc, 55, true) str = str .. c:fmt(lines[1]) for i=2,#lines do str = str .. '\n' .. string.rep(' ',5) .. c:fmt(lines[i]) end end end return color:darken(0.8):bg(str) end; end; } |
| | | |
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 .. 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 .. 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
self.curs.y = math.max(h, self.curs.y + self.curs.maxh) self.curs.maxh = 0 end; attach = function(self, elt, x, y, w, h, ...) local content = '' if self.width - self.curs.x < w then self:nl() end for _, v in pairs{...} do content = content .. ';' .. core.formspec_escape(tostring(v)) end self.src = self.src .. string.format('%s[%f,%f;%f,%f%s]', elt, x,y, w,h, content) if h > self.curs.maxh then self.curs.maxh = h end end; add = function(self, elt, w, h, ...) local ax, ay = self.curs.x, self.curs.y self:attach(elt, ax,ay, w,h, ...) ................................................................................ -- takes a configuration table mapping affinities to colors. -- 'neutral' is the only required affinity return function(a) local color = a.color and a.color:readable(0.65, 1.0) if color == nil then color = l.color(.5,.5,.5) end local str = a.title if a.desc then str = str .. '\n' .. color:fmt(core.wrap_text(a.desc,60)) end if a.props then -- str = str .. '\n' for _,prop in pairs(a.props) do local c if prop.color and l.color.id(prop.color) then c = prop.color:readable(0.6, 1.0) ................................................................................ str = str .. '\n ' .. c:fmt('* ') if prop.title then str = str .. c:brighten(1.2):fmt(prop.title) .. ': ' end local lines = core.wrap_text(prop.desc, 55, true) str = str .. c:fmt(lines[1]) for i=2,#lines do str = str .. '\n' .. string.rep(' ',5) .. c:fmt(lines[i]) end end end return color:darken(0.8):bg(str) end; end; } |
Modified starlit.ct from [ee106030ea] to [f4a136801c].
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
...
159
160
161
162
163
164
165
166
|
~~~ $ curl https://c.hale.su/starlit/tarball/starlit.tar.gz | tar x $ curl https://c.hale.su/starlit/uv/asset.cpxz | xzcat | cpio -i ~~~ eventually i might make proper release tarballs available that bundle the game and assets together, but the game isn't stable enough to do that yet. ## engine starlit is developed against a bleeding-edge version of minetest. it definitely won't work with anything older than v5.7, and ideally you should build directly from master. starlit is best used with a patched version of minetest, though it is compatible with vanilla. the recommended patches are: * [>p11143 11143] - fix third-person view orientation p11143: https://github.com/minetest/minetest/pull/11143.diff ### shadows i was delighted to see dynamic shadows land in minetest, and i hope the implementation will eventually mature. however, as it stands, there are severe issues with shadows that make them essentially incompatible with complex meshes like the Starlit player character meshes. for the sake of those who don't mind these glitches, Starlit does enable shadows, but i unfortunately have to recommend that you disable them until the minetest devs get their act together on this feature. ## gameplay starlit is somewhat unusual in how it uses the minetest engine. it's a voxel game but not of the minecraft variety. you do have some control over your environment, but it's limited and exerting it is much more expensive than you might be used to -- the focus of the game is figuring out how to work with nature, not against it. Farthest Shadow has little patience for those who do not show her the respect a living world is due, and she is unconcerned with human virtues like "mercy" or "fairness" or "proportionate retribution". this is to say, starlit is [*mean], by design. * chance plays an important role. your escape pod might land in the midst of a lush, temperate forest with plenty of nearby shipwrecks to scavenge. or it might land in the exact geographic center of a vast, harsh desert that your suit's cooling systems can't protect you from, ten klicks from anything of value. "unfair", you say? tough. Farthest Shadow doesn't care about your feelings. * death is much worse than a slap on the wrist. when you die, you drop your possessions and your suit, and respawn naked at your spawn point. this is a serious danger, as you might be kilometers away from your spawn point -- and there's no guarantee someone else won't take your suit before you can find your way back to it. good luck crossing long distances without climate control! if you haven't carefully prepared for this eventuality by keeping a spare suit by your spawn point, death can be devastating, to the point of making the game unsurvivable without another player's help. ### scenarios your starting character configuration depends on the scenario you select. (right now this is configured in minetest settings, which is intensely awkward, but i don't have a better solution). the scenario controls your species, sex, and starting inventory. [*neither species nor sex is cosmetic]; e.g. human females are physically weaker but psionically stronger than males. the current playable scenarios are: #### Imperial Expat [*phenotype]: human female [*starting gear]: Commune survival kit > Hoping to escape a miserable life deep in the grinding gears of the capitalist machine for the bracing freedom of the frontier, you sought entry as a colonist to the new Commune world of Thousand Petal. Fate -- which is to say, terrorists -- intervened, and you wound up stranded on Farthest Shadow with little more than the nanosuit on your back, ship blown to tatters and your soul thoroughly mauled by the explosion of a twisted alien artifact -- which SOMEONE neglected to inform you your ride would be carrying. > At least you got some handy psionic powers out of this whole clusterfuck. Hopefully they're safe to use. ................................................................................ a Ritual is triggered directly from the psionics menu. as the name implies, these are complex, powerful abilities that require large amounts of Psi and time to meditate before they trigger, and any interruption will cancel the ability (though it will not restore any lost psi). the most famous Ritual is of course Conjoin Metric, which Starlit astropaths use in conjunction with powerful amplifiers to perform long-distance FTL jumps -- but without centuries of dedication to the art, the best you can hope for if you manage to learn this storied power is to move yourself a few kilometers. a Contextual ability is triggered in a specific situation, usually by interacting with a certain kind of object. Contextual abilities often require specialized equipment, to the point that many Starlit practitioners maintain their own Psionics Lab. ## legal starlit source code (*.lua, *.conf, *.txt, *.csd files) is released under the GNU AGPLv3. assets (images, sounds, models, and anything else in the repo that doesn't qualify as source code) are released under the CC-BY-NC-SA 3.0 license. sound files with the prefix `default-` are taken from Minetest Game, whose assets are available under the CC-BY-SA 3.0 license. |
|
|
|
|
|
|
|
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
...
159
160
161
162
163
164
165
166
|
~~~ $ curl https://c.hale.su/starlit/tarball/starlit.tar.gz | tar x $ curl https://c.hale.su/starlit/uv/asset.cpxz | xzcat | cpio -i ~~~ eventually i might make proper release tarballs available that bundle the game and assets together, but the game isn't stable enough to do that yet. ## engine starlit is developed against a bleeding-edge version of Luanti. it definitely won't work with anything older than v5.7, and ideally you should build directly from master. starlit is best used with a patched version of Luanti, though it is compatible with vanilla. the recommended patches are: * [>p11143 11143] - fix third-person view orientation p11143: https://github.com/minetest/minetest/pull/11143.diff ### shadows i was delighted to see dynamic shadows land in Luanti, and i hope the implementation will eventually mature. however, as it stands, there are severe issues with shadows that make them essentially incompatible with complex meshes like the Starlit player character meshes. for the sake of those who don't mind these glitches, Starlit does enable shadows, but i unfortunately have to recommend that you disable them until the Luanti devs get their act together on this feature. ## gameplay starlit is somewhat unusual in how it uses the Luanti engine. it's a voxel game but not of the minecraft variety. you do have some control over your environment, but it's limited and exerting it is much more expensive than you might be used to -- the focus of the game is figuring out how to work with nature, not against it. Farthest Shadow has little patience for those who do not show her the respect a living world is due, and she is unconcerned with human virtues like "mercy" or "fairness" or "proportionate retribution". this is to say, starlit is [*mean], by design. * chance plays an important role. your escape pod might land in the midst of a lush, temperate forest with plenty of nearby shipwrecks to scavenge. or it might land in the exact geographic center of a vast, harsh desert that your suit's cooling systems can't protect you from, ten klicks from anything of value. "unfair", you say? tough. Farthest Shadow doesn't care about your feelings. * death is much worse than a slap on the wrist. when you die, you drop your possessions and your suit, and respawn naked at your spawn point. this is a serious danger, as you might be kilometers away from your spawn point -- and there's no guarantee someone else won't take your suit before you can find your way back to it. good luck crossing long distances without climate control! if you haven't carefully prepared for this eventuality by keeping a spare suit by your spawn point, death can be devastating, to the point of making the game unsurvivable without another player's help. ### scenarios your starting character configuration depends on the scenario you select. (right now this is configured in Luanti settings, which is intensely awkward, but i don't have a better solution). the scenario controls your species, sex, and starting inventory. [*neither species nor sex is cosmetic]; e.g. human females are physically weaker but psionically stronger than males. the current playable scenarios are: #### Imperial Expat [*phenotype]: human female [*starting gear]: Commune survival kit > Hoping to escape a miserable life deep in the grinding gears of the capitalist machine for the bracing freedom of the frontier, you sought entry as a colonist to the new Commune world of Thousand Petal. Fate -- which is to say, terrorists -- intervened, and you wound up stranded on Farthest Shadow with little more than the nanosuit on your back, ship blown to tatters and your soul thoroughly mauled by the explosion of a twisted alien artifact -- which SOMEONE neglected to inform you your ride would be carrying. > At least you got some handy psionic powers out of this whole clusterfuck. Hopefully they're safe to use. ................................................................................ a Ritual is triggered directly from the psionics menu. as the name implies, these are complex, powerful abilities that require large amounts of Psi and time to meditate before they trigger, and any interruption will cancel the ability (though it will not restore any lost psi). the most famous Ritual is of course Conjoin Metric, which Starlit astropaths use in conjunction with powerful amplifiers to perform long-distance FTL jumps -- but without centuries of dedication to the art, the best you can hope for if you manage to learn this storied power is to move yourself a few kilometers. a Contextual ability is triggered in a specific situation, usually by interacting with a certain kind of object. Contextual abilities often require specialized equipment, to the point that many Starlit practitioners maintain their own Psionics Lab. ## legal starlit source code (*.lua, *.conf, *.txt, *.csd files) is released under the GNU AGPLv3. assets (images, sounds, models, and anything else in the repo that doesn't qualify as source code) are released under the CC-BY-NC-SA 3.0 license. sound files with the prefix `default-` are taken from Luanti Game, whose assets are available under the CC-BY-SA 3.0 license. |