commit b1fe0b2ad4788ab55644999cc5b361d9cf0ed365 Author: Kimapr Date: Wed Oct 23 06:57:37 2019 +0500 Start of the history diff --git a/.cdbrelease.lua b/.cdbrelease.lua new file mode 100644 index 0000000..1f5180c --- /dev/null +++ b/.cdbrelease.lua @@ -0,0 +1,11 @@ +-- LUALOCALS < --------------------------------------------------------- +local dofile + = dofile +-- LUALOCALS > --------------------------------------------------------- + +return { + user = "Kimapr", + pkg = "nodecore-skyblock", + min = "5.0", + version = dofile("./mods/nc_api/version.lua") +} diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..fe79f6f --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +version.lua export-subst +.git* export-ignore +.lua* export-ignore +docs export-ignore +src export-ignore diff --git a/.luacheckrc b/.luacheckrc new file mode 100644 index 0000000..ba6434e --- /dev/null +++ b/.luacheckrc @@ -0,0 +1,3 @@ +globals = {"minetest", "ItemStack", "VoxelArea", "vector", "nodecore", "include", "SecureRandom"} +color = false +quiet = 1 diff --git a/.lualocals b/.lualocals new file mode 100644 index 0000000..4128e08 --- /dev/null +++ b/.lualocals @@ -0,0 +1,8 @@ +~print +minetest +ItemStack +VoxelArea +vector +nodecore +include +SecureRandom diff --git a/CONTRIBUTING b/CONTRIBUTING new file mode 100644 index 0000000..2686240 --- /dev/null +++ b/CONTRIBUTING @@ -0,0 +1,50 @@ +======================================================================== +------------------------------------------------------------------------ + +For your contribution to be included in this project, you must +understand and agree to the terms in this document at the time of +contribution. + +- A "contribution" consists of all files, patches and changes, source + control commits, comments and other metadata submitted to the project + maintainer(s) for inclusion or other use in the project. + +- All contributions must consist only of your own original work, to + which you retain copyright, or to which copyright is not applicable. + +- All copyrightable portions must be non-exclusively, perpetually and + irrevocably licensed under the same license terms as the overall + project. + +- You will receive attribution in the project's license, in the form of + "Portions (C) ...", which shall cover all portions of all + contributions. You agree that this constitutes adequate attribution + under the terms of the license. + +- You may request to be attributed pseudonymously at the time of + submission. Unless otherwise specified, source control metadata + will be used for attribution. + +........................................................................ + +Other Guidelines: + +- Non-included contributions to the project, such as hosting or other + services, content such as videos/streams, screenshots/galleries, + reviews, stories and other publicity do not need to follow the + guidelines above unless they are intended to also be eligible for + inclusion directly in the project. + +- Keep original media source files that are not directly used by the + game engine (e.g. *.blend, *.xcf, *.svg) in folders named "src" in the + appropriate mod/area. These will NOT be distributed with the source + repo, but will not be packaged by ContentDB to keep download sizes + minimal. + +- Lua code indentation style is based on this script: + http://notebook.kulchenko.com/programming/lua-beautifier-in-55-lines-of-perl + (except with INDENT set to "\t" for tabs instead of spaces) + This is very similar to the style used by ZeroBrane Studio. + +------------------------------------------------------------------------ +======================================================================== diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..59eadc0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,24 @@ +Copyright (C)2018-2019 Aaron Suen +Portions Copyright (C)2019 LoneWolfHT +Portions Copyright (C)2019 Magik Eh +Portions Copyright (C)2019 Terifo +Portions Copyright (C)2019 GreenXenith + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README b/README new file mode 100644 index 0000000..565224b --- /dev/null +++ b/README @@ -0,0 +1,66 @@ +======================================================================== + + \ /\ + \ / \ + /\ \ /\ |\ / / \ /\ |\ / + | \ | / \ | \ / | / \ | \ / + | \ | | | | | |__ | | | | / |__ + \ \/ | | | | | \ / | | |/ | + \ \ / | / \ \ / \ / |\ \ + \ \/ |/ \ \/ \/ | \ \ + +======================================================================== + NodeCore - An original, immersive puzzle/adventure game for Minetest +------------------------------------------------------------------------ + +NodeCore is a major reconstruction of survival gameplay from the ground +up. Relearn much of what you thought you knew about Minetest! + +Features: + +- Immersive gameplay. Zero in-game pop-up GUIs. Minimal HUDs. + All interactions take place in continuous first-person perspective. + Nothing gets between you and the game world. + +- Nearly everything is on the grid. Item stacks settle onto the grid + and persist. Complex machines (e.g. furnaces, storage) are built + in-world and can be designed, customized, optimized. + +- In-world crafting. Assemble more complex recipes directly on the grid + or in-place. Learn how to "pummel" nodes to hammer things together + or break things apart. + +- Built-in player guide and hint system provides low-spoiler guidance. + +- Rich and subtle interactions. Some materials dig and transform in + stages. Some materials slump into repose when stacked high. Some + things transform if conditions are met, but transform faster based + on environment. Experiment and see what effects what! + +- Build complex in-game systems. Design your own furnace. Construct + digital logic circuits. Build gears and rotary machinery. Assemble + portable storage containers. + +- Eggcorns! + +------------------------------------------------------------------------ + +NodeCore is (C)2018-2019 by Aaron Suen +MIT License (http://www.opensource.org/licenses/MIT) +See included LICENSE file for full details and credits + +Minetest ContentDB Listing: + https://content.minetest.net/packages/Warr1024/nodecore/ + +GitLab: + https://gitlab.com/sztest/nodecore + +Discord: + https://discord.gg/SHq2tkb + +IRC: + #nodecore on chat.freenode.net + (bridged to Discord) + +------------------------------------------------------------------------ +======================================================================== diff --git a/WISHLIST b/WISHLIST new file mode 100644 index 0000000..977ded7 --- /dev/null +++ b/WISHLIST @@ -0,0 +1,51 @@ +======================================================================== + -----===== PUBLIC CONTRIBUTION WISHLIST =====----- +------------------------------------------------------------------------ +Remember, check out the CONTRIBUTING file for guidelines on contributing +to the project! + +- Translations: + - NodeCore is running Weblate: + https://nodecore.mine.nu/trans/projects/nodecore/core/ + - Contact the NodeCore Developer(s) to get an account if you + want to contribute translations. + +- Help (PRs and/or advocacy) with Minetest engine issues: + - >5.0.1 Release: Improvements already in the development branch + of the engine are expected to benefit NodeCore, e.g. #8701. + - #7245: This is blocking making navigation challenges and + distinguishing nodes with similar appearance into gameplay + elements. + - #8952: This causes hidden bases and other items to be visible + through walls and other terrain in our MP server. + - #8141: We want cleaner player name labels, and to move + the touchtip from screen-space into node-space. + - #7020: This bug requires NodeCore to maintain a workaround for + the engine in its own code. + +- Publicity and player content: + - Help spread NodeCore! Share your experiences, screenshots, + videos and streams! + - Let the developers know if you have shared something about + NodeCore, or would like guidance creating something to share. + +- Player model enhancements + - Check that UV maps are consistent with existing skins, + e.g. MTG Sam or MC Steve, for TP authors to more easily + adapt existing skins. + +- Improved versions of any art assets (sounds, textures). + - All textures for base inclusion should be 16x (keep + high-def textures to texture packs). + - It must be practical to maintain a consistent style for + other assets, including future related ones. + - Animated fluid textures (especially both stationary and + flowing water) would be especially appreciated. + +- Help maintaining the hint system. + - Development of hints often lags behind development of new + features, sometimes significantly. + - Hint organization and content is subject to improvement. + +........................................................................ +======================================================================== diff --git a/docs/design.txt b/docs/design.txt new file mode 100644 index 0000000..d498703 --- /dev/null +++ b/docs/design.txt @@ -0,0 +1,31 @@ +======================================================================== +CORE DESIGN PRINCIPLES +------------------------------------------------------------------------ + +- Do as much in node-space in the world as possible. + - Minimize use of off-grid entities. + - Avoid encapsulating things in inventories, machines, GUIs. + - Crafting and transforming in-world. +- Minimal set of primitive composable functions. + - Each node should do one job (or one part of a job). + - Only include the most primitive, fungible components. + - Avoid redundant functionality, include fewest possible + different elements. + - Complex emergent gameplay by combining simple nodes. +- Challenging and constrained gameplay. + - Limited inventories, very restricted item storage, e.g. one + stack per node. + - Large, complex machines to design and build for resource + transformations. + - Subtle environmental hazards, like deadfalls and pestilence. +- Rich, subtle interactions. + - Digging, placing, punching and battering. + - Different effects from different tools (including empty hand). + - Different faces of node may have different effects. +- Focus on puzzle-oriented single-player/cooperative gameplay. + - Avoid dependence on action, combat, PvP. + - Slow-moving hazards, players have a chance to think and plan. + - Acessible for slow reflexes, slow networks, mobile devices. + +........................................................................ +======================================================================== diff --git a/docs/icebox.txt b/docs/icebox.txt new file mode 100644 index 0000000..e11b4a7 --- /dev/null +++ b/docs/icebox.txt @@ -0,0 +1,57 @@ +======================================================================== +ICEBOX: Low-Priority Ideas +------------------------------------------------------------------------ + + #### ##### #### # # ###### ##### #### + # # # # # # # # # # # + #### # # # # # # ##### # # #### + # ##### # # # # # ##### # + # # # # # # # # # # # # + #### # #### # ###### ###### # # #### + +- Release an official beta pack/edition. + - Modpack of experimental features vs. alternate game by branch? + +- Flammable/igniter ABM should be reversed, so we scan over few igniters + instead of many flammables? + +- Wandering fluids API for concrete, glass? + +- AStMs: Active Stack Modifiers. + - Operate on all visinv nodes. + - Possibly operate on player inventories? + +- Make separate walkable/non-walkable stack nodes. + - Should sticks and eggcorns be non-walkable? + +- Code Quality. + - Scripts to validate dependency graph. + - Tag deps directly in code at place of use. + - Auto-generate mod.conf / depends.txt + - Scripts for automatic metapackage mods? + - Git hooks (and git hook setup scripts)? + +- API Cleanup + - Utils + - Box mueller (and repeated box mueller sum) and exporand + - Break up the nc_api monstrosity. + - nc_api_base to create _G.nodecore and include for all. + - nc_api metamod that just depends on ALL other api's. + - nc_all metamod for 3rd party mod authors...? + - Heat API + - Unified heating/cooling number from env. + - Proper API for burning up items + - on_burn? burns_to? + - Unify heat transformations into recipe system with + cooking recipes? + - Unify nc_items and visinv API. + - Stack nodes are "special", get first-class support. + +- Make neighbor/distance calcs consistent. + - We're using scan_flood in some places, face checks in others, + and find_nodes_in_area (cuboid) in others. + - Diamond shape would be most consistent. + - Should require face touching, not diagonal. + +........................................................................ +======================================================================== diff --git a/docs/issues.txt b/docs/issues.txt new file mode 100644 index 0000000..8b96c57 --- /dev/null +++ b/docs/issues.txt @@ -0,0 +1,37 @@ +======================================================================== +ISSUES: Bugs, Cleanup and Refinements +------------------------------------------------------------------------ + + #### ##### #### # # ###### ##### #### + # # # # # # # # # # # + #### # # # # # # ##### # # #### + # ##### # # # # # ##### # + # # # # # # # # # # # # + #### # #### # ###### ###### # # #### + +- Design principles doc is badly out of date, needs to reflect lessons + learned and things observed about where the game is headed. + +- Less cumbersome scaling controls. + - Use loitering or staring, or some other passive input + instead of a pummel recipe. + - Should hopefully make the process feel more natural. + - Need multiple handholds (i.e. ceil+wall version) since + player no longer picks the surface. + - With no death/respawn, and no fast-travel, we need to + buff player movement to balance that out. + +- Hint system updates. + - Need a "witness" system for spontaneous in-world processes, + such as tree growth or lode cooling. Credit players within + a certain distance and line-of-sight. + - Feedback/issues URL? + - Look for new URL buttons in 5.0+ + +- Reinstate and update toolbelt once engine PR #8701 is released + - Alternative item strategy with dedicated slots for each + inventory space, which can be empty if in hand instead. + - Consider a "backpack" approach as opposed to toolbelt. + +........................................................................ +======================================================================== diff --git a/docs/roadmap.txt b/docs/roadmap.txt new file mode 100644 index 0000000..c7a585e --- /dev/null +++ b/docs/roadmap.txt @@ -0,0 +1,175 @@ +======================================================================== +ROADMAP: Large New Development Projects +------------------------------------------------------------------------ + + #### ##### #### # # ###### ##### #### + # # # # # # # # # # # + #### # # # # # # ##### # # #### + # ##### # # # # # ##### # + # # # # # # # # # # # # + #### # #### # ###### ###### # # #### + +- Split this doc into "core gameplay" and "side quest" forks? + +- Lux Ore + - Reconsider mapgen depth; push downwards? + - Players accumulate radiation. + - Player health API to allow registering multiple reasons + for player health loss (injury, radiation) + - Radiation fades, washes off faster with water. + - Stacks also radioactive. Tools too but less so. + - Infuse other materials + - Infuse clear glass to make "smoked" glass. + - Does not transmit light. + - See-thru only from one side. + - Infuse chromatic glass to make piezo glass. + - Step on it or punch it to emit light. + - Button/touchplate for optics. + +- Trees/logs. + - Tree trunks as falling nodes, dig as logs. + - Logs as non-falling nodes, facedir. + +- Sand renewability. + - Dirt turns to sand if left near water. + - Stronger near more water. + - Stronger near flowing water. + +- Torches + - Burning nodes with ash parts, to display torch lifetime + - Create a "strike-anywhere match" by adding other + materials (sand, and something to react with like + gravel or lux infusion) to instantly light on + punching a solid enough surface. + +- Advanced Tools + - Sickle / kopesh, choppy + snappy, recursive harvesting. + - Mop/broom for mass stack pickup. + - Sponge on a staff for a mop, thatch on a staff for broom. + - Broom recipe feels more right, but requires more work... + +- Tinted glass: can see thru only one way and not others, does not + transmit light? Infuse non-chromatic glass w/ lux? + +- Player knockback coming in 5.1+? + - Allow players to push others around by punching? + - Use for door conveyors? + +- Doors + - Automation via laser ablation propulsion. + - Some materials cannot be operated by hand? + - Stirling engine using light gradient? + - Water or steam for rotary power? + - Arrangements to auto-return if propulsion removed? + - Push fluids, falling_nodes, items, ents as appropriate? + - Also move items sitting atop? + - Use as press for quick packing recipes? + +- Domain Wall Sensor + - Adapt from sztest? + - Field Generator? + - Power an annealed lode block from 2 opposite faces. + - Generates particle effect at mapblock boundary. + +- Thatch + - Collect grass and dry in sun, or pummel sticks into wood fiber. + - Nodes that reduce fall damage, decorative for building. + - Brushes for painting, writing system. + - Broom to sweep scattered item stacks together. + +- Water and lava surface springs. + - Access to water for forges. + - Access to lava for lighting, firestarting, glass? + +- Lava quenching, new material? + +- Lurk Ore + - Moves freely among air-exposed stone while no player is looking. + - Follows after player, attempting to cause harm. + - Weakens nodes above/below player into falling nodes, + e.g. loose cobble, gravel? + - Steals items from player, drops onto ground or absorbs them + into body? Saps tool durability? + - Ignites flammables it passes by? + - Downgrades or absorbs ores nearby by contact or air floodfill? + - Creates illusionary nodes you can fall through? + - Cannot be dug or damaged directly. + - Digging it yields plain stone, but converts up to 2 + surrounding stone nodes into Lurk. + - Need to dig all around it so it cannot move, then apply Some + time-integrated process to convert it to useful form. + +- Threats + - Visceral + - Flammable/toxic gas? + - Monsters: stone-lurkers, mimics. + - Lightning, meteor strikes? + - Creeping + - Cellular automata hazards. + - From exploration, delving too deep, leaving things to rot, etc. + - Blights, Fungi + +- Social features + - Randomize player appearance/colors. + - Shirt/pants, possibly w/ stripes/patterns + - Skin color, hair color, eye color? + - Add more holiday outfits. + - Track server lag in metadata? + +- New writing system based on charcoal + - Draw a symbol on surfaces by pummeling w/ charcoal + - ...or maybe make ink from coal+water, use a brush? + - Punch symbol w/ charcoal to rotate thru alphabet + - Use a special/reduced alphabet? + +- Smoked glass + - Lux-infuse clear glass. + - Does not transmit light. + - See thru only in one direction. + - Useful for hidden bases. + +- Digital logic + lighting via optics. + - Piezo Crystal Node + - Emits light briefly when punched or stepped on + - Need to interpolate player paths for "stepped on" logic + - Lux-infused chromatic glass? + - Pistons or rack&pinions for affecting world stuff. + - Laser ablation propulsion + - Gray code absolute game time to determine distance (logarithmic by load) + - Advanced optics? + - Polarization? Phase? Interference and superposition? + +- Rotary power? + - Stirling engine? + - Rotors? + - Conveyors? + - Steam as a classic fluid? + +- New materials to craft with. + - Dungeon materials, stonework? + - Decorations for dungeons + - Tree sap from stumps? Resin? Rubber? Shellac? + - Small plants? Reeds? Mallows? + - Sea stars, anenome, coral, other underwater things? + - Fungi, esp. tree-destroying ones, blight? + - Oil, natural gas? Fossils and fossil fuels? + - Geode, hydra crystals, radioactives? + - Shipwrecks or alien tech + - Slow-moving animals? Snails? Miniature spice worms? + - Non-portable things, like "spawners" or wormholes + - Tubers and taproots, cacti, and other "defensive" plantlife + - Plant-like CA animals, like bee nests and clouds of bees? + Termine mounds? Ant colonies? Coral? + - Popeggcorn? + - Ores that smelt via heating and then rapid quenching? + +- System for transporting cargo. + - Trains of minecarts? + - Conveyors, elevators? + +- Vary player walking speed based on nodes under feet? + +- Use gravity vector to make flowing water push the player? + +........................................................................ +======================================================================== diff --git a/docs/screenshot-world/.gitignore b/docs/screenshot-world/.gitignore new file mode 100644 index 0000000..15eee1d --- /dev/null +++ b/docs/screenshot-world/.gitignore @@ -0,0 +1,8 @@ +auth.* +env_meta.* +force_loaded.* +ipban.* +mod_storage +players.* +players +world.mt diff --git a/docs/screenshot-world/Makefile b/docs/screenshot-world/Makefile new file mode 100644 index 0000000..21c8eb9 --- /dev/null +++ b/docs/screenshot-world/Makefile @@ -0,0 +1,3 @@ +clean: + lua5.1 mapclean.lua | sqlite3 map.sqlite + cp world.mt.dist world.mt diff --git a/docs/screenshot-world/map.sqlite b/docs/screenshot-world/map.sqlite new file mode 100644 index 0000000..979df1d Binary files /dev/null and b/docs/screenshot-world/map.sqlite differ diff --git a/docs/screenshot-world/map_meta.txt b/docs/screenshot-world/map_meta.txt new file mode 100644 index 0000000..872b2a2 --- /dev/null +++ b/docs/screenshot-world/map_meta.txt @@ -0,0 +1,202 @@ +mgv7_np_ridge = { + lacunarity = 2 + persistence = 0.75 + octaves = 4 + offset = 0 + scale = 1 + flags = defaults + spread = (100,100,100) + seed = 6467 +} +mgv7_np_mountain = { + lacunarity = 2 + persistence = 0.63 + octaves = 5 + offset = -0.6 + scale = 1 + flags = defaults + spread = (250,350,250) + seed = 5333 +} +mgv7_np_float_base_height = { + lacunarity = 2 + persistence = 0.7 + octaves = 4 + offset = 48 + scale = 24 + flags = defaults + spread = (300,300,300) + seed = 907 +} +mgv7_np_ridge_uwater = { + lacunarity = 2 + persistence = 0.6 + octaves = 5 + offset = 0 + scale = 1 + flags = defaults + spread = (1000,1000,1000) + seed = 85039 +} +mgv7_np_mount_height = { + lacunarity = 2 + persistence = 0.6 + octaves = 3 + offset = 256 + scale = 112 + flags = defaults + spread = (1000,1000,1000) + seed = 72449 +} +mgv7_np_filler_depth = { + lacunarity = 2 + persistence = 0.7 + octaves = 3 + offset = 0 + scale = 1.2 + flags = defaults + spread = (150,150,150) + seed = 261 +} +mgv7_np_height_select = { + lacunarity = 2 + persistence = 0.7 + octaves = 6 + offset = -8 + scale = 16 + flags = defaults + spread = (500,500,500) + seed = 4213 +} +mgv7_dungeon_ymax = 31000 +mgv7_dungeon_ymin = -31000 +mgv7_cavern_threshold = 0.7 +mg_flags = caves, dungeons, light, decorations, biomes +seed = 14531853857515683775 +mgv7_np_cave1 = { + lacunarity = 2 + persistence = 0.5 + octaves = 3 + offset = 0 + scale = 12 + flags = defaults + spread = (61,61,61) + seed = 52534 +} +mg_biome_np_humidity = { + lacunarity = 2 + persistence = 0.5 + octaves = 3 + offset = 50 + scale = 50 + flags = defaults + spread = (1000,1000,1000) + seed = 842 +} +mg_biome_np_humidity_blend = { + lacunarity = 2 + persistence = 1 + octaves = 2 + offset = 0 + scale = 1.5 + flags = defaults + spread = (8,8,8) + seed = 90003 +} +mgv7_float_mount_exponent = 0.75 +mgv7_np_terrain_persist = { + lacunarity = 2 + persistence = 0.6 + octaves = 3 + offset = 0.6 + scale = 0.1 + flags = defaults + spread = (2000,2000,2000) + seed = 539 +} +mg_name = v7 +mgv7_np_cave2 = { + lacunarity = 2 + persistence = 0.5 + octaves = 3 + offset = 0 + scale = 12 + flags = defaults + spread = (67,67,67) + seed = 10325 +} +water_level = 1 +mg_biome_np_heat_blend = { + lacunarity = 2 + persistence = 1 + octaves = 2 + offset = 0 + scale = 1.5 + flags = defaults + spread = (8,8,8) + seed = 13 +} +mgv7_cavern_limit = -256 +mgv7_cavern_taper = 256 +mgv7_np_cavern = { + lacunarity = 2 + persistence = 0.63 + octaves = 5 + offset = 0 + scale = 1 + flags = defaults + spread = (384,128,384) + seed = 723 +} +mgv7_np_floatland_base = { + lacunarity = 2 + persistence = 0.6 + octaves = 5 + offset = -0.6 + scale = 1.5 + flags = defaults + spread = (600,600,600) + seed = 114 +} +mg_biome_np_heat = { + lacunarity = 2 + persistence = 0.5 + octaves = 3 + offset = 50 + scale = 50 + flags = defaults + spread = (1000,1000,1000) + seed = 5349 +} +chunksize = 5 +mapgen_limit = 31000 +mgv7_np_terrain_alt = { + lacunarity = 2 + persistence = 0.6 + octaves = 5 + offset = 4 + scale = 25 + flags = defaults + spread = (600,600,600) + seed = 5934 +} +mgv7_mount_zero_level = 0 +mgv7_spflags = mountains, ridges, nofloatlands, caverns +mgv7_large_cave_depth = -33 +mgv7_float_mount_height = 128 +mgv7_float_mount_density = 0.6 +mgv7_cave_width = 0.09 +mgv7_lava_depth = -256 +mgv7_floatland_level = 1280 +mgv7_np_terrain_base = { + lacunarity = 2 + persistence = 0.6 + octaves = 5 + offset = 4 + scale = 70 + flags = defaults + spread = (600,600,600) + seed = 82341 +} +mgv7_shadow_limit = 1024 +[end_of_params] diff --git a/docs/screenshot-world/mapclean.lua b/docs/screenshot-world/mapclean.lua new file mode 100644 index 0000000..7514d94 --- /dev/null +++ b/docs/screenshot-world/mapclean.lua @@ -0,0 +1,44 @@ +-- LUALOCALS < --------------------------------------------------------- +local math, pairs, table + = math, pairs, table +local math_ceil, math_floor, table_concat, table_sort + = math.ceil, math.floor, table.concat, table.sort +-- LUALOCALS > --------------------------------------------------------- + +local min = { + x = -192, + y = -16, + z = -192 +} +local max = { + x = 64, + y = 32, + z = -64 +} + +for k, v in pairs(min) do min[k] = math_floor(v / 80) * 5 end +for k, v in pairs(max) do max[k] = math_ceil(v / 80) * 5 end + +local t = {} +for x = min.x, max.x do + for y = min.y, max.y do + for z = min.z, max.z do + t[#t + 1] = x + 4096 * y + 16777216 * z + end + end +end +table_sort(t) + +print("create table if not exists keep(id integer primary key);") +print("begin transaction;") +for s = 1, #t, 100 do + local e = s + 99 + if e > #t then e = #t end + local u = {} + for i = s, e do u[#u + 1] = t[i] end + print("insert into keep(id) values(" .. table_concat(u, "),(") .. ");") +end +print("commit;") +print("delete from blocks where pos not in (select distinct id from keep);") +print("drop table keep;") +print("vacuum;") diff --git a/docs/screenshot-world/world.mt.dist b/docs/screenshot-world/world.mt.dist new file mode 100644 index 0000000..1634c87 --- /dev/null +++ b/docs/screenshot-world/world.mt.dist @@ -0,0 +1,3 @@ +gameid = nodecore +backend = sqlite3 +load_mod_nc_reative = true diff --git a/docs/screenshot-world/worldmods/mockup/init.lua b/docs/screenshot-world/worldmods/mockup/init.lua new file mode 100644 index 0000000..c21d94a --- /dev/null +++ b/docs/screenshot-world/worldmods/mockup/init.lua @@ -0,0 +1,23 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest + = minetest +-- LUALOCALS > --------------------------------------------------------- + +minetest.settings:set("time_speed", 0) +minetest.after(0, function() minetest.set_timeofday(0.5) end) + +local function setup(p) + local n = p:get_player_name() + + local v = minetest.get_player_privs(n) + v.fly = true + v.fast = true + v.give = true + v.interact = true + v.nc_reative = true + minetest.set_player_privs(n, v) + + p:set_pos({x = -113, y = 5, z = -93}) +end +minetest.register_on_joinplayer(setup) +minetest.register_on_respawnplayer(setup) diff --git a/game.conf b/game.conf new file mode 100644 index 0000000..dad872e --- /dev/null +++ b/game.conf @@ -0,0 +1,2 @@ +name = NodeCore Skyblock +description = Skyblock version of an original, immersive puzzle/adventure game with NO popup GUIs, minimal HUDs. diff --git a/menu/background.png b/menu/background.png new file mode 100644 index 0000000..fbed046 Binary files /dev/null and b/menu/background.png differ diff --git a/menu/header.png b/menu/header.png new file mode 100644 index 0000000..55e318f Binary files /dev/null and b/menu/header.png differ diff --git a/menu/icon.png b/menu/icon.png new file mode 100644 index 0000000..b018707 Binary files /dev/null and b/menu/icon.png differ diff --git a/menu/src/header.svg b/menu/src/header.svg new file mode 100644 index 0000000..eab9ef7 --- /dev/null +++ b/menu/src/header.svg @@ -0,0 +1,227 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/menu/src/icon.svg b/menu/src/icon.svg new file mode 100644 index 0000000..2505033 --- /dev/null +++ b/menu/src/icon.svg @@ -0,0 +1,134 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/menu/src/icon.xcf b/menu/src/icon.xcf new file mode 100644 index 0000000..8985737 Binary files /dev/null and b/menu/src/icon.xcf differ diff --git a/mods/nc_api/fx_digparticles.lua b/mods/nc_api/fx_digparticles.lua new file mode 100644 index 0000000..af533ee --- /dev/null +++ b/mods/nc_api/fx_digparticles.lua @@ -0,0 +1,41 @@ +-- LUALOCALS < --------------------------------------------------------- +local math, minetest, nodecore, pairs + = math, minetest, nodecore, pairs +local math_ceil, math_floor, math_random + = math.ceil, math.floor, math.random +-- LUALOCALS > --------------------------------------------------------- + +function nodecore.digparticles(nodedef, partdef) + if partdef.forcetexture then + partdef.texture = partdef.forcetexture + local id = minetest.add_particlespawner(partdef) + return function() minetest.delete_particlespawner(id) end + end + + local img = {} + if nodedef.tiles then + for i = 1, 6 do + img[#img + 1] = nodedef.tiles[i > #nodedef.tiles and #nodedef.tiles or i] + end + elseif nodedef.inventory_image then + img[1] = nodedef.inventory_image + end + if #img < 1 then return minetest.log("no pummel tile images found!") end + img = nodecore.pickrand(img) + if img.name then img = img.name end + + partdef.amount = partdef.amount and math_ceil(partdef.amount / 4) or 4 + + local t = {} + for _ = 1, 4 do + partdef.texture = img .. "^[mask:[combine\\:16x16\\:" + .. math_floor(math_random() * 12) .. "," + .. math_floor(math_random() * 12) .. "=nc_api_pummel.png" + t[#t + 1] = minetest.add_particlespawner(partdef) + end + return function() + for _, v in pairs(t) do + minetest.delete_particlespawner(v) + end + end +end diff --git a/mods/nc_api/init.lua b/mods/nc_api/init.lua new file mode 100644 index 0000000..0fb6ff3 --- /dev/null +++ b/mods/nc_api/init.lua @@ -0,0 +1,76 @@ +-- LUALOCALS < --------------------------------------------------------- +-- SKIP: include nodecore +local dofile, error, minetest, pairs, rawget, rawset, setmetatable, + table, type + = dofile, error, minetest, pairs, rawget, rawset, setmetatable, + table, type +local table_concat, table_insert + = table.concat, table.insert +-- LUALOCALS > --------------------------------------------------------- + +local nodecore = rawget(_G, "nodecore") or {} +rawset(_G, "nodecore", nodecore) + +local include = rawget(_G, "include") or function(...) + local parts = {...} + table_insert(parts, 1, minetest.get_modpath(minetest.get_current_modname())) + if parts[#parts]:sub(-4) ~= ".lua" then + parts[#parts] = parts[#parts] .. ".lua" + end + return dofile(table_concat(parts, "/")) +end +rawset(_G, "include", include) + +nodecore.product = "NodeCore Skyblock" +nodecore.version = include("version") + +local function callguard(n, t, k, v) + if type(v) ~= "function" then return v end + return function(first, ...) + if first == t then + error("called " .. n .. ":" .. k .. "() instead of " .. n .. "." .. k .. "()") + end + return v(first, ...) + end +end +for k, v in pairs(minetest) do + minetest[k] = callguard("minetest", minetest, k, v) +end +setmetatable(nodecore, { + __newindex = function(t, k, v) + rawset(nodecore, k, callguard("nodecore", t, k, v)) + end + }) + +include("issue7020") + +include("util_misc") +include("util_falling") +include("util_scan_flood") +include("util_node_is") +include("util_toolcaps") +include("util_stack") +include("util_phealth") +include("util_facedir") +include("util_sound") +include("util_translate") +include("util_ezschematic") +include("match") + +include("fx_digparticles") + +include("register_limited_abm") +include("register_soaking_abm") +include("register_ambiance") +include("register_mods") +include("mapgen_shared") + +include("item_on_register") +include("item_drop_in_place") +include("item_falling_repose") +include("item_alternate_loose") +include("item_group_visinv") +include("item_oldnames") +include("item_tool_wears_to") +include("item_tool_sounds") +include("item_punch_sounds") diff --git a/mods/nc_api/issue7020.lua b/mods/nc_api/issue7020.lua new file mode 100644 index 0000000..6e02241 --- /dev/null +++ b/mods/nc_api/issue7020.lua @@ -0,0 +1,22 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, pairs, setmetatable, type + = minetest, pairs, setmetatable, type +-- LUALOCALS > --------------------------------------------------------- + +local bifn = minetest.registered_entities["__builtin:falling_node"] +local falling = { + set_node = function(self, node, meta, ...) + meta = meta or {} + if type(meta) ~= "table" then meta = meta:to_table() end + for _, v1 in pairs(meta.inventory or {}) do + for k2, v2 in pairs(v1) do + if type(v2) == "userdata" then + v1[k2] = v2:to_string() + end + end + end + return bifn.set_node(self, node, meta, ...) + end +} +setmetatable(falling, bifn) +minetest.register_entity(":__builtin:falling_node", falling) diff --git a/mods/nc_api/item_alternate_loose.lua b/mods/nc_api/item_alternate_loose.lua new file mode 100644 index 0000000..c8ee758 --- /dev/null +++ b/mods/nc_api/item_alternate_loose.lua @@ -0,0 +1,109 @@ +-- LUALOCALS < --------------------------------------------------------- +local math, minetest, nodecore, pairs, type + = math, minetest, nodecore, pairs, type +local math_pow + = math.pow +-- LUALOCALS > --------------------------------------------------------- + +--[[ +Nodes that have an "alternate_loose = { ... }" definition when +registered will be registered as a pair, one being the "loose" version +and the other being the normal "solid" one. Solid-specific attributes +can be set via "alternate_solid = { ... }". The solid version will +transform to the loose one when dug, and the loose to solid when +pummeled. +--]] + +local looseimg = "^nc_api_loose.png" + +nodecore.register_on_register_item(function(name, def) + if def.type ~= "node" then return end + + local loose = def.alternate_loose + if not loose then return end + + if not loose.tiles then + loose.tiles = nodecore.underride({}, def.tiles) + for k, v in pairs(loose.tiles) do + if type(v) == "string" then + loose.tiles[k] = v .. looseimg + elseif type(v) == "table" then + loose.tiles[k] = nodecore.underride({ + name = v.name .. looseimg + }, v) + end + end + end + + nodecore.underride(loose, def) + + loose.name = name .. "_loose" + if loose.oldnames then + for k, v in pairs(loose.oldnames) do + loose.oldnames[k] = v .. "_loose" + end + end + loose.description = "Loose " .. loose.description + loose.groups = nodecore.underride({}, loose.groups or {}) + loose.groups.falling_node = 1 + loose.groups.loose_repack = 1 + + if loose.groups.crumbly and not loose.no_repack then + minetest.after(0, function() + nodecore.register_craft({ + label = "repack " .. loose.name, + action = "pummel", + nodes = { + {match = loose.name, replace = name} + }, + toolgroups = {thumpy = loose.repack_level or 1}, + }) + end) + end + + loose.alternate_loose = nil + loose.alternate_solid = nil + loose.repack_to = name + minetest.register_node(loose.name, loose) + + local solid = nodecore.underride(def.alternate_solid or {}, def) + solid.drop_in_place = solid.drop_in_place or loose.name + + solid.alternate_loose = nil + solid.alternate_solid = nil + minetest.register_node(name, solid) + + return true + end) + +nodecore.register_soaking_abm({ + label = "loose self-repacking", + nodenames = {"group:loose_repack"}, + interval = 10, + chance = 1, + limited_max = 100, + limited_alert = 1000, + soakrate = function(pos, node) + local bnode = minetest.get_node({x = pos.x, y = pos.y - 1, z = pos.z}) + local bdef = minetest.registered_items[bnode.name] or {} + if (not bdef.groups) or bdef.groups.falling_node then return false end + + local weight = 1 + for dy = 1, 8 do + local n = minetest.get_node({x = pos.x, y = pos.y + dy, z = pos.z}) + local def = minetest.registered_items[n.name] or {} + if def and def.groups and def.groups.falling_node then + local w = def.crush_damage or 1 + if w < 1 then w = 1 end + weight = weight + w + end + end + local def = minetest.registered_items[node.name] or {} + return weight * 2 / math_pow(2, def.repack_level or 1) + end, + soakcheck = function(data, pos, node) + if data.total < 100 then return end + local def = minetest.registered_items[node.name] or {} + return minetest.set_node(pos, {name = def.repack_to}) + end + }) diff --git a/mods/nc_api/item_drop_in_place.lua b/mods/nc_api/item_drop_in_place.lua new file mode 100644 index 0000000..00c5402 --- /dev/null +++ b/mods/nc_api/item_drop_in_place.lua @@ -0,0 +1,38 @@ +-- LUALOCALS < --------------------------------------------------------- +local ItemStack, minetest, nodecore, pairs, type + = ItemStack, minetest, nodecore, pairs, type +-- LUALOCALS > --------------------------------------------------------- + +--[[ +Nodes with a "drop_in_place" spec transform on node drop by dropping +into place of existing node instead of digger inventory. +--]] + +nodecore.register_on_register_item(function(_, def) + if def.type ~= "node" then return end + local dip = def.drop_in_place + if dip then + if type(dip) ~= "table" then dip = {name = dip} end + def.drop = def.drop or "" + def.node_dig_prediction = def.node_dig_prediction or dip.name + local st = def.silktouch + if st == nil then + st = {} + for k, v in pairs(def.groups or {}) do + st[k] = v + 5 + end + end + def.after_dig_node = def.after_dig_node or function(pos, node, _, digger) + if st and digger and nodecore.toolspeed( + digger:get_wielded_item(), st) then + local stack = ItemStack(node.name) + stack = digger:get_inventory():add_item("main", + stack:to_string()) + if stack:is_empty() then return end + do return nodecore.item_eject(pos, stack) end + end + dip.param2 = node.param2 + minetest.set_node(pos, dip) + end + end + end) diff --git a/mods/nc_api/item_falling_repose.lua b/mods/nc_api/item_falling_repose.lua new file mode 100644 index 0000000..8825647 --- /dev/null +++ b/mods/nc_api/item_falling_repose.lua @@ -0,0 +1,109 @@ +-- LUALOCALS < --------------------------------------------------------- +local math, minetest, nodecore, pairs + = math, minetest, nodecore, pairs +local math_random + = math.random +-- LUALOCALS > --------------------------------------------------------- + +--[[ +Nodes with the "falling_repose" group will not only fall if unsupported +from below, but if there is a sufficient drop off the sides, so simulate +an "angle of repose." +--]] + +function nodecore.falling_repose_drop(posfrom, posto, node) + minetest.spawn_falling_node(posto, node, minetest.get_meta(posfrom)) + minetest.remove_node(posfrom) + posfrom.y = posfrom.y + 1 + return nodecore.fallcheck(posfrom) +end + +nodecore.register_on_register_item(function(_, def) + if def.type ~= "node" then return end + + def.groups = def.groups or {} + + if def.groups.falling_repose then def.groups.falling_node = 1 end + + def.repose_drop = def.repose_drop or nodecore.falling_repose_drop + end) + +function minetest.spawn_falling_node(pos, node, meta) + node = node or minetest.get_node(pos) + if node.name == "air" or node.name == "ignore" then + return false + end + local obj = minetest.add_entity(pos, "__builtin:falling_node") + if obj then + obj:get_luaentity():set_node(node, meta or minetest.get_meta(pos):to_table()) + minetest.remove_node(pos) + return true + end + return false +end + +local function check_empty(pos, dx, dy, dz) + for ndy = dy, 1 do + local p = {x = pos.x + dx, y = pos.y + ndy, z = pos.z + dz} + if not nodecore.buildable_to(p) then return end + end + return {x = pos.x + dx, y = pos.y, z = pos.z + dz} +end +function nodecore.falling_repose_check(pos) + if minetest.check_single_for_falling(pos) then return end + local node = minetest.get_node(pos) + local def = minetest.registered_items[node.name] or {} + local repose = def.groups and def.groups.falling_repose + if not repose then return end + + -- Reposing nodes can always sit comfortably atop + -- a non-moving node; it's only when stacked on other + -- falling nodes that they can slip off. + local sitdef = minetest.registered_items[minetest.get_node( + {x = pos.x, y = pos.y - 1, z = pos.z}).name] + if not (sitdef and sitdef.groups and sitdef.groups.falling_node) + then return end + + local open = {} + local ok = check_empty(pos, 1, -repose, 0) + if ok then open[1] = ok end + ok = check_empty(pos, -1, -repose, 0) + if ok then open[#open + 1] = ok end + ok = check_empty(pos, 0, -repose, 1) + if ok then open[#open + 1] = ok end + ok = check_empty(pos, 0, -repose, -1) + if ok then open[#open + 1] = ok end + if #open < 1 then return end + return def.repose_drop(pos, open[math_random(1, #open)], node) +end + +local reposeq +local qqty +local qmax = 100 +local function reposeall() + for _, v in pairs(reposeq) do v() end + reposeq = nil + qqty = nil +end +nodecore.register_limited_abm({ + label = "Falling Repose", + nodenames = {"group:falling_repose"}, + neighbors = {"air"}, + interval = 2, + chance = 5, + action = function(pos) + if not reposeq then + reposeq = {} + qqty = 0 + minetest.after(0, reposeall) + end + local f = function() nodecore.falling_repose_check(pos) end + if #reposeq > qmax then + local i = math_random(1, qqty) + if i < qmax then reposeq[i] = f end + else + reposeq[#reposeq + 1] = f + end + qqty = qqty + 1 + end + }) diff --git a/mods/nc_api/item_group_visinv.lua b/mods/nc_api/item_group_visinv.lua new file mode 100644 index 0000000..730f71d --- /dev/null +++ b/mods/nc_api/item_group_visinv.lua @@ -0,0 +1,196 @@ +-- LUALOCALS < --------------------------------------------------------- +local ItemStack, math, minetest, nodecore, pairs, setmetatable, type, + vector + = ItemStack, math, minetest, nodecore, pairs, setmetatable, type, + vector +local math_floor, math_pi, math_random, math_sqrt + = math.floor, math.pi, math.random, math.sqrt +-- LUALOCALS > --------------------------------------------------------- + +--[[ +Helpers for visible inventory. Use "visinv" node group. +Sets up on_construct, after_destruct and an ABM to manage +the visual entities. +--]] + +local modname = minetest.get_current_modname() + +------------------------------------------------------------------------ +-- VISIBLE STACK ENTITY + +function nodecore.stackentprops(stack, yaw, rotate) + local props = { + hp_max = 1, + physical = false, + collide_with_objects = false, + collisionbox = {0, 0, 0, 0, 0, 0}, + visual = "wielditem", + visual_size = {x = 0.4, y = 0.4 }, + textures = {""}, + spritediv = {x = 1, y = 1}, + initial_sprite_basepos = {x = 0, y = 0}, + is_visible = false, + static_save = false + } + local scale = 0 + yaw = yaw or 0 + if stack then + if type(stack) == "string" then stack = ItemStack(stack) end + props.is_visible = not stack:is_empty() + props.textures[1] = stack:get_name() + + local ratio = stack:get_count() / stack:get_stack_max() + scale = math_sqrt(ratio) * 0.15 + 0.25 + props.visual_size = {x = scale, y = scale} + + props.automatic_rotate = rotate + and rotate * 2 / math_sqrt(math_sqrt(ratio)) or nil + + if ratio == 1 then ratio = 1 - (stack:get_wear() / 65536) end + + if ratio ~= 1 then yaw = yaw + 1/8 + 3/8 * (1 - ratio) end + yaw = yaw - 2 * math_floor(yaw / 2) + end + return props, scale, yaw * math_pi / 2 +end + +minetest.register_entity(modname .. ":stackent", { + initial_properties = nodecore.stackentprops(), + is_stack = true, + itemcheck = function(self) + local pos = self.object:get_pos() + local stack = nodecore.stack_get(pos) + if not stack or stack:is_empty() then return self.object:remove() end + + local rp = vector.round(pos) + local props, scale, yaw = nodecore.stackentprops(stack, + rp.x * 3 + rp.y * 5 + rp.z * 7) + rp.y = rp.y + scale - 31/64 + + local obj = self.object + obj:set_properties(props) + obj:set_yaw(yaw) + obj:set_pos(rp) + end, + on_activate = function(self) + self.cktime = 0.00001 + end, + on_step = function(self, dtime) + self.cktime = (self.cktime or 0) - dtime + if self.cktime > 0 then return end + self.cktime = 1 + return self:itemcheck() + end + }) + +function nodecore.visinv_update_ents(pos, node) + node = node or minetest.get_node(pos) + local def = minetest.registered_items[node.name] or {} + local max = def.groups and def.groups.visinv and 1 or 0 + + local found = {} + for _, v in pairs(minetest.get_objects_inside_radius(pos, 0.5)) do + if v and v.get_luaentity and v:get_luaentity() + and v:get_luaentity().is_stack then + found[#found + 1] = v + end + end + + if #found < max then + minetest.add_entity(pos, modname .. ":stackent") + else + while #found > max do + found[#found]:remove() + found[#found] = nil + end + end + + return found +end + +------------------------------------------------------------------------ +-- ITEM ENT APPEARANCE + +local bii = minetest.registered_entities["__builtin:item"] +local item = { + set_item = function(self, ...) + local realobj = self.object + self.object = {} + setmetatable(self.object, { + __index = { + set_properties = function() end + } + }) + bii.set_item(self, ...) + self.object = realobj + + self.rotdir = self.rotdir or math_random(1, 2) * 2 - 3 + local p, s = nodecore.stackentprops(self.itemstring, 0, self.rotdir) + p.physical = true + s = s / math_sqrt(2) + p.collisionbox = {-s, -s, -s, s, s, s} + return realobj:set_properties(p) + end +} +setmetatable(item, bii) +minetest.register_entity(":__builtin:item", item) + +------------------------------------------------------------------------ +-- NODE REGISTRATION HELPERS + +function nodecore.visinv_on_construct(pos) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + inv:set_size("solo", 1) + nodecore.visinv_update_ents(pos) +end + +function nodecore.visinv_after_destruct(pos) + nodecore.visinv_update_ents(pos) + nodecore.fallcheck(pos) +end + +nodecore.register_on_register_item(function(_, def) + if def.type ~= "node" then return end + + def.groups = def.groups or {} + + if def.groups.visinv then + def.on_construct = def.on_construct or nodecore.visinv_on_construct + def.after_destruct = def.after_destruct or nodecore.visinv_after_destruct + end + end) + +nodecore.register_limited_abm({ + label = "VisInv Check", + nodenames = {"group:visinv"}, + interval = 1, + chance = 1, + action = function(...) return nodecore.visinv_update_ents(...) end + }) + +------------------------------------------------------------------------ +-- DIG INVENTORY + +local digpos +local old_node_dig = minetest.node_dig +minetest.node_dig = function(pos, ...) + nodecore.stack_sounds(pos, "dug") + local function helper(...) + digpos = nil + return ... + end + digpos = pos + return helper(old_node_dig(pos, ...)) +end +local old_get_node_drops = minetest.get_node_drops +minetest.get_node_drops = function(...) + local drops = old_get_node_drops(...) + if not digpos then return drops end + drops = drops or {} + local stack = nodecore.stack_get(digpos) + if stack and not stack:is_empty() then + drops[#drops + 1] = stack + end + return drops +end diff --git a/mods/nc_api/item_oldnames.lua b/mods/nc_api/item_oldnames.lua new file mode 100644 index 0000000..0050514 --- /dev/null +++ b/mods/nc_api/item_oldnames.lua @@ -0,0 +1,14 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore, pairs + = minetest, nodecore, pairs +-- LUALOCALS > --------------------------------------------------------- + +nodecore.register_on_register_item(function(name, def) + if def.oldnames then + for _, v in pairs(def.oldnames) do + if not minetest.registered_items[v] then + minetest.register_alias(v, name) + end + end + end + end) diff --git a/mods/nc_api/item_on_register.lua b/mods/nc_api/item_on_register.lua new file mode 100644 index 0000000..0fc8553 --- /dev/null +++ b/mods/nc_api/item_on_register.lua @@ -0,0 +1,17 @@ +-- LUALOCALS < --------------------------------------------------------- +local ipairs, minetest, nodecore + = ipairs, minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +nodecore.register_on_register_item, +nodecore.registered_on_register_item += nodecore.mkreg() + +local oldreg = minetest.register_item +function minetest.register_item(name, def, ...) + for _, v in ipairs(nodecore.registered_on_register_item) do + local x = v(name, def, ...) + if x then return x end + end + return oldreg(name, def, ...) +end diff --git a/mods/nc_api/item_punch_sounds.lua b/mods/nc_api/item_punch_sounds.lua new file mode 100644 index 0000000..24e6a59 --- /dev/null +++ b/mods/nc_api/item_punch_sounds.lua @@ -0,0 +1,40 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore + = minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +local lasthit = {} + +minetest.register_on_punchnode(function(pos, node, puncher) + if not puncher then return end + local pname = puncher:get_player_name() + local now = minetest.get_us_time() / 1000000 + local last = lasthit[pname] or 0 + if now - last < 0.25 then return end + lasthit[pname] = now + + local def = minetest.registered_items[node.name] or {} + local wield = puncher:get_wielded_item() + if (not def.sounds) or (not def.groups) + or (not nodecore.toolspeed(wield, def.groups)) then + nodecore.node_sound(pos, "dig") + else + nodecore.node_sound(pos, "dig", + {except = puncher}) + end + + if wield:get_wear() >= (65536 * 0.95) then + minetest.sound_play("nc_api_toolwear", + {object = puncher, gain = 0.5}) + end + end) + +minetest.register_on_dignode(function(pos, node, digger) + return nodecore.node_sound(pos, "dug", + {node = node, except = digger}) + end) + +minetest.register_on_placenode(function(pos, node, placer) + return nodecore.node_sound(pos, "place", + {node = node, except = placer}) + end) diff --git a/mods/nc_api/item_tool_sounds.lua b/mods/nc_api/item_tool_sounds.lua new file mode 100644 index 0000000..433a492 --- /dev/null +++ b/mods/nc_api/item_tool_sounds.lua @@ -0,0 +1,11 @@ +-- LUALOCALS < --------------------------------------------------------- +local nodecore + = nodecore +-- LUALOCALS > --------------------------------------------------------- + +nodecore.register_on_register_item(function(_, def) + if def.type == "tool" then + def.sound = def.sound or {} + def.sound.breaks = def.sound.breaks or {name = "nc_api_toolbreak", gain = 1} + end + end) diff --git a/mods/nc_api/item_tool_wears_to.lua b/mods/nc_api/item_tool_wears_to.lua new file mode 100644 index 0000000..c99b002 --- /dev/null +++ b/mods/nc_api/item_tool_wears_to.lua @@ -0,0 +1,20 @@ +-- LUALOCALS < --------------------------------------------------------- +local ItemStack, minetest, nodecore + = ItemStack, minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +nodecore.register_on_register_item(function(_, def) + if def.tool_wears_to then + def.after_use = def.after_use or function(what, who, _, dp) + what:add_wear(dp.wear) + if what:get_count() == 0 then + if def.sound and def.sound.breaks then + minetest.sound_play(def.sound.breaks, + {object = who, gain = 0.5}) + end + return ItemStack(def.tool_wears_to) + end + return what + end + end + end) diff --git a/mods/nc_api/locale/nc_api.ja.tr b/mods/nc_api/locale/nc_api.ja.tr new file mode 100644 index 0000000..204837c --- /dev/null +++ b/mods/nc_api/locale/nc_api.ja.tr @@ -0,0 +1,4 @@ +# textdomain: nc_api +(C)2018-2019 by Aaron Suen =(C)2018-2019 から Aaron Suen +(and 1 more hint)=(さらに1つのヒント) +(and @1 more hints)=(さらに@1つのヒント) diff --git a/mods/nc_api/locale/nc_api.pt.tr b/mods/nc_api/locale/nc_api.pt.tr new file mode 100644 index 0000000..391279c --- /dev/null +++ b/mods/nc_api/locale/nc_api.pt.tr @@ -0,0 +1,145 @@ +# textdomain: nc_api +(C)2018-2019 by Aaron Suen =(C)2018-2019 por Aaron Suen +(and 1 more hint)=( e mais 1 dica) +(and @1 more hints)=(e mais @1 dicas) +- Crafting is done by building recipes in-world.=- A Criação de Itens é feita construindo as receitas pelo mundo. +- If a recipe exists, you will see a special particle effect.=- Se uma receita existe, você verá um efeito especial de partícula sair do node. +- Items picked up try to fit into the current selected slot first.=- Os itens pegados são primeiramente armazenados no espaço atualmente selecionado. +- Order and specific face of placement may matter for crafting.=- A ordem e a face em que os itens são colocados pode importar no processo de criação. +- Recipes are time-based, punching faster does not speed up.=- Receitas são cronometradas, bater mais forte não afetará a velocidade delas. +- Sneak+drop to count out single items from stack.=- Use os comandos de agachar e soltar juntos para soltar um só item. +- Some recipes require "pummeling" a node.=- Algumas receitas necessitam que você "esmurre" um node. +- Stacks may be pummeled, exact item count may matter.=- Amontoados de itens podem ser esmurrados, pode ser que precise de uma quantidade exata do item. +- There is NO inventory screen.=- NÃO EXISTE tela de inventário. +- To pummel, punch a node repeatedly, WITHOUT digging.=- Para esmurrar, bata num node repetidamente, SEM QUEBRÁ-LO. +- Wielded item, target face, and surrounding nodes may matter.=- O item segurado, a face do objeto alvo e os nodes ao redor podem importar durante a criação de algo. +- You do not have to punch very fast (about 1 per second).=- Você não precisa bater muito rápido(basta 1 batida por segundo). +About=Sobre +Active Lens=Lente Ativa +Active Prism=Prisma Ativo +Aggregate=Agregar +Air=Ar +Annealed Lode=Veio Mineral Recozido +Annealed Lode Bar=Barra de Veio Mineral Recozida +Annealed Lode Hatchet=Machado de Veio Mineral Recozida +Annealed Lode Hatchet Head=Cabeça de Machado de Veio Mineral Recozida +Annealed Lode Mallet=Marreta de Veio Mineral Recozida +Annealed Lode Mallet Head=Cabeça de Marreta de Veio Mineral Recozida +Annealed Lode Mattock=Enxada de Veio Mineral Recozida +Annealed Lode Mattock Head=Cabeça de Enxada de Veio Mineral Recozida +Annealed Lode Pick=Picareta de Veio Mineral Recozida +Annealed Lode Pick Head=Cabeça de Picareta de Veio Mineral Recozida +Annealed Lode Prill=Lascas de Veio Mineral Recozida +Annealed Lode Rod=Vara de Veio Mineral Recozida +Annealed Lode Spade=Pá de Veio Mineral Recozida +Annealed Lode Spade Head=Cabeça de Pá de Veio Mineral Recozida +Ash=Cinza +Ash Lump=Nódulo de Cinzas +Burning Embers=Brasa Quente +Charcoal=Carvão Vegetal +Charcoal Lump=Nódulo de Carvão Vegetal +Chromatic Glass=Vidro Cromático +Clear Glass=Vidro Transparente +Cobble=Pedregulho +Cobble Hinged Panel=Painel de Pedregulho Articulado +Cobble Panel=Painel de Pedregulho +Crude Glass=Vidro Bruto +DEVELOPMENT VERSION=VERSÃO EM DESENVOLVIMENTO +Dirt=Terra +Eggcorn=Semente de Carvalho +Fire=Fogo +Float Glass=Vidro Float +Glowing Lode=Veio Mineral Incandescente +Glowing Lode Bar=Barra de Veio Mineral Incandescente +Glowing Lode Hatchet=Machado de Veio Mineral Incandescente +Glowing Lode Hatchet Head=Cabeça de Machado Veio Mineral Incandescente +Glowing Lode Mallet=Marreta de Veio Mineral Incandescente +Glowing Lode Mallet Head=Cabeça de Marreta Veio Mineral Incandescente +Glowing Lode Mattock=Enxada de Veio Mineral Incandescente +Glowing Lode Mattock Head=Cabeça de Enxada Veio Mineral Incandescente +Glowing Lode Pick=Picareta de Veio Mineral Incandescente +Glowing Lode Pick Head=Cabeça de Picareta de Veio Mineral Incandescente +Glowing Lode Prill=Lascas de Veio Mineral Incandescente +Glowing Lode Rod=Vara de Veio Mineral Incandescente +Glowing Lode Spade=Pá de Veio Mineral Incandescente +Glowing Lode Spade Head=Cabeça de Pá Veio Mineral Incandescente +Grass=Grama +Gravel=Cascalho +Hints=Dicas +Ignore=Ignorar +Injury=Ferir +Inventory=Inventário +Leaves=Folhas +Lens=Lente +Living Sponge=Esponja Viva +Lode Cobble=Veio de Pedregulho +Lode Ore=Veio Mineral +Loose Cobble=Pedregulho Solta +Loose Dirt=Terra Solta +Loose Gravel=Cascalho Solto +Loose Leaves=Folhas Soltas +Loose Lode Cobble=Veio de Pedregulho Solto +Loose Sand=Areia Solta +Molten Glass=Vidro Derretido +Molten Rock=Pedra Derretida +Player's Guide: Inventory Management=Guia do Jogador: Gerenciamento de Inventário +Player's Guide: Pummeling Recipes=Guia do Jogador: Receitas por Esmurrada +Prism=Prisma +Progress: @1 complete, @2 current, @3 future=Progresso: @1 completo(s), @2 atual(is), @3 futuro(s) +Pummel=Esmurrar +Sand=Areia +See included LICENSE file for full details and credits=Veja o arquivo de LICENSA incluso para créditos e maiores detalhes +Shining Lens=Lente Brilhante +Sponge=Esponja +Staff=Bastão +Stick=Graveto +Stone=Pedra +Stone Chip=Pedaço de Pedra +Stone-Tipped Hatchet=Machado com Ponta de Pedra +Stone-Tipped Mallet=Marreta com Ponta de Pedra +Stone-Tipped Pick=Picareta com Ponta de Pedra +Stone-Tipped Spade=Pá com Ponta de Pedra +Stump=Toco +Tempered Lode=Veio Mineral Temperado +Tempered Lode Bar=Barra de Veio Mineral Temperado +Tempered Lode Hatchet=Machado de Veio Mineral Temperado +Tempered Lode Hatchet Head=Cabeça de Machado de Veio Mineral Temperado +Tempered Lode Mallet=Marreta de Veio Mineral Temperado +Tempered Lode Mallet Head=Cabeça de Marreta de Veio Mineral Temperado +Tempered Lode Mattock=Enxada de Veio Mineral Temperado +Tempered Lode Mattock Head=Cabeça de Enxada de Veio Mineral Temperado +Tempered Lode Pick=Picareta de Veio Mineral Temperado +Tempered Lode Pick Head=Cabeça de Picareta de Veio Mineral Temperado +Tempered Lode Prill=Lascas de Veio Mineral Temperado +Tempered Lode Rod=Vara de Veio Mineral Temperado +Tempered Lode Spade=Pá de Veio Mineral Temperado +Tempered Lode Spade Head=Cabeça de Enxada de Veio Mineral Temperado +Tote (1 Slot)=Bolsa (1 Compartimento) +Tote (2 Slots)=Bolsa (2 Compartimentos) +Tote (3 Slots)=Bolsa (3 Compartimentos) +Tote (4 Slots)=Bolsa (4 Compartimentos) +Tote (5 Slots)=Bolsa (5 Compartimentos) +Tote (6 Slots)=Bolsa (6 Compartimentos) +Tote (7 Slots)=Bolsa (7 Compartimentos) +Tote (8 Slots)=Bolsa (8 Compartimentos) +Tote Handle=Alça de Bolsa +Tree Trunk=Tronco de Árvore +Unknown Item=Item Desconhecido +Water=Água +Wet Aggregate=Massa Úmida +Wet Sponge=Esponja Molhada +Wooden Adze=Enxó de Madeira +Wooden Frame=Estrutura de Madeira +Wooden Hatchet=Machado de Madeira +Wooden Hatchet Head=Cabeça de Machado de Madeira +Wooden Hinged Panel=Painel Articulado de Madeira +Wooden Ladder=Escada de Madeira +Wooden Mallet=Marreta de Madeira +Wooden Mallet Head=Cabeça de Marreta de Madeira +Wooden Panel=Painel de Madeira +Wooden Pick=Picareta de Madeira +Wooden Pick Head=Cabeça de Picareta de Madeira +Wooden Plank=Tábua de Madeira +Wooden Shelf=Estante de Madeira +Wooden Spade=Pá de Madeira +Wooden Spade Head=Cabeça de Pá de Madeira diff --git a/mods/nc_api/locale/nc_api.pt_BR.tr b/mods/nc_api/locale/nc_api.pt_BR.tr new file mode 100644 index 0000000..2594a21 --- /dev/null +++ b/mods/nc_api/locale/nc_api.pt_BR.tr @@ -0,0 +1,143 @@ +# textdomain: nc_api +(C)2018-2019 by Aaron Suen =(C)2018-2019 por Aaron Suen +- Crafting is done by building recipes in-world.=- A Criação de Itens é feita construindo as receitas pelo mundo. +- If a recipe exists, you will see a special particle effect.=- Se uma receita existe, você verá um efeito especial de partícula sair do node. +- Items picked up try to fit into the current selected slot first.=- Os itens pegados são primeiramente armazenados no espaço atualmente selecionado. +- Order and specific face of placement may matter for crafting.=- A ordem e a face em que os itens são colocados pode importar no processo de criação. +- Recipes are time-based, punching faster does not speed up.=- Receitas são cronometradas, bater mais forte não afetará a velocidade delas. +- Sneak+drop to count out single items from stack.=- Use os comandos de agachar e soltar juntos para soltar um só item. +- Some recipes require "pummeling" a node.=- Algumas receitas necessitam que você "esmurre" um node. +- Stacks may be pummeled, exact item count may matter.=- Amontoados de itens podem ser esmurrados, pode ser que precise de uma quantidade exata do item. +- There is NO inventory screen.=- NÃO EXISTE tela de inventário. +- To pummel, punch a node repeatedly, WITHOUT digging.=- Para esmurrar, bata num node repetidamente, SEM QUEBRÁ-LO. +- Wielded item, target face, and surrounding nodes may matter.=- O item segurado, a face do objeto alvo e os nodes ao redor podem importar durante a criação de algo. +- You do not have to punch very fast (about 1 per second).=- Você não precisa bater muito rápido(basta 1 batida por segundo). +About=Sobre +Active Lens=Lente Ativa +Active Prism=Prisma Ativo +Aggregate=Agregar +Air=Ar +Annealed Lode=Veio Mineral Recozido +Annealed Lode Bar=Barra de Veio Mineral Recozida +Annealed Lode Hatchet=Machado de Veio Mineral Recozida +Annealed Lode Hatchet Head=Cabeça de Machado de Veio Mineral Recozida +Annealed Lode Mallet=Marreta de Veio Mineral Recozida +Annealed Lode Mallet Head=Cabeça de Marreta de Veio Mineral Recozida +Annealed Lode Mattock=Enxada de Veio Mineral Recozida +Annealed Lode Mattock Head=Cabeça de Enxada de Veio Mineral Recozida +Annealed Lode Pick=Picareta de Veio Mineral Recozida +Annealed Lode Pick Head=Cabeça de Picareta de Veio Mineral Recozida +Annealed Lode Prill=Lascas de Veio Mineral Recozida +Annealed Lode Rod=Vara de Veio Mineral Recozida +Annealed Lode Spade=Pá de Veio Mineral Recozida +Annealed Lode Spade Head=Cabeça de Pá de Veio Mineral Recozida +Ash=Cinza +Ash Lump=Nódulo de Cinzas +Burning Embers=Brasa Quente +Charcoal=Carvão Vegetal +Charcoal Lump=Nódulo de Carvão Vegetal +Chromatic Glass=Vidro Cromático +Clear Glass=Vidro Transparente +Cobble=Pedregulho +Cobble Hinged Panel=Painel de Pedregulho Articulado +Cobble Panel=Painel de Pedregulho +Crude Glass=Vidro Bruto +DEVELOPMENT VERSION=VERSÃO EM DESENVOLVIMENTO +Dirt=Terra +Eggcorn=Semente de Carvalho +Fire=Fogo +Float Glass=Vidro Float +Glowing Lode=Veio Mineral Incandescente +Glowing Lode Bar=Barra de Veio Mineral Incandescente +Glowing Lode Hatchet=Machado de Veio Mineral Incandescente +Glowing Lode Hatchet Head=Cabeça de Machado Veio Mineral Incandescente +Glowing Lode Mallet=Marreta de Veio Mineral Incandescente +Glowing Lode Mallet Head=Cabeça de Marreta Veio Mineral Incandescente +Glowing Lode Mattock=Enxada de Veio Mineral Incandescente +Glowing Lode Mattock Head=Cabeça de Enxada Veio Mineral Incandescente +Glowing Lode Pick=Picareta de Veio Mineral Incandescente +Glowing Lode Pick Head=Cabeça de Picareta de Veio Mineral Incandescente +Glowing Lode Prill=Lascas de Veio Mineral Incandescente +Glowing Lode Rod=Vara de Veio Mineral Incandescente +Glowing Lode Spade=Pá de Veio Mineral Incandescente +Glowing Lode Spade Head=Cabeça de Pá Veio Mineral Incandescente +Grass=Grama +Gravel=Cascalho +Hints=Dicas +Ignore=Ignorar +Injury=Ferir +Inventory=Inventário +Leaves=Folhas +Lens=Lente +Living Sponge=Esponja Viva +Lode Cobble=Veio de Pedregulho +Lode Ore=Veio Mineral +Loose Cobble=Pedregulho Solta +Loose Dirt=Terra Solta +Loose Gravel=Cascalho Solto +Loose Leaves=Folhas Soltas +Loose Lode Cobble=Veio de Pedregulho Solto +Loose Sand=Areia Solta +Molten Glass=Vidro Derretido +Molten Rock=Pedra Derretida +Player's Guide: Inventory Management=Guia do Jogador: Gerenciamento de Inventário +Player's Guide: Pummeling Recipes=Guia do Jogador: Receitas por Esmurrada +Prism=Prisma +Progress: @1 complete, @2 current, @3 future=Progresso: @1 completo(s), @2 atual(is), @3 futuro(s) +Pummel=Esmurrar +Sand=Areia +See included LICENSE file for full details and credits=Veja o arquivo de LICENSA incluso para créditos e maiores detalhes +Shining Lens=Lente Brilhante +Sponge=Esponja +Staff=Bastão +Stick=Graveto +Stone=Pedra +Stone Chip=Pedaço de Pedra +Stone-Tipped Hatchet=Machado com Ponta de Pedra +Stone-Tipped Mallet=Marreta com Ponta de Pedra +Stone-Tipped Pick=Picareta com Ponta de Pedra +Stone-Tipped Spade=Pá com Ponta de Pedra +Stump=Toco +Tempered Lode=Veio Mineral Temperado +Tempered Lode Bar=Barra de Veio Mineral Temperado +Tempered Lode Hatchet=Machado de Veio Mineral Temperado +Tempered Lode Hatchet Head=Cabeça de Machado de Veio Mineral Temperado +Tempered Lode Mallet=Marreta de Veio Mineral Temperado +Tempered Lode Mallet Head=Cabeça de Marreta de Veio Mineral Temperado +Tempered Lode Mattock=Enxada de Veio Mineral Temperado +Tempered Lode Mattock Head=Cabeça de Enxada de Veio Mineral Temperado +Tempered Lode Pick=Picareta de Veio Mineral Temperado +Tempered Lode Pick Head=Cabeça de Picareta de Veio Mineral Temperado +Tempered Lode Prill=Lascas de Veio Mineral Temperado +Tempered Lode Rod=Vara de Veio Mineral Temperado +Tempered Lode Spade=Pá de Veio Mineral Temperado +Tempered Lode Spade Head=Cabeça de Enxada de Veio Mineral Temperado +Tote (1 Slot)=Bolsa (1 Compartimento) +Tote (2 Slots)=Bolsa (2 Compartimentos) +Tote (3 Slots)=Bolsa (3 Compartimentos) +Tote (4 Slots)=Bolsa (4 Compartimentos) +Tote (5 Slots)=Bolsa (5 Compartimentos) +Tote (6 Slots)=Bolsa (6 Compartimentos) +Tote (7 Slots)=Bolsa (7 Compartimentos) +Tote (8 Slots)=Bolsa (8 Compartimentos) +Tote Handle=Alça de Bolsa +Tree Trunk=Tronco de Árvore +Unknown Item=Item Desconhecido +Water=Água +Wet Aggregate=Massa Úmida +Wet Sponge=Esponja Molhada +Wooden Adze=Enxó de Madeira +Wooden Frame=Estrutura de Madeira +Wooden Hatchet=Machado de Madeira +Wooden Hatchet Head=Cabeça de Machado de Madeira +Wooden Hinged Panel=Painel Articulado de Madeira +Wooden Ladder=Escada de Madeira +Wooden Mallet=Marreta de Madeira +Wooden Mallet Head=Cabeça de Marreta de Madeira +Wooden Panel=Painel de Madeira +Wooden Pick=Picareta de Madeira +Wooden Pick Head=Cabeça de Picareta de Madeira +Wooden Plank=Tábua de Madeira +Wooden Shelf=Estante de Madeira +Wooden Spade=Pá de Madeira +Wooden Spade Head=Cabeça de Pá de Madeira diff --git a/mods/nc_api/locale/src/Makefile b/mods/nc_api/locale/src/Makefile new file mode 100644 index 0000000..227efb2 --- /dev/null +++ b/mods/nc_api/locale/src/Makefile @@ -0,0 +1,2 @@ +update: + cd .. && perl -w src/update.pl diff --git a/mods/nc_api/locale/src/en.txt b/mods/nc_api/locale/src/en.txt new file mode 100644 index 0000000..1df90a3 --- /dev/null +++ b/mods/nc_api/locale/src/en.txt @@ -0,0 +1,771 @@ +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-10-04 22:56+0000\n" +"PO-Revision-Date: 2019-10-04 22:56+0000\n" +"Last-Translator: Weblate Admin \n" +"Language-Team: English \n" +"Language: en\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 3.8\n" + +msgid "(C)2018-2019 by Aaron Suen " +msgstr "(C)2018-2019 by Aaron Suen " + +msgid "(and 1 more hint)" +msgstr "(and 1 more hint)" + +msgid "(and @1 more hints)" +msgstr "(and @1 more hints)" + +msgid "- "Furnaces" are not a thing; discover smelting with open flames." +msgstr "- "Furnaces" are not a thing; discover smelting with open flames." + +msgid "- "Torches" are not a thing; use fire as your first light source." +msgstr "[REMOVED]" + +msgid "- @1" +msgstr "- @1" + +msgid "- Can't dig trees or grass? Search for sticks in the canopy." +msgstr "- Can't dig trees or grass? Search for sticks in the canopy." + +msgid "- Crafting is done by building recipes in-world." +msgstr "- Crafting is done by building recipes in-world." + +msgid "- DONE: @1" +msgstr "- DONE: @1" + +msgid "- Drop items onto ground to create stack nodes. They do not decay." +msgstr "- Drop items onto ground to create stack nodes. They do not decay." + +msgid "- If a recipe exists, you will see a special particle effect." +msgstr "- If a recipe exists, you will see a special particle effect." + +msgid "- Items picked up try to fit into the current selected slot first." +msgstr "- Items picked up try to fit into the current selected slot first." + +msgid "- Order and specific face of placement may matter for crafting." +msgstr "- Order and specific face of placement may matter for crafting." + +msgid "- Ores may be hidden, but revealed by subtle clues in terrain." +msgstr "- Ores may be hidden, but revealed by subtle clues in terrain." + +msgid "- Recipes are time-based, punching faster does not speed up." +msgstr "- Recipes are time-based, punching faster does not speed up." + +msgid "- Sneak+drop to count out single items from stack." +msgstr "- Sneak+drop to count out single items from stack." + +msgid "- Some recipes require "pummeling" a node." +msgstr "- Some recipes require "pummeling" a node." + +msgid "- Stacks may be pummeled, exact item count may matter." +msgstr "- Stacks may be pummeled, exact item count may matter." + +msgid "- Stuck in a pit? Pummel surfaces barehanded to find places to climb." +msgstr "- Stuck in a pit? Pummel surfaces barehanded to find places to climb." + +msgid "- The game is challenging by design, sometimes frustrating. DON'T GIVE UP!" +msgstr "- The game is challenging by design, sometimes frustrating. DON'T GIVE UP!" + +msgid "- There is NO inventory screen." +msgstr "- There is NO inventory screen." + +msgid "- To pummel, punch a node repeatedly, WITHOUT digging." +msgstr "- To pummel, punch a node repeatedly, WITHOUT digging." + +msgid "- Trouble lighting a fire? Try using longer sticks, more tinder." +msgstr "- Trouble lighting a fire? Try using longer sticks, more tinder." + +msgid "- Wielded item, target face, and surrounding nodes may matter." +msgstr "- Wielded item, target face, and surrounding nodes may matter." + +msgid "- You do not have to punch very fast (about 1 per second)." +msgstr "- You do not have to punch very fast (about 1 per second)." + +msgid "About" +msgstr "About" + +msgid "Active Lens" +msgstr "Active Lens" + +msgid "Active Prism" +msgstr "Active Prism" + +msgid "Aggregate" +msgstr "Aggregate" + +msgid "Air" +msgstr "Air" + +msgid "Annealed Lode" +msgstr "Annealed Lode" + +msgid "Annealed Lode Bar" +msgstr "Annealed Lode Bar" + +msgid "Annealed Lode Hatchet" +msgstr "Annealed Lode Hatchet" + +msgid "Annealed Lode Hatchet Head" +msgstr "Annealed Lode Hatchet Head" + +msgid "Annealed Lode Mallet" +msgstr "Annealed Lode Mallet" + +msgid "Annealed Lode Mallet Head" +msgstr "Annealed Lode Mallet Head" + +msgid "Annealed Lode Mattock" +msgstr "Annealed Lode Mattock" + +msgid "Annealed Lode Mattock Head" +msgstr "Annealed Lode Mattock Head" + +msgid "Annealed Lode Pick" +msgstr "Annealed Lode Pick" + +msgid "Annealed Lode Pick Head" +msgstr "Annealed Lode Pick Head" + +msgid "Annealed Lode Prill" +msgstr "Annealed Lode Prill" + +msgid "Annealed Lode Rod" +msgstr "Annealed Lode Rod" + +msgid "Annealed Lode Spade" +msgstr "Annealed Lode Spade" + +msgid "Annealed Lode Spade Head" +msgstr "Annealed Lode Spade Head" + +msgid "Ash" +msgstr "Ash" + +msgid "Ash Lump" +msgstr "Ash Lump" + +msgid "Burning Embers" +msgstr "Burning Embers" + +msgid "Charcoal" +msgstr "Charcoal" + +msgid "Charcoal Lump" +msgstr "Charcoal Lump" + +msgid "Chromatic Glass" +msgstr "Chromatic Glass" + +msgid "Clear Glass" +msgstr "Clear Glass" + +msgid "Cobble" +msgstr "Cobble" + +msgid "Cobble Hinged Panel" +msgstr "Cobble Hinged Panel" + +msgid "Cobble Panel" +msgstr "Cobble Panel" + +msgid "Crude Glass" +msgstr "Crude Glass" + +msgid "DEVELOPMENT VERSION" +msgstr "DEVELOPMENT VERSION" + +msgid "Dirt" +msgstr "Dirt" + +msgid "Discord: https://discord.gg/SHq2tkb" +msgstr "Discord: https://discord.gg/SHq2tkb" + +msgid "Eggcorn" +msgstr "Eggcorn" + +msgid "Fire" +msgstr "Fire" + +msgid "Float Glass" +msgstr "Float Glass" + +msgid "GitLab: https://gitlab.com/sztest/nodecore" +msgstr "GitLab: https://gitlab.com/sztest/nodecore" + +msgid "Glowing Lode" +msgstr "Glowing Lode" + +msgid "Glowing Lode Bar" +msgstr "Glowing Lode Bar" + +msgid "Glowing Lode Hatchet" +msgstr "Glowing Lode Hatchet" + +msgid "Glowing Lode Hatchet Head" +msgstr "Glowing Lode Hatchet Head" + +msgid "Glowing Lode Mallet" +msgstr "Glowing Lode Mallet" + +msgid "Glowing Lode Mallet Head" +msgstr "Glowing Lode Mallet Head" + +msgid "Glowing Lode Mattock" +msgstr "Glowing Lode Mattock" + +msgid "Glowing Lode Mattock Head" +msgstr "Glowing Lode Mattock Head" + +msgid "Glowing Lode Pick" +msgstr "Glowing Lode Pick" + +msgid "Glowing Lode Pick Head" +msgstr "Glowing Lode Pick Head" + +msgid "Glowing Lode Prill" +msgstr "Glowing Lode Prill" + +msgid "Glowing Lode Rod" +msgstr "Glowing Lode Rod" + +msgid "Glowing Lode Spade" +msgstr "Glowing Lode Spade" + +msgid "Glowing Lode Spade Head" +msgstr "Glowing Lode Spade Head" + +msgid "Grass" +msgstr "Grass" + +msgid "Gravel" +msgstr "Gravel" + +msgid "Hints" +msgstr "Hints" + +msgid "Ignore" +msgstr "Ignore" + +msgid "Infused Annealed Lode Hatchet" +msgstr "Infused Annealed Lode Hatchet" + +msgid "Infused Annealed Lode Mallet" +msgstr "Infused Annealed Lode Mallet" + +msgid "Infused Annealed Lode Mattock" +msgstr "Infused Annealed Lode Mattock" + +msgid "Infused Annealed Lode Pick" +msgstr "Infused Annealed Lode Pick" + +msgid "Infused Annealed Lode Spade" +msgstr "Infused Annealed Lode Spade" + +msgid "Infused Tempered Lode Hatchet" +msgstr "Infused Tempered Lode Hatchet" + +msgid "Infused Tempered Lode Mallet" +msgstr "Infused Tempered Lode Mallet" + +msgid "Infused Tempered Lode Mattock" +msgstr "Infused Tempered Lode Mattock" + +msgid "Infused Tempered Lode Pick" +msgstr "Infused Tempered Lode Pick" + +msgid "Infused Tempered Lode Spade" +msgstr "Infused Tempered Lode Spade" + +msgid "Injury" +msgstr "Injury" + +msgid "Inventory" +msgstr "Inventory" + +msgid "Leaves" +msgstr "Leaves" + +msgid "Lens" +msgstr "Lens" + +msgid "Living Sponge" +msgstr "Living Sponge" + +msgid "Lode Cobble" +msgstr "Lode Cobble" + +msgid "Lode Crate" +msgstr "Lode Crate" + +msgid "Lode Ore" +msgstr "Lode Ore" + +msgid "Loose Cobble" +msgstr "Loose Cobble" + +msgid "Loose Dirt" +msgstr "Loose Dirt" + +msgid "Loose Gravel" +msgstr "Loose Gravel" + +msgid "Loose Leaves" +msgstr "Loose Leaves" + +msgid "Loose Lode Cobble" +msgstr "Loose Lode Cobble" + +msgid "Loose Lux Cobble" +msgstr "Loose Lux Cobble" + +msgid "Loose Sand" +msgstr "Loose Sand" + +msgid "Lux Cobble" +msgstr "Lux Cobble" + +msgid "Lux Flow" +msgstr "Lux Flow" + +msgid "MIT License (http://www.opensource.org/licenses/MIT)" +msgstr "MIT License (http://www.opensource.org/licenses/MIT)" + +msgid "Molten Glass" +msgstr "Molten Glass" + +msgid "Molten Rock" +msgstr "Molten Rock" + +msgid "NodeCore" +msgstr "NodeCore" + +msgid "Not all game content is covered by hints. Explore!" +msgstr "Not all game content is covered by hints. Explore!" + +msgid "Player's Guide: Inventory Management" +msgstr "Player's Guide: Inventory Management" + +msgid "Player's Guide: Pummeling Recipes" +msgstr "Player's Guide: Pummeling Recipes" + +msgid "Player's Guide: Tips and Guidance" +msgstr "Player's Guide: Tips and Guidance" + +msgid "Prism" +msgstr "Prism" + +msgid "Progress: @1 complete, @2 current, @3 future" +msgstr "Progress: @1 complete, @2 current, @3 future" + +msgid "Pummel" +msgstr "Pummel" + +msgid "Sand" +msgstr "Sand" + +msgid "See included LICENSE file for full details and credits" +msgstr "See included LICENSE file for full details and credits" + +msgid "Shining Lens" +msgstr "Shining Lens" + +msgid "Sponge" +msgstr "Sponge" + +msgid "Staff" +msgstr "Staff" + +msgid "Stick" +msgstr "Stick" + +msgid "Stone" +msgstr "Stone" + +msgid "Stone Chip" +msgstr "Stone Chip" + +msgid "Stone-Tipped Hatchet" +msgstr "Stone-Tipped Hatchet" + +msgid "Stone-Tipped Mallet" +msgstr "Stone-Tipped Mallet" + +msgid "Stone-Tipped Pick" +msgstr "Stone-Tipped Pick" + +msgid "Stone-Tipped Spade" +msgstr "Stone-Tipped Spade" + +msgid "Stump" +msgstr "Stump" + +msgid "Tempered Lode" +msgstr "Tempered Lode" + +msgid "Tempered Lode Bar" +msgstr "Tempered Lode Bar" + +msgid "Tempered Lode Hatchet" +msgstr "Tempered Lode Hatchet" + +msgid "Tempered Lode Hatchet Head" +msgstr "Tempered Lode Hatchet Head" + +msgid "Tempered Lode Mallet" +msgstr "Tempered Lode Mallet" + +msgid "Tempered Lode Mallet Head" +msgstr "Tempered Lode Mallet Head" + +msgid "Tempered Lode Mattock" +msgstr "Tempered Lode Mattock" + +msgid "Tempered Lode Mattock Head" +msgstr "Tempered Lode Mattock Head" + +msgid "Tempered Lode Pick" +msgstr "Tempered Lode Pick" + +msgid "Tempered Lode Pick Head" +msgstr "Tempered Lode Pick Head" + +msgid "Tempered Lode Prill" +msgstr "Tempered Lode Prill" + +msgid "Tempered Lode Rod" +msgstr "Tempered Lode Rod" + +msgid "Tempered Lode Spade" +msgstr "Tempered Lode Spade" + +msgid "Tempered Lode Spade Head" +msgstr "Tempered Lode Spade Head" + +msgid "Tips" +msgstr "Tips" + +msgid "Tote (1 Slot)" +msgstr "Tote (1 Slot)" + +msgid "Tote (2 Slots)" +msgstr "Tote (2 Slots)" + +msgid "Tote (3 Slots)" +msgstr "Tote (3 Slots)" + +msgid "Tote (4 Slots)" +msgstr "Tote (4 Slots)" + +msgid "Tote (5 Slots)" +msgstr "Tote (5 Slots)" + +msgid "Tote (6 Slots)" +msgstr "Tote (6 Slots)" + +msgid "Tote (7 Slots)" +msgstr "Tote (7 Slots)" + +msgid "Tote (8 Slots)" +msgstr "Tote (8 Slots)" + +msgid "Tote Handle" +msgstr "Tote Handle" + +msgid "Tree Trunk" +msgstr "Tree Trunk" + +msgid "Unknown Item" +msgstr "Unknown Item" + +msgid "Water" +msgstr "Water" + +msgid "Wet Aggregate" +msgstr "Wet Aggregate" + +msgid "Wet Sponge" +msgstr "Wet Sponge" + +msgid "Wooden Adze" +msgstr "Wooden Adze" + +msgid "Wooden Frame" +msgstr "Wooden Frame" + +msgid "Wooden Hatchet" +msgstr "Wooden Hatchet" + +msgid "Wooden Hatchet Head" +msgstr "Wooden Hatchet Head" + +msgid "Wooden Hinged Panel" +msgstr "Wooden Hinged Panel" + +msgid "Wooden Ladder" +msgstr "Wooden Ladder" + +msgid "Wooden Mallet" +msgstr "Wooden Mallet" + +msgid "Wooden Mallet Head" +msgstr "Wooden Mallet Head" + +msgid "Wooden Panel" +msgstr "Wooden Panel" + +msgid "Wooden Pick" +msgstr "Wooden Pick" + +msgid "Wooden Pick Head" +msgstr "Wooden Pick Head" + +msgid "Wooden Plank" +msgstr "Wooden Plank" + +msgid "Wooden Shelf" +msgstr "Wooden Shelf" + +msgid "Wooden Spade" +msgstr "Wooden Spade" + +msgid "Wooden Spade Head" +msgstr "Wooden Spade Head" + +msgid "activate a lens" +msgstr "activate a lens" + +msgid "assemble a staff from sticks" +msgstr "assemble a staff from sticks" + +msgid "assemble a wooden frame from staves" +msgstr "assemble a wooden frame from staves" + +msgid "assemble a wooden ladder from sticks" +msgstr "assemble a wooden ladder from sticks" + +msgid "assemble a wooden shelf from frames and planks" +msgstr "assemble a wooden shelf from frames and planks" + +msgid "assemble a wooden tool" +msgstr "assemble a wooden tool" + +msgid "assemble an adze out of sticks" +msgstr "assemble an adze out of sticks" + +msgid "assemble an annealed lode tote handle" +msgstr "assemble an annealed lode tote handle" + +msgid "bash a plank into sticks" +msgstr "bash a plank into sticks" + +msgid "break cobble into chips" +msgstr "break cobble into chips" + +msgid "carve a wooden plank completely" +msgstr "carve a wooden plank completely" + +msgid "carve wooden tool heads from planks" +msgstr "carve wooden tool heads from planks" + +msgid "chip chromatic glass into prisms" +msgstr "chip chromatic glass into prisms" + +msgid "chisel a hinge groove into a wooden plank" +msgstr "chisel a hinge groove into a wooden plank" + +msgid "chisel a hinge groove into cobble" +msgstr "chisel a hinge groove into cobble" + +msgid "chop a glowing lode cube into prills" +msgstr "chop a glowing lode cube into prills" + +msgid "chop a lode crate back apart" +msgstr "chop a lode crate back apart" + +msgid "chop chromatic glass into lenses" +msgstr "chop chromatic glass into lenses" + +msgid "chop lode a rod back into bars" +msgstr "chop lode a rod back into bars" + +msgid "chop up charcoal" +msgstr "chop up charcoal" + +msgid "cold-forge annealed lode prills into a tool head" +msgstr "cold-forge annealed lode prills into a tool head" + +msgid "cold-forge lode down completely" +msgstr "cold-forge lode down completely" + +msgid "cool molten glass into crude glass" +msgstr "cool molten glass into crude glass" + +msgid "cut down a tree" +msgstr "cut down a tree" + +msgid "dig up a tree stump" +msgstr "dig up a tree stump" + +msgid "dig up dirt" +msgstr "dig up dirt" + +msgid "dig up gravel" +msgstr "dig up gravel" + +msgid "dig up lode ore" +msgstr "dig up lode ore" + +msgid "dig up lux cobble" +msgstr "dig up lux cobble" + +msgid "dig up sand" +msgstr "dig up sand" + +msgid "dig up stone" +msgstr "dig up stone" + +msgid "dry out a sponge" +msgstr "dry out a sponge" + +msgid "find a lode stratum" +msgstr "find a lode stratum" + +msgid "find a sponge" +msgstr "find a sponge" + +msgid "find a stick" +msgstr "find a stick" + +msgid "find an eggcorn" +msgstr "find an eggcorn" + +msgid "find ash" +msgstr "find ash" + +msgid "find charcoal" +msgstr "find charcoal" + +msgid "find deep stone strata" +msgstr "find deep stone strata" + +msgid "find dry (loose) leaves" +msgstr "find dry (loose) leaves" + +msgid "find lode ore" +msgstr "find lode ore" + +msgid "find lux" +msgstr "find lux" + +msgid "find molten rock" +msgstr "find molten rock" + +msgid "hammer a lode bar back to a prill" +msgstr "hammer a lode bar back to a prill" + +msgid "hammer a lode prill into a bar" +msgstr "hammer a lode prill into a bar" + +msgid "hammer a metal rod into a cobble panel" +msgstr "hammer a metal rod into a cobble panel" + +msgid "hammer a staff into a lubricated wooden panel" +msgstr "hammer a staff into a lubricated wooden panel" + +msgid "hammer lode bars into a rod" +msgstr "hammer lode bars into a rod" + +msgid "harvest a sponge" +msgstr "harvest a sponge" + +msgid "https://content.minetest.net/packages/Warr1024/nodecore/" +msgstr "https://content.minetest.net/packages/Warr1024/nodecore/" + +msgid "lubricate a cobble panel with graphite" +msgstr "lubricate a cobble panel with graphite" + +msgid "lubricate a wooden panel with graphite" +msgstr "lubricate a wooden panel with graphite" + +msgid "lux-infuse a lode tool" +msgstr "lux-infuse a lode tool" + +msgid "make an anvil by tempering a lode cube" +msgstr "make an anvil by tempering a lode cube" + +msgid "make fire by rubbing sticks together" +msgstr "make fire by rubbing sticks together" + +msgid "make wet aggregate" +msgstr "make wet aggregate" + +msgid "melt down lode metal from lode cobble" +msgstr "melt down lode metal from lode cobble" + +msgid "melt sand into glass" +msgstr "melt sand into glass" + +msgid "mix gravel into ash to make aggregate" +msgstr "mix gravel into ash to make aggregate" + +msgid "mold molten glass into clear glass" +msgstr "mold molten glass into clear glass" + +msgid "mold molten glass into float glass" +msgstr "mold molten glass into float glass" + +msgid "observe a lux reaction" +msgstr "observe a lux reaction" + +msgid "observe lux criticality" +msgstr "observe lux criticality" + +msgid "pack high-quality charcoal" +msgstr "pack high-quality charcoal" + +msgid "pack stone chips back into cobble" +msgstr "pack stone chips back into cobble" + +msgid "plant an eggcorn" +msgstr "plant an eggcorn" + +msgid "produce light from a lens" +msgstr "produce light from a lens" + +msgid "put a stone tip onto a wooden tool" +msgstr "put a stone tip onto a wooden tool" + +msgid "quench molten glass into chromatic glass" +msgstr "quench molten glass into chromatic glass" + +msgid "scale a sheer overhang" +msgstr "scale a sheer overhang" + +msgid "scale a sheer wall" +msgstr "scale a sheer wall" + +msgid "sinter glowing lode prills into a cube" +msgstr "sinter glowing lode prills into a cube" + +msgid "solder lode rods into crates" +msgstr "solder lode rods into crates" + +msgid "split a tree trunk into planks" +msgstr "split a tree trunk into planks" + +msgid "squeeze out a sponge" +msgstr "squeeze out a sponge" + +msgid "temper a lode tool head" +msgstr "temper a lode tool head" + +msgid "weld glowing lode pick and spade heads together" +msgstr "weld glowing lode pick and spade heads together" diff --git a/mods/nc_api/locale/src/fr.txt b/mods/nc_api/locale/src/fr.txt new file mode 100644 index 0000000..4f8f6e6 --- /dev/null +++ b/mods/nc_api/locale/src/fr.txt @@ -0,0 +1,2 @@ +msgid "" +msgstr "X-Generator: Weblate\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit" \ No newline at end of file diff --git a/mods/nc_api/locale/src/it.txt b/mods/nc_api/locale/src/it.txt new file mode 100644 index 0000000..4f8f6e6 --- /dev/null +++ b/mods/nc_api/locale/src/it.txt @@ -0,0 +1,2 @@ +msgid "" +msgstr "X-Generator: Weblate\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit" \ No newline at end of file diff --git a/mods/nc_api/locale/src/ja.txt b/mods/nc_api/locale/src/ja.txt new file mode 100644 index 0000000..8b0fa25 --- /dev/null +++ b/mods/nc_api/locale/src/ja.txt @@ -0,0 +1,21 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2019-10-04 22:59+0000\n" +"Last-Translator: Terifo \n" +"Language-Team: Japanese \n" +"Language: ja\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 3.8\n" + +msgid "(and @1 more hints)" +msgstr "(さらに@1つのヒント)" + +msgid "(and 1 more hint)" +msgstr "(さらに1つのヒント)" + +msgid "(C)2018-2019 by Aaron Suen " +msgstr "(C)2018-2019 から Aaron Suen " diff --git a/mods/nc_api/locale/src/pt.txt b/mods/nc_api/locale/src/pt.txt new file mode 100644 index 0000000..8902c76 --- /dev/null +++ b/mods/nc_api/locale/src/pt.txt @@ -0,0 +1,633 @@ +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-12 14:44+0000\n" +"PO-Revision-Date: 2019-10-04 22:56+0000\n" +"Last-Translator: Terifo \n" +"Language-Team: Portuguese \n" +"Language: pt\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 3.8\n" + +msgid "(C)2018-2019 by Aaron Suen " +msgstr "(C)2018-2019 por Aaron Suen " + +msgid "- Crafting is done by building recipes in-world." +msgstr "- A Criação de Itens é feita construindo as receitas pelo mundo." + +msgid "- Drop items onto ground to create stack nodes. They do not decay." +msgstr "- Solte itens no chão para criar um node de itens amontoados. Eles não desaparecem." + +msgid "- If a recipe exists, you will see a special particle effect." +msgstr "- Se uma receita existe, você verá um efeito especial de partícula sair do node." + +msgid "- Items picked up try to fit into the current selected slot first." +msgstr "- Os itens pegados são primeiramente armazenados no espaço atualmente selecionado." + +msgid "- Order and specific face of placement may matter for crafting." +msgstr "- A ordem e a face em que os itens são colocados pode importar no processo de criação." + +msgid "- Recipes are time-based, punching faster does not speed up." +msgstr "- Receitas são cronometradas, bater mais forte não afetará a velocidade delas." + +msgid "- Sneak+drop to count out single items from stack." +msgstr "- Use os comandos de agachar e soltar juntos para soltar um só item." + +msgid "- Some recipes require "pummeling" a node." +msgstr "- Algumas receitas necessitam que você "esmurre" um node." + +msgid "- Stacks may be pummeled, exact item count may matter." +msgstr "- Amontoados de itens podem ser esmurrados, pode ser que precise de uma quantidade exata do item." + +msgid "- There is NO inventory screen." +msgstr "- NÃO EXISTE tela de inventário." + +msgid "- To pummel, punch a node repeatedly, WITHOUT digging." +msgstr "- Para esmurrar, bata num node repetidamente, SEM QUEBRÁ-LO." + +msgid "- Wielded item, target face, and surrounding nodes may matter." +msgstr "- O item segurado, a face do objeto alvo e os nodes ao redor podem importar durante a criação de algo." + +msgid "- You do not have to punch very fast (about 1 per second)." +msgstr "- Você não precisa bater muito rápido(basta 1 batida por segundo)." + +msgid "...and 1 more hint..." +msgstr "...e mais 1 dica..." + +msgid "...and @1 more hints..." +msgstr "...e mais @1 dicas..." + +msgid "...have you activated a lens yet?" +msgstr "...você já ativou uma lente?" + +msgid "...have you assembled a staff from sticks yet?" +msgstr "...você já montou um bastão usando gravetos?" + +msgid "...have you assembled a wooden frame yet?" +msgstr "...você já montou um estrutura de madeira?" + +msgid "...have you assembled a wooden ladder yet?" +msgstr "...você já montou uma escada de madeira?" + +msgid "...have you assembled a wooden shelf yet?" +msgstr "...você já montou uma estante de madeira?" + +msgid "...have you assembled a wooden tool yet?" +msgstr "...você já montou uma ferramenta de madeira?" + +msgid "...have you assembled an adze out of sticks yet?" +msgstr "...você já montou um enxó usando gravetos?" + +msgid "...have you assembled an annealed lode tote handle yet?" +msgstr "...você já montou uma alça de bolsa recozida?" + +msgid "...have you bashed a plank into sticks yet?" +msgstr "...você já quebrou uma tábua em gravetos batendo nela?" + +msgid "...have you broken cobble into chips yet?" +msgstr "...você já quebrou pedregulho em pedaços?" + +msgid "...have you carved a wooden plank completely yet?" +msgstr "...você já entalhou completamente uma tábua de madeira?" + +msgid "...have you carved wooden tool heads from planks yet?" +msgstr "...você já transformou uma tábua em cabeças de ferramentas, entalhando a madeira?" + +msgid "...have you chipped chromatic glass into prisms yet?" +msgstr "...você já quebrou um vidro cromático em prismas, lascando o vidro?" + +msgid "...have you chopped a lode cube into prills yet?" +msgstr "...você já quebrou um veio mineral em lascas, usando um machado?" + +msgid "...have you chopped chromatic glass into lenses yet?" +msgstr "...você já quebrou vidro cromático em lentes, usando um machado?" + +msgid "...have you chopped up charcoal yet?" +msgstr "...você já quebrou carvão usando um machado?" + +msgid "...have you cold-forged an annealed lode tool head yet?" +msgstr "...você já fez uma forja fria de uma cabeça de ferramenta de veio mineral?" + +msgid "...have you cold-forged lode down completely yet?" +msgstr "...você já fez uma forja fria de um veio mineral?" + +msgid "...have you cooled molten glass into crude glass yet?" +msgstr "...você já esfriou vidro derretido para que este virasse vidro cru?" + +msgid "...have you cut down a tree yet?" +msgstr "...você já cortou uma árvore?" + +msgid "...have you dug up a tree stump yet?" +msgstr "...você já desenterrou um toco de árvore?" + +msgid "...have you dug up dirt yet?" +msgstr "...você já cavou terra?" + +msgid "...have you dug up gravel yet?" +msgstr "...você já cavou cascalho?" + +msgid "...have you dug up lode ore yet?" +msgstr "...você já desenterrou um veio mineral?" + +msgid "...have you dug up sand yet?" +msgstr "...você já cavou areia?" + +msgid "...have you dug up stone yet?" +msgstr "...você já cavou pedra?" + +msgid "...have you found a lode stratum yet?" +msgstr "...você já encontrou um estrato de veio mineral?" + +msgid "...have you found ash yet?" +msgstr "...você já encontrou cinzas?" + +msgid "...have you found charcoal yet?" +msgstr "...você já encontrou carvão?" + +msgid "...have you found deep stone strata yet?" +msgstr "...você já encontrou um estrato de pedra profunda?" + +msgid "...have you found dry leaves yet?" +msgstr "...você já encontrou folhas secas?" + +msgid "...have you found eggcorns yet?" +msgstr "...você já encontrou semente de carvalho?" + +msgid "...have you found lode ore yet?" +msgstr "...você já encontrou um veio mineral?" + +msgid "...have you found molten rock yet?" +msgstr "...você já encontrou pedra derretida (lava)?" + +msgid "...have you found sponges yet?" +msgstr "...você já encontrou esponjas?" + +msgid "...have you found sticks yet?" +msgstr "...você já encontrou gravetos?" + +msgid "...have you made fire by rubbing sticks together yet?" +msgstr "...você já fez fogo esfregando gravetos?" + +msgid "...have you melted down lode metal yet?" +msgstr "...você já derreteu um veio mineral?" + +msgid "...have you melted sand into glass yet?" +msgstr "...você já transformou areia em vidro, derretendo a areia?" + +msgid "...have you molded molten glass into clear glass yet?" +msgstr "...você já moldou vidro derretido em vidro transparente?" + +msgid "...have you packed high-quality charcoal yet?" +msgstr "...você já juntou carvão de alta qualidade?" + +msgid "...have you packed stone chips back into cobble yet?" +msgstr "...você já juntou pedaços de pedra para que virassem pedregulho?" + +msgid "...have you planted an eggcorn yet?" +msgstr "...você já plantou uma semente de carvalho?" + +msgid "...have you produced light from a lens yet?" +msgstr "...você já gerou luz a partir de uma lente?" + +msgid "...have you put a stone tip onto a tool yet?" +msgstr "...você já colocou uma ponta de pedra em uma ferramenta?" + +msgid "...have you quenched molten glass into chromatic glass yet?" +msgstr "...você já temperou vidro derretido para que virasse vidro cromático?" + +msgid "...have you sintered glowing lode into a cube yet?" +msgstr "...você já moldou veio mineral incandescente em um cubo?" + +msgid "...have you split a tree trunk into planks yet?" +msgstr "...você já fez tábuas quebrando troncos de madeira?" + +msgid "...have you tempered a lode anvil yet?" +msgstr "...você já fez uma bigorna temperando veio mineral?" + +msgid "...have you tempered a lode tool head yet?" +msgstr "...você já fez uma cabeça de ferramenta temperando veio mineral?" + +msgid "...have you welded a lode pick and spade together yet?" +msgstr "...você já soldou uma picareta de veio mineral com uma pá de veio mineral?" + +msgid "About" +msgstr "Sobre" + +msgid "Active Lens" +msgstr "Lente Ativa" + +msgid "Active Prism" +msgstr "Prisma Ativo" + +msgid "Aggregate" +msgstr "Agregar" + +msgid "Air" +msgstr "Ar" + +msgid "Annealed Lode" +msgstr "Veio Mineral Recozido" + +msgid "Annealed Lode Bar" +msgstr "Barra de Veio Mineral Recozida" + +msgid "Annealed Lode Hatchet" +msgstr "Machado de Veio Mineral Recozida" + +msgid "Annealed Lode Hatchet Head" +msgstr "Cabeça de Machado de Veio Mineral Recozida" + +msgid "Annealed Lode Mallet" +msgstr "Marreta de Veio Mineral Recozida" + +msgid "Annealed Lode Mallet Head" +msgstr "Cabeça de Marreta de Veio Mineral Recozida" + +msgid "Annealed Lode Mattock" +msgstr "Enxada de Veio Mineral Recozida" + +msgid "Annealed Lode Mattock Head" +msgstr "Cabeça de Enxada de Veio Mineral Recozida" + +msgid "Annealed Lode Pick" +msgstr "Picareta de Veio Mineral Recozida" + +msgid "Annealed Lode Pick Head" +msgstr "Cabeça de Picareta de Veio Mineral Recozida" + +msgid "Annealed Lode Prill" +msgstr "Lascas de Veio Mineral Recozida" + +msgid "Annealed Lode Rod" +msgstr "Vara de Veio Mineral Recozida" + +msgid "Annealed Lode Spade" +msgstr "Pá de Veio Mineral Recozida" + +msgid "Annealed Lode Spade Head" +msgstr "Cabeça de Pá de Veio Mineral Recozida" + +msgid "Ash" +msgstr "Cinza" + +msgid "Ash Lump" +msgstr "Nódulo de Cinzas" + +msgid "Burning Embers" +msgstr "Brasa Quente" + +msgid "Charcoal" +msgstr "Carvão Vegetal" + +msgid "Charcoal Lump" +msgstr "Nódulo de Carvão Vegetal" + +msgid "Chromatic Glass" +msgstr "Vidro Cromático" + +msgid "Clear Glass" +msgstr "Vidro Transparente" + +msgid "Cobble" +msgstr "Pedregulho" + +msgid "Cobble Hinged Panel" +msgstr "Painel de Pedregulho Articulado" + +msgid "Cobble Panel" +msgstr "Painel de Pedregulho" + +msgid "Crude Glass" +msgstr "Vidro Bruto" + +msgid "DEVELOPMENT VERSION" +msgstr "VERSÃO EM DESENVOLVIMENTO" + +msgid "Dirt" +msgstr "Terra" + +msgid "Discord: https://discord.gg/SHq2tkb" +msgstr "Discord: https://discord.gg/SHq2tkb" + +msgid "Eggcorn" +msgstr "Semente de Carvalho" + +msgid "Fire" +msgstr "Fogo" + +msgid "Float Glass" +msgstr "Vidro Float" + +msgid "GitLab: https://gitlab.com/sztest/nodecore" +msgstr "GitLab: https://gitlab.com/sztest/nodecore" + +msgid "Glowing Lode" +msgstr "Veio Mineral Incandescente" + +msgid "Glowing Lode Bar" +msgstr "Barra de Veio Mineral Incandescente" + +msgid "Glowing Lode Hatchet" +msgstr "Machado de Veio Mineral Incandescente" + +msgid "Glowing Lode Hatchet Head" +msgstr "Cabeça de Machado Veio Mineral Incandescente" + +msgid "Glowing Lode Mallet" +msgstr "Marreta de Veio Mineral Incandescente" + +msgid "Glowing Lode Mallet Head" +msgstr "Cabeça de Marreta Veio Mineral Incandescente" + +msgid "Glowing Lode Mattock" +msgstr "Enxada de Veio Mineral Incandescente" + +msgid "Glowing Lode Mattock Head" +msgstr "Cabeça de Enxada Veio Mineral Incandescente" + +msgid "Glowing Lode Pick" +msgstr "Picareta de Veio Mineral Incandescente" + +msgid "Glowing Lode Pick Head" +msgstr "Cabeça de Picareta de Veio Mineral Incandescente" + +msgid "Glowing Lode Prill" +msgstr "Lascas de Veio Mineral Incandescente" + +msgid "Glowing Lode Rod" +msgstr "Vara de Veio Mineral Incandescente" + +msgid "Glowing Lode Spade" +msgstr "Pá de Veio Mineral Incandescente" + +msgid "Glowing Lode Spade Head" +msgstr "Cabeça de Pá Veio Mineral Incandescente" + +msgid "Grass" +msgstr "Grama" + +msgid "Gravel" +msgstr "Cascalho" + +msgid "Hints" +msgstr "Dicas" + +msgid "Ignore" +msgstr "Ignorar" + +msgid "Injury" +msgstr "Ferir" + +msgid "Inventory" +msgstr "Inventário" + +msgid "Leaves" +msgstr "Folhas" + +msgid "Lens" +msgstr "Lente" + +msgid "Living Sponge" +msgstr "Esponja Viva" + +msgid "Lode Cobble" +msgstr "Veio de Pedregulho" + +msgid "Lode Ore" +msgstr "Veio Mineral" + +msgid "Loose Cobble" +msgstr "Pedregulho Solta" + +msgid "Loose Dirt" +msgstr "Terra Solta" + +msgid "Loose Gravel" +msgstr "Cascalho Solto" + +msgid "Loose Leaves" +msgstr "Folhas Soltas" + +msgid "Loose Lode Cobble" +msgstr "Veio de Pedregulho Solto" + +msgid "Loose Sand" +msgstr "Areia Solta" + +msgid "MIT License: http://www.opensource.org/licenses/MIT" +msgstr "Licensa MIT: http://www.opensource.org/licenses/MIT" + +msgid "Molten Glass" +msgstr "Vidro Derretido" + +msgid "Molten Rock" +msgstr "Pedra Derretida" + +msgid "NodeCore" +msgstr "NodeCore" + +msgid "Not all game content is covered by hints. Explore!" +msgstr "As dicas não cobrem todo o conteúdo do jogo. Explore!" + +msgid "Player's Guide: Inventory Management" +msgstr "Guia do Jogador: Gerenciamento de Inventário" + +msgid "Player's Guide: Pummeling Recipes" +msgstr "Guia do Jogador: Receitas por Esmurrada" + +msgid "Prism" +msgstr "Prisma" + +msgid "Progress: @1 complete, @2 current, @3 future" +msgstr "Progresso: @1 completo(s), @2 atual(is), @3 futuro(s)" + +msgid "Pummel" +msgstr "Esmurrar" + +msgid "Sand" +msgstr "Areia" + +msgid "See included LICENSE file for full details and credits" +msgstr "Veja o arquivo de LICENSA incluso para créditos e maiores detalhes" + +msgid "Shining Lens" +msgstr "Lente Brilhante" + +msgid "Sponge" +msgstr "Esponja" + +msgid "Staff" +msgstr "Bastão" + +msgid "Stick" +msgstr "Graveto" + +msgid "Stone" +msgstr "Pedra" + +msgid "Stone Chip" +msgstr "Pedaço de Pedra" + +msgid "Stone-Tipped Hatchet" +msgstr "Machado com Ponta de Pedra" + +msgid "Stone-Tipped Mallet" +msgstr "Marreta com Ponta de Pedra" + +msgid "Stone-Tipped Pick" +msgstr "Picareta com Ponta de Pedra" + +msgid "Stone-Tipped Spade" +msgstr "Pá com Ponta de Pedra" + +msgid "Stump" +msgstr "Toco" + +msgid "Teleport to get unstuck (but you can't bring your items)" +msgstr "Teleporte para desprender-se (mas você perderá seus itens)" + +msgid "Tempered Lode" +msgstr "Veio Mineral Temperado" + +msgid "Tempered Lode Bar" +msgstr "Barra de Veio Mineral Temperado" + +msgid "Tempered Lode Hatchet" +msgstr "Machado de Veio Mineral Temperado" + +msgid "Tempered Lode Hatchet Head" +msgstr "Cabeça de Machado de Veio Mineral Temperado" + +msgid "Tempered Lode Mallet" +msgstr "Marreta de Veio Mineral Temperado" + +msgid "Tempered Lode Mallet Head" +msgstr "Cabeça de Marreta de Veio Mineral Temperado" + +msgid "Tempered Lode Mattock" +msgstr "Enxada de Veio Mineral Temperado" + +msgid "Tempered Lode Mattock Head" +msgstr "Cabeça de Enxada de Veio Mineral Temperado" + +msgid "Tempered Lode Pick" +msgstr "Picareta de Veio Mineral Temperado" + +msgid "Tempered Lode Pick Head" +msgstr "Cabeça de Picareta de Veio Mineral Temperado" + +msgid "Tempered Lode Prill" +msgstr "Lascas de Veio Mineral Temperado" + +msgid "Tempered Lode Rod" +msgstr "Vara de Veio Mineral Temperado" + +msgid "Tempered Lode Spade" +msgstr "Pá de Veio Mineral Temperado" + +msgid "Tempered Lode Spade Head" +msgstr "Cabeça de Enxada de Veio Mineral Temperado" + +msgid "Tote (1 Slot)" +msgstr "Bolsa (1 Compartimento)" + +msgid "Tote (2 Slots)" +msgstr "Bolsa (2 Compartimentos)" + +msgid "Tote (3 Slots)" +msgstr "Bolsa (3 Compartimentos)" + +msgid "Tote (4 Slots)" +msgstr "Bolsa (4 Compartimentos)" + +msgid "Tote (5 Slots)" +msgstr "Bolsa (5 Compartimentos)" + +msgid "Tote (6 Slots)" +msgstr "Bolsa (6 Compartimentos)" + +msgid "Tote (7 Slots)" +msgstr "Bolsa (7 Compartimentos)" + +msgid "Tote (8 Slots)" +msgstr "Bolsa (8 Compartimentos)" + +msgid "Tote Handle" +msgstr "Alça de Bolsa" + +msgid "Tree Trunk" +msgstr "Tronco de Árvore" + +msgid "Unknown Item" +msgstr "Item Desconhecido" + +msgid "Version" +msgstr "Versão" + +msgid "Water" +msgstr "Água" + +msgid "Wet Aggregate" +msgstr "Massa Úmida" + +msgid "Wet Sponge" +msgstr "Esponja Molhada" + +msgid "Wooden Adze" +msgstr "Enxó de Madeira" + +msgid "Wooden Frame" +msgstr "Estrutura de Madeira" + +msgid "Wooden Hatchet" +msgstr "Machado de Madeira" + +msgid "Wooden Hatchet Head" +msgstr "Cabeça de Machado de Madeira" + +msgid "Wooden Hinged Panel" +msgstr "Painel Articulado de Madeira" + +msgid "Wooden Ladder" +msgstr "Escada de Madeira" + +msgid "Wooden Mallet" +msgstr "Marreta de Madeira" + +msgid "Wooden Mallet Head" +msgstr "Cabeça de Marreta de Madeira" + +msgid "Wooden Panel" +msgstr "Painel de Madeira" + +msgid "Wooden Pick" +msgstr "Picareta de Madeira" + +msgid "Wooden Pick Head" +msgstr "Cabeça de Picareta de Madeira" + +msgid "Wooden Plank" +msgstr "Tábua de Madeira" + +msgid "Wooden Shelf" +msgstr "Estante de Madeira" + +msgid "Wooden Spade" +msgstr "Pá de Madeira" + +msgid "Wooden Spade Head" +msgstr "Cabeça de Pá de Madeira" + +msgid "https://content.minetest.net/packages/Warr1024/nodecore/" +msgstr "https://content.minetest.net/packages/Warr1024/nodecore/" + +msgid "(and @1 more hints)" +msgstr "(e mais @1 dicas)" + +msgid "(and 1 more hint)" +msgstr "( e mais 1 dica)" diff --git a/mods/nc_api/locale/src/pt_BR.txt b/mods/nc_api/locale/src/pt_BR.txt new file mode 100644 index 0000000..3b07385 --- /dev/null +++ b/mods/nc_api/locale/src/pt_BR.txt @@ -0,0 +1,627 @@ +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-12 14:44+0000\n" +"PO-Revision-Date: 2019-09-12 14:44+0000\n" +"Last-Translator: Weblate Admin \n" +"Language-Team: Portuguese (Brazil) \n" +"Language: pt_BR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 3.8\n" + +msgid "(C)2018-2019 by Aaron Suen " +msgstr "(C)2018-2019 por Aaron Suen " + +msgid "- Crafting is done by building recipes in-world." +msgstr "- A Criação de Itens é feita construindo as receitas pelo mundo." + +msgid "- Drop items onto ground to create stack nodes. They do not decay." +msgstr "- Solte itens no chão para criar um node de itens amontoados. Eles não desaparecem." + +msgid "- If a recipe exists, you will see a special particle effect." +msgstr "- Se uma receita existe, você verá um efeito especial de partícula sair do node." + +msgid "- Items picked up try to fit into the current selected slot first." +msgstr "- Os itens pegados são primeiramente armazenados no espaço atualmente selecionado." + +msgid "- Order and specific face of placement may matter for crafting." +msgstr "- A ordem e a face em que os itens são colocados pode importar no processo de criação." + +msgid "- Recipes are time-based, punching faster does not speed up." +msgstr "- Receitas são cronometradas, bater mais forte não afetará a velocidade delas." + +msgid "- Sneak+drop to count out single items from stack." +msgstr "- Use os comandos de agachar e soltar juntos para soltar um só item." + +msgid "- Some recipes require "pummeling" a node." +msgstr "- Algumas receitas necessitam que você "esmurre" um node." + +msgid "- Stacks may be pummeled, exact item count may matter." +msgstr "- Amontoados de itens podem ser esmurrados, pode ser que precise de uma quantidade exata do item." + +msgid "- There is NO inventory screen." +msgstr "- NÃO EXISTE tela de inventário." + +msgid "- To pummel, punch a node repeatedly, WITHOUT digging." +msgstr "- Para esmurrar, bata num node repetidamente, SEM QUEBRÁ-LO." + +msgid "- Wielded item, target face, and surrounding nodes may matter." +msgstr "- O item segurado, a face do objeto alvo e os nodes ao redor podem importar durante a criação de algo." + +msgid "- You do not have to punch very fast (about 1 per second)." +msgstr "- Você não precisa bater muito rápido(basta 1 batida por segundo)." + +msgid "...and 1 more hint..." +msgstr "...e mais 1 dica..." + +msgid "...and @1 more hints..." +msgstr "...e mais @1 dicas..." + +msgid "...have you activated a lens yet?" +msgstr "...você já ativou uma lente?" + +msgid "...have you assembled a staff from sticks yet?" +msgstr "...você já montou um bastão usando gravetos?" + +msgid "...have you assembled a wooden frame yet?" +msgstr "...você já montou um estrutura de madeira?" + +msgid "...have you assembled a wooden ladder yet?" +msgstr "...você já montou uma escada de madeira?" + +msgid "...have you assembled a wooden shelf yet?" +msgstr "...você já montou uma estante de madeira?" + +msgid "...have you assembled a wooden tool yet?" +msgstr "...você já montou uma ferramenta de madeira?" + +msgid "...have you assembled an adze out of sticks yet?" +msgstr "...você já montou um enxó usando gravetos?" + +msgid "...have you assembled an annealed lode tote handle yet?" +msgstr "...você já montou uma alça de bolsa recozida?" + +msgid "...have you bashed a plank into sticks yet?" +msgstr "...você já quebrou uma tábua em gravetos batendo nela?" + +msgid "...have you broken cobble into chips yet?" +msgstr "...você já quebrou pedregulho em pedaços?" + +msgid "...have you carved a wooden plank completely yet?" +msgstr "...você já entalhou completamente uma tábua de madeira?" + +msgid "...have you carved wooden tool heads from planks yet?" +msgstr "...você já transformou uma tábua em cabeças de ferramentas, entalhando a madeira?" + +msgid "...have you chipped chromatic glass into prisms yet?" +msgstr "...você já quebrou um vidro cromático em prismas, lascando o vidro?" + +msgid "...have you chopped a lode cube into prills yet?" +msgstr "...você já quebrou um veio mineral em lascas, usando um machado?" + +msgid "...have you chopped chromatic glass into lenses yet?" +msgstr "...você já quebrou vidro cromático em lentes, usando um machado?" + +msgid "...have you chopped up charcoal yet?" +msgstr "...você já quebrou carvão usando um machado?" + +msgid "...have you cold-forged an annealed lode tool head yet?" +msgstr "...você já fez uma forja fria de uma cabeça de ferramenta de veio mineral?" + +msgid "...have you cold-forged lode down completely yet?" +msgstr "...você já fez uma forja fria de um veio mineral?" + +msgid "...have you cooled molten glass into crude glass yet?" +msgstr "...você já esfriou vidro derretido para que este virasse vidro cru?" + +msgid "...have you cut down a tree yet?" +msgstr "...você já cortou uma árvore?" + +msgid "...have you dug up a tree stump yet?" +msgstr "...você já desenterrou um toco de árvore?" + +msgid "...have you dug up dirt yet?" +msgstr "...você já cavou terra?" + +msgid "...have you dug up gravel yet?" +msgstr "...você já cavou cascalho?" + +msgid "...have you dug up lode ore yet?" +msgstr "...você já desenterrou um veio mineral?" + +msgid "...have you dug up sand yet?" +msgstr "...você já cavou areia?" + +msgid "...have you dug up stone yet?" +msgstr "...você já cavou pedra?" + +msgid "...have you found a lode stratum yet?" +msgstr "...você já encontrou um estrato de veio mineral?" + +msgid "...have you found ash yet?" +msgstr "...você já encontrou cinzas?" + +msgid "...have you found charcoal yet?" +msgstr "...você já encontrou carvão?" + +msgid "...have you found deep stone strata yet?" +msgstr "...você já encontrou um estrato de pedra profunda?" + +msgid "...have you found dry leaves yet?" +msgstr "...você já encontrou folhas secas?" + +msgid "...have you found eggcorns yet?" +msgstr "...você já encontrou semente de carvalho?" + +msgid "...have you found lode ore yet?" +msgstr "...você já encontrou um veio mineral?" + +msgid "...have you found molten rock yet?" +msgstr "...você já encontrou pedra derretida (lava)?" + +msgid "...have you found sponges yet?" +msgstr "...você já encontrou esponjas?" + +msgid "...have you found sticks yet?" +msgstr "...você já encontrou gravetos?" + +msgid "...have you made fire by rubbing sticks together yet?" +msgstr "...você já fez fogo esfregando gravetos?" + +msgid "...have you melted down lode metal yet?" +msgstr "...você já derreteu um veio mineral?" + +msgid "...have you melted sand into glass yet?" +msgstr "...você já transformou areia em vidro, derretendo a areia?" + +msgid "...have you molded molten glass into clear glass yet?" +msgstr "...você já moldou vidro derretido em vidro transparente?" + +msgid "...have you packed high-quality charcoal yet?" +msgstr "...você já juntou carvão de alta qualidade?" + +msgid "...have you packed stone chips back into cobble yet?" +msgstr "...você já juntou pedaços de pedra para que virassem pedregulho?" + +msgid "...have you planted an eggcorn yet?" +msgstr "...você já plantou uma semente de carvalho?" + +msgid "...have you produced light from a lens yet?" +msgstr "...você já gerou luz a partir de uma lente?" + +msgid "...have you put a stone tip onto a tool yet?" +msgstr "...você já colocou uma ponta de pedra em uma ferramenta?" + +msgid "...have you quenched molten glass into chromatic glass yet?" +msgstr "...você já temperou vidro derretido para que virasse vidro cromático?" + +msgid "...have you sintered glowing lode into a cube yet?" +msgstr "...você já moldou veio mineral incandescente em um cubo?" + +msgid "...have you split a tree trunk into planks yet?" +msgstr "...você já fez tábuas quebrando troncos de madeira?" + +msgid "...have you tempered a lode anvil yet?" +msgstr "...você já fez uma bigorna temperando veio mineral?" + +msgid "...have you tempered a lode tool head yet?" +msgstr "...você já fez uma cabeça de ferramenta temperando veio mineral?" + +msgid "...have you welded a lode pick and spade together yet?" +msgstr "...você já soldou uma picareta de veio mineral com uma pá de veio mineral?" + +msgid "About" +msgstr "Sobre" + +msgid "Active Lens" +msgstr "Lente Ativa" + +msgid "Active Prism" +msgstr "Prisma Ativo" + +msgid "Aggregate" +msgstr "Agregar" + +msgid "Air" +msgstr "Ar" + +msgid "Annealed Lode" +msgstr "Veio Mineral Recozido" + +msgid "Annealed Lode Bar" +msgstr "Barra de Veio Mineral Recozida" + +msgid "Annealed Lode Hatchet" +msgstr "Machado de Veio Mineral Recozida" + +msgid "Annealed Lode Hatchet Head" +msgstr "Cabeça de Machado de Veio Mineral Recozida" + +msgid "Annealed Lode Mallet" +msgstr "Marreta de Veio Mineral Recozida" + +msgid "Annealed Lode Mallet Head" +msgstr "Cabeça de Marreta de Veio Mineral Recozida" + +msgid "Annealed Lode Mattock" +msgstr "Enxada de Veio Mineral Recozida" + +msgid "Annealed Lode Mattock Head" +msgstr "Cabeça de Enxada de Veio Mineral Recozida" + +msgid "Annealed Lode Pick" +msgstr "Picareta de Veio Mineral Recozida" + +msgid "Annealed Lode Pick Head" +msgstr "Cabeça de Picareta de Veio Mineral Recozida" + +msgid "Annealed Lode Prill" +msgstr "Lascas de Veio Mineral Recozida" + +msgid "Annealed Lode Rod" +msgstr "Vara de Veio Mineral Recozida" + +msgid "Annealed Lode Spade" +msgstr "Pá de Veio Mineral Recozida" + +msgid "Annealed Lode Spade Head" +msgstr "Cabeça de Pá de Veio Mineral Recozida" + +msgid "Ash" +msgstr "Cinza" + +msgid "Ash Lump" +msgstr "Nódulo de Cinzas" + +msgid "Burning Embers" +msgstr "Brasa Quente" + +msgid "Charcoal" +msgstr "Carvão Vegetal" + +msgid "Charcoal Lump" +msgstr "Nódulo de Carvão Vegetal" + +msgid "Chromatic Glass" +msgstr "Vidro Cromático" + +msgid "Clear Glass" +msgstr "Vidro Transparente" + +msgid "Cobble" +msgstr "Pedregulho" + +msgid "Cobble Hinged Panel" +msgstr "Painel de Pedregulho Articulado" + +msgid "Cobble Panel" +msgstr "Painel de Pedregulho" + +msgid "Crude Glass" +msgstr "Vidro Bruto" + +msgid "DEVELOPMENT VERSION" +msgstr "VERSÃO EM DESENVOLVIMENTO" + +msgid "Dirt" +msgstr "Terra" + +msgid "Discord: https://discord.gg/SHq2tkb" +msgstr "Discord: https://discord.gg/SHq2tkb" + +msgid "Eggcorn" +msgstr "Semente de Carvalho" + +msgid "Fire" +msgstr "Fogo" + +msgid "Float Glass" +msgstr "Vidro Float" + +msgid "GitLab: https://gitlab.com/sztest/nodecore" +msgstr "GitLab: https://gitlab.com/sztest/nodecore" + +msgid "Glowing Lode" +msgstr "Veio Mineral Incandescente" + +msgid "Glowing Lode Bar" +msgstr "Barra de Veio Mineral Incandescente" + +msgid "Glowing Lode Hatchet" +msgstr "Machado de Veio Mineral Incandescente" + +msgid "Glowing Lode Hatchet Head" +msgstr "Cabeça de Machado Veio Mineral Incandescente" + +msgid "Glowing Lode Mallet" +msgstr "Marreta de Veio Mineral Incandescente" + +msgid "Glowing Lode Mallet Head" +msgstr "Cabeça de Marreta Veio Mineral Incandescente" + +msgid "Glowing Lode Mattock" +msgstr "Enxada de Veio Mineral Incandescente" + +msgid "Glowing Lode Mattock Head" +msgstr "Cabeça de Enxada Veio Mineral Incandescente" + +msgid "Glowing Lode Pick" +msgstr "Picareta de Veio Mineral Incandescente" + +msgid "Glowing Lode Pick Head" +msgstr "Cabeça de Picareta de Veio Mineral Incandescente" + +msgid "Glowing Lode Prill" +msgstr "Lascas de Veio Mineral Incandescente" + +msgid "Glowing Lode Rod" +msgstr "Vara de Veio Mineral Incandescente" + +msgid "Glowing Lode Spade" +msgstr "Pá de Veio Mineral Incandescente" + +msgid "Glowing Lode Spade Head" +msgstr "Cabeça de Pá Veio Mineral Incandescente" + +msgid "Grass" +msgstr "Grama" + +msgid "Gravel" +msgstr "Cascalho" + +msgid "Hints" +msgstr "Dicas" + +msgid "Ignore" +msgstr "Ignorar" + +msgid "Injury" +msgstr "Ferir" + +msgid "Inventory" +msgstr "Inventário" + +msgid "Leaves" +msgstr "Folhas" + +msgid "Lens" +msgstr "Lente" + +msgid "Living Sponge" +msgstr "Esponja Viva" + +msgid "Lode Cobble" +msgstr "Veio de Pedregulho" + +msgid "Lode Ore" +msgstr "Veio Mineral" + +msgid "Loose Cobble" +msgstr "Pedregulho Solta" + +msgid "Loose Dirt" +msgstr "Terra Solta" + +msgid "Loose Gravel" +msgstr "Cascalho Solto" + +msgid "Loose Leaves" +msgstr "Folhas Soltas" + +msgid "Loose Lode Cobble" +msgstr "Veio de Pedregulho Solto" + +msgid "Loose Sand" +msgstr "Areia Solta" + +msgid "MIT License: http://www.opensource.org/licenses/MIT" +msgstr "Licensa MIT: http://www.opensource.org/licenses/MIT" + +msgid "Molten Glass" +msgstr "Vidro Derretido" + +msgid "Molten Rock" +msgstr "Pedra Derretida" + +msgid "NodeCore" +msgstr "NodeCore" + +msgid "Not all game content is covered by hints. Explore!" +msgstr "As dicas não cobrem todo o conteúdo do jogo. Explore!" + +msgid "Player's Guide: Inventory Management" +msgstr "Guia do Jogador: Gerenciamento de Inventário" + +msgid "Player's Guide: Pummeling Recipes" +msgstr "Guia do Jogador: Receitas por Esmurrada" + +msgid "Prism" +msgstr "Prisma" + +msgid "Progress: @1 complete, @2 current, @3 future" +msgstr "Progresso: @1 completo(s), @2 atual(is), @3 futuro(s)" + +msgid "Pummel" +msgstr "Esmurrar" + +msgid "Sand" +msgstr "Areia" + +msgid "See included LICENSE file for full details and credits" +msgstr "Veja o arquivo de LICENSA incluso para créditos e maiores detalhes" + +msgid "Shining Lens" +msgstr "Lente Brilhante" + +msgid "Sponge" +msgstr "Esponja" + +msgid "Staff" +msgstr "Bastão" + +msgid "Stick" +msgstr "Graveto" + +msgid "Stone" +msgstr "Pedra" + +msgid "Stone Chip" +msgstr "Pedaço de Pedra" + +msgid "Stone-Tipped Hatchet" +msgstr "Machado com Ponta de Pedra" + +msgid "Stone-Tipped Mallet" +msgstr "Marreta com Ponta de Pedra" + +msgid "Stone-Tipped Pick" +msgstr "Picareta com Ponta de Pedra" + +msgid "Stone-Tipped Spade" +msgstr "Pá com Ponta de Pedra" + +msgid "Stump" +msgstr "Toco" + +msgid "Teleport to get unstuck (but you can't bring your items)" +msgstr "Teleporte para desprender-se (mas você perderá seus itens)" + +msgid "Tempered Lode" +msgstr "Veio Mineral Temperado" + +msgid "Tempered Lode Bar" +msgstr "Barra de Veio Mineral Temperado" + +msgid "Tempered Lode Hatchet" +msgstr "Machado de Veio Mineral Temperado" + +msgid "Tempered Lode Hatchet Head" +msgstr "Cabeça de Machado de Veio Mineral Temperado" + +msgid "Tempered Lode Mallet" +msgstr "Marreta de Veio Mineral Temperado" + +msgid "Tempered Lode Mallet Head" +msgstr "Cabeça de Marreta de Veio Mineral Temperado" + +msgid "Tempered Lode Mattock" +msgstr "Enxada de Veio Mineral Temperado" + +msgid "Tempered Lode Mattock Head" +msgstr "Cabeça de Enxada de Veio Mineral Temperado" + +msgid "Tempered Lode Pick" +msgstr "Picareta de Veio Mineral Temperado" + +msgid "Tempered Lode Pick Head" +msgstr "Cabeça de Picareta de Veio Mineral Temperado" + +msgid "Tempered Lode Prill" +msgstr "Lascas de Veio Mineral Temperado" + +msgid "Tempered Lode Rod" +msgstr "Vara de Veio Mineral Temperado" + +msgid "Tempered Lode Spade" +msgstr "Pá de Veio Mineral Temperado" + +msgid "Tempered Lode Spade Head" +msgstr "Cabeça de Enxada de Veio Mineral Temperado" + +msgid "Tote (1 Slot)" +msgstr "Bolsa (1 Compartimento)" + +msgid "Tote (2 Slots)" +msgstr "Bolsa (2 Compartimentos)" + +msgid "Tote (3 Slots)" +msgstr "Bolsa (3 Compartimentos)" + +msgid "Tote (4 Slots)" +msgstr "Bolsa (4 Compartimentos)" + +msgid "Tote (5 Slots)" +msgstr "Bolsa (5 Compartimentos)" + +msgid "Tote (6 Slots)" +msgstr "Bolsa (6 Compartimentos)" + +msgid "Tote (7 Slots)" +msgstr "Bolsa (7 Compartimentos)" + +msgid "Tote (8 Slots)" +msgstr "Bolsa (8 Compartimentos)" + +msgid "Tote Handle" +msgstr "Alça de Bolsa" + +msgid "Tree Trunk" +msgstr "Tronco de Árvore" + +msgid "Unknown Item" +msgstr "Item Desconhecido" + +msgid "Version" +msgstr "Versão" + +msgid "Water" +msgstr "Água" + +msgid "Wet Aggregate" +msgstr "Massa Úmida" + +msgid "Wet Sponge" +msgstr "Esponja Molhada" + +msgid "Wooden Adze" +msgstr "Enxó de Madeira" + +msgid "Wooden Frame" +msgstr "Estrutura de Madeira" + +msgid "Wooden Hatchet" +msgstr "Machado de Madeira" + +msgid "Wooden Hatchet Head" +msgstr "Cabeça de Machado de Madeira" + +msgid "Wooden Hinged Panel" +msgstr "Painel Articulado de Madeira" + +msgid "Wooden Ladder" +msgstr "Escada de Madeira" + +msgid "Wooden Mallet" +msgstr "Marreta de Madeira" + +msgid "Wooden Mallet Head" +msgstr "Cabeça de Marreta de Madeira" + +msgid "Wooden Panel" +msgstr "Painel de Madeira" + +msgid "Wooden Pick" +msgstr "Picareta de Madeira" + +msgid "Wooden Pick Head" +msgstr "Cabeça de Picareta de Madeira" + +msgid "Wooden Plank" +msgstr "Tábua de Madeira" + +msgid "Wooden Shelf" +msgstr "Estante de Madeira" + +msgid "Wooden Spade" +msgstr "Pá de Madeira" + +msgid "Wooden Spade Head" +msgstr "Cabeça de Pá de Madeira" + +msgid "https://content.minetest.net/packages/Warr1024/nodecore/" +msgstr "https://content.minetest.net/packages/Warr1024/nodecore/" diff --git a/mods/nc_api/locale/src/update.pl b/mods/nc_api/locale/src/update.pl new file mode 100644 index 0000000..54a79ae --- /dev/null +++ b/mods/nc_api/locale/src/update.pl @@ -0,0 +1,51 @@ +#!/usr/bin/perl -w +use strict; +use warnings; +use JSON qw(from_json); + +sub getlang { + my $lang = shift(); + my %db; + open(my $fh, "-|", "curl", "https://nodecore.mine.nu/trans/api/translations/nodecore/core/$lang/file/") or die($!); + open(my $raw, ">", "src/$lang.txt") or die($!); + my $id; + while(<$fh>) { + print $raw $_; + m#^\s*msgid\s+"(.*)"\s*$# and $id = $1; + m#^\s*msgstr\s+"(.*)"\s*$# or next; + my $str = $1; + $str =~ m#\S# or next; + $db{$id} = $str; + } + close($fh); + close($raw); + return \%db; +} + +sub savelang { + my $lang = shift(); + my $en = shift(); + my %db = %{getlang($lang)}; + map { $en->{$_} and $db{$_} ne $_ or delete $db{$_} } keys %db; + %db or return; + open(my $fh, ">", "nc_api.$lang.tr") or die($!); + print $fh "# textdomain: nc_api\n"; + print $fh map { "$_=$db{$_}\n" } sort keys %db; + close($fh); + warn("updated: $lang\n"); +} + +my $en = getlang("en"); +my $page = "https://nodecore.mine.nu/trans/api/translations/?format=json"; +while($page) { + open(my $fh, "-|", "curl", $page) or die($!); + my $json = from_json(do { local $/; <$fh> }); + close($fh); + $page = $json->{next}; + for my $r ( @{$json->{results}} ) { + $r->{component}->{slug} eq "core" or next; + $r->{component}->{project}->{slug} eq "nodecore" or next; + my $code = $r->{language}->{code}; + $code eq 'en' or savelang($code, $en); + } +} diff --git a/mods/nc_api/mapgen_shared.lua b/mods/nc_api/mapgen_shared.lua new file mode 100644 index 0000000..e87c1c3 --- /dev/null +++ b/mods/nc_api/mapgen_shared.lua @@ -0,0 +1,41 @@ +-- LUALOCALS < --------------------------------------------------------- +local VoxelArea, ipairs, math, minetest, nodecore, table + = VoxelArea, ipairs, math, minetest, nodecore, table +local math_floor, table_insert + = math.floor, table.insert +-- LUALOCALS > --------------------------------------------------------- + +local mapgens = {} +nodecore.registered_mapgen_shared = mapgens + +local prios = {} + +function nodecore.register_mapgen_shared(func, prio) + prio = prio or 0 + local min = 1 + local max = #mapgens + 1 + while max > min do + local try = math_floor((min + max) / 2) + local oldp = prios[try] + if prio < oldp then + min = try + 1 + else + max = try + end + end + table_insert(mapgens, min, func) + table_insert(prios, min, prio) +end + +minetest.register_on_generated(function(minp, maxp) + local vm, emin, emax = minetest.get_mapgen_object("voxelmanip") + local data = vm:get_data() + local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax}) + + for _, v in ipairs(mapgens) do + v(minp, maxp, area, data, vm, emin, emax) + end + + vm:set_data(data) + vm:write_to_map() + end) diff --git a/mods/nc_api/match.lua b/mods/nc_api/match.lua new file mode 100644 index 0000000..574b758 --- /dev/null +++ b/mods/nc_api/match.lua @@ -0,0 +1,88 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore, pairs, type + = minetest, nodecore, pairs, type +-- LUALOCALS > --------------------------------------------------------- + +local match_skip = { + name = true, + param2 = true, + param = true, + groups = true, + stack = true, + count = true, + excess = true, + wear = true, + stacked = true, + any = true +} + +function nodecore.match(thing, crit) + if not thing then return end + + if type(crit) == "string" then crit = {name = crit} end + + if crit.any then + for _, v in pairs(crit.any) do + local found = nodecore.match(thing, v) + if found then return found end + end + return + end + + thing.count = thing.count or 1 + + thing = nodecore.underride({}, thing) + if thing.stack then + thing.name = thing.stack:get_name() + thing.count = thing.stack:get_count() + thing.wear = thing.stack:get_wear() + thing.stacked = true + end + if not thing.name then + thing = nodecore.underride(thing, minetest.get_node(thing)) + end + local def = minetest.registered_items[thing.name] + if (not thing.stacked) and def and def.groups and def.groups.is_stack_only then + local stack = nodecore.stack_get(thing) + if stack and not stack:is_empty() then + thing.name = stack:get_name() + def = minetest.registered_items[thing.name] + thing.count = stack:get_count() + thing.wear = stack:get_wear() + end + thing.stacked = true + end + if crit.stacked and not thing.stacked then return end + if crit.stacked == false and thing.stacked then return end + + if crit.name and thing.name ~= crit.name then return end + if crit.param2 and thing.param2 ~= crit.param2 then return end + if crit.param and thing.param ~= crit.param then return end + if crit.count and thing.count < crit.count then return end + if crit.count and (not crit.excess) and thing.count > crit.count then return end + if crit.count == nil and thing.count ~= 1 then return end + if crit.wear then + if crit.wear < 1 then crit.wear = crit.wear * 65535 end + if thing.wear > crit.wear then return end + end + + if crit.groups then + if (not def) or (not def.groups) then return end + for k, v in pairs(crit.groups) do + if v == true then + if not def.groups[k] then return end + elseif v == false then + if def.groups[k] then return end + else + if def.groups[k] ~= v then return end + end + end + end + for k, v in pairs(crit) do + if not match_skip[k] then + if not def or def[k] ~= v then return end + end + end + + return thing +end diff --git a/mods/nc_api/mod.conf b/mods/nc_api/mod.conf new file mode 100644 index 0000000..276d325 --- /dev/null +++ b/mods/nc_api/mod.conf @@ -0,0 +1 @@ +name = nc_api diff --git a/mods/nc_api/register_ambiance.lua b/mods/nc_api/register_ambiance.lua new file mode 100644 index 0000000..cc9c876 --- /dev/null +++ b/mods/nc_api/register_ambiance.lua @@ -0,0 +1,65 @@ +-- LUALOCALS < --------------------------------------------------------- +local math, minetest, nodecore + = math, minetest, nodecore +local math_random + = math.random +-- LUALOCALS > --------------------------------------------------------- + +function nodecore.register_ambiance(def) + local max = def.queue_max or 100 + local rate = 1 / (def.queue_rate or 20) + + local seen = {} + local queue = {} + local total = 0 + + local batch + local time = 0 + minetest.register_globalstep(function(dtime) + time = time + dtime + while time > rate do + if not batch then + if #queue < 1 then return end + batch = queue + queue = {} + total = 0 + seen = {} + end + + local opts = batch[#batch] + batch[#batch] = nil + if #batch < 1 then batch = nil end + + opts.name = opts.name or def.sound_name + opts.gain = opts.gain or def.sound_gain + minetest.sound_play(opts.name, opts) + + time = time - rate + end + end) + + def.action = function(pos) + local hash = minetest.hash_node_position(pos) + if seen[hash] then return end + seen[hash] = true + local opts + if def.check then + opts = def.check(pos) + if not opts then return end + else + opts = {} + end + opts.pos = pos + if #queue < max then + queue[#queue + 1] = opts + else + local r = math_random(1, total + 1) + if r <= #queue then + queue[r] = opts + end + end + total = total + 1 + end + + return nodecore.register_limited_abm(def) +end diff --git a/mods/nc_api/register_limited_abm.lua b/mods/nc_api/register_limited_abm.lua new file mode 100644 index 0000000..5e260f0 --- /dev/null +++ b/mods/nc_api/register_limited_abm.lua @@ -0,0 +1,74 @@ +-- LUALOCALS < --------------------------------------------------------- +local math, minetest, nodecore, pairs, unpack + = math, minetest, nodecore, pairs, unpack +local math_random + = math.random +-- LUALOCALS > --------------------------------------------------------- + +local genlabels = 0 + +function nodecore.register_limited_abm(def) + def = nodecore.underride(def, { + limited_queue = {}, + limited_seen = {}, + limited_qty = 0, + limited_max = 1000, + limited_interval = 1, + limited_jitter = 0.05, + limited_action = def.action or function() end, + catch_up = false + }) + + if not def.label then + def.label = minetest.get_current_modname() .. ":" .. genlabels + genlabels = genlabels + 1 + end + def.limited_alert = def.limited_alert or def.limited_max + + def.action = function(pos, ...) + local hash = minetest.hash_node_position(pos) + local seen = def.limited_seen + if seen[hash] then return end + seen[hash] = true + + local q = def.limited_queue + local max = def.limited_max + local nqty = def.limited_qty + 1 + if #q < max then + q[#q + 1] = {pos, ...} + else + local r = math_random(1, nqty) + if r <= #q then q[r] = {pos, ...} end + end + def.limited_qty = nqty + end + + local function pumpq() + minetest.after(def.limited_interval + - def.limited_jitter + + def.limited_jitter * math_random() * 2, + pumpq) + + if def.limited_qty >= def.limited_alert then + minetest.log("limited abm \"" .. def.label .. "\" filled (" + .. def.limited_qty .. "/" .. def.limited_max .. ")") + end + + local act = def.limited_action + for _, args in pairs(def.limited_queue) do + local pos = args[1] + local node = pos and args[2] + local nn = node and minetest.get_node_or_nil(pos) + if nn and nn.name == node.name then + act(unpack(args)) + end + end + + def.limited_queue = {} + def.limited_seen = {} + def.limited_qty = 0 + end + pumpq() + + return minetest.register_abm(def) +end diff --git a/mods/nc_api/register_mods.lua b/mods/nc_api/register_mods.lua new file mode 100644 index 0000000..72c3551 --- /dev/null +++ b/mods/nc_api/register_mods.lua @@ -0,0 +1,34 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore, pairs, string, table + = minetest, nodecore, pairs, string, table +local string_format, table_concat, table_sort + = string.format, table.concat, table.sort +-- LUALOCALS > --------------------------------------------------------- + +nodecore.coremods = {} + +function nodecore.amcoremod(v) + nodecore.coremods[minetest.get_current_modname()] = (v == nil) or v +end +nodecore.amcoremod() + +for k, v in pairs(minetest.registered_chatcommands) do + if k == "mods" then + minetest.override_chatcommand(k, nodecore.underride({ + func = function() + local mods = {} + for _, n in pairs(minetest.get_modnames()) do + if not nodecore.coremods[n] then + mods[#mods + 1] = n + end + end + table_sort(mods) + return true, string_format("%s(%s)%s%s", + nodecore.product, + nodecore.version or "DEV", + #mods > 0 and " + " or "", + table_concat(mods, ", ")) + end + }, v)) + end +end diff --git a/mods/nc_api/register_soaking_abm.lua b/mods/nc_api/register_soaking_abm.lua new file mode 100644 index 0000000..0b5fea5 --- /dev/null +++ b/mods/nc_api/register_soaking_abm.lua @@ -0,0 +1,68 @@ +-- LUALOCALS < --------------------------------------------------------- +local error, math, minetest, nodecore, type + = error, math, minetest, nodecore, type +local math_floor, math_sqrt + = math.floor, math.sqrt +-- LUALOCALS > --------------------------------------------------------- + +function nodecore.register_soaking_abm(def) + def.qtyfield = def.qtyfield or "soakqty" + def.timefield = def.timefield or "soaktime" + + def.soakinterval = def.soakinterval or ((def.interval or 1) * (def.chance or 1)) + + if not def.soakrate then error("soaking abm missing soakrate callback") end + if not def.soakcheck then error("soaking abm missing soakcheck callback") end + + def.soakvary = def.soakvary or 0.25 + if not def.soakrand then + if def.soakvary then + def.soakrand = function(rate, ticks) + return rate * (1 + def.soakvary * nodecore.boxmuller() + / math_sqrt(ticks)) * ticks + end + else + def.soakrand = function(rate, ticks) return rate * ticks end + end + end + + def.action = function(pos, ...) + local now = minetest.get_gametime() + + local meta = minetest.get_meta(pos) + local total = meta:get_float(def.qtyfield) or 0 + local start = meta:get_float(def.timefield) + start = start and start ~= 0 and start or now + + local rate = 0 + local delta = 0 + if start <= now then + rate = def.soakrate(pos, ...) + if rate == false then + meta:set_string(def.qtyfield, "") + meta:set_string(def.timefield, "") + return + end + rate = rate or 0 + local ticks = 1 + math_floor((now - start) / def.soakinterval) + delta = def.soakrand(rate, ticks) + total = total + delta + start = start + ticks * def.soakinterval + end + + local set = def.soakcheck({ + rate = rate, + delta = delta, + total = total + }, pos, ...) + if set == false then + meta:set_string(def.qtyfield, "") + meta:set_string(def.timefield, "") + return + end + meta:set_float(def.qtyfield, set and type(set) == "number" and set or total) + meta:set_float(def.timefield, start) + end + + return nodecore.register_limited_abm(def) +end diff --git a/mods/nc_api/sounds/nc_api_toolbreak.0.ogg b/mods/nc_api/sounds/nc_api_toolbreak.0.ogg new file mode 100644 index 0000000..a2e5417 Binary files /dev/null and b/mods/nc_api/sounds/nc_api_toolbreak.0.ogg differ diff --git a/mods/nc_api/sounds/nc_api_toolbreak.1.ogg b/mods/nc_api/sounds/nc_api_toolbreak.1.ogg new file mode 100644 index 0000000..5d5c5f4 Binary files /dev/null and b/mods/nc_api/sounds/nc_api_toolbreak.1.ogg differ diff --git a/mods/nc_api/sounds/nc_api_toolbreak.2.ogg b/mods/nc_api/sounds/nc_api_toolbreak.2.ogg new file mode 100644 index 0000000..a5afd26 Binary files /dev/null and b/mods/nc_api/sounds/nc_api_toolbreak.2.ogg differ diff --git a/mods/nc_api/sounds/nc_api_toolwear.0.ogg b/mods/nc_api/sounds/nc_api_toolwear.0.ogg new file mode 100644 index 0000000..0fa600c Binary files /dev/null and b/mods/nc_api/sounds/nc_api_toolwear.0.ogg differ diff --git a/mods/nc_api/sounds/nc_api_toolwear.1.ogg b/mods/nc_api/sounds/nc_api_toolwear.1.ogg new file mode 100644 index 0000000..04a02eb Binary files /dev/null and b/mods/nc_api/sounds/nc_api_toolwear.1.ogg differ diff --git a/mods/nc_api/sounds/nc_api_toolwear.2.ogg b/mods/nc_api/sounds/nc_api_toolwear.2.ogg new file mode 100644 index 0000000..d7e3f8e Binary files /dev/null and b/mods/nc_api/sounds/nc_api_toolwear.2.ogg differ diff --git a/mods/nc_api/textures/nc_api_loose.png b/mods/nc_api/textures/nc_api_loose.png new file mode 100644 index 0000000..03e11d0 Binary files /dev/null and b/mods/nc_api/textures/nc_api_loose.png differ diff --git a/mods/nc_api/textures/nc_api_pummel.png b/mods/nc_api/textures/nc_api_pummel.png new file mode 100644 index 0000000..b86a594 Binary files /dev/null and b/mods/nc_api/textures/nc_api_pummel.png differ diff --git a/mods/nc_api/util_ezschematic.lua b/mods/nc_api/util_ezschematic.lua new file mode 100644 index 0000000..e866149 --- /dev/null +++ b/mods/nc_api/util_ezschematic.lua @@ -0,0 +1,26 @@ +-- LUALOCALS < --------------------------------------------------------- +local error, ipairs, minetest, nodecore + = error, ipairs, minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +function nodecore.ezschematic(key, yslices, init) + local size = {} + local data = {} + size.y = #yslices + for y, ys in ipairs(yslices) do + if size.z and size.z ~= #ys then error("inconsistent z size") end + size.z = #ys + for z, zs in ipairs(ys) do + if size.x and size.x ~= #zs then error("inconsistent x size") end + size.x = #zs + for x = 1, zs:len() do + data[(z - 1) * size.x * size.y + (y - 1) * size.x + x] + = key[zs:sub(x, x)] + end + end + end + init = init or {} + init.size = size + init.data = data + return minetest.register_schematic(init) +end diff --git a/mods/nc_api/util_facedir.lua b/mods/nc_api/util_facedir.lua new file mode 100644 index 0000000..60e8344 --- /dev/null +++ b/mods/nc_api/util_facedir.lua @@ -0,0 +1,58 @@ +-- LUALOCALS < --------------------------------------------------------- +local nodecore, pairs, vector + = nodecore, pairs, vector +-- LUALOCALS > --------------------------------------------------------- + +local alldirs = {} +for _, v in pairs(nodecore.dirs()) do + alldirs[v.n] = v +end + +local facedirs = { + {"u", "w"}, + {"u", "n"}, + {"u", "e"}, + {"n", "u"}, + {"n", "w"}, + {"n", "d"}, + {"n", "e"}, + {"s", "d"}, + {"s", "w"}, + {"s", "u"}, + {"s", "e"}, + {"e", "s"}, + {"e", "u"}, + {"e", "n"}, + {"e", "d"}, + {"w", "s"}, + {"w", "d"}, + {"w", "n"}, + {"w", "u"}, + {"d", "s"}, + {"d", "e"}, + {"d", "n"}, + {"d", "w"}, + [0] = {"u", "s"} +} + +local function cross(a, b) + return { + x = a.y * b.z - a.z * b.y, + y = a.z * b.x - a.x * b.z, + z = a.x * b.y - a.y * b.x + } +end + +for k, t in pairs(facedirs) do + t.id = k + t.t = alldirs[t[1]] + t.f = alldirs[t[2]] + t[2] = nil + t[1] = nil + t.l = cross(t.t, t.f) + t.r = vector.multiply(t.l, -1) + t.b = vector.multiply(t.t, -1) + t.k = vector.multiply(t.f, -1) +end + +nodecore.facedirs = facedirs diff --git a/mods/nc_api/util_falling.lua b/mods/nc_api/util_falling.lua new file mode 100644 index 0000000..c9f1598 --- /dev/null +++ b/mods/nc_api/util_falling.lua @@ -0,0 +1,19 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore, pairs + = minetest, nodecore, pairs +-- LUALOCALS > --------------------------------------------------------- + +local queue + +function nodecore.fallcheck(pos) + if not queue then + queue = {} + minetest.after(0, function() + for _, p in pairs(queue) do + minetest.check_for_falling(p) + end + queue = nil + end) + end + queue[minetest.pos_to_string(pos)] = pos +end diff --git a/mods/nc_api/util_misc.lua b/mods/nc_api/util_misc.lua new file mode 100644 index 0000000..4b22216 --- /dev/null +++ b/mods/nc_api/util_misc.lua @@ -0,0 +1,273 @@ +-- LUALOCALS < --------------------------------------------------------- +local ItemStack, ipairs, math, minetest, nodecore, pairs, type, unpack + = ItemStack, ipairs, math, minetest, nodecore, pairs, type, unpack +local math_cos, math_log, math_pi, math_random, math_sin, math_sqrt + = math.cos, math.log, math.pi, math.random, math.sin, math.sqrt +-- LUALOCALS > --------------------------------------------------------- + +for k, v in pairs(minetest) do + if type(v) == "function" then + -- Late-bind in case minetest methods overridden. + nodecore[k] = function(...) return minetest[k](...) end + else + nodecore[k] = v + end +end + +local function underride(t, u, u2, ...) + if u2 then underride(u, u2, ...) end + for k, v in pairs(u) do + if t[k] == nil then + t[k] = v + elseif type(t[k]) == "table" and type(v) == "table" then + underride(t[k], v) + end + end + return t +end +nodecore.underride = underride + +function nodecore.mkreg() + local t = {} + local f = function(x) t[#t + 1] = x end + return f, t +end + +function nodecore.memoize(func) + local cache + return function() + if cache then return cache[1] end + cache = {func()} + return cache[1] + end +end + +function nodecore.dirs() + return { + {n = "e", x = 1, y = 0, z = 0}, + {n = "w", x = -1, y = 0, z = 0}, + {n = "u", x = 0, y = 1, z = 0}, + {n = "d", x = 0, y = -1, z = 0}, + {n = "n", x = 0, y = 0, z = 1}, + {n = "s", x = 0, y = 0, z = -1} + } +end + +function nodecore.pickrand(tbl, weight) + weight = weight or function() end + local t = {} + local max = 0 + for k, v in pairs(tbl) do + local w = weight(v) or 1 + if w > 0 then + max = max + w + t[#t + 1] = {w = w, k = k, v = v} + end + end + if max <= 0 then return end + max = math_random() * max + for _, v in ipairs(t) do + max = max - v.w + if max <= 0 then return v.v, v.k end + end +end + +do + local saved + function nodecore.boxmuller() + local old = saved + if old then + saved = nil + return old + end + local r = math_sqrt(-2 * math_log(math_random())) + local t = 2 * math_pi * math_random() + saved = r * math_sin(t) + return r * math_cos(t) + end +end + +function nodecore.extend_item(name, func) + local orig = minetest.registered_items[name] or {} + local copy = {} + for k, v in pairs(orig) do copy[k] = v end + copy = func(copy, orig) or copy + minetest.register_item(":" .. name, copy) +end + +function nodecore.fixedbox(x, ...) + return {type = "fixed", fixed = { + x or {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}, + ... + }} +end + +function nodecore.interact(player) + if type(player) ~= "string" then + player = player:get_player_name() + end + return minetest.get_player_privs(player).interact +end + +function nodecore.wieldgroup(who, group) + local wielded = who and who:get_wielded_item() + local nodedef = minetest.registered_nodes[wielded:get_name()] + if nodedef then return nodedef.groups and nodedef.groups[group] end + local caps = wielded and wielded:get_tool_capabilities() + return caps and caps.groupcaps and caps.groupcaps[group] +end + +function nodecore.toolspeed(what, groups) + if not what then return end + local dg = what:get_tool_capabilities().groupcaps + local t + for gn, lv in pairs(groups) do + local gt = dg[gn] + gt = gt and gt.times + gt = gt and gt[lv] + if gt and (not t or t > gt) then t = gt end + end + if (not t) and (not what:is_empty()) then + return nodecore.toolspeed(ItemStack(""), groups) + end + return t +end + +function nodecore.interval(after, func) + local function go() + minetest.after(after, go) + return func() + end + minetest.after(after, go) +end + +function nodecore.wear_wield(player, groups, qty) + local wielded = player:get_wielded_item() + if wielded then + local wdef = wielded:get_definition() + local tp = wielded:get_tool_capabilities() + local dp = minetest.get_dig_params(groups, tp) + if wdef and wdef.after_use then + wielded = wdef.after_use(wielded, player, nil, dp) or wielded + else + if not minetest.settings:get_bool("creative_mode") then + wielded:add_wear(dp.wear * (qty or 1)) + if wielded:get_count() <= 0 and wdef.sound + and wdef.sound.breaks then + minetest.sound_play(wdef.sound.breaks, + {object = player, gain = 0.5}) + end + end + end + return player:set_wielded_item(wielded) + end +end + +function nodecore.consume_wield(player, qty) + local wielded = player:get_wielded_item() + if wielded then + local wdef = wielded:get_definition() + if wdef.stack_max > 1 and qty then + local have = wielded:get_count() - qty + if have <= 0 then + wielded = ItemStack("") + else + wielded:set_count(have) + end + end + return player:set_wielded_item(wielded) + end +end + +function nodecore.loaded_mods() + local t = {} + for _, v in pairs(minetest.get_modnames()) do + t[v] = true + end + return t +end + +function nodecore.node_group(name, pos, node) + node = node or minetest.get_node(pos) + local def = minetest.registered_nodes[node.name] or {} + return def.groups and def.groups[name] +end + +function nodecore.item_eject(pos, stack, speed, qty, vel) + stack = ItemStack(stack) + speed = speed or 0 + vel = vel or {x = 0, y = 0, z = 0} + if speed == 0 and vel.x == 0 and vel.y == 0 and vel.z == 0 + and nodecore.place_stack and minetest.get_node(pos).name == "air" then + stack:set_count(stack:get_count() * (qty or 1)) + return nodecore.place_stack(pos, stack) + end + for _ = 1, (qty or 1) do + local v = { + x = vel.x + (math_random() - 0.5) * speed, + y = vel.y + math_random() * speed, + z = vel.z + (math_random() - 0.5) * speed, + } + local p = { + x = v.x > 0 and pos.x + 0.4 or v.x < 0 and pos.x - 0.4 or pos.x, + y = pos.y + 0.25, + z = v.z > 0 and pos.z + 0.4 or v.z < 0 and pos.z - 0.4 or pos.z, + } + local obj = minetest.add_item(p, stack) + if obj then obj:set_velocity(v) end + end +end + +function nodecore.quenched(pos) + return #minetest.find_nodes_in_area( + {x = pos.x - 1, y = pos.y - 1, z = pos.z - 1}, + {x = pos.x + 1, y = pos.y + 1, z = pos.z + 1}, + {"group:coolant"}) > 0 +end + +function nodecore.node_spin_custom(...) + local arr = {...} + arr[0] = false + local lut = {} + for i = 1, #arr do + lut[arr[i - 1]] = arr[i] + end + lut[arr[#arr]] = arr[1] + local qty = #arr + + return function(pos, node, clicker, itemstack) + node = node or minetest.get_node(pos) + node.param2 = lut[node.param2] or lut[false] + if clicker:is_player() then + minetest.log(clicker:get_player_name() .. " spins " + .. node.name .. " at " .. minetest.pos_to_string(pos) + .. " to param2 " .. node.param2 .. " (" + .. qty .. " total)") + end + minetest.swap_node(pos, node) + nodecore.node_sound(pos, "place") + local def = minetest.registered_items[node.name] or {} + if def.on_spin then def.on_spin(pos, node) end + return itemstack + end +end +function nodecore.node_spin_filtered(func) + local rots = {} + for i = 0, 23 do + local f = nodecore.facedirs[i] + local hit + for j = 1, #rots do + if not hit then + local o = nodecore.facedirs[rots[j]] + hit = hit or func(f, o) + end + end + if not hit then rots[#rots + 1] = f.id end + end + return nodecore.node_spin_custom(unpack(rots)) +end + +function nodecore.node_change(pos, node, newname) + if node.name == newname then return end + return minetest.set_node(pos, underride({name = newname}, node)) +end diff --git a/mods/nc_api/util_node_is.lua b/mods/nc_api/util_node_is.lua new file mode 100644 index 0000000..cd2f8cb --- /dev/null +++ b/mods/nc_api/util_node_is.lua @@ -0,0 +1,13 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore + = minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +function nodecore.buildable_to(thing) + if not thing.name then + thing = nodecore.underride(thing, minetest.get_node(thing)) + end + if thing.name == "ignore" then return end + local def = minetest.registered_items[thing.name] or {} + return def.buildable_to +end diff --git a/mods/nc_api/util_phealth.lua b/mods/nc_api/util_phealth.lua new file mode 100644 index 0000000..1607889 --- /dev/null +++ b/mods/nc_api/util_phealth.lua @@ -0,0 +1,32 @@ +-- LUALOCALS < --------------------------------------------------------- +local math, minetest, nodecore + = math, minetest, nodecore +local math_ceil + = math.ceil +-- LUALOCALS > --------------------------------------------------------- + +local function getphealth(player) + return player:get_hp() + player:get_meta():get_float("dhp") +end +nodecore.getphealth = getphealth + +local function setphealth(player, hp) + if hp > 20 then hp = 20 end + if hp < 0 then hp = 0 end + local whole = math_ceil(hp) + if whole == 0 then whole = 1 end + local dhp = hp - whole + player:get_meta():set_float("dhp", dhp) + return player:set_hp(whole) +end +nodecore.setphealth = setphealth + +local function addphealth(player, hp) + return setphealth(player, getphealth(player) + hp) +end +nodecore.addphealth = addphealth + +function nodecore.node_punch_hurt(pos, node, puncher, ...) + if puncher and puncher:is_player() then addphealth(puncher, -1) end + return minetest.node_punch(pos, node, puncher, ...) +end diff --git a/mods/nc_api/util_scan_flood.lua b/mods/nc_api/util_scan_flood.lua new file mode 100644 index 0000000..da7eb7b --- /dev/null +++ b/mods/nc_api/util_scan_flood.lua @@ -0,0 +1,41 @@ +-- LUALOCALS < --------------------------------------------------------- +local ipairs, math, minetest, nodecore, pairs, table + = ipairs, math, minetest, nodecore, pairs, table +local math_random, table_insert + = math.random, table.insert +-- LUALOCALS > --------------------------------------------------------- + +local dirs = nodecore.dirs() + +function nodecore.scan_flood(pos, range, func) + local q = {pos} + local seen = { } + for d = 0, range do + local nxt = {} + for _, p in ipairs(q) do + local res = func(p, d) + if res then return res end + if res == nil then + for _, v in pairs(dirs) do + local np = { + x = p.x + v.x, + y = p.y + v.y, + z = p.z + v.z + } + local nk = minetest.hash_node_position(np) + if not seen[nk] then + seen[nk] = true + np.dir = v + table_insert(nxt, np) + end + end + end + end + if #nxt < 1 then break end + for i = 1, #nxt do + local j = math_random(1, #nxt) + nxt[i], nxt[j] = nxt[j], nxt[i] + end + q = nxt + end +end diff --git a/mods/nc_api/util_sound.lua b/mods/nc_api/util_sound.lua new file mode 100644 index 0000000..87d7bf4 --- /dev/null +++ b/mods/nc_api/util_sound.lua @@ -0,0 +1,76 @@ +-- LUALOCALS < --------------------------------------------------------- +local ItemStack, ipairs, math, minetest, nodecore, pairs, type, unpack, + vector + = ItemStack, ipairs, math, minetest, nodecore, pairs, type, unpack, + vector +local math_exp, math_random, math_sin, math_sqrt + = math.exp, math.random, math.sin, math.sqrt +-- LUALOCALS > --------------------------------------------------------- + +local oldplay = minetest.sound_play +function minetest.sound_play(name, spec, ...) + if spec and type(spec) == "table" and spec.pitch == nil then + spec.pitch = math_exp((math_random() - 0.5) * (spec.pitchvary or 0.05)) + end + return oldplay(name, spec, ...) +end + +function nodecore.windiness(y) + if y < 0 then return 0 end + if y > 512 then y = 512 end + return math_sqrt(y) * (1 + 0.5 * math_sin(minetest.get_gametime() / 5)) +end + +function nodecore.stack_sounds(pos, kind, stack) + stack = stack or nodecore.stack_get(pos) + stack = ItemStack(stack) + if stack:is_empty() then return end + local def = minetest.registered_items[stack:get_name()] or {} + if (not def.sounds) or (not def.sounds[kind]) then return end + local t = {} + for k, v in pairs(def.sounds[kind]) do t[k] = v end + t.pos = pos + return minetest.sound_play(t.name, t) +end +function nodecore.stack_sounds_delay(...) + local t = {...} + minetest.after(0, function() + nodecore.stack_sounds(unpack(t)) + end) +end +function nodecore.sounds(name, gfoot, gdug, gplace) + return { + footstep = {name = name, gain = gfoot or 0.2}, + dig = {name = name, gain = gdug or 0.5}, + dug = {name = name, gain = gdug or 1}, + place = {name = name, gain = gplace or 1} + } +end + +function nodecore.sound_play_except(name, def, pname) + if not pname then + return minetest.sound_play(name, def) + end + if type(pname) ~= "string" then + pname = pname:get_player_name() + end + for _, p in ipairs(minetest.get_connected_players()) do + local pn = p:get_player_name() + if pn ~= pname and ((not def.pos) + or (vector.distance(p:get_pos(), def.pos) <= 32)) then + def.to_player = pn + minetest.sound_play(name, def) + end + end +end + +function nodecore.node_sound(pos, kind, opts) + if nodecore.stack_sounds(pos, kind) then return end + local node = opts and opts.node or minetest.get_node(pos) + local def = minetest.registered_items[node.name] or {} + if (not def.sounds) or (not def.sounds[kind]) then return end + local t = {} + for k, v in pairs(def.sounds[kind]) do t[k] = v end + t.pos = pos + return nodecore.sound_play_except(t.name, t, opts and opts.except) +end diff --git a/mods/nc_api/util_stack.lua b/mods/nc_api/util_stack.lua new file mode 100644 index 0000000..7dcd164 --- /dev/null +++ b/mods/nc_api/util_stack.lua @@ -0,0 +1,79 @@ +-- LUALOCALS < --------------------------------------------------------- +local ItemStack, ipairs, minetest, nodecore + = ItemStack, ipairs, minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +local function family(stack) + if stack:is_empty() then return "" end + local name = stack:get_name() + local def = minetest.registered_items[name] + return def and def.stackfamily or stack:to_string() +end +function nodecore.stack_merge(dest, src) + if dest:is_empty() then return dest:add_item(src) end + if family(src) ~= family(dest) then + return dest:add_item(src) + end + local o = src:get_name() + src:set_name(dest:get_name()) + src = dest:add_item(src) + if not src:is_empty() then + src:set_name(o) + end + return src +end + +function nodecore.node_inv(pos) + return minetest.get_meta(pos):get_inventory() +end + +function nodecore.stack_get(pos) + return nodecore.node_inv(pos):get_stack("solo", 1) +end + +local function update(pos, ...) + for _, v in ipairs(nodecore.visinv_update_ents(pos)) do + v:get_luaentity():itemcheck() + end + return ... +end + +function nodecore.stack_set(pos, stack) + return update(pos, nodecore.node_inv(pos):set_stack("solo", 1, ItemStack(stack))) +end + +function nodecore.stack_add(pos, stack) + local node = minetest.get_node(pos) + local def = minetest.registered_items[node.name] or {} + if def.stack_allow then + local ret = def.stack_allow(pos, node, stack) + if ret == false then return stack end + if ret and ret ~= true then return ret end + end + stack = ItemStack(stack) + local item = nodecore.stack_get(pos) + local left + if item:is_empty() then + left = nodecore.node_inv(pos):add_item("solo", stack) + else + left = nodecore.stack_merge(item, stack) + nodecore.stack_set(pos, item) + end + if left:get_count() ~= stack:get_count() then + nodecore.stack_sounds(pos, "place") + end + return update(pos, left) +end + +function nodecore.stack_giveto(pos, player) + local stack = nodecore.stack_get(pos) + local qty = stack:get_count() + if qty < 1 then return true end + + stack = player:get_inventory():add_item("main", stack) + if stack:get_count() == qty then return stack:is_empty() end + + nodecore.stack_sounds(pos, "dug") + nodecore.stack_set(pos, stack) + return stack:is_empty() +end diff --git a/mods/nc_api/util_toolcaps.lua b/mods/nc_api/util_toolcaps.lua new file mode 100644 index 0000000..321d829 --- /dev/null +++ b/mods/nc_api/util_toolcaps.lua @@ -0,0 +1,35 @@ +-- LUALOCALS < --------------------------------------------------------- +local math, nodecore, pairs + = math, nodecore, pairs +local math_pow + = math.pow +-- LUALOCALS > --------------------------------------------------------- + +local basetimes = { + cracky = 3, + thumpy = 2, + choppy = 2, + crumbly = 0.5, + snappy = 0.4, +} + +function nodecore.toolcaps(opts) + if opts.uses == nil then opts.uses = 1 end + local gcaps = {} + for gn, bt in pairs(basetimes) do + local lv = opts[gn] + if lv then + local times = {} + for n = 1, lv do + local tt = math_pow(0.5, lv - n) * bt + if tt < 0.25 then tt = 0.25 end + times[n] = tt + end + gcaps[gn] = { + times = times, + uses = 5 * math_pow(3, lv) * opts.uses + } + end + end + return { groupcaps = gcaps, opts = opts } +end diff --git a/mods/nc_api/util_translate.lua b/mods/nc_api/util_translate.lua new file mode 100644 index 0000000..f529d0e --- /dev/null +++ b/mods/nc_api/util_translate.lua @@ -0,0 +1,48 @@ +-- LUALOCALS < --------------------------------------------------------- +local ipairs, minetest, nodecore, pairs, table, type + = ipairs, minetest, nodecore, pairs, table, type +local table_sort + = table.sort +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +local strings = {} +local strings_dirty + +local prefix = minetest.translate(modname, "x") +prefix = prefix:sub(1, prefix:find(modname) - 1) + +function nodecore.translate_inform(str) + if (not str) or (type(str) ~= "string") or (#str < 1) + or (str:sub(1, #prefix) == prefix) then return end + + if not strings[str] then + strings[str] = true + strings_dirty = true + end + + return true +end + +function nodecore.translate(str, ...) + if not nodecore.translate_inform(str) then return str end + return minetest.translate(modname, str, ...) +end + +minetest.register_globalstep(function() + if not strings_dirty then return end + strings_dirty = nil + + local keys = {} + for k in pairs(strings) do keys[#keys + 1] = k end + table_sort(keys) + + local data = "# textdomain: " .. modname .. "\n" + for _, k in ipairs(keys) do + data = data .. k .. "=" .. "\n" + end + + local p = minetest.get_worldpath() .. "/" .. modname .. ".template.tr" + return minetest.safe_file_write(p, data) + end) diff --git a/mods/nc_api/version.lua b/mods/nc_api/version.lua new file mode 100644 index 0000000..dc63d37 --- /dev/null +++ b/mods/nc_api/version.lua @@ -0,0 +1,12 @@ +-- LUALOCALS < --------------------------------------------------------- +local math, tonumber + = math, tonumber +local math_floor + = math.floor +-- LUALOCALS > --------------------------------------------------------- + +local stamp = tonumber("$Format:%at$") +if not stamp then return end +stamp = math_floor((stamp - 1540612800) / 60) +stamp = ("00000000" .. stamp):sub(-8) +return stamp .. "-$Format:%h$" diff --git a/mods/nc_api_craft/craft_check.lua b/mods/nc_api_craft/craft_check.lua new file mode 100644 index 0000000..0e21a9b --- /dev/null +++ b/mods/nc_api_craft/craft_check.lua @@ -0,0 +1,168 @@ +-- LUALOCALS < --------------------------------------------------------- +local ItemStack, ipairs, minetest, nodecore, pairs, type + = ItemStack, ipairs, minetest, nodecore, pairs, type +-- LUALOCALS > --------------------------------------------------------- + +local function addgroups(sum, pos) + local node = minetest.get_node(pos) + local def = minetest.registered_items[node.name] or {} + if not def.groups then return end + for k, v in pairs(def.groups) do + sum[k] = (sum[k] or 0) + v + end +end + +local function craftcheck(recipe, pos, node, data, xx, xz, zx, zz) + local function rel(x, y, z) + return { + x = pos.x + xx * x + zx * z, + y = pos.y + y, + z = pos.z + xz * x + zz * z + } + end + data.rel = rel + data.wield = ItemStack(data.wield or data.crafter and data.crafter:get_wielded_item()) + if recipe.check and not recipe.check(pos, data) then return end + if recipe.wield and (not data.wield or not nodecore.match( + {stack = data.wield}, recipe.wield)) then return end + if recipe.normal then + if data.pointed.type ~= "node" or + recipe.normal.y ~= data.pointed.above.y - data.pointed.under.y then return end + local rx = recipe.normal.x * xx + recipe.normal.z * zx + if rx ~= data.pointed.above.x - data.pointed.under.x then return end + local rz = recipe.normal.x * xz + recipe.normal.z * zz + if rz ~= data.pointed.above.z - data.pointed.under.z then return end + end + for _, v in pairs(recipe.nodes) do + if v ~= recipe.root and v.match then + local p = rel(v.x, v.y, v.z) + if not nodecore.match(p, v.match) then return end + end + end + if recipe.touchgroups then + local sum = {} + addgroups(sum, rel(1, 0, 0)) + addgroups(sum, rel(-1, 0, 0)) + addgroups(sum, rel(0, 1, 0)) + addgroups(sum, rel(0, -1, 0)) + addgroups(sum, rel(0, 0, 1)) + addgroups(sum, rel(0, 0, -1)) + for k, v in pairs(recipe.touchgroups) do + local w = sum[k] or 0 + if v > 0 and w < v then return end + if v <= 0 and w > -v then return end + end + end + local mindur = recipe.duration or 0 + if type(mindur) == "function" then mindur = mindur(recipe, pos, node, data) end + if recipe.toolgroups then + if not data.wield then return end + local dg = data.wield:get_tool_capabilities().groupcaps + local t + for gn, lv in pairs(recipe.toolgroups) do + local gt = dg[gn] + gt = gt and gt.times + gt = gt and gt[lv] + if gt and (not t or t > gt) then t = gt end + end + if not t then return end + mindur = mindur + t + end + if mindur > 0 then + if not data.duration then return end + local dur = data.duration + if type(dur) == "function" then dur = dur(pos, data) end + if not dur or dur < mindur then + if data.inprogress then data.inprogress(pos, data) end + return 1 + end + end + if data.before then data.before(pos, data) end + if recipe.before then recipe.before(pos, data) end + for _, v in ipairs(recipe.nodes) do + if v.replace then + local p = rel(v.x, v.y, v.z) + local r = v.replace + while type(r) == "function" do + r = r(p, v) + end + if r and type(r) == "string" then + r = {name = r} + end + if v.match.excess then + local s = nodecore.stack_get(p) + local x = s:get_count() - (v.match.count or 1) + if x > 0 then + s:set_count(x) + nodecore.item_eject(p, s, 0.001) + end + nodecore.stack_set(p, ItemStack("")) + end + if r then + local n = minetest.get_node(p) + r.param2 = n.param2 + minetest.set_node(p, r) + nodecore.node_sound(p, "place") + nodecore.fallcheck(p) + end + end + end + if recipe.items then + for _, v in pairs(recipe.items) do + nodecore.item_eject(rel(v.x or 0, v.y or 0, v.z or 0), + v.name, v.scatter, v.count, v.velocity) + end + end + if recipe.consumewield then + nodecore.consume_wield(data.crafter, recipe.consumewield) + elseif recipe.toolgroups and recipe.toolwear and data.crafter then + nodecore.wear_wield(data.crafter, recipe.toolgroups, recipe.toolwear) + end + if recipe.after then recipe.after(pos, data) end + if data.after then data.after(pos, data) end + if nodecore.player_stat_add then + nodecore.player_stat_add(1, data.crafter, "craft", recipe.label) + end + minetest.log((data.crafter and data.crafter:get_player_name() or "unknown") + .. " completed recipe \"" .. recipe.label .. "\" at " .. + minetest.pos_to_string(pos) .. " upon " .. node.name) + return true +end + +local function tryall(rc, pos, node, data) + local function go(xx, xz, zx, zz) + return craftcheck(rc, pos, node, data, xx, xz, zx, zz) + end + local r = go(1, 0, 0, 1) + if r then return r end + if not rc.norotate then + r = go(0, -1, 1, 0) + or go(-1, 0, 0, -1) + or go(0, 1, -1, 0) + if r then return r end + if not rc.nomirror then + r = go(-1, 0, 0, 1) + or go(0, 1, 1, 0) + or go(1, 0, 0, -1) + or go(0, -1, -1, 0) + end + end + return r +end + +function nodecore.craft_check(pos, node, data) + data = data or {} + node.x = pos.x + node.y = pos.y + node.z = pos.z + data.pos = pos + data.node = node + for _, rc in ipairs(nodecore.craft_recipes) do + if data.action == rc.action + and nodecore.match(node, rc.root.match) then + data.recipe = rc + local r = tryall(rc, pos, node, data) + if r then return r == true end + end + end +end diff --git a/mods/nc_api_craft/fx_smoke.lua b/mods/nc_api_craft/fx_smoke.lua new file mode 100644 index 0000000..3b05292 --- /dev/null +++ b/mods/nc_api_craft/fx_smoke.lua @@ -0,0 +1,41 @@ +-- LUALOCALS < --------------------------------------------------------- +local math, minetest, nodecore, type + = math, minetest, nodecore, type +local math_random + = math.random +-- LUALOCALS > --------------------------------------------------------- + +local smoking = {} + +function nodecore.smokefx(pos, time, qty) + local now = minetest.get_us_time() / 1000000 + local key = minetest.hash_node_position(pos) + local old = smoking[key] + if old and now < old.exp then minetest.delete_particlespawner(old.id) end + if (not time) or (time <= 0) then + smoking[key] = nil + return + end + if type(qty) ~= "number" then qty = 1 end + if qty < 1 then + if math_random() > qty then return end + qty = 1 + end + smoking[key] = { + id = minetest.add_particlespawner({ + texture = "nc_api_craft_smoke.png", + collisiondetection = true, + amount = (qty or 2) * time, + time = time, + minpos = {x = pos.x - 0.4, y = pos.y - 0.4, z = pos.z - 0.4}, + maxpos = {x = pos.x + 0.4, y = pos.y + 0.4, z = pos.z + 0.4}, + minvel = {x = -0.1, y = 0.3, z = -0.1}, + maxvel = {x = 0.1, y = 0.7, z = 0.1}, + minexptime = 1, + maxexptime = 5, + minsize = 1, + maxsize = 3 + }), + exp = now + time + } +end diff --git a/mods/nc_api_craft/init.lua b/mods/nc_api_craft/init.lua new file mode 100644 index 0000000..880bbdd --- /dev/null +++ b/mods/nc_api_craft/init.lua @@ -0,0 +1,13 @@ +-- LUALOCALS < --------------------------------------------------------- +local include, nodecore + = include, nodecore +-- LUALOCALS > --------------------------------------------------------- + +nodecore.amcoremod() + +include("register_craft") +include("craft_check") +include("item_place_node") +include("on_punchnode") +include("fx_smoke") +include("register_cook_abm") diff --git a/mods/nc_api_craft/item_place_node.lua b/mods/nc_api_craft/item_place_node.lua new file mode 100644 index 0000000..deceeb1 --- /dev/null +++ b/mods/nc_api_craft/item_place_node.lua @@ -0,0 +1,25 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore + = minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +local old_place = minetest.item_place_node +function minetest.item_place_node(itemstack, placer, pointed_thing, ...) + local old_add = minetest.add_node + minetest.add_node = function(pos, node, ...) + local function helper2(...) + nodecore.craft_check(pos, node, { + action = "place", + crafter = placer, + pointed = pointed_thing + }) + return ... + end + return helper2(old_add(pos, node, ...)) + end + local function helper(...) + minetest.add_node = old_add + return ... + end + return helper(old_place(itemstack, placer, pointed_thing, ...)) +end diff --git a/mods/nc_api_craft/mod.conf b/mods/nc_api_craft/mod.conf new file mode 100644 index 0000000..7d5be9f --- /dev/null +++ b/mods/nc_api_craft/mod.conf @@ -0,0 +1,2 @@ +name = nc_api_craft +depends = nc_api diff --git a/mods/nc_api_craft/on_punchnode.lua b/mods/nc_api_craft/on_punchnode.lua new file mode 100644 index 0000000..d1e5ccf --- /dev/null +++ b/mods/nc_api_craft/on_punchnode.lua @@ -0,0 +1,91 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore, vector + = minetest, nodecore, vector +-- LUALOCALS > --------------------------------------------------------- + +local function pummelparticles(_, data) + local pointed = data.pointed + local nodedef = data.nodedef + local pname = data.pname + + local stack = nodecore.stack_get(data.node) + if stack and not stack:is_empty() then + nodedef = minetest.registered_items[stack:get_name()] or nodedef + end + + local a = pointed.above + local b = pointed.under + local vel = vector.subtract(a, b) + local mid = vector.multiply(vector.add(a, b), 0.5) + local p1 = {x = vel.y, y = vel.z, z = vel.x} + local p2 = {x = vel.z, y = vel.x, z = vel.y} + local s1 = vector.add(vector.add(mid, vector.multiply(p1, 0.5)), vector.multiply(p2, 0.5)) + local s2 = vector.add(vector.add(mid, vector.multiply(p1, -0.5)), vector.multiply(p2, -0.5)) + vel = vector.multiply(vel, 0.5) + + data.clearfx = nodecore.digparticles(nodedef, nodecore.underride( + nodecore.underride({}, data.recipe.pumparticles or {}), + { + amount = 8, + time = 1.5, + minpos = s1, + maxpos = s2, + minvel = vel, + maxvel = vel, + minexptime = 0.4, + maxexptime = 0.9, + minsize = 1, + maxsize = 5, + playername = pname + }) + ) +end + +local pummeling = {} + +minetest.register_on_punchnode(function(pos, node, puncher, pointed) + if not puncher:is_player() then return end + local pname = puncher:get_player_name() + if not nodecore.interact(pname) then return end + + node = node or minetest.get_node(pos) + local def = minetest.registered_items[node.name] or {} + + local now = minetest.get_us_time() / 1000000 * 3 + local pum = { + action = "pummel", + crafter = puncher, + pname = pname, + pos = pos, + pointed = pointed, + node = node, + nodedef = def, + start = now, + wield = puncher:get_wielded_item():to_string(), + count = 0, + inprogress = pummelparticles + } + + local old = pummeling[pname] + if old and old.clearfx then old.clearfx() end + + local hash = minetest.hash_node_position + if old and hash(old.pos) == hash(pum.pos) + and hash(old.pointed.above) == hash(pum.pointed.above) + and hash(old.pointed.under) == hash(pum.pointed.under) + and pum.wield == old.wield + and old.last >= (now - 3) + then pum = old end + + pum.count = pum.count + 1 + pum.last = now + pum.duration = now - pum.start - 1 + pummeling[pname] = pum + + if pum.count < 2 then return end + + if nodecore.craft_check(pos, node, nodecore.underride({}, pum)) then + pummeling[pname] = nil + return + end + end) diff --git a/mods/nc_api_craft/register_cook_abm.lua b/mods/nc_api_craft/register_cook_abm.lua new file mode 100644 index 0000000..bbbd58f --- /dev/null +++ b/mods/nc_api_craft/register_cook_abm.lua @@ -0,0 +1,81 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore, type + = minetest, nodecore, type +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +local function getduration(_, data) + local meta = minetest.get_meta(data.node) + + local md = meta:get_string(modname) or "" + md = (md ~= "") and minetest.deserialize(md) or {} + + if md.label ~= data.recipe.label + or md.count ~= nodecore.stack_get(data.node):get_count() + or not md.start + then return 0 end + + return minetest.get_gametime() - md.start +end + +local function playcookfx(pos, cookfx, sound, smokeqty, smoketime) + if not cookfx then return end + if cookfx == true or cookfx and cookfx[sound] then + minetest.sound_play("nc_api_craft_" .. sound, + {gain = 1, pos = pos}) + end + if cookfx == true or cookfx and cookfx.smoke then + if cookfx ~= true and type(cookfx.smoke) == "number" then + smokeqty = smokeqty * cookfx.smoke + end + nodecore.smokefx(pos, smoketime, smokeqty) + end +end + +local function inprogress(pos, data) + local meta = minetest.get_meta(data.node) + local recipe = data.recipe + + local md = meta:get_string(modname) or "" + md = (md ~= "") and minetest.deserialize(md) or {} + + local count = nodecore.stack_get(data.node):get_count() + if md.label ~= recipe.label or md.count ~= count or not md.start then + md = { + label = recipe.label, + count = count, + start = minetest.get_gametime() + } + meta:set_string(modname, minetest.serialize(md)) + end + + data.progressing = true + + return playcookfx(pos, recipe.cookfx, "sizzle", 2, 1) +end + +local function cookdone(pos, data) + local meta = minetest.get_meta(pos) + local recipe = data.recipe + meta:set_float(recipe.label, 0) + return playcookfx(pos, recipe.cookfx, "hiss", 80, 0.2) +end + +function nodecore.register_cook_abm(def) + def.interval = def.interval or 1 + def.chance = def.chance or 1 + def.action = function(pos, node) + local data = { + action = "cook", + duration = getduration, + inprogress = inprogress, + after = cookdone + } + nodecore.craft_check(pos, node, data) + if not data.progressing then + minetest.get_meta(pos):set_string(modname, "") + end + end + nodecore.register_limited_abm(def) +end diff --git a/mods/nc_api_craft/register_craft.lua b/mods/nc_api_craft/register_craft.lua new file mode 100644 index 0000000..6535687 --- /dev/null +++ b/mods/nc_api_craft/register_craft.lua @@ -0,0 +1,69 @@ +-- LUALOCALS < --------------------------------------------------------- +local error, math, nodecore, pairs, table, type + = error, math, nodecore, pairs, table, type +local math_floor, table_insert + = math.floor, table.insert +-- LUALOCALS > --------------------------------------------------------- + +local craft_recipes = {} +nodecore.craft_recipes = craft_recipes + +local id = 0 + +function nodecore.register_craft(recipe) + recipe.action = recipe.action or "place" + local canrot + recipe.nodes = recipe.nodes or {} + for _, v in pairs(recipe.nodes) do + v.x = v.x or 0 + v.y = v.y or 0 + v.z = v.z or 0 + if type(v.match) == "table" and v.match.count then + v.match.excess = v.match.excess or true + end + canrot = canrot or v.x ~= 0 or v.z ~= 0 + if v.x == 0 and v.y == 0 and v.z == 0 then + recipe.root = v + end + end + if not recipe.root or not recipe.root.match then + error "recipe.nodes must have a match for 0,0,0" + end + if not recipe.label then + id = id + 1 + recipe.label = "unnamed " .. recipe.action .. " " .. id + end + if recipe.toolgroups and recipe.toolwear ~= false then + recipe.toolwear = 1 + end + if not canrot then recipe.norotate = true end + if recipe.normal then + recipe.normal.x = recipe.normal.x or 0 + recipe.normal.y = recipe.normal.y or 0 + recipe.normal.z = recipe.normal.z or 0 + end + if recipe.items then + for k, v in pairs(recipe.items) do + if type(v) == "string" then + recipe.items[k] = {name = v} + end + end + end + if recipe.wield and type(recipe.wield) == "table" then + recipe.wield.count = recipe.wield.count or false + end + local newp = recipe.priority or 0 + + local min = 1 + local max = #craft_recipes + 1 + while max > min do + local try = math_floor((min + max) / 2) + local oldp = craft_recipes[try].priority or 0 + if newp < oldp then + min = try + 1 + else + max = try + end + end + table_insert(craft_recipes, min, recipe) +end diff --git a/mods/nc_api_craft/sounds/nc_api_craft_hiss.0.ogg b/mods/nc_api_craft/sounds/nc_api_craft_hiss.0.ogg new file mode 100644 index 0000000..3ca6d64 Binary files /dev/null and b/mods/nc_api_craft/sounds/nc_api_craft_hiss.0.ogg differ diff --git a/mods/nc_api_craft/sounds/nc_api_craft_sizzle.0.ogg b/mods/nc_api_craft/sounds/nc_api_craft_sizzle.0.ogg new file mode 100644 index 0000000..2b38eea Binary files /dev/null and b/mods/nc_api_craft/sounds/nc_api_craft_sizzle.0.ogg differ diff --git a/mods/nc_api_craft/sounds/nc_api_craft_sizzle.1.ogg b/mods/nc_api_craft/sounds/nc_api_craft_sizzle.1.ogg new file mode 100644 index 0000000..2a088da Binary files /dev/null and b/mods/nc_api_craft/sounds/nc_api_craft_sizzle.1.ogg differ diff --git a/mods/nc_api_craft/sounds/nc_api_craft_sizzle.2.ogg b/mods/nc_api_craft/sounds/nc_api_craft_sizzle.2.ogg new file mode 100644 index 0000000..7aeb7bf Binary files /dev/null and b/mods/nc_api_craft/sounds/nc_api_craft_sizzle.2.ogg differ diff --git a/mods/nc_api_craft/textures/nc_api_craft_smoke.png b/mods/nc_api_craft/textures/nc_api_craft_smoke.png new file mode 100644 index 0000000..7c85559 Binary files /dev/null and b/mods/nc_api_craft/textures/nc_api_craft_smoke.png differ diff --git a/mods/nc_concrete/crafting.lua b/mods/nc_concrete/crafting.lua new file mode 100644 index 0000000..b09b752 --- /dev/null +++ b/mods/nc_concrete/crafting.lua @@ -0,0 +1,146 @@ +-- LUALOCALS < --------------------------------------------------------- +local math, minetest, nodecore, pairs, vector + = math, minetest, nodecore, pairs, vector +local math_random + = math.random +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +local ashdirs = { + {x = 1, y = -1, z = 0}, + {x = -1, y = -1, z = 0}, + {x = 0, y = -1, z = 1}, + {x = 0, y = -1, z = -1} +} + +nodecore.register_craft({ + label = "mix concrete (fail)", + action = "pummel", + priority = 2, + toolgroups = {thumpy = 1}, + normal = {y = 1}, + nodes = { + { + match = {groups = {gravel = true}} + }, + { + x = 1, + y = -1, + match = {buildable_to = true} + }, + { + y = -1, + match = "nc_fire:ash", + replace = "air" + } + }, + after = function(pos) + local dirs = {} + for _, d in pairs(ashdirs) do + local p = vector.add(pos, d) + if nodecore.buildable_to(p) then + dirs[#dirs + 1] = {pos = p, qty = 0} + end + end + for _ = 1, 8 do + local p = dirs[math_random(1, #dirs)] + p.qty = p.qty + 1 + end + for _, v in pairs(dirs) do + if v.qty > 0 then + nodecore.item_eject(v.pos, "nc_fire:lump_ash " .. v.qty) + end + end + end + }) + +nodecore.register_craft({ + label = "mix concrete", + action = "pummel", + priority = 1, + toolgroups = {thumpy = 1}, + normal = {y = 1}, + nodes = { + { + match = {groups = {gravel = true}}, + replace = "air" + }, + { + y = -1, + match = "nc_fire:ash", + replace = modname .. ":aggregate" + } + } + }) + +local flow = modname .. ":wet_flowing" +local src = modname .. ":wet_source" + +nodecore.register_limited_abm({ + label = "Aggregate Wettening", + interval = 1, + chance = 2, + limited_max = 100, + nodenames = {modname .. ":aggregate"}, + neighbors = {"group:water"}, + action = function(pos) + minetest.set_node(pos, {name = src}) + nodecore.node_sound(pos, "place") + end + }) + +nodecore.register_limited_abm({ + label = "Aggregate Wandering", + interval = 4, + chance = 2, + limited_max = 100, + nodenames = {src}, + neighbors = {flow}, + action = function(pos, node) + local meta = minetest.get_meta(pos) + local gen = meta:get_int("agggen") + if gen >= 8 and math_random(1, 2) == 1 then + minetest.set_node(pos, {name = "nc_terrain:cobble"}) + return nodecore.node_sound(pos, "place") + end + local miny = pos.y + local found = {} + nodecore.scan_flood(pos, 2, function(p) + local nn = minetest.get_node(p).name + if nn == src then return end + if nn ~= flow then return false end + if p.y > miny then return end + if p.y == miny then + found[#found + 1] = p + return + end + miny = p.y + found = {p} + end) + if #found < 1 then return end + local np = nodecore.pickrand(found) + nodecore.node_sound(pos, "dig") + minetest.set_node(np, node) + minetest.get_meta(np):set_int("agggen", gen + 1) + minetest.set_node(pos, {name = flow, param2 = 7}) + end + }) + +nodecore.register_craft({ + label = "aggregate curing", + action = "cook", + duration = 300, + cookfx = {smoke = 0.05}, + check = function(pos) + return not minetest.find_node_near(pos, 1, {flow, "group:water"}) + end, + nodes = { + { + match = src, + replace = "nc_terrain:stone" + } + } + }) + +nodecore.register_cook_abm({nodenames = {src}}) diff --git a/mods/nc_concrete/init.lua b/mods/nc_concrete/init.lua new file mode 100644 index 0000000..c22b565 --- /dev/null +++ b/mods/nc_concrete/init.lua @@ -0,0 +1,9 @@ +-- LUALOCALS < --------------------------------------------------------- +local include, nodecore + = include, nodecore +-- LUALOCALS > --------------------------------------------------------- + +nodecore.amcoremod() + +include("node") +include("crafting") diff --git a/mods/nc_concrete/mod.conf b/mods/nc_concrete/mod.conf new file mode 100644 index 0000000..199f6aa --- /dev/null +++ b/mods/nc_concrete/mod.conf @@ -0,0 +1,2 @@ +name = nc_concrete +depends = nc_api, nc_api_craft, nc_fire, nc_terrain diff --git a/mods/nc_concrete/node.lua b/mods/nc_concrete/node.lua new file mode 100644 index 0000000..ea09527 --- /dev/null +++ b/mods/nc_concrete/node.lua @@ -0,0 +1,43 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore + = minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +minetest.register_node(modname .. ":aggregate", { + description = "Aggregate", + tiles = {"nc_terrain_gravel.png^(nc_fire_ash.png^[mask:nc_concrete_mask.png)"}, + groups = { + crumbly = 2, + falling_node = 1, + falling_repose = 1 + }, + crush_damage = 1, + sounds = nodecore.sounds("nc_terrain_chompy") + }) + +local wettile = "nc_terrain_stone.png^(nc_fire_ash.png^[mask:nc_concrete_mask.png)" +local wetdef = { + description = "Wet Aggregate", + tiles = {wettile}, + special_tiles = {wettile, wettile}, + liquid_viscosity = 15, + liquid_renewable = false, + liquid_range = 1, + liquid_alternative_flowing = modname .. ":wet_flowing", + liquid_alternative_source = modname .. ":wet_source", + walkable = false, + diggable = false, + drowning = 1, + post_effect_color = {a = 240, r = 32, g = 32, b = 32}, + sounds = nodecore.sounds("nc_terrain_chompy") +} +minetest.register_node(modname .. ":wet_source", nodecore.underride({ + liquidtype = "source" + }, wetdef)) +minetest.register_node(modname .. ":wet_flowing", nodecore.underride({ + drawtype = "flowingliquid", + liquidtype = "flowing", + paramtype2 = "flowingliquid" + }, wetdef)) diff --git a/mods/nc_concrete/textures/nc_concrete_mask.png b/mods/nc_concrete/textures/nc_concrete_mask.png new file mode 100644 index 0000000..9b86dba Binary files /dev/null and b/mods/nc_concrete/textures/nc_concrete_mask.png differ diff --git a/mods/nc_doors/init.lua b/mods/nc_doors/init.lua new file mode 100644 index 0000000..9899a41 --- /dev/null +++ b/mods/nc_doors/init.lua @@ -0,0 +1,9 @@ +-- LUALOCALS < --------------------------------------------------------- +local include, nodecore + = include, nodecore +-- LUALOCALS > --------------------------------------------------------- + +nodecore.amcoremod() + +include("operate") +include("register") diff --git a/mods/nc_doors/mod.conf b/mods/nc_doors/mod.conf new file mode 100644 index 0000000..d3c8e0a --- /dev/null +++ b/mods/nc_doors/mod.conf @@ -0,0 +1,2 @@ +name = nc_doors +depends = nc_api, nc_api_craft, nc_fire, nc_lode, nc_terrain, nc_woodwork diff --git a/mods/nc_doors/operate.lua b/mods/nc_doors/operate.lua new file mode 100644 index 0000000..51db00b --- /dev/null +++ b/mods/nc_doors/operate.lua @@ -0,0 +1,107 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore, pairs, vector + = minetest, nodecore, pairs, vector +-- LUALOCALS > --------------------------------------------------------- + +local function hingeaxis(pos, node) + local fd = node and node.param2 or 0 + fd = nodecore.facedirs[fd] + fd = vector.multiply(vector.add(fd.f, fd.r), 0.5) + return { + x = fd.x == 0 and 0 or pos.x + fd.x, + y = fd.y == 0 and 0 or pos.y + fd.y, + z = fd.z == 0 and 0 or pos.z + fd.z + } +end + +local squelch = {} +minetest.register_globalstep(function() squelch = {} end) + +local is_door = {groups = { door = true }} + +function nodecore.operate_door(pos, node, dir) + if squelch[minetest.pos_to_string(pos)] then return end + node = node or minetest.get_node_or_nil(pos) + if (not node) or (not nodecore.match(node, is_door)) then return end + + local fd = nodecore.facedirs[node.param2 or 0] + local rotdir + if vector.equals(dir, fd.k) or vector.equals(dir, fd.r) then + rotdir = "r" + elseif vector.equals(dir, fd.l) or vector.equals(dir, fd.f) then + rotdir = "f" + else return end + + local found = {} + local hinge = hingeaxis(pos, node) + if nodecore.scan_flood(pos, 128, function(p) + local n = minetest.get_node_or_nil(p) + if not n then return true end + if (not nodecore.match(n, is_door)) + or (not vector.equals(hingeaxis(p, n), hinge)) then return false end + found[minetest.pos_to_string(p)] = {pos = p, node = n} + end + ) then return end + + local toop = {} + for k, v in pairs(found) do + local ffd = nodecore.facedirs[v.node.param2 or 0] + local to = vector.add(v.pos, ffd[rotdir]) + + if (not found[minetest.pos_to_string(to)]) + and (not nodecore.buildable_to(to)) + then return end + + local str = minetest.pos_to_string(to) + if squelch[str] then return end + + v.str = str + v.to = to + v.fd = ffd + + toop[k .. "l"] = { + pos = vector.add(v.pos, ffd.l), + dir = rotdir == "r" and ffd.k or ffd.f + } + toop[k .. "k"] = { + pos = vector.add(v.pos, ffd.k), + dir = rotdir == "r" and ffd.r or ffd.l + } + end + + local toset = {} + for k, v in pairs(found) do + toset[k] = {pos = v.pos, name = "air"} + squelch[k] = true + squelch[v.str] = true + end + for _, v in pairs(found) do + for i, xfd in pairs(nodecore.facedirs) do + if vector.equals(xfd.t, v.fd.t) + and vector.equals(xfd.r, rotdir == "r" and v.fd.f or v.fd.k) then + toset[minetest.pos_to_string(v.to)] = { + pos = v.to, + name = v.node.name, + param2 = i + } + break + end + end + end + + for _, v in pairs(toset) do + minetest.set_node(v.pos, v) + if v.name ~= "air" then + local p = vector.round(vector.multiply(v.pos, 0.25)) + local k = "sfx" .. minetest.pos_to_string(p) + if not squelch[k] then + squelch[k] = true + minetest.sound_play("nc_doors_operate", + {pos = v.pos, gain = 0.5}) + end + end + end + for _, v in pairs(toop) do + nodecore.operate_door(v.pos, nil, v.dir) + end +end diff --git a/mods/nc_doors/register.lua b/mods/nc_doors/register.lua new file mode 100644 index 0000000..8d5cf94 --- /dev/null +++ b/mods/nc_doors/register.lua @@ -0,0 +1,148 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore, pairs, vector + = minetest, nodecore, pairs, vector +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +local function doorop(pos, node, _, _, pointed) + if (not pointed.above) or (not pointed.under) then return end + local force = vector.subtract(pointed.under, pointed.above) + return nodecore.operate_door(pos, node, force) +end + +local tilemods = { + {idx = 1, part = "end", tran = "R180"}, + {idx = 2, part = "end", tran = "FX"}, + {idx = 3, part = "side", tran = "I"}, + {idx = 6, part = "side", tran = "R180"} +} + +function nodecore.register_door(basemod, basenode, desc, pin) + local basefull = basemod .. ":" .. basenode + local basedef = minetest.registered_nodes[basefull] + + local tiles = nodecore.underride({}, basedef.tiles) + while #tiles < 6 do tiles[#tiles + 1] = tiles[#tiles] end + for k, v in pairs(tiles) do tiles[k] = v.name or v end + for _, v in pairs(tilemods) do + tiles[v.idx] = tiles[v.idx] .. "^nc_doors_hinge_" .. v.part + .. "_base.png^[transform" .. v.tran + end + + local paneldef = nodecore.underride({}, { + name = modname .. ":panel_" .. basenode, + description = (desc or basedef.description) .. " Panel", + tiles = tiles, + paramtype2 = "facedir", + silktouch = false, + on_rightclick = nodecore.node_spin_filtered(function(a, b) + return vector.equals(a.f, b.r) + and vector.equals(a.r, b.f) + end), + }, basedef) + paneldef.drop = nil + paneldef.alternate_loose = nil + paneldef.drop_in_place = nil + paneldef.after_dig_node = nil + + minetest.register_node(paneldef.name, paneldef) + + local t = minetest.registered_items[pin].tiles + t = t[3] or t[2] or t[1] + t = t.name or t + tiles = nodecore.underride({}, tiles) + for _, v in pairs(tilemods) do + tiles[v.idx] = tiles[v.idx] .. "^((" .. t .. ")^[mask:nc_doors_hinge_" .. v.part + .. "_mask.png^[transform" .. v.tran .. ")" + end + + local groups = nodecore.underride({door = 1}, basedef.groups) + local doordef = nodecore.underride({ + name = modname .. ":door_" .. basenode, + description = (desc or basedef.description) .. " Hinged Panel", + tiles = tiles, + drop = pin, + drop_in_place = paneldef.name, + on_rightclick = doorop, + groups = groups + }, paneldef) + + minetest.register_node(doordef.name, doordef) + + nodecore.register_craft({ + label = "drill door " .. basenode:lower(), + action = "pummel", + toolgroups = {thumpy = 3}, + normal = {y = 1}, + nodes = { + { + match = "nc_lode:rod_tempered", + }, + { + y = -1, + match = basefull, + replace = paneldef.name + } + } + }) + + nodecore.register_craft({ + label = "lubricate door " .. basenode:lower(), + check = function(_, data) + return minetest.get_meta(data.rel(0, -1, 0)) + :get_float("doorlube") ~= 1 + end, + nodes = { + { + match = "nc_fire:lump_coal", + replace = "air" + }, + { + y = -1, + match = paneldef.name, + } + }, + after = function(pos, data) + minetest.get_meta(data.rel(0, -1, 0)):set_float("doorlube", 1) + return nodecore.digparticles( + minetest.registered_nodes["nc_fire:coal8"], + { + collisiondetection = true, + amount = 10, + time = 0.2, + minpos = {x = pos.x - 0.4, y = pos.y - 0.5, z = pos.z - 0.4}, + maxpos = {x = pos.x + 0.4, y = pos.y - 0.45, z = pos.z + 0.4}, + minexptime = 0.1, + maxexptime = 1, + minsize = 1, + maxsize = 3 + } + ) + end + }) + nodecore.register_craft({ + label = "door pin " .. basenode:lower(), + action = "pummel", + toolgroups = {thumpy = 1}, + normal = {y = 1}, + check = function(_, data) + return minetest.get_meta(data.rel(0, -1, 0)) + :get_float("doorlube") == 1 + end, + nodes = { + { + match = pin, + replace = "air" + }, + { + y = -1, + match = paneldef.name, + replace = doordef.name + } + } + }) +end + +nodecore.register_door("nc_woodwork", "plank", "Wooden", "nc_woodwork:staff") +nodecore.register_door("nc_terrain", "cobble", "Cobble", "nc_lode:rod_tempered") diff --git a/mods/nc_doors/sounds/nc_doors_operate.0.ogg b/mods/nc_doors/sounds/nc_doors_operate.0.ogg new file mode 100644 index 0000000..8854c51 Binary files /dev/null and b/mods/nc_doors/sounds/nc_doors_operate.0.ogg differ diff --git a/mods/nc_doors/textures/nc_doors_hinge_end_base.png b/mods/nc_doors/textures/nc_doors_hinge_end_base.png new file mode 100644 index 0000000..3a898ae Binary files /dev/null and b/mods/nc_doors/textures/nc_doors_hinge_end_base.png differ diff --git a/mods/nc_doors/textures/nc_doors_hinge_end_mask.png b/mods/nc_doors/textures/nc_doors_hinge_end_mask.png new file mode 100644 index 0000000..553b689 Binary files /dev/null and b/mods/nc_doors/textures/nc_doors_hinge_end_mask.png differ diff --git a/mods/nc_doors/textures/nc_doors_hinge_side_base.png b/mods/nc_doors/textures/nc_doors_hinge_side_base.png new file mode 100644 index 0000000..068bbb3 Binary files /dev/null and b/mods/nc_doors/textures/nc_doors_hinge_side_base.png differ diff --git a/mods/nc_doors/textures/nc_doors_hinge_side_mask.png b/mods/nc_doors/textures/nc_doors_hinge_side_mask.png new file mode 100644 index 0000000..5e775fe Binary files /dev/null and b/mods/nc_doors/textures/nc_doors_hinge_side_mask.png differ diff --git a/mods/nc_envsound/init.lua b/mods/nc_envsound/init.lua new file mode 100644 index 0000000..8bf1787 --- /dev/null +++ b/mods/nc_envsound/init.lua @@ -0,0 +1,55 @@ +-- LUALOCALS < --------------------------------------------------------- +local math, minetest, nodecore, pairs, vector + = math, minetest, nodecore, pairs, vector +local math_exp, math_random + = math.exp, math.random +-- LUALOCALS > --------------------------------------------------------- + +nodecore.amcoremod() + +local function check(pos, done) + local sp = { + x = pos.x + math_random() * 64 - 32, + y = pos.y + math_random() * 64 - 32, + z = pos.z + math_random() * 64 - 32, + } + + local dist = vector.distance(sp, pos) + if dist > 32 or dist < 4 then return end + for p in pairs(done) do + if vector.distance(sp, p) < 32 then return end + end + if minetest.get_node(sp).name ~= "air" then return end + + local light = minetest.get_node_light(sp, 0.5) + if light == 15 then + if sp.y <= 0 then return end + minetest.sound_play("nc_envsound_air", { + pos = sp, + gain = nodecore.windiness(sp.y) / 100 + }) + elseif light < 4 then + minetest.sound_play("nc_envsound_drip", { + pos = sp, + pitchvary = 0.4, + gain = math_exp(math_random()) / 5 + }) + end + + done[pos] = true +end + +local oldpos = {} +local function run() + minetest.after(math_random(), run) + local done = {} + for _, pl in pairs(minetest.get_connected_players()) do + local pname = pl:get_player_name() + local pos = pl:get_pos() + local op = oldpos[pname] or pos + oldpos[pname] = pos + pos = vector.add(pos, vector.multiply(vector.subtract(pos, op), 3)) + check(pos, done) + end +end +run() diff --git a/mods/nc_envsound/mod.conf b/mods/nc_envsound/mod.conf new file mode 100644 index 0000000..137346a --- /dev/null +++ b/mods/nc_envsound/mod.conf @@ -0,0 +1,2 @@ +name = nc_envsound +depends = nc_api, nc_tree diff --git a/mods/nc_envsound/sounds/nc_envsound_air.ogg b/mods/nc_envsound/sounds/nc_envsound_air.ogg new file mode 100644 index 0000000..e4f1388 Binary files /dev/null and b/mods/nc_envsound/sounds/nc_envsound_air.ogg differ diff --git a/mods/nc_envsound/sounds/nc_envsound_drip.0.ogg b/mods/nc_envsound/sounds/nc_envsound_drip.0.ogg new file mode 100644 index 0000000..ad064fa Binary files /dev/null and b/mods/nc_envsound/sounds/nc_envsound_drip.0.ogg differ diff --git a/mods/nc_envsound/sounds/nc_envsound_drip.1.ogg b/mods/nc_envsound/sounds/nc_envsound_drip.1.ogg new file mode 100644 index 0000000..0d74ef4 Binary files /dev/null and b/mods/nc_envsound/sounds/nc_envsound_drip.1.ogg differ diff --git a/mods/nc_envsound/sounds/nc_envsound_drip.2.ogg b/mods/nc_envsound/sounds/nc_envsound_drip.2.ogg new file mode 100644 index 0000000..4262dd3 Binary files /dev/null and b/mods/nc_envsound/sounds/nc_envsound_drip.2.ogg differ diff --git a/mods/nc_fire/abm.lua b/mods/nc_fire/abm.lua new file mode 100644 index 0000000..92d59c2 --- /dev/null +++ b/mods/nc_fire/abm.lua @@ -0,0 +1,98 @@ +-- LUALOCALS < --------------------------------------------------------- +local ipairs, math, minetest, nodecore, pairs, vector + = ipairs, math, minetest, nodecore, pairs, vector +local math_random + = math.random +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +do + local flamedirs = nodecore.dirs() + local embers = {} + minetest.after(0, function() + for k, v in pairs(minetest.registered_items) do + if v.groups.ember then + embers[k] = true + end + end + end) + nodecore.register_limited_abm({ + label = "Fire Requires/Consumes Embers and Emits Particles", + interval = 1, + chance = 1, + nodenames = {modname .. ":fire"}, + action = function(pos) + if math_random(1, 5) == 1 then + minetest.add_particlespawner({ + amount = math_random(1, 3), + time = 1, + minpos = vector.subtract(pos, 0.5), + maxpos = vector.add(pos, 0.5), + minvel = {x = -1, y = 2, z = -1}, + maxvel = {x = 1, y = 2.5, z = 1}, + minacc = {x = -0.1, y = 0, z = -0.1}, + maxacc = {x = 0.1, y = 0, z = 0.1}, + minxeptime = 1, + maxexptime = 3, + minsize = 0.1, + maxsize = 0.2, + collisiondetection = true, + collision_removal = true, + texture = "nc_fire_spark.png", + glow = math_random(5, 9) + }) + end + + local found = {} + for _, dp in ipairs(flamedirs) do + local npos = vector.add(pos, dp) + local node = minetest.get_node_or_nil(npos) + if (not node) or embers[node.name] then + found[#found + 1] = npos + end + end + if #found < 1 then + return minetest.remove_node(pos) + end + local picked = nodecore.pickrand(found) + return nodecore.fire_check_expend(picked) + end + }) +end + +nodecore.register_limited_abm({ + label = "Flammables Ignite", + interval = 5, + chance = 1, + nodenames = {"group:flammable"}, + neighbors = {"group:igniter"}, + action = function(pos, node) + return nodecore.fire_check_ignite(pos, node) + end + }) + +nodecore.register_limited_abm({ + label = "Fuel Burning/Snuffing", + interval = 1, + chance = 1, + nodenames = {"group:ember"}, + action = function(pos, node) + local snuff, vents = nodecore.fire_check_snuff(pos, node) + if snuff or not vents then return end + for i = 1, #vents do + if vents[i].q < 1 then + minetest.set_node(vents[i], {name = modname .. ":fire"}) + end + end + end + }) + +nodecore.register_ambiance({ + label = "Flame Ambiance", + nodenames = {modname .. ":fire"}, + interval = 1, + chance = 1, + sound_name = "nc_fire_flamy", + sound_gain = 0.3 + }) diff --git a/mods/nc_fire/api.lua b/mods/nc_fire/api.lua new file mode 100644 index 0000000..cddebed --- /dev/null +++ b/mods/nc_fire/api.lua @@ -0,0 +1,154 @@ +-- LUALOCALS < --------------------------------------------------------- +local ItemStack, ipairs, math, minetest, nodecore, pairs, type, vector + = ItemStack, ipairs, math, minetest, nodecore, pairs, type, vector +local math_floor, math_pow, math_random + = math.floor, math.pow, math.random +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +nodecore.fire_max = 8 + +do + local flamedirs = nodecore.dirs() + local ventitems = {} + minetest.after(0, function() + for k, v in pairs(minetest.registered_items) do + if v.groups.flammable and not v.groups.fire_fuel + and not v.on_ignite or v.groups.flame or v.name == "air" then + ventitems[k] = v.groups.flame or 0 + end + end + end) + local stackonly = {} + minetest.after(0, function() + for k, v in pairs(minetest.registered_items) do + if v.groups.is_stack_only then + stackonly[k] = true + end + end + end) + function nodecore.fire_vents(pos) + local found = {} + for _, dp in ipairs(flamedirs) do + local npos = vector.add(pos, dp) + local node = minetest.get_node_or_nil(npos) + if not node then return end + + local q + if stackonly[node.name] then + q = ventitems[nodecore.stack_get(npos):get_name()] + else + q = ventitems[node.name] + end + if q then + npos.q = q + found[#found + 1] = npos + end + end + return found + end +end + +local function burneject(pos, stack) + if type(stack) == "table" then + for _, v in pairs(stack) do + burneject(pos, v) + end + return + end + if type(stack) == "string" then stack = ItemStack(stack) end + if not stack.is_empty then return end + if stack and (not stack:is_empty()) then + local p = nodecore.scan_flood(pos, 2, nodecore.buildable_to) + nodecore.item_eject(p or pos, stack, 1) + end +end + +function nodecore.fire_ignite(pos, node) + node = node or minetest.get_node(pos) + local def = minetest.registered_items[node.name] + if def and def.on_ignite then + local ign = def.on_ignite + if type(ign) == "function" then + ign = ign(pos, node) + if ign == true then return end + end + burneject(pos, ign) + end + + local fuel = nodecore.node_group("fire_fuel", pos, node) or 0 + if fuel < 0 then fuel = 0 end + if fuel > nodecore.fire_max then fuel = nodecore.fire_max end + fuel = math_floor(fuel) + if fuel > 0 then + minetest.set_node(pos, {name = modname .. ":ember" .. fuel}) + else + minetest.set_node(pos, {name = modname .. ":fire"}) + end + + minetest.sound_play("nc_fire_ignite", {gain = 1, pos = pos}) + minetest.sound_play("nc_fire_flamy", {gain = 3, pos = pos}) + nodecore.fallcheck(pos) + return true +end + +function nodecore.fire_check_ignite(pos, node, force, ...) + local vents = nodecore.fire_vents(pos) + if (not vents) or #vents < 1 then return end + + if nodecore.quenched(pos) then return end + + if not force then + node = node or minetest.get_node(pos) + local def = minetest.registered_items[node.name] or {} + local flam = def.groups and def.groups.flammable + if not flam then return end + if math_random(1, flam) ~= 1 then return end + end + + return nodecore.fire_ignite(pos, node, ...) +end + +local function snuff(cons, coal, pos, node, ember) + ember = ember or nodecore.node_group("ember", pos, node) + if not ember then return end + ember = ember - cons + if ember > 0 then + if coal then + minetest.set_node(pos, {name = modname .. ":coal" .. ember}) + minetest.sound_play("nc_fire_snuff", {gain = 1, pos = pos}) + else + minetest.set_node(pos, {name = modname .. ":ember" .. ember}) + end + else + minetest.set_node(pos, {name = modname .. ":ash"}) + minetest.sound_play("nc_fire_snuff", {gain = 1, pos = pos}) + end + nodecore.fallcheck(pos) + return true +end + +function nodecore.fire_snuff(...) return snuff(1, true, ...) end +function nodecore.fire_expend(...) return snuff(1, false, ...) end + +function nodecore.fire_check_expend(pos, node) + local ember = nodecore.node_group("ember", pos, node) + if not ember then return end + local r = math_random(1, 16 * math_pow(2, ember)) + if r == 1 then return nodecore.fire_expend(pos, node, ember) end +end + +local function snuffcheck(pos, node) + if nodecore.quenched(pos) then return true end + local vents = nodecore.fire_vents(pos, node) + if not vents then return end + if #vents < 1 then return true end + return false, vents +end + +function nodecore.fire_check_snuff(pos, node) + local res, vents = snuffcheck(pos, node) + res = res and nodecore.fire_snuff(pos) + return res, vents +end diff --git a/mods/nc_fire/firestarting.lua b/mods/nc_fire/firestarting.lua new file mode 100644 index 0000000..e301c7b --- /dev/null +++ b/mods/nc_fire/firestarting.lua @@ -0,0 +1,39 @@ +-- LUALOCALS < --------------------------------------------------------- +local ItemStack, math, minetest, nodecore + = ItemStack, math, minetest, nodecore +local math_random + = math.random +-- LUALOCALS > --------------------------------------------------------- + +nodecore.register_craft({ + label = "stick fire starting", + action = "pummel", + wield = { + groups = {firestick = true} + }, + nodes = { + {match = {groups = {firestick = true}}} + }, + consumewield = 1, + duration = 5, + before = function(pos, data) + local w = data.wield and ItemStack(data.wield):get_name() or "" + local wd = minetest.registered_items[w] or {} + local wg = wd.groups or {} + local fs = wg.firestick or 1 + local nd = minetest.registered_items[data.node.name] or {} + local ng = nd.groups or {} + fs = fs * (ng.firestick or 1) + + if math_random(1, 4) > fs then return end + nodecore.fire_ignite(pos) + + if math_random(1, 4) > fs then return end + local dir = nodecore.pickrand(nodecore.dirs()) + return nodecore.fire_check_ignite({ + x = pos.x + dir.x, + y = pos.y + dir.y, + z = pos.z + dir.z + }) + end + }) diff --git a/mods/nc_fire/init.lua b/mods/nc_fire/init.lua new file mode 100644 index 0000000..041ca33 --- /dev/null +++ b/mods/nc_fire/init.lua @@ -0,0 +1,12 @@ +-- LUALOCALS < --------------------------------------------------------- +local include, nodecore + = include, nodecore +-- LUALOCALS > --------------------------------------------------------- + +nodecore.amcoremod() + +include("api") +include("node") +include("lumps") +include("abm") +include("firestarting") diff --git a/mods/nc_fire/lumps.lua b/mods/nc_fire/lumps.lua new file mode 100644 index 0000000..e4b9b28 --- /dev/null +++ b/mods/nc_fire/lumps.lua @@ -0,0 +1,69 @@ +-- LUALOCALS < --------------------------------------------------------- +local math, minetest, nodecore + = math, minetest, nodecore +local math_floor + = math.floor +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +minetest.register_craftitem(modname .. ":lump_ash", { + description = "Ash Lump", + inventory_image = modname .. "_ash.png^[mask:" .. modname .. "_lump.png", + sounds = nodecore.sounds("nc_terrain_crunchy") + }) +minetest.register_craftitem(modname .. ":lump_coal", { + description = "Charcoal Lump", + inventory_image = modname .. "_coal_4.png^[mask:" .. modname .. "_lump.png", + groups = {flammable = 1}, + sounds = nodecore.sounds("nc_terrain_crunchy") + }) + +local function split(items, name, qty) + local two = math_floor(qty / 2) + if two > 0 then + items[#items + 1] = {name = name .. " 2", count = two, scatter = 5} + end + qty = qty - (two * 2) + if qty > 0 then + items[#items + 1] = {name = name, count = qty, scatter = 5} + end +end +for num = 0, nodecore.fire_max do + local items = {} + split(items, modname .. ":lump_coal", num) + split(items, modname .. ":lump_ash", nodecore.fire_max - num) + local name = modname .. ((num == 0) and ":ash" or (":coal" .. num)) + nodecore.register_craft({ + label = "chop " .. name, + action = "pummel", + toolgroups = {choppy = 1}, + nodes = { + {match = name, replace = "air"} + }, + items = items + }) +end + +nodecore.register_craft({ + label = "compress ash block", + action = "pummel", + toolgroups = {thumpy = 1}, + nodes = { + { + match = {name = modname .. ":lump_ash", count = 8}, + replace = modname .. ":ash" + } + } + }) +nodecore.register_craft({ + label = "compress coal block", + action = "pummel", + toolgroups = {thumpy = 2}, + nodes = { + { + match = {name = modname .. ":lump_coal", count = 8}, + replace = modname .. ":coal8" + } + } + }) diff --git a/mods/nc_fire/mod.conf b/mods/nc_fire/mod.conf new file mode 100644 index 0000000..41de7e8 --- /dev/null +++ b/mods/nc_fire/mod.conf @@ -0,0 +1,2 @@ +name = nc_fire +depends = nc_api, nc_api_craft, nc_terrain diff --git a/mods/nc_fire/node.lua b/mods/nc_fire/node.lua new file mode 100644 index 0000000..133d67f --- /dev/null +++ b/mods/nc_fire/node.lua @@ -0,0 +1,126 @@ +-- LUALOCALS < --------------------------------------------------------- +local math, minetest, nodecore + = math, minetest, nodecore +local math_floor, math_sqrt + = math.floor, math.sqrt +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +minetest.register_node(modname .. ":fire", { + description = "Fire", + drawtype = "firelike", + visual_scale = 1.5, + tiles = { + { + name = "nc_fire_fire.png", + animation = { + ["type"] = "vertical_frames", + aspect_w = 24, + aspect_h = 24, + length = 0.6 + } + } + }, + paramtype = "light", + light_source = 12, + groups = { + igniter = 1, + flame = 1, + flame_sound = 1, + }, + damage_per_second = 2, + sunlight_propagates = true, + floodable = true, + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + drop = "" + }) + +local function txr(name, opaq) + local full = modname .. "_" .. name .. ".png" + if opaq and opaq < 1 then + full = "(" .. full .. "^[opacity:" + .. math_floor(256 * math_sqrt(opaq)) .. ")" + end + return full +end + +local function txrcoal(num) + local name = txr("ash") + local base = math_floor(num / 2) + if base > 0 then + for i = base, 1, -1 do + name = name .. "^" .. txr("coal_" .. i) + end + end + local rem = (num / 2) - base + if rem > 0 then + name = name .. "^" .. txr("coal_" .. (base + 1), rem) + end + return name +end + +for num = 1, nodecore.fire_max do + minetest.register_node(modname .. ":coal" .. num, { + description = "Charcoal", + tiles = {txrcoal(num) .. "^[noalpha"}, + groups = { + crumbly = 1, + flammable = 5 - math_floor(num / nodecore.fire_max * 4), + falling_node = 1, + fire_fuel = num, + charcoal = num + }, + crush_damage = 1, + sounds = nodecore.sounds("nc_terrain_crunchy") + }) +end + +local function txrember(num) + local name = txrcoal(num) + local base = math_floor(num / 2) + if base > 0 then + name = name .. "^" .. txr("ember_" .. base) + end + local rem = (num / 2) - base + if rem > 0 then + name = name .. "^" .. txr("ember_" .. (base + 1), rem) + end + return name +end + +for num = 1, nodecore.fire_max do + minetest.register_node(modname .. ":ember" .. num, { + description = "Burning Embers", + tiles = {txrember(num) .. "^[noalpha"}, + paramtype = "light", + light_source = 6, + groups = { + igniter = 1, + ember = num, + falling_node = 1 + }, + drop = "", + diggable = false, + damage_per_second = 2, + on_punch = nodecore.node_punch_hurt, + crush_damage = 1, + sounds = nodecore.sounds("nc_terrain_crunchy") + }) +end +minetest.register_alias(modname .. ":fuel", modname .. ":ember2") + +minetest.register_node(modname .. ":ash", { + description = "Ash", + tiles = {modname .. "_ash.png"}, + groups = { + falling_node = 1, + falling_repose = 1, + crumbly = 1 + }, + crush_damage = 0.25, + sounds = nodecore.sounds("nc_terrain_swishy") + }) diff --git a/mods/nc_fire/sounds/nc_fire_flamy.0.ogg b/mods/nc_fire/sounds/nc_fire_flamy.0.ogg new file mode 100644 index 0000000..be9b953 Binary files /dev/null and b/mods/nc_fire/sounds/nc_fire_flamy.0.ogg differ diff --git a/mods/nc_fire/sounds/nc_fire_flamy.1.ogg b/mods/nc_fire/sounds/nc_fire_flamy.1.ogg new file mode 100644 index 0000000..46a7954 Binary files /dev/null and b/mods/nc_fire/sounds/nc_fire_flamy.1.ogg differ diff --git a/mods/nc_fire/sounds/nc_fire_flamy.2.ogg b/mods/nc_fire/sounds/nc_fire_flamy.2.ogg new file mode 100644 index 0000000..4ad02a0 Binary files /dev/null and b/mods/nc_fire/sounds/nc_fire_flamy.2.ogg differ diff --git a/mods/nc_fire/sounds/nc_fire_ignite.0.ogg b/mods/nc_fire/sounds/nc_fire_ignite.0.ogg new file mode 100644 index 0000000..fe2dcde Binary files /dev/null and b/mods/nc_fire/sounds/nc_fire_ignite.0.ogg differ diff --git a/mods/nc_fire/sounds/nc_fire_snuff.0.ogg b/mods/nc_fire/sounds/nc_fire_snuff.0.ogg new file mode 100644 index 0000000..eee17b8 Binary files /dev/null and b/mods/nc_fire/sounds/nc_fire_snuff.0.ogg differ diff --git a/mods/nc_fire/textures/nc_fire_ash.png b/mods/nc_fire/textures/nc_fire_ash.png new file mode 100644 index 0000000..e928d4d Binary files /dev/null and b/mods/nc_fire/textures/nc_fire_ash.png differ diff --git a/mods/nc_fire/textures/nc_fire_coal_1.png b/mods/nc_fire/textures/nc_fire_coal_1.png new file mode 100644 index 0000000..c312e65 Binary files /dev/null and b/mods/nc_fire/textures/nc_fire_coal_1.png differ diff --git a/mods/nc_fire/textures/nc_fire_coal_2.png b/mods/nc_fire/textures/nc_fire_coal_2.png new file mode 100644 index 0000000..4ab9102 Binary files /dev/null and b/mods/nc_fire/textures/nc_fire_coal_2.png differ diff --git a/mods/nc_fire/textures/nc_fire_coal_3.png b/mods/nc_fire/textures/nc_fire_coal_3.png new file mode 100644 index 0000000..38b7b66 Binary files /dev/null and b/mods/nc_fire/textures/nc_fire_coal_3.png differ diff --git a/mods/nc_fire/textures/nc_fire_coal_4.png b/mods/nc_fire/textures/nc_fire_coal_4.png new file mode 100644 index 0000000..79b846b Binary files /dev/null and b/mods/nc_fire/textures/nc_fire_coal_4.png differ diff --git a/mods/nc_fire/textures/nc_fire_ember_1.png b/mods/nc_fire/textures/nc_fire_ember_1.png new file mode 100644 index 0000000..67904fb Binary files /dev/null and b/mods/nc_fire/textures/nc_fire_ember_1.png differ diff --git a/mods/nc_fire/textures/nc_fire_ember_2.png b/mods/nc_fire/textures/nc_fire_ember_2.png new file mode 100644 index 0000000..5f26930 Binary files /dev/null and b/mods/nc_fire/textures/nc_fire_ember_2.png differ diff --git a/mods/nc_fire/textures/nc_fire_ember_3.png b/mods/nc_fire/textures/nc_fire_ember_3.png new file mode 100644 index 0000000..490f867 Binary files /dev/null and b/mods/nc_fire/textures/nc_fire_ember_3.png differ diff --git a/mods/nc_fire/textures/nc_fire_ember_4.png b/mods/nc_fire/textures/nc_fire_ember_4.png new file mode 100644 index 0000000..b07c29a Binary files /dev/null and b/mods/nc_fire/textures/nc_fire_ember_4.png differ diff --git a/mods/nc_fire/textures/nc_fire_fire.png b/mods/nc_fire/textures/nc_fire_fire.png new file mode 100644 index 0000000..d64414e Binary files /dev/null and b/mods/nc_fire/textures/nc_fire_fire.png differ diff --git a/mods/nc_fire/textures/nc_fire_lump.png b/mods/nc_fire/textures/nc_fire_lump.png new file mode 100644 index 0000000..1b5498c Binary files /dev/null and b/mods/nc_fire/textures/nc_fire_lump.png differ diff --git a/mods/nc_fire/textures/nc_fire_spark.png b/mods/nc_fire/textures/nc_fire_spark.png new file mode 100644 index 0000000..8fa7a90 Binary files /dev/null and b/mods/nc_fire/textures/nc_fire_spark.png differ diff --git a/mods/nc_fire/textures/src/coals.xcf b/mods/nc_fire/textures/src/coals.xcf new file mode 100644 index 0000000..e83b257 Binary files /dev/null and b/mods/nc_fire/textures/src/coals.xcf differ diff --git a/mods/nc_guide/api.lua b/mods/nc_guide/api.lua new file mode 100644 index 0000000..feeaeaa --- /dev/null +++ b/mods/nc_guide/api.lua @@ -0,0 +1,43 @@ +-- LUALOCALS < --------------------------------------------------------- +local nodecore, type + = nodecore, type +-- LUALOCALS > --------------------------------------------------------- + +nodecore.hints = {} + +local function conv(spec) + if not spec then + return function() return true end + end + if type(spec) == "function" then return spec end + if type(spec) == "table" then + local f = spec[1] + if f == true then + return function(db) + for i = 2, #spec do + if db[spec[i]] then return true end + end + end + end + return function(db) + for i = 1, #spec do + if not db[spec[i]] then return end + end + return true + end + end + return function(db) return db[spec] end +end + +function nodecore.addhint(text, goal, reqs) + local hints = nodecore.hints + local t = nodecore.translate(text) + local h = { + text = nodecore.translate("- @1", t), + done = nodecore.translate("- DONE: @1", t), + goal = conv(goal), + reqs = conv(reqs) + } + hints[#hints + 1] = h + return h +end diff --git a/mods/nc_guide/hints.lua b/mods/nc_guide/hints.lua new file mode 100644 index 0000000..df615e8 --- /dev/null +++ b/mods/nc_guide/hints.lua @@ -0,0 +1,451 @@ +-- LUALOCALS < --------------------------------------------------------- +local nodecore + = nodecore +-- LUALOCALS > --------------------------------------------------------- + +local addhint = nodecore.addhint + +------------------------------------------------------------------------ +-- SCALING + +addhint("scale a sheer wall", "scale sheer walls") +addhint("scale a sheer overhang", "scale sheer ceilings") + +------------------------------------------------------------------------ +-- TERRAIN + +addhint("dig up dirt", + "dig:nc_terrain:dirt_loose" +) + +addhint("dig up gravel", + "dig:nc_terrain:gravel_loose", + "toolcap:crumbly:2" +) + +addhint("dig up sand", + "dig:nc_terrain:sand_loose" +) + +addhint("dig up stone", + "dig:nc_terrain:cobble_loose", + "toolcap:cracky:2" +) + +addhint("find deep stone strata", + "group:hard_stone", + "nc_terrain:cobble_loose" +) + +addhint("find molten rock", + "group:lava", + "nc_terrain:cobble_loose" +) + +------------------------------------------------------------------------ +-- SPONGE + +addhint("find a sponge", + {true, + "nc_sponge:sponge", + "nc_sponge:sponge_wet", + "nc_sponge:sponge_living" + } +) + +addhint("harvest a sponge", + "inv:nc_sponge:sponge_wet", + {true, + "nc_sponge:sponge", + "nc_sponge:sponge_wet", + "nc_sponge:sponge_living" + } +) + +addhint("dry out a sponge", + "nc_sponge:sponge", + {true, + "nc_sponge:sponge", + "nc_sponge:sponge_wet", + "nc_sponge:sponge_living" + } +) + +addhint("squeeze out a sponge", + "squeeze sponge", + {true, + "nc_sponge:sponge", + "nc_sponge:sponge_wet", + "nc_sponge:sponge_living" + } +) + +------------------------------------------------------------------------ +-- TREE + +addhint("find dry (loose) leaves", + "nc_tree:leaves_loose" +) + +addhint("find an eggcorn", + "nc_tree:eggcorn" +) + +addhint("plant an eggcorn", + "eggcorn planting", + {"nc_tree:eggcorn", "nc_terrain:dirt_loose"} +) + +addhint("find a stick", + "nc_tree:stick" +) + +addhint("cut down a tree", + "dig:nc_tree:tree", + "toolcap:choppy:2" +) + +addhint("dig up a tree stump", + "dig:nc_tree:root", + "toolcap:choppy:4" +) + +------------------------------------------------------------------------ +-- FIRE + +addhint("make fire by rubbing sticks together", + "stick fire starting", + "nc_tree:stick" +) + +addhint("find ash", + "nc_fire:ash", + "stick fire starting" +) + +addhint("find charcoal", + "group:charcoal", + "stick fire starting" +) + +addhint("chop up charcoal", + "nc_fire:lump_coal", + "group:charcoal" +) + +addhint("pack high-quality charcoal", + "nc_fire:coal" .. nodecore.fire_max, + "nc_fire:lump_coal" +) + +------------------------------------------------------------------------ +-- WOODWORK + +addhint("assemble a staff from sticks", + "assemble staff", + "nc_tree:stick" +) + +addhint("assemble an adze out of sticks", + "assemble wood adze", + {true, "nc_tree:stick", "nc_woodwork:staff"} +) + +addhint("assemble a wooden ladder from sticks", + "assemble wood ladder", + {true, "nc_tree:stick", "nc_woodwork:staff"} +) + +addhint("assemble a wooden frame from staves", + "assemble wood frame", + {true, "nc_tree:stick", "nc_woodwork:staff"} +) + +addhint("split a tree trunk into planks", + "split tree to planks", + {true, "nc_woodwork:adze", "nc_woodwork:tool_hatchet"} +) + +addhint("carve wooden tool heads from planks", + "carve nc_woodwork:plank", + "split tree to planks" +) + +addhint("assemble a wooden tool", + {true, + "assemble wood mallet", + "assemble wood spade", + "assemble wood hatchet", + "assemble wood pick", + }, + "carve nc_woodwork:plank" +) + +addhint("carve a wooden plank completely", + "carve nc_woodwork:toolhead_pick", + "carve nc_woodwork:plank" +) + +addhint("bash a plank into sticks", + "bash planks to sticks", + {"nc_woodwork:plank", "toolcap:thumpy:3"} +) + +addhint("assemble a wooden shelf from frames and planks", + "assemble wood shelf", + {"nc_woodwork:plank", "nc_woodwork:frame"} +) + +------------------------------------------------------------------------ +-- STONEWORK + +addhint("break cobble into chips", + "break cobble to chips", + "nc_terrain:cobble_loose" +) + +addhint("pack stone chips back into cobble", + "repack chips to cobble", + "nc_stonework:chip" +) + +addhint("put a stone tip onto a wooden tool", + {true, + "assemble nc_stonework:tool_mallet", + "assemble nc_stonework:tool_spade", + "assemble nc_stonework:tool_hatchet", + "assemble nc_stonework:tool_pick" + }, + "nc_stonework:chip" +) + +------------------------------------------------------------------------ +-- CONCRETE + +addhint("mix gravel into ash to make aggregate", + "mix concrete", + {"nc_terrain:gravel_loose", "nc_fire:ash"} +) + +addhint("make wet aggregate", + {true, "nc_concrete:wet_source", "nc_concrete:wet_flowing"}, + "mix concrete" +) + +------------------------------------------------------------------------ +-- LODE + +addhint("find a lode stratum", + "group:lodey" +) + +addhint("find lode ore", + "nc_lode:ore", + "group:lodey" +) + +addhint("dig up lode ore", + "nc_lode:cobble_loose", + "nc_lode:ore" +) + +addhint("melt down lode metal from lode cobble", + {true, + "nc_lode:prill_hot", + "nc_lode:prill_annealed", + "nc_lode:prill_tempered" + }, + "nc_lode:cobble_loose" +) + +addhint("sinter glowing lode prills into a cube", + "forge lode block", + {true, + "nc_lode:prill_hot", + "nc_lode:prill_annealed", + "nc_lode:prill_tempered" + } +) + +addhint("chop a glowing lode cube into prills", + "break apart lode block", + "forge lode block" +) + +addhint("make an anvil by tempering a lode cube", + "nc_lode:block_tempered", + "forge lode block" +) + +addhint("cold-forge annealed lode prills into a tool head", + "anvil making lode toolhead_mallet", + "nc_lode:block_tempered" +) + +addhint("cold-forge lode down completely", + "anvil making lode prills", + "nc_lode:block_tempered" +) + +addhint("temper a lode tool head", + {true, + "nc_lode:toolhead_mallet_tempered", + "nc_lode:toolhead_spade_tempered", + "nc_lode:toolhead_hatchet_tempered", + "nc_lode:toolhead_pick_tempered" + }, + "anvil making lode toolhead_mallet" +) + +addhint("weld glowing lode pick and spade heads together", + "assemble lode mattock head", + "anvil making lode toolhead_pick" +) + +addhint("hammer a lode prill into a bar", + "anvil making lode bar", + "nc_lode:block_tempered" +) + +addhint("hammer a lode bar back to a prill", + "anvil recycle lode bar", + "anvil making lode bar" +) + +addhint("hammer lode bars into a rod", + "anvil making lode rod", + "anvil making lode bar" +) + +addhint("chop lode a rod back into bars", + "recycle lode rod", + "anvil making lode rod" +) + +addhint("solder lode rods into crates", + "assemble lode shelf", + "anvil making lode rod" +) + +addhint("chop a lode crate back apart", + "break apart lode shelf", + "assemble lode shelf" +) + +------------------------------------------------------------------------ +-- DOORS + +addhint("chisel a hinge groove into a wooden plank", + "drill door plank", + {"anvil making lode rod", "split tree to planks"} +) + +addhint("lubricate a wooden panel with graphite", + "lubricate door plank", + "drill door plank" +) + +addhint("hammer a staff into a lubricated wooden panel", + "door pin plank", + "lubricate door plank" +) + +addhint("chisel a hinge groove into cobble", + "drill door cobble", + {"anvil making lode rod", "nc_terrain:cobble"} +) + +addhint("lubricate a cobble panel with graphite", + "lubricate door cobble", + "drill door cobble" +) + +addhint("hammer a metal rod into a cobble panel", + "door pin cobble", + "lubricate door cobbleWWW" +) + +------------------------------------------------------------------------ +-- LUX + +addhint("find lux", + "group:lux_emit" +) + +addhint("dig up lux cobble", + "dig:group:lux_cobble", + "group:lux_emit" +) + +addhint("observe a lux reaction", + "group:lux_hot", + "group:lux_cobble" +) + +addhint("observe lux criticality", + "group:lux_cobble_max", + "group:lux_hot" +) + +addhint("lux-infuse a lode tool", + "group:lux_tool", + "group:lux_cobble_max" +) + +------------------------------------------------------------------------ +-- TOTE + +addhint("assemble an annealed lode tote handle", + "craft tote handle", + {"nc_lode:block_annealed", "nc_woodwork:shelf"} +) + +------------------------------------------------------------------------ +-- OPTICS + +addhint("melt sand into glass", + "group:silica", + "nc_terrain:sand_loose" +) + +addhint("quench molten glass into chromatic glass", + "nc_optics:glass_opaque", + "group:silica" +) + +addhint("mold molten glass into clear glass", + "nc_optics:glass", + "group:silica" +) + +addhint("mold molten glass into float glass", + "nc_optics:glass_float", + {"nc_optics:glass", "group:lava"} +) + +addhint("cool molten glass into crude glass", + "nc_optics:glass_crude", + "group:silica" +) + +addhint("chip chromatic glass into prisms", + "nc_optics:prism", + "nc_optics:glass_opaque" +) + +addhint("chop chromatic glass into lenses", + "nc_optics:lens", + "nc_optics:glass_opaque" +) + +local opticactive = {true, "nc_optics:lens_on", "nc_optics:prism_on"} + +addhint("activate a lens", + opticactive, + "nc_optics:lens" +) + +addhint("produce light from a lens", + "nc_optics:lens_glow", + opticactive +) diff --git a/mods/nc_guide/init.lua b/mods/nc_guide/init.lua new file mode 100644 index 0000000..39b653f --- /dev/null +++ b/mods/nc_guide/init.lua @@ -0,0 +1,10 @@ +-- LUALOCALS < --------------------------------------------------------- +local include, nodecore + = include, nodecore +-- LUALOCALS > --------------------------------------------------------- + +nodecore.amcoremod() + +include("api") +include("hints") +include("invtab") diff --git a/mods/nc_guide/invtab.lua b/mods/nc_guide/invtab.lua new file mode 100644 index 0000000..f110ca4 --- /dev/null +++ b/mods/nc_guide/invtab.lua @@ -0,0 +1,90 @@ +-- LUALOCALS < --------------------------------------------------------- +local ipairs, math, minetest, nodecore, pairs, table + = ipairs, math, minetest, nodecore, pairs, table +local math_floor, math_random, table_remove, table_sort + = math.floor, math.random, table.remove, table.sort +-- LUALOCALS > --------------------------------------------------------- + +local pcache = {} + +local strings = { + onemore = "(and 1 more hint)", + fewmore = "(and @1 more hints)", + progress = "Progress: @1 complete, @2 current, @3 future", + explore = "Not all game content is covered by hints. Explore!" +} + +for k, v in pairs(strings) do + nodecore.translate_inform(v) + strings[k] = function(...) return nodecore.translate(v, ...) end +end + +local function gethint(player) + local pname = player:get_player_name() + + local now = math_floor(minetest.get_us_time() / 1000000 / 5) + local cached = pcache[pname] + if cached and cached.time == now then return cached.found end + + local rawdb = nodecore.statsdb[pname] or {} + local db = {} + for _, r in ipairs({"inv", "punch", "dig", "place", "craft"}) do + for k, v in pairs(rawdb[r] or {}) do + db[k] = v + db[r .. ":" .. k] = v + end + end + for k, v in pairs(minetest.registered_items) do + if db[k] then + if v.tool_capabilities and v.tool_capabilities.groupcaps then + for gn, gv in pairs(v.tool_capabilities.groupcaps) do + for gt in pairs(gv.times or {}) do + db["toolcap:" .. gn .. ":" .. gt] = true + end + end + end + for gn, gv in pairs(v.groups or {}) do + db["group:" .. gn] = gv + end + end + end + + local done = {} + local found = {} + for _, hint in ipairs(nodecore.hints) do + if hint.goal(db) then + done[#done + 1] = hint.done + elseif hint.reqs(db) then + found[#found + 1] = hint.text + end + end + local prog = #found + local left = #(nodecore.hints) - prog - #done + + while #found > 5 do + table_remove(found, math_random(1, #found)) + end + while #found < 5 do + local j = math_random(1, #done) + found[#found + 1] = done[j] + table_remove(done, j) + end + table_sort(found) + if #found == (prog - 1) then + found[#found + 1] = strings.onemore() + elseif #found < prog then + found[#found + 1] = strings.fewmore(prog - #found) + end + + found[#found + 1] = "" + found[#found + 1] = strings.progress(#done, prog, left) + found[#found + 1] = strings.explore() + + pcache[pname] = {time = now, found = found} + return found +end + +nodecore.register_inventory_tab({ + title = "Hints", + content = gethint + }) diff --git a/mods/nc_guide/mod.conf b/mods/nc_guide/mod.conf new file mode 100644 index 0000000..b74a521 --- /dev/null +++ b/mods/nc_guide/mod.conf @@ -0,0 +1,2 @@ +name = nc_guide +depends = nc_fire, nc_player_gui, nc_stats diff --git a/mods/nc_items/burnup.lua b/mods/nc_items/burnup.lua new file mode 100644 index 0000000..040cd86 --- /dev/null +++ b/mods/nc_items/burnup.lua @@ -0,0 +1,20 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore + = minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +if nodecore.loaded_mods().nc_fire then + nodecore.register_limited_abm({ + label = "Flammable ItemStacks Ignite", + interval = 5, + chance = 1, + nodenames = {modname .. ":stack"}, + neighbors = {"group:igniter"}, + action = function(pos) + local stack = nodecore.stack_get(pos) + return nodecore.fire_check_ignite(pos, {name = stack:get_name()}) + end + }) +end diff --git a/mods/nc_items/ent_falling.lua b/mods/nc_items/ent_falling.lua new file mode 100644 index 0000000..090b057 --- /dev/null +++ b/mods/nc_items/ent_falling.lua @@ -0,0 +1,64 @@ +-- LUALOCALS < --------------------------------------------------------- +local ItemStack, math, minetest, nodecore, pairs, setmetatable, unpack + = ItemStack, math, minetest, nodecore, pairs, setmetatable, unpack +local math_random + = math.random +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +local function readd(oldadd, pos, item, ...) + local stack = ItemStack(item) + item = stack:get_name() + if stack:get_count() ~= 1 or (not + minetest.registered_nodes[item]) then + return oldadd(pos, item, ...) + end + local npos = nodecore.scan_flood(pos, 5, + function(p) + if p.y > pos.y and math_random() < 0.95 then return end + if p.y > pos.y + 1 then return end + if nodecore.buildable_to(p) then return p end + end) + if not npos then return oldadd(pos, item, ...) end + minetest.set_node(npos, {name = item}) +end + +local bifn = minetest.registered_entities["__builtin:falling_node"] +local falling = { + set_node = function(self, node, meta, ...) + if node and node.name == modname .. ":stack" + and meta and meta.inventory and meta.inventory.solo then + local stack = ItemStack(meta.inventory.solo[1] or "") + if not stack:is_empty() then + local ent = minetest.add_item(self.object:get_pos(), stack) + if ent then ent:set_velocity({x = 0, y = 0, z = 0}) end + return self.object:remove() + end + end + return bifn.set_node(self, node, meta, ...) + end, + on_step = function(...) + local oldadd = minetest.add_item + local drops = {} + minetest.add_item = function(pos, item, ...) + drops[#drops + 1] = {pos, item, ...} + end + local oldnode = minetest.add_node + minetest.add_node = function(pos, node, ...) + oldnode(pos, node, ...) + for _, v in pairs(drops) do + readd(oldadd, unpack(v)) + end + drops = {} + end + local function helper(...) + minetest.add_item = oldadd + minetest.add_node = oldnode + return ... + end + return helper(bifn.on_step(...)) + end +} +setmetatable(falling, bifn) +minetest.register_entity(":__builtin:falling_node", falling) diff --git a/mods/nc_items/ent_item.lua b/mods/nc_items/ent_item.lua new file mode 100644 index 0000000..443cfc3 --- /dev/null +++ b/mods/nc_items/ent_item.lua @@ -0,0 +1,41 @@ +-- LUALOCALS < --------------------------------------------------------- +local ItemStack, math, minetest, nodecore, setmetatable, vector + = ItemStack, math, minetest, nodecore, setmetatable, vector +local math_random + = math.random +-- LUALOCALS > --------------------------------------------------------- + +local bii = minetest.registered_entities["__builtin:item"] +local newbii = { + on_step = function(self, dtime, ...) + bii.on_step(self, dtime, ...) + if self.moving_state then return end + local pos = vector.round(self.object:get_pos()) + local i = ItemStack(self.itemstring) + pos = nodecore.scan_flood(pos, 5, + function(p) + if p.y > pos.y and math_random() < 0.95 then return end + if p.y > pos.y + 1 then return end + i = nodecore.stack_add(p, i) + if i:is_empty() then return p end + if nodecore.buildable_to(p) then return p end + end) + if not pos then return end + if not i:is_empty() then nodecore.place_stack(pos, i) end + self.itemstring = "" + self.object:remove() + end, + on_punch = function(self, whom, ...) + if not nodecore.interact(whom) then return end + bii.on_punch(self, whom, ...) + if self.itemstring ~= "" then + local v = self.object:get_velocity() + v.x = v.x + math_random() * 5 - 2.5 + v.y = v.y + math_random() * 5 - 2.5 + v.z = v.z + math_random() * 5 - 2.5 + self.object:set_velocity(v) + end + end +} +setmetatable(newbii, bii) +minetest.register_entity(":__builtin:item", newbii) diff --git a/mods/nc_items/hooks.lua b/mods/nc_items/hooks.lua new file mode 100644 index 0000000..336cfda --- /dev/null +++ b/mods/nc_items/hooks.lua @@ -0,0 +1,82 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore, setmetatable, vector + = minetest, nodecore, setmetatable, vector +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +nodecore.register_cook_abm({nodenames = {modname .. ":stack"}}) + +function minetest.item_place(itemstack, placer, pointed_thing, param2) + if not nodecore.interact(placer) then return end + if pointed_thing.type == "node" and placer and + not placer:get_player_control().sneak then + local n = minetest.get_node(pointed_thing.under) + local nn = n.name + local nd = minetest.registered_items[nn] + if nd and nd.on_rightclick then + return nd.on_rightclick(pointed_thing.under, n, + placer, itemstack, pointed_thing) or itemstack, false + end + end + local def = itemstack:get_definition() + if def.type == "node" and not def.place_as_item then + return minetest.item_place_node(itemstack, placer, pointed_thing, param2) + end + if not itemstack:is_empty() then + local above = minetest.get_pointed_thing_position(pointed_thing, true) + if above and nodecore.buildable_to(above) then + nodecore.place_stack(above, itemstack:take_item(), placer, pointed_thing) + end + end + return itemstack +end + +if minetest.raycast then + local olddrop = minetest.item_drop + function minetest.item_drop(item, player, ...) + local oldadd = minetest.add_item + function minetest.add_item(pos, stack, ...) + if not minetest.raycast then + return oldadd(pos, stack, ...) + end + + local start = player:get_pos() + local eyeheight = player:get_properties().eye_height or 1.625 + start.y = start.y + eyeheight + local target = vector.add(start, vector.multiply(player:get_look_dir(), 4)) + local pointed = minetest.raycast(start, target, false)() + if (not pointed) or pointed.type ~= "node" then + return oldadd(pos, stack, ...) + end + + local dummyent = {} + setmetatable(dummyent, { + __index = function() + return function() return {} end + end + }) + + local name = stack:get_name() + local function tryplace(p) + if nodecore.match(p, {name = name, count = false}) then + stack = nodecore.stack_add(p, stack) + if stack:is_empty() then return dummyent end + end + if nodecore.buildable_to(p) then + nodecore.place_stack(p, stack, player) + return dummyent + end + end + + return tryplace(pointed.under) + or tryplace(pointed.above) + or oldadd(pos, stack, ...) + end + local function helper(...) + minetest.add_item = oldadd + return ... + end + return helper(olddrop(item, player, ...)) + end +end diff --git a/mods/nc_items/init.lua b/mods/nc_items/init.lua new file mode 100644 index 0000000..1ffa5a7 --- /dev/null +++ b/mods/nc_items/init.lua @@ -0,0 +1,13 @@ +-- LUALOCALS < --------------------------------------------------------- +local include, nodecore + = include, nodecore +-- LUALOCALS > --------------------------------------------------------- + +nodecore.amcoremod() + +include('node') +include('ent_item') +include('ent_falling') +include('hooks') +include('burnup') +include('pulverize') diff --git a/mods/nc_items/mod.conf b/mods/nc_items/mod.conf new file mode 100644 index 0000000..a4492f4 --- /dev/null +++ b/mods/nc_items/mod.conf @@ -0,0 +1,2 @@ +name = nc_items +depends = nc_api, nc_api_craft, nc_fire diff --git a/mods/nc_items/node.lua b/mods/nc_items/node.lua new file mode 100644 index 0000000..68fae65 --- /dev/null +++ b/mods/nc_items/node.lua @@ -0,0 +1,100 @@ +-- LUALOCALS < --------------------------------------------------------- +local ItemStack, minetest, nodecore + = ItemStack, minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +local function pezdispense(pos) + local above = {x = pos.x, y = pos.y + 1, z = pos.z} + local node = minetest.get_node(above) + if node.name ~= modname .. ":stack" then + return nodecore.visinv_update_ents(pos) + end + nodecore.place_stack(pos, nodecore.stack_get(above)) + minetest.remove_node(above) + nodecore.visinv_update_ents(pos) + return pezdispense(above) +end + +minetest.register_node(modname .. ":stack", { + drawtype = "nodebox", + node_box = nodecore.fixedbox( + {-0.5, -0.5, -0.5, 0.5, -7/16, 0.5} + ), + use_texture_alpha = true, + tiles = { + "nc_items_shadow.png", + "nc_items_blank.png", + }, + walkable = true, + selection_box = nodecore.fixedbox( + {-0.4, -0.5, -0.4, 0.4, 0.3, 0.4} + ), + collision_box = nodecore.fixedbox(), + drop = {}, + groups = { + snappy = 1, + falling_repose = 1, + visinv = 1, + is_stack_only = 1 + }, + paramtype = "light", + sunlight_propagates = true, + repose_drop = function(posfrom, posto) + local stack = nodecore.stack_get(posfrom) + if stack and not stack:is_empty() then + nodecore.item_eject(posto, stack) + end + return minetest.remove_node(posfrom) + end, + on_rightclick = function(pos, node, whom, stack, pointed, ...) + if not nodecore.interact(whom) then return stack end + local def = nodecore.stack_get(pos):get_definition() or {} + if def.stack_rightclick then + local rtn = def.stack_rightclick(pos, node, whom, stack, pointed, ...) + if rtn then return rtn end + end + return nodecore.stack_add(pos, stack) + end, + on_construct = function(pos, ...) + minetest.after(0, function() + return nodecore.stack_sounds(pos, "place") + end) + return nodecore.visinv_on_construct(pos, ...) + end, + after_dig_node = pezdispense + }) + +function nodecore.place_stack(pos, stack, placer, pointed_thing) + stack = ItemStack(stack) + + local below = {x = pos.x, y = pos.y - 1, z = pos.z} + if minetest.get_node(below).name == modname .. ":stack" then + stack = nodecore.stack_add(below, stack) + if stack:is_empty() then return end + end + + if stack:get_count() == 1 then + local def = minetest.registered_nodes[stack:get_name()] + if def and def.groups and def.groups.stack_as_node then + minetest.set_node(pos, {name = stack:get_name()}) + if def.after_place_node then + def.after_place_node(pos, nil, stack) + end + return nodecore.fallcheck(pos) + end + end + + minetest.set_node(pos, {name = modname .. ":stack"}) + nodecore.stack_set(pos, stack) + if placer and pointed_thing then + nodecore.craft_check(pos, {name = stack:get_name()}, { + action = "place", + crafter = placer, + pointed = pointed_thing + }) + end + + return nodecore.fallcheck(pos) +end diff --git a/mods/nc_items/pulverize.lua b/mods/nc_items/pulverize.lua new file mode 100644 index 0000000..ddf0ecc --- /dev/null +++ b/mods/nc_items/pulverize.lua @@ -0,0 +1,18 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, pairs + = minetest, pairs +-- LUALOCALS > --------------------------------------------------------- + +minetest.register_privilege("pulverize", { + description = "Can use the /pulverize command", + give_to_singleplayer = false, + give_to_admin = false + }) + +for k, v in pairs(minetest.registered_chatcommands) do + if k == "pulverize" then + v.privs = v.privs or {} + v.privs.pulverize = true + minetest.override_chatcommand(k, v) + end +end diff --git a/mods/nc_items/textures/nc_items_blank.png b/mods/nc_items/textures/nc_items_blank.png new file mode 100644 index 0000000..ada6be5 Binary files /dev/null and b/mods/nc_items/textures/nc_items_blank.png differ diff --git a/mods/nc_items/textures/nc_items_shadow.png b/mods/nc_items/textures/nc_items_shadow.png new file mode 100644 index 0000000..ce0898b Binary files /dev/null and b/mods/nc_items/textures/nc_items_shadow.png differ diff --git a/mods/nc_lode/init.lua b/mods/nc_lode/init.lua new file mode 100644 index 0000000..a672d5b --- /dev/null +++ b/mods/nc_lode/init.lua @@ -0,0 +1,13 @@ +-- LUALOCALS < --------------------------------------------------------- +local include, nodecore + = include, nodecore +-- LUALOCALS > --------------------------------------------------------- + +nodecore.amcoremod() + +include("ore") +include("metallurgy") +include("oresmelt") +include("tools") +include("shafts") +include("shelf") diff --git a/mods/nc_lode/metallurgy.lua b/mods/nc_lode/metallurgy.lua new file mode 100644 index 0000000..29b3a4b --- /dev/null +++ b/mods/nc_lode/metallurgy.lua @@ -0,0 +1,175 @@ +-- LUALOCALS < --------------------------------------------------------- +local ItemStack, minetest, nodecore, pairs, type + = ItemStack, minetest, nodecore, pairs, type +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +local tempers = { + { + name = "hot", + desc = "Glowing", + sound = "annealed", + glow = true + }, + { + name = "annealed", + desc = "Annealed", + sound = "annealed" + }, + { + name = "tempered", + desc = "Tempered", + sound = "tempered" + } +} + +function nodecore.register_lode(shape, rawdef) + for _, temper in pairs(tempers) do + local def = nodecore.underride({}, rawdef) + def = nodecore.underride(def, { + description = temper.desc .. " Lode " .. shape, + name = (shape .. "_" .. temper.name):lower():gsub(" ", "_"), + groups = { + cracky = 3, + falling_node = temper.name == "hot" and 1 or nil + }, + ["metal_temper_" .. temper.name] = true, + metal_alt_hot = modname .. ":" .. shape:lower() .. "_hot", + metal_alt_annealed = modname .. ":" .. shape:lower() .. "_annealed", + metal_alt_tempered = modname .. ":" .. shape:lower() .. "_tempered", + sounds = nodecore.sounds("nc_lode_" .. temper.sound) + }) + def.metal_temper_cool = (not def.metal_temper_hot) or nil + if not temper.glow then + def.light_source = nil + else + def.groups = def.groups or {} + def.groups.falling_node = 1 + def.damage_per_second = 2 + end + + if def.tiles then + local t = {} + for k, v in pairs(def.tiles) do + t[k] = v:gsub("#", temper.name) + end + def.tiles = t + end + for k, v in pairs(def) do + if type(v) == "string" then + def[k] = v:gsub("##", temper.desc):gsub("#", temper.name) + end + end + + if def.bytemper then def.bytemper(temper, def) end + + local fullname = modname .. ":" .. def.name + minetest.register_item(fullname, def) + if def.type == "node" then + nodecore.register_cook_abm({nodenames = {fullname}}) + end + end +end + +nodecore.register_lode("Block", { + type = "node", + description = "## Lode", + tiles = { modname .. "_#.png" }, + light_source = 8, + crush_damage = 4 + }) + +nodecore.register_lode("Prill", { + type = "craft", + inventory_image = modname .. "_#.png^[mask:" .. modname .. "_mask_prill.png", + }) + +local function replacestack(pos, alt) + local stack = nodecore.stack_get(pos) + if stack:is_empty() then stack = nil end + local node = minetest.get_node(pos) + local name = stack and stack:get_name() or node.name + local def = minetest.registered_items[name] or {} + alt = def["metal_alt_" .. alt] + if not alt then return nodecore.remove_node(pos) end + if stack then + local repl = ItemStack(alt) + local qty = stack:get_count() + if qty == 0 then qty = 1 end + repl:set_count(qty * repl:get_count()) + nodecore.remove_node(pos) + return nodecore.item_eject(pos, repl) + else + nodecore.set_node(pos, {name = alt}) + nodecore.fallcheck(pos) + end +end + +nodecore.register_craft({ + label = "lode stack heating", + action = "cook", + touchgroups = {flame = 3}, + duration = 30, + cookfx = true, + nodes = {{match = {metal_temper_cool = true, count = false}}}, + after = function(pos) return replacestack(pos, "hot") end + }) + +nodecore.register_craft({ + label = "lode stack annealing", + action = "cook", + touchgroups = {flame = 0}, + duration = 120, + priority = -1, + cookfx = {smoke = true, hiss = true}, + nodes = {{match = {metal_temper_hot = true, count = false}}}, + after = function(pos) return replacestack(pos, "annealed") end + }) + +nodecore.register_craft({ + label = "lode stack quenching", + action = "cook", + touchgroups = {flame = 0}, + check = function(pos) + return #minetest.find_nodes_in_area( + {x = pos.x - 1, y = pos.y - 1, z = pos.z - 1}, + {x = pos.x + 1, y = pos.y + 1, z = pos.z + 1}, + {"group:coolant"}) > 0 + end, + cookfx = true, + nodes = {{match = {metal_temper_hot = true, count = false}}}, + after = function(pos) return replacestack(pos, "tempered") end + }) + +-- Because of how massive they are, forging a block is a hot-working process. +nodecore.register_craft({ + label = "forge lode block", + action = "pummel", + toolgroups = {thumpy = 3}, + nodes = { + { + match = {name = modname .. ":prill_hot", count = 8}, + replace = "air" + } + }, + items = { + modname .. ":block_hot" + } + }) + +-- Blocks can be chopped back into prills using only hardened tools. +nodecore.register_craft({ + label = "break apart lode block", + action = "pummel", + toolgroups = {choppy = 5}, + nodes = { + { + match = modname .. ":block_hot", + replace = "air" + } + }, + items = { + {name = modname .. ":prill_hot 2", count = 4, scatter = 5} + } + }) diff --git a/mods/nc_lode/mod.conf b/mods/nc_lode/mod.conf new file mode 100644 index 0000000..dbf0171 --- /dev/null +++ b/mods/nc_lode/mod.conf @@ -0,0 +1,2 @@ +name = nc_lode +depends = nc_api, nc_items, nc_terrain diff --git a/mods/nc_lode/ore.lua b/mods/nc_lode/ore.lua new file mode 100644 index 0000000..68fdbc5 --- /dev/null +++ b/mods/nc_lode/ore.lua @@ -0,0 +1,195 @@ +-- LUALOCALS < --------------------------------------------------------- +local math, minetest, nodecore, pairs + = math, minetest, nodecore, pairs +local math_floor, math_pow + = math.floor, math.pow +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +local function reg(suff, def) + def = nodecore.underride(def, { + description = "Lode " .. suff, + name = suff:lower(), + is_ground_content = true, + groups = { cracky = 2, lodey = 1 }, + sounds = nodecore.sounds("nc_terrain_stony") + }) + def.fullname = modname .. ":" .. def.name + def.oldnames = {"nc_iron:" .. def.name} + + minetest.register_node(def.fullname, def) + + return def.fullname +end + +local stratstone = {} +local stratore = {} +local stone = reg("Stone", { + description = "Stone", + tiles = { "nc_terrain_stone.png^(" .. modname .. "_ore.png^[mask:" + .. modname .. "_mask_ore.png^[opacity:48)" }, + drop_in_place = "nc_terrain:cobble", + strata = stratstone + }) +stratstone[1] = stone +local ore = reg("Ore", { + tiles = { "nc_terrain_stone.png^(" .. modname .. "_ore.png^[mask:" + .. modname .. "_mask_ore.png)" }, + drop_in_place = modname .. ":cobble", + strata = stratore + }) +stratore[1] = ore +for i = 1, nodecore.hard_stone_strata do + local hst = nodecore.hard_stone_tile(i) + stratstone[i + 1] = reg("Stone_" .. i, { + description = "Stone", + tiles = { hst .. "^(" .. modname .. "_ore.png^[mask:" + .. modname .. "_mask_ore.png^[opacity:48)" }, + drop_in_place = modname .. ((i > 1) + and (":stone_" .. (i - 1)) or ":stone"), + groups = { + lodey = 1, + cracky = i + 2, + hard_stone = i + } + }) + stratore[i + 1] = reg("Ore_" .. i, { + description = "Lode Ore", + tiles = { hst .. "^(" .. modname .. "_ore.png^[mask:" + .. modname .. "_mask_ore.png)" }, + drop_in_place = modname .. ":cobble", + groups = { + lodey = 1, + cracky = i + 2, + hard_stone = i + } + }) +end + +reg("Cobble", { + tiles = { modname .. "_ore.png^nc_terrain_cobble.png" }, + groups = { + lode_cobble = 1, + cracky = 2, + lodey = 1 + }, + alternate_loose = { + repack_level = 2, + groups = { + cracky = 0, + crumbly = 2, + falling_repose = 3 + }, + sounds = nodecore.sounds("nc_terrain_chompy") + } + }) + +reg("cobble_hot", { + description = "Glowing Lode Cobble", + tiles = { + "nc_terrain_gravel.png^nc_terrain_cobble.png", + modname .. "_hot.png^nc_terrain_cobble.png", + "nc_terrain_gravel.png^(" .. modname .. "_hot.png^[mask:" + .. modname .. "_mask_molten.png)^nc_terrain_cobble.png" + }, + groups = { cracky = 0, lodey = 1 }, + damage_per_second = 2, + on_punch = nodecore.node_punch_hurt + }) + +local oreid = 0 +local function regore(name, def) + oreid = oreid + 1 + return minetest.register_ore(nodecore.underride(def, { + name = modname .. oreid, + ore_type = "scatter", + ore = name, + wherein = "nc_terrain:stone", + random_factor = 0, + noise_params = { + offset = 0, + scale = 4, + spread = {x = 40, y = 5, z = 40}, + seed = 12497, + octaves = 3, + persist = 0.5, + flags = "eased", + }, + noise_threshold = 1.3 + }, def)) +end +for y = 0, 7 do + local def = { + y_max = 64 - 32 * math_pow(2, y), + y_min = 64 - 32 * math_pow(2, y + 1), + clust_num_ores = math_floor(4 * math_pow(2, y)), + clust_size = math_floor(3 * math_pow(1.25, y)), + clust_scarcity = math_floor(8 * 8 * 8 * 4 * math_pow(1.25, y)), + } + if y == 7 then def.y_min = nil end + regore(ore, def) +end +regore(ore, { + y_max = 48, + clust_num_ores = 3, + clust_size = 2, + clust_scarcity = 8 * 8 * 8, + }) +regore(stone, { + y_max = 32, + clust_num_ores = 4, + clust_size = 3, + clust_scarcity = 2 * 2 * 2, + }) + +local c_ore = minetest.get_content_id(ore) +local c_lodestone = minetest.get_content_id(stone) +local getstoneids = nodecore.memoize(function() + local stoneids = {} + local stratadata = nodecore.stratadata() + for _, id in pairs({ + c_lodestone, + minetest.get_content_id(ore), + minetest.get_content_id("nc_terrain:stone") + }) do + stoneids[id] = true + for _, v in pairs(stratadata.altsbyid[id] or {}) do + stoneids[v] = true + end + end + return stoneids + end) + +nodecore.register_mapgen_shared(function(minp, maxp, area, data) + local stoneids = getstoneids() + + local function bad(x, y, z) + local c = data[area:index(x, y, z)] + return not stoneids[c] + end + + for z = minp.z, maxp.z do + for y = minp.y, maxp.y do + for x = minp.x, maxp.x do + local i = area:index(x, y, z) + if data[i] == c_ore then + if x == minp.x + or x == maxp.x + or y == minp.y + or y == maxp.y + or z == minp.z + or z == maxp.z + or bad(x + 1, y, z) + or bad(x - 1, y, z) + or bad(x, y + 1, z) + or bad(x, y - 1, z) + or bad(x, y, z + 1) + or bad(x, y, z - 1) + then data[i] = c_lodestone + end + end + end + end + end +end) diff --git a/mods/nc_lode/oresmelt.lua b/mods/nc_lode/oresmelt.lua new file mode 100644 index 0000000..6db4b8f --- /dev/null +++ b/mods/nc_lode/oresmelt.lua @@ -0,0 +1,81 @@ +-- LUALOCALS < --------------------------------------------------------- +local math, minetest, nodecore + = math, minetest, nodecore +local math_exp, math_floor, math_log, math_random + = math.exp, math.floor, math.log, math.random +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +local logadj = math_log(2) +local function exporand() + local r = 0 + while r == 0 do r = math_random() end + return math_floor(math_exp(-math_log(r) * logadj)) +end + +nodecore.register_craft({ + label = "heat lode cobble", + action = "cook", + touchgroups = {flame = 3}, + duration = 30, + cookfx = true, + nodes = { + { + match = {groups = {lode_cobble = true}}, + replace = modname .. ":cobble_hot" + } + } + }) + +nodecore.register_limited_abm({ + label = "lode cobble drain", + nodenames = {modname .. ":cobble_hot"}, + interval = 1, + chance = 1, + action = function(pos) + local below = {x = pos.x, y = pos.y - 1, z = pos.z} + if nodecore.match(below, {walkable = true}) then return end + minetest.set_node(pos, {name = "nc_terrain:cobble"}) + nodecore.node_sound(pos, "place") + return nodecore.item_eject(below, modname + .. ":prill_hot " .. exporand()) + end + }) + +nodecore.register_craft({ + label = "lode ore cooling", + action = "cook", + touchgroups = {flame = 0}, + duration = 30, + priority = -1, + cookfx = {smoke = true, hiss = true}, + nodes = { + { + match = modname .. ":cobble_hot", + replace = modname .. ":cobble" + } + } + }) + +nodecore.register_craft({ + label = "lode ore quenching", + action = "cook", + touchgroups = {flame = 0}, + cookfx = true, + check = function(pos) + return #minetest.find_nodes_in_area( + {x = pos.x - 1, y = pos.y - 1, z = pos.z - 1}, + {x = pos.x + 1, y = pos.y + 1, z = pos.z + 1}, + {"group:coolant"}) > 0 + end, + nodes = { + { + match = modname .. ":cobble_hot", + replace = modname .. ":cobble" + } + } + }) + +nodecore.register_cook_abm({nodenames = {"group:lode_cobble"}, neighbors = {"group:flame"}}) +nodecore.register_cook_abm({nodenames = {modname .. ":cobble_hot"}}) diff --git a/mods/nc_lode/shafts.lua b/mods/nc_lode/shafts.lua new file mode 100644 index 0000000..60fae55 --- /dev/null +++ b/mods/nc_lode/shafts.lua @@ -0,0 +1,111 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore + = minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +nodecore.register_lode("Bar", { + ["type"] = "node", + description = "## Lode Bar", + drawtype = "nodebox", + node_box = nodecore.fixedbox(-1/16, -0.5, -1/16, 1/16, 0, 1/16), + tiles = { modname .. "_#.png" }, + light_source = 1, + crush_damage = 1, + paramtype = "light", + sunlight_propagates = true, + groups = { + falling_repose = 1 + } + }) + +nodecore.register_craft({ + label = "anvil making lode bar", + priority = -1, + action = "pummel", + toolgroups = {thumpy = 3}, + nodes = { + { + match = modname .. ":prill_annealed", + replace = "air" + }, + { + y = -1, + match = modname .. ":block_tempered" + } + }, + items = { + modname .. ":bar_annealed" + } + }) + +nodecore.register_craft({ + label = "anvil recycle lode bar", + priority = -1, + action = "pummel", + toolgroups = {thumpy = 3}, + normal = {y = 1}, + nodes = { + { + match = modname .. ":bar_annealed", + replace = "air" + }, + { + y = -1, + match = modname .. ":block_tempered" + } + }, + items = { + modname .. ":prill_annealed" + } + }) + +nodecore.register_lode("Rod", { + ["type"] = "node", + description = "## Lode Rod", + drawtype = "nodebox", + node_box = nodecore.fixedbox(-1/16, -0.5, -1/16, 1/16, 0.5, 1/16), + tiles = { modname .. "_#.png" }, + light_source = 2, + crush_damage = 2, + paramtype = "light", + sunlight_propagates = true, + groups = { + falling_repose = 2 + } + }) + +nodecore.register_craft({ + label = "anvil making lode rod", + action = "pummel", + toolgroups = {thumpy = 3}, + nodes = { + { + match = { name = modname .. ":bar_annealed", count = 2 }, + replace = "air" + }, + { + y = -1, + match = modname .. ":block_tempered" + } + }, + items = { + modname .. ":rod_annealed" + } + }) + +nodecore.register_craft({ + label = "recycle lode rod", + action = "pummel", + toolgroups = {choppy = 3}, + nodes = { + { + match = modname .. ":rod_annealed", + replace = "air" + } + }, + items = { + { name = modname .. ":bar_annealed", count = 2 } + } + }) diff --git a/mods/nc_lode/shelf.lua b/mods/nc_lode/shelf.lua new file mode 100644 index 0000000..ed7ff56 --- /dev/null +++ b/mods/nc_lode/shelf.lua @@ -0,0 +1,120 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore + = minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +local function tile(n) + return { + name = modname .. "_annealed.png^[mask:" .. modname .. "_shelf_" .. n .. ".png", + backface_culling = false + } +end + +local function doplace(stack, clicker, pointed_thing, ...) + local function helper(left, ok, ...) + if ok then nodecore.node_sound(pointed_thing.above, "place") end + return left, ok, ... + end + return helper(minetest.item_place_node(stack, clicker, pointed_thing, ...)) +end + +local function cbox(s) return nodecore.fixedbox(-s, -s, -s, s, s, s) end +minetest.register_node(modname .. ":shelf", { + description = "Lode Crate", + drawtype = "nodebox", + node_box = cbox(127/256), + collision_box = cbox(0.5), + selection_box = cbox(0.5), + tiles = {tile("side"), tile("base"), tile("side")}, + groups = { + cracky = 3, + visinv = 1, + container = 1, + totable = 1 + }, + paramtype = "light", + sunlight_propagates = true, + sounds = nodecore.sounds("nc_lode_annealed"), + on_construct = function(pos) + local inv = minetest.get_meta(pos):get_inventory() + inv:set_size("solo", 1) + nodecore.visinv_update_ents(pos) + end, + on_rightclick = function(pos, _, clicker, stack, pointed_thing) + if not nodecore.interact(clicker) then return end + if pointed_thing.above.y < pointed_thing.under.y then + return doplace(stack, clicker, pointed_thing) + end + if not stack or stack:is_empty() then return end + local def = minetest.registered_items[stack:get_name()] or {} + if def.groups and def.groups.visinv then + return doplace(stack, clicker, pointed_thing) + end + return nodecore.stack_add(pos, stack) + end, + on_punch = function(pos, node, puncher, pointed_thing, ...) + minetest.node_punch(pos, node, puncher, pointed_thing, ...) + if not nodecore.interact(puncher) then return end + if pointed_thing.above.y < pointed_thing.under.y then return end + return nodecore.stack_giveto(pos, puncher) + end, + on_dig = function(pos, node, digger, ...) + if nodecore.stack_giveto(pos, digger) then + return minetest.node_dig(pos, node, digger, ...) + end + end, + stack_allow = function(_, _, stack) + local def = minetest.registered_items[stack:get_name()] or {} + if def.groups and def.groups.container then return false end + end + }) + +nodecore.register_craft({ + label = "assemble lode shelf", + norotate = true, + action = "pummel", + toolgroups = {thumpy = 3}, + nodes = { + {match = modname .. ":prill_hot", replace = "air"}, + {x = -1, z = -1, match = modname .. ":rod_annealed", replace = modname .. ":shelf"}, + {x = 1, z = -1, match = modname .. ":rod_annealed", replace = modname .. ":shelf"}, + {x = -1, z = 1, match = modname .. ":rod_annealed", replace = modname .. ":shelf"}, + {x = 1, z = 1, match = modname .. ":rod_annealed", replace = modname .. ":shelf"}, + }, + items = { + modname .. ":prill_annealed" + } + }) + +nodecore.register_craft({ + label = "assemble lode shelf", + norotate = true, + action = "pummel", + toolgroups = {thumpy = 3}, + nodes = { + {match = modname .. ":prill_hot", replace = "air"}, + {x = -1, z = 0, match = modname .. ":rod_annealed", replace = modname .. ":shelf"}, + {x = 1, z = 0, match = modname .. ":rod_annealed", replace = modname .. ":shelf"}, + {x = 0, z = -1, match = modname .. ":rod_annealed", replace = modname .. ":shelf"}, + {x = 0, z = 1, match = modname .. ":rod_annealed", replace = modname .. ":shelf"}, + }, + items = { + modname .. ":prill_annealed" + } + }) + +nodecore.register_craft({ + label = "break apart lode shelf", + norotate = true, + action = "pummel", + toolgroups = {choppy = 3}, + check = function(pos) return nodecore.stack_get(pos):is_empty() end, + nodes = { + {match = modname .. ":shelf", replace = "air"}, + }, + items = { + {name = modname .. ":bar_annealed 2", scatter = 0.001} + } + }) diff --git a/mods/nc_lode/sounds/nc_lode_annealed.0.ogg b/mods/nc_lode/sounds/nc_lode_annealed.0.ogg new file mode 100644 index 0000000..b5add8c Binary files /dev/null and b/mods/nc_lode/sounds/nc_lode_annealed.0.ogg differ diff --git a/mods/nc_lode/sounds/nc_lode_annealed.1.ogg b/mods/nc_lode/sounds/nc_lode_annealed.1.ogg new file mode 100644 index 0000000..aaab8f8 Binary files /dev/null and b/mods/nc_lode/sounds/nc_lode_annealed.1.ogg differ diff --git a/mods/nc_lode/sounds/nc_lode_annealed.2.ogg b/mods/nc_lode/sounds/nc_lode_annealed.2.ogg new file mode 100644 index 0000000..2d6dea5 Binary files /dev/null and b/mods/nc_lode/sounds/nc_lode_annealed.2.ogg differ diff --git a/mods/nc_lode/sounds/nc_lode_annealed.3.ogg b/mods/nc_lode/sounds/nc_lode_annealed.3.ogg new file mode 100644 index 0000000..014c9ec Binary files /dev/null and b/mods/nc_lode/sounds/nc_lode_annealed.3.ogg differ diff --git a/mods/nc_lode/sounds/nc_lode_annealed.4.ogg b/mods/nc_lode/sounds/nc_lode_annealed.4.ogg new file mode 100644 index 0000000..11479cc Binary files /dev/null and b/mods/nc_lode/sounds/nc_lode_annealed.4.ogg differ diff --git a/mods/nc_lode/sounds/nc_lode_tempered.0.ogg b/mods/nc_lode/sounds/nc_lode_tempered.0.ogg new file mode 100644 index 0000000..b01f94f Binary files /dev/null and b/mods/nc_lode/sounds/nc_lode_tempered.0.ogg differ diff --git a/mods/nc_lode/sounds/nc_lode_tempered.1.ogg b/mods/nc_lode/sounds/nc_lode_tempered.1.ogg new file mode 100644 index 0000000..38e6231 Binary files /dev/null and b/mods/nc_lode/sounds/nc_lode_tempered.1.ogg differ diff --git a/mods/nc_lode/sounds/nc_lode_tempered.2.ogg b/mods/nc_lode/sounds/nc_lode_tempered.2.ogg new file mode 100644 index 0000000..aa375e8 Binary files /dev/null and b/mods/nc_lode/sounds/nc_lode_tempered.2.ogg differ diff --git a/mods/nc_lode/sounds/nc_lode_tempered.3.ogg b/mods/nc_lode/sounds/nc_lode_tempered.3.ogg new file mode 100644 index 0000000..dabc464 Binary files /dev/null and b/mods/nc_lode/sounds/nc_lode_tempered.3.ogg differ diff --git a/mods/nc_lode/sounds/nc_lode_tempered.4.ogg b/mods/nc_lode/sounds/nc_lode_tempered.4.ogg new file mode 100644 index 0000000..a7d190d Binary files /dev/null and b/mods/nc_lode/sounds/nc_lode_tempered.4.ogg differ diff --git a/mods/nc_lode/textures/nc_lode_annealed.png b/mods/nc_lode/textures/nc_lode_annealed.png new file mode 100644 index 0000000..20c2f1b Binary files /dev/null and b/mods/nc_lode/textures/nc_lode_annealed.png differ diff --git a/mods/nc_lode/textures/nc_lode_hot.png b/mods/nc_lode/textures/nc_lode_hot.png new file mode 100644 index 0000000..a66260d Binary files /dev/null and b/mods/nc_lode/textures/nc_lode_hot.png differ diff --git a/mods/nc_lode/textures/nc_lode_mask_molten.png b/mods/nc_lode/textures/nc_lode_mask_molten.png new file mode 100644 index 0000000..22379be Binary files /dev/null and b/mods/nc_lode/textures/nc_lode_mask_molten.png differ diff --git a/mods/nc_lode/textures/nc_lode_mask_ore.png b/mods/nc_lode/textures/nc_lode_mask_ore.png new file mode 100644 index 0000000..dcb0890 Binary files /dev/null and b/mods/nc_lode/textures/nc_lode_mask_ore.png differ diff --git a/mods/nc_lode/textures/nc_lode_mask_prill.png b/mods/nc_lode/textures/nc_lode_mask_prill.png new file mode 100644 index 0000000..0a9f551 Binary files /dev/null and b/mods/nc_lode/textures/nc_lode_mask_prill.png differ diff --git a/mods/nc_lode/textures/nc_lode_ore.png b/mods/nc_lode/textures/nc_lode_ore.png new file mode 100644 index 0000000..4a608df Binary files /dev/null and b/mods/nc_lode/textures/nc_lode_ore.png differ diff --git a/mods/nc_lode/textures/nc_lode_shelf_base.png b/mods/nc_lode/textures/nc_lode_shelf_base.png new file mode 100644 index 0000000..03247f5 Binary files /dev/null and b/mods/nc_lode/textures/nc_lode_shelf_base.png differ diff --git a/mods/nc_lode/textures/nc_lode_shelf_side.png b/mods/nc_lode/textures/nc_lode_shelf_side.png new file mode 100644 index 0000000..466e0e0 Binary files /dev/null and b/mods/nc_lode/textures/nc_lode_shelf_side.png differ diff --git a/mods/nc_lode/textures/nc_lode_tempered.png b/mods/nc_lode/textures/nc_lode_tempered.png new file mode 100644 index 0000000..2cd1292 Binary files /dev/null and b/mods/nc_lode/textures/nc_lode_tempered.png differ diff --git a/mods/nc_lode/textures/nc_lode_tool_handle.png b/mods/nc_lode/textures/nc_lode_tool_handle.png new file mode 100644 index 0000000..75eb849 Binary files /dev/null and b/mods/nc_lode/textures/nc_lode_tool_handle.png differ diff --git a/mods/nc_lode/textures/nc_lode_tool_hatchet.png b/mods/nc_lode/textures/nc_lode_tool_hatchet.png new file mode 100644 index 0000000..2eecd1e Binary files /dev/null and b/mods/nc_lode/textures/nc_lode_tool_hatchet.png differ diff --git a/mods/nc_lode/textures/nc_lode_tool_mallet.png b/mods/nc_lode/textures/nc_lode_tool_mallet.png new file mode 100644 index 0000000..adb3d30 Binary files /dev/null and b/mods/nc_lode/textures/nc_lode_tool_mallet.png differ diff --git a/mods/nc_lode/textures/nc_lode_tool_mattock.png b/mods/nc_lode/textures/nc_lode_tool_mattock.png new file mode 100644 index 0000000..9d68f0c Binary files /dev/null and b/mods/nc_lode/textures/nc_lode_tool_mattock.png differ diff --git a/mods/nc_lode/textures/nc_lode_tool_pick.png b/mods/nc_lode/textures/nc_lode_tool_pick.png new file mode 100644 index 0000000..d1c5aaf Binary files /dev/null and b/mods/nc_lode/textures/nc_lode_tool_pick.png differ diff --git a/mods/nc_lode/textures/nc_lode_tool_spade.png b/mods/nc_lode/textures/nc_lode_tool_spade.png new file mode 100644 index 0000000..376d53f Binary files /dev/null and b/mods/nc_lode/textures/nc_lode_tool_spade.png differ diff --git a/mods/nc_lode/textures/nc_lode_toolhead_hatchet.png b/mods/nc_lode/textures/nc_lode_toolhead_hatchet.png new file mode 100644 index 0000000..1dc6cf2 Binary files /dev/null and b/mods/nc_lode/textures/nc_lode_toolhead_hatchet.png differ diff --git a/mods/nc_lode/textures/nc_lode_toolhead_mallet.png b/mods/nc_lode/textures/nc_lode_toolhead_mallet.png new file mode 100644 index 0000000..9e81500 Binary files /dev/null and b/mods/nc_lode/textures/nc_lode_toolhead_mallet.png differ diff --git a/mods/nc_lode/textures/nc_lode_toolhead_mattock.png b/mods/nc_lode/textures/nc_lode_toolhead_mattock.png new file mode 100644 index 0000000..398b3f8 Binary files /dev/null and b/mods/nc_lode/textures/nc_lode_toolhead_mattock.png differ diff --git a/mods/nc_lode/textures/nc_lode_toolhead_pick.png b/mods/nc_lode/textures/nc_lode_toolhead_pick.png new file mode 100644 index 0000000..c5dde19 Binary files /dev/null and b/mods/nc_lode/textures/nc_lode_toolhead_pick.png differ diff --git a/mods/nc_lode/textures/nc_lode_toolhead_spade.png b/mods/nc_lode/textures/nc_lode_toolhead_spade.png new file mode 100644 index 0000000..9baa940 Binary files /dev/null and b/mods/nc_lode/textures/nc_lode_toolhead_spade.png differ diff --git a/mods/nc_lode/tools.lua b/mods/nc_lode/tools.lua new file mode 100644 index 0000000..9aac8c8 --- /dev/null +++ b/mods/nc_lode/tools.lua @@ -0,0 +1,120 @@ +-- LUALOCALS < --------------------------------------------------------- +local ipairs, minetest, nodecore, pairs, type + = ipairs, minetest, nodecore, pairs, type +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +local function toolhead(name, groups, prills) + local n = name:lower() + + if type(groups) == "string" then groups = {groups} end + local function toolcap(nn) + local t = {} + for _, k in ipairs(groups) do t[k] = nn end + return nodecore.toolcaps(t) + end + + nodecore.register_lode("toolhead_" .. n, { + type = "craft", + description = "## Lode " .. name .. " Head", + inventory_image = modname .. "_#.png^[mask:" .. + modname .. "_toolhead_" .. n .. ".png", + stack_max = 1 + }) + + nodecore.register_lode("tool_" .. n, { + type = "tool", + description = "## Lode " .. name, + inventory_image = modname .. "_tool_handle.png^(" .. + modname .. "_#.png^[mask:" .. + modname .. "_tool_" .. n .. ".png)", + stack_max = 1, + tool_capabilities = toolcap(4), + bytemper = function(t, d) + if t.name == "tempered" then + d.tool_capabilities = toolcap(5) + end + end, + groups = { flammable = 4 }, + metal_alt_hot = modname .. ":prill_hot " .. prills, + tool_wears_to = modname .. ":prill_# " .. prills, + on_ignite = modname .. ":prill_# " .. prills + }) + + for _, t in pairs({"annealed", "tempered"}) do + nodecore.register_craft({ + label = "assemble lode " .. n, + normal = {y = 1}, + nodes = { + {match = modname .. ":toolhead_" .. n .. "_" .. t, + replace = "air"}, + {y = -1, match = "nc_woodwork:staff", replace = "air"}, + }, + items = { + {y = -1, name = modname .. ":tool_" .. n .. "_" .. t}, + } + }) + end +end + +toolhead("Mallet", "thumpy", 3) +toolhead("Spade", "crumbly", 2) +toolhead("Hatchet", "choppy", 2) +toolhead("Pick", "cracky", 1) + +local function forge(from, fromqty, to, prills) + return nodecore.register_craft({ + label = "anvil making lode " .. (to or "prills"), + action = "pummel", + toolgroups = {thumpy = 3}, + nodes = { + { + match = {name = modname .. ":" .. from .. "_annealed", + count = fromqty}, + replace = "air" + }, + { + y = -1, + match = modname .. ":block_tempered" + } + }, + items = { + to and (modname .. ":" .. to .. "_annealed") or nil, + prills and {name = modname .. ":prill_annealed", count = prills, + scatter = 5} or nil + } + }) +end +forge("prill", 3, "toolhead_mallet") +forge("toolhead_mallet", nil, "toolhead_spade", 1) +forge("toolhead_spade", nil, "toolhead_hatchet") +forge("toolhead_hatchet", nil, "toolhead_pick", 1) +forge("toolhead_pick", nil, nil, 1) + +toolhead("Mattock", {"cracky", "crumbly"}, 3) +local function mattock(a, b) + return nodecore.register_craft({ + label = "assemble lode mattock head", + action = "pummel", + toolgroups = {thumpy = 3}, + normal = {y = 1}, + nodes = { + { + y = a, + match = modname .. ":toolhead_pick_hot", + replace = "air" + }, + { + y = b, + match = modname .. ":toolhead_spade_hot", + replace = "air" + } + }, + items = { + modname .. ":toolhead_mattock_hot" + } + }) +end +mattock(0, -1) +mattock(-1, 0) diff --git a/mods/nc_lux/cherenkov.lua b/mods/nc_lux/cherenkov.lua new file mode 100644 index 0000000..3edef63 --- /dev/null +++ b/mods/nc_lux/cherenkov.lua @@ -0,0 +1,47 @@ +-- LUALOCALS < --------------------------------------------------------- +local math, minetest, nodecore, pairs, vector + = math, minetest, nodecore, pairs, vector +local math_floor, math_random + = math.floor, math.random +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +local function check(pos, player) + local p = player:get_pos(); + p = { + x = p.x + math_random() * 8 - 4, + y = p.y + math_random() * 8 - 4, + z = p.z + math_random() * 8 - 4, + } + local light = minetest.get_node_light(p) + if (not light) or (light >= 4) then return end + local rel = vector.subtract(p, pos) + local dsqr = rel.x * rel.x + rel.y * rel.y + rel.z * rel.z + if math_random() * 512 < dsqr then return end + minetest.add_particlespawner({ + amount = math_floor(math_random() * 5) + 1, + time = 0.1, + minpos = p, + maxpos = p, + minvel = vector.multiply(vector.normalize(rel), 4), + maxvel = vector.multiply(vector.normalize(rel), 8), + texture = modname .. "_base.png^[mask:" .. modname .. "_mask.png^[opacity:32", + minexptime = 0.05, + maxexptime = 0.25, + playername = player:get_player_name(), + glow = 1 + }) +end + +nodecore.register_limited_abm({ + label = "Lux Reaction", + interval = 1, + chance = 2, + nodenames = {"group:lux_emit"}, + action = function(pos) + for _, player in pairs(minetest.get_connected_players()) do + check(pos, player) + end + end + }) diff --git a/mods/nc_lux/fluid.lua b/mods/nc_lux/fluid.lua new file mode 100644 index 0000000..a37d87b --- /dev/null +++ b/mods/nc_lux/fluid.lua @@ -0,0 +1,82 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore, pairs, vector + = minetest, nodecore, pairs, vector +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +local wetdef = { + description = "Lux Flow", + tiles = {modname .. "_base.png"}, + special_tiles = {modname .. "_base.png", modname .. "_base.png"}, + alpha = 64, + liquid_viscosity = 0, + liquid_renewable = false, + liquid_range = 2, + liquid_alternative_flowing = modname .. ":flux_flowing", + liquid_alternative_source = modname .. ":flux_source", + pointable = false, + walkable = false, + diggable = false, + buildable_to = true, + light_source = 10, + damage_per_second = 1, + drowning = 0, + groups = { lux_emit = 10, lux_fluid = 1 }, + post_effect_color = {a = 64, r = 251, g = 241, b = 143}, + sounds = nodecore.sounds("nc_terrain_chompy") +} +minetest.register_node(modname .. ":flux_source", nodecore.underride({ + drawtype = "liquid", + liquidtype = "source" + }, wetdef)) +minetest.register_node(modname .. ":flux_flowing", nodecore.underride({ + drawtype = "flowingliquid", + liquidtype = "flowing", + paramtype2 = "flowingliquid" + }, wetdef)) + +local outdirs = {} +for _, v in pairs(nodecore.dirs()) do + if v.y <= 0 then + outdirs[#outdirs + 1] = v + end +end +nodecore.register_limited_abm({ + label = "Lux Flow Leakage", + interval = 1, + chance = 2, + limited_max = 100, + nodenames = {"group:lux_cobble_max"}, + action = function(pos) + for _, v in pairs(outdirs) do + local p = vector.add(pos, v) + if minetest.get_node(p).name ~= modname .. ":flux_source" + and nodecore.buildable_to(p) then + minetest.set_node(p, {name = modname .. ":flux_source"}) + end + end + end + }) + +local indirs = {} +for _, v in pairs(nodecore.dirs()) do + if v.y >= 0 then + indirs[#indirs + 1] = v + end +end +nodecore.register_limited_abm({ + label = "Lux Flow Ebb", + interval = 1, + chance = 2, + limited_max = 100, + nodenames = {modname .. ":flux_source"}, + action = function(pos) + for _, v in pairs(indirs) do + local p = vector.add(pos, v) + local def = minetest.registered_nodes[minetest.get_node(p).name] + if def and def.groups and def.groups.lux_cobble_max then return end + end + minetest.remove_node(pos) + end + }) diff --git a/mods/nc_lux/init.lua b/mods/nc_lux/init.lua new file mode 100644 index 0000000..2e6eb22 --- /dev/null +++ b/mods/nc_lux/init.lua @@ -0,0 +1,12 @@ +-- LUALOCALS < --------------------------------------------------------- +local include, nodecore + = include, nodecore +-- LUALOCALS > --------------------------------------------------------- + +nodecore.amcoremod() + +include("ore") +include("fluid") +include("react") +include("tools") +include("cherenkov") diff --git a/mods/nc_lux/mod.conf b/mods/nc_lux/mod.conf new file mode 100644 index 0000000..be01e71 --- /dev/null +++ b/mods/nc_lux/mod.conf @@ -0,0 +1,2 @@ +name = nc_lux +depends = nc_api, nc_api_craft, nc_lode, nc_terrain diff --git a/mods/nc_lux/ore.lua b/mods/nc_lux/ore.lua new file mode 100644 index 0000000..f487c56 --- /dev/null +++ b/mods/nc_lux/ore.lua @@ -0,0 +1,108 @@ +-- LUALOCALS < --------------------------------------------------------- +local math, minetest, nodecore + = math, minetest, nodecore +local math_floor, math_pow + = math.floor, math.pow +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +for i = 1, 8 do + minetest.register_node(modname .. ":cobble" .. i, { + description = "Lux Cobble", + tiles = { + "nc_terrain_gravel.png^((" .. modname .. "_base.png^[mask:" + .. modname .. "_mask.png)^[opacity:" + .. (i * 32) .. ")^nc_terrain_cobble.png" + }, + stackfamily = modname .. ":cobble", + groups = { + lux_cobble = 1, + lux_emit = i, + cracky = 1, + lux_cobble_max = i == 8 and 1 or nil, + igniter = i > 4 and 1 or nil, + lux_hot = i > 4 and 1 or nil + }, + alternate_loose = { + stackfamily = modname .. ":cobble_loose", + repack_level = 2, + groups = { + cracky = 0, + crumbly = 2, + falling_repose = 3, + }, + drop = modname .. ":cobble1_loose", + sounds = nodecore.sounds("nc_terrain_chompy") + }, + crush_damage = 2, + sounds = nodecore.sounds("nc_terrain_stony"), + light_source = i + 1 + }) +end + +local strata = {} +minetest.register_node(modname .. ":stone", { + description = "Stone", + tiles = {"nc_terrain_stone.png"}, + strata = strata, + groups = { + lux_emit = 1, + cracky = 2 + }, + light_source = 1, + drop_in_place = modname .. ":cobble1", + sounds = nodecore.sounds("nc_terrain_stony") + }) +strata[1] = modname .. ":stone" + +for i = 1, nodecore.hard_stone_strata do + local n = modname .. ":stone_" .. i + strata[i + 1] = n + minetest.register_node(n, { + description = "Stone", + tiles = {nodecore.hard_stone_tile(i)}, + groups = { + lux_emit = 1, + cracky = i + 2, + hard_stone = i + }, + light_source = 1, + drop_in_place = modname .. ((i > 1) + and (":stone_" .. (i - 1)) or ":stone"), + sounds = nodecore.sounds("nc_terrain_stony") + }) +end + +local oreid = 0 +local function regore(def) + oreid = oreid + 1 + return minetest.register_ore(nodecore.underride(def, { + name = modname .. oreid, + ore_type = "scatter", + ore = modname .. ":stone", + wherein = "nc_terrain:stone", + clust_num_ores = 3, + clust_size = 2, + random_factor = 0, + noise_params = { + offset = 0, + scale = 4, + spread = {x = 40, y = 5, z = 40}, + seed = 5672, + octaves = 3, + persist = 0.5, + flags = "eased", + }, + noise_threshold = 1.2 + }, def)) +end +for y = 0, 7 do + local def = { + y_max = 32 - 48 * math_pow(2, y), + y_min = 32 - 48 * math_pow(2, y + 1), + clust_scarcity = math_floor(8 * 8 * 8 * 8 * math_pow(0.67, y)), + } + if y == 7 then def.y_min = nil end + regore(def) +end diff --git a/mods/nc_lux/react.lua b/mods/nc_lux/react.lua new file mode 100644 index 0000000..39d0011 --- /dev/null +++ b/mods/nc_lux/react.lua @@ -0,0 +1,102 @@ +-- LUALOCALS < --------------------------------------------------------- +local ItemStack, math, minetest, nodecore, pairs, vector + = ItemStack, math, minetest, nodecore, pairs, vector +local math_ceil + = math.ceil +-- LUALOCALS > --------------------------------------------------------- + +local function stackgroup(stack, grp) + stack = ItemStack(stack) + if stack:is_empty() then return end + local name = stack:get_name() + local def = minetest.registered_items[name] + return def and def.groups and def.groups[grp] and name +end + +local function luxqty(pos) + local minp = vector.subtract(pos, {x = 1, y = 1, z = 1}) + local maxp = vector.add(pos, {x = 1, y = 1, z = 1}) + local qty = #minetest.find_nodes_in_area(minp, maxp, {"group:lux_emit"}) + for _, p in pairs(minetest.find_nodes_with_meta(minp, maxp)) do + if stackgroup(nodecore.stack_get(p), "lux_emit") then + qty = qty + 1 + end + end + for _, p in pairs(minetest.get_connected_players()) do + if vector.distance(pos, vector.add(p:get_pos(), {x = 0, y = 1, z = 0})) < 2 then + local inv = p:get_inventory() + for i = 1, inv:get_size("main") do + if stackgroup(inv:get_stack("main", i), "lux_emit") then + qty = qty + 1 + end + end + end + end + qty = math_ceil(qty / 2) + if qty > 8 then qty = 8 end + return qty +end + +nodecore.register_limited_abm({ + label = "Lux Reaction", + interval = 1, + chance = 2, + limited_max = 100, + nodenames = {"group:lux_cobble"}, + action = function(pos, node) + local qty = luxqty(pos) + local name = node.name:gsub("cobble%d", "cobble" .. qty) + if name == node.name then return end + minetest.set_node(pos, {name = name}) + end + }) + +nodecore.register_limited_abm({ + label = "Lux Stack Reaction", + interval = 1, + chance = 2, + limited_max = 100, + limited_alert = 1000, + nodenames = {"group:visinv"}, + action = function(pos) + local stack = nodecore.stack_get(pos) + if stack:is_empty() then return end + local name = stackgroup(stack, "lux_cobble") + if not name then return end + local qty = luxqty(pos) + name = name:gsub("cobble%d", "cobble" .. qty) + if name == stack:get_name() then return end + stack:set_name(name) + nodecore.stack_set(pos, stack) + end + }) + +local function playercheck(player) + local found + local stacks = {} + local inv = player:get_inventory() + for i = 1, inv:get_size("main") do + local stack = inv:get_stack("main", i) + if stackgroup(stack, "lux_cobble") then + stacks[i] = stack + found = true + end + end + if not found then return end + local qty = luxqty(vector.add(player:get_pos(), {x = 0, y = 1, z = 0})) + for k, v in pairs(stacks) do + local name = v:get_name() + local nn = name:gsub("cobble%d", "cobble" .. qty) + if name ~= nn then + v:set_name(nn) + inv:set_stack("main", k, v) + end + end +end +local function playercheckall() + minetest.after(1, playercheckall) + for _, p in pairs(minetest.get_connected_players()) do + playercheck(p) + end +end +playercheckall() diff --git a/mods/nc_lux/textures/nc_lux_base.png b/mods/nc_lux/textures/nc_lux_base.png new file mode 100644 index 0000000..abe9fb1 Binary files /dev/null and b/mods/nc_lux/textures/nc_lux_base.png differ diff --git a/mods/nc_lux/textures/nc_lux_gravel.png b/mods/nc_lux/textures/nc_lux_gravel.png new file mode 100644 index 0000000..ab2dc08 Binary files /dev/null and b/mods/nc_lux/textures/nc_lux_gravel.png differ diff --git a/mods/nc_lux/textures/nc_lux_mask.png b/mods/nc_lux/textures/nc_lux_mask.png new file mode 100644 index 0000000..4eec5cc Binary files /dev/null and b/mods/nc_lux/textures/nc_lux_mask.png differ diff --git a/mods/nc_lux/tools.lua b/mods/nc_lux/tools.lua new file mode 100644 index 0000000..3ac831d --- /dev/null +++ b/mods/nc_lux/tools.lua @@ -0,0 +1,95 @@ +-- LUALOCALS < --------------------------------------------------------- +local ItemStack, math, minetest, nodecore, pairs, vector + = ItemStack, math, minetest, nodecore, pairs, vector +local math_floor, math_pow + = math.floor, math.pow +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +local convert = {} +local charge = {} + +for _, shape in pairs({'mallet', 'spade', 'hatchet', 'pick', 'mattock'}) do + for _, temper in pairs({'tempered', 'annealed'}) do + local orig = minetest.registered_items["nc_lode:tool_" .. shape .. "_" .. temper] + + local def = nodecore.underride({ + description = "Infused " .. orig.description, + inventory_image = orig.inventory_image .. "^(" .. modname + .. "_base.png^[mask:nc_lode_tool_" .. shape .. ".png^[opacity:64])", + tool_wears_to = orig.name + }, orig) + def.after_use = nil + + def.groups = def.groups or {} + def.groups.lux_tool = 1 + + local tc = {} + for k, v in pairs(orig.tool_capabilities.opts) do + tc[k] = v + 1 + end + tc.uses = 0.5 + def.tool_capabilities = nodecore.toolcaps(tc) + + def.name = modname .. ":tool_" .. shape .. "_" .. temper + minetest.register_tool(def.name, def) + + convert[orig.name] = def.name + charge[def.name] = true + end +end + +local function isfluid(pos) + local def = minetest.registered_nodes[minetest.get_node(pos).name] + return def and def.groups and def.groups.lux_fluid +end +local indirs = {} +for _, v in pairs(nodecore.dirs()) do + if v.y == 0 then + indirs[#indirs + 1] = v + end +end +nodecore.register_soaking_abm({ + label = "Lux Infusion", + interval = 2, + chance = 1, + nodenames = {"group:visinv"}, + neighbors = {"group:lux_fluid"}, + soakrate = function(pos) + local stack = nodecore.stack_get(pos) + local name = stack:get_name() + if (not charge[name]) and (not convert[name]) then return false end + + local above = vector.add(pos, {x = 0, y = 1, z = 0}) + if not isfluid(above) then return false end + local qty = 1 + for _, v in pairs(indirs) do + if isfluid(vector.add(pos, v)) then qty = qty + 1 end + end + + local dist = nodecore.scan_flood(above, 14, function(p, d) + if p.dir and p.dir.y < 0 then return false end + local nn = minetest.get_node(p).name + if nn == modname .. ":flux_source" then return d end + if nn ~= modname .. ":flux_flowing" then return false end + end) + if not dist then return false end + + return qty * 20 / math_pow(2, dist / 2) + end, + soakcheck = function(data, pos) + local stack = nodecore.stack_get(pos) + local name = stack:get_name() + local dw = math_floor(data.total) + if charge[name] then + stack:add_wear(-dw) + nodecore.stack_set(pos, stack) + elseif convert[name] and stack:get_wear() < 3277 then + stack = ItemStack(convert[name]) + stack:set_wear(65535 - dw) + nodecore.stack_set(pos, stack) + end + return data.total - dw + end + }) diff --git a/mods/nc_nodefall/damage.lua b/mods/nc_nodefall/damage.lua new file mode 100644 index 0000000..ebdbea3 --- /dev/null +++ b/mods/nc_nodefall/damage.lua @@ -0,0 +1,43 @@ +-- LUALOCALS < --------------------------------------------------------- +local ItemStack, minetest, nodecore, pairs + = ItemStack, minetest, nodecore, pairs +-- LUALOCALS > --------------------------------------------------------- + +local function getcrushdamage(name, alreadyloose) + local def = minetest.registered_items[name] + if def and def.crush_damage then return def.crush_damage end + if alreadyloose then return 0 end + return getcrushdamage(name .. "_loose", true) +end + +local function register(fallname, mult, getname) + local fallnode = minetest.registered_entities[fallname] + + local oldtick = fallnode.on_step + fallnode.on_step = function(self, dtime, ...) + self.crush_damage = self.crush_damage or getcrushdamage(getname(self)) + if self.crush_damage <= 0 then + return oldtick(self, dtime, ...) + end + + local pos = self.object:get_pos() + pos.y = pos.y - 1 + local v = -self.object:get_velocity().y + if v <= 0 then + return oldtick(self, dtime, ...) + end + local q = v * v * dtime * self.crush_damage * mult + for _, o in pairs(minetest.get_objects_inside_radius(pos, 1)) do + if o:is_player() then + nodecore.addphealth(o, -q) + end + end + + return oldtick(self, dtime, ...) + end + + minetest.register_entity(":" .. fallname, fallnode) +end + +register("__builtin:falling_node", 1, function(s) return s.node.name end) +register("__builtin:item", 0.2, function(s) return ItemStack(s.itemstring):get_name() end) diff --git a/mods/nc_nodefall/disturb.lua b/mods/nc_nodefall/disturb.lua new file mode 100644 index 0000000..a7b1ac1 --- /dev/null +++ b/mods/nc_nodefall/disturb.lua @@ -0,0 +1,79 @@ +-- LUALOCALS < --------------------------------------------------------- +local ipairs, math, minetest, nodecore, vector + = ipairs, math, minetest, nodecore, vector +local math_floor, math_random + = math.floor, math.random +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +local falling = {groups = {falling_node = true}} +local radius = {x = 2, y = 2, z = 2} + +local function fallcheck(name, start) + if not nodecore.interact(name) then return end + + local target = vector.add(start, { + x = math_random() * 128 - 64, + y = math_random() * 128 - 64, + z = math_random() * 128 - 64 + }) + local pointed = minetest.raycast(start, target, false)() + if not pointed or not pointed.under then return end + local pos = pointed.under + + local found = minetest.find_nodes_in_area( + vector.subtract(pos, radius), + vector.add(pos, radius), + "group:falling_node" + ) + if #found < 1 then return end + pos = nodecore.pickrand(found) + + local miny = pos.y - 64 + pos.y = pos.y - 1 + while pos.y >= miny and nodecore.match(pos, falling) do pos.y = pos.y - 1 end + if pos.y < miny then return end + pos.y = pos.y + 1 + local prev = minetest.get_node(pos).name + nodecore.falling_repose_check(pos) + if minetest.get_node(pos).name ~= prev then + minetest.log(modname .. ": " .. name .. " disturbed " + .. prev .. " at " .. minetest.pos_to_string(pos)) + end +end + +local function queuechecks(qty, name, pos) + if qty < 1 then return end + minetest.after(0, function() + for _ = 1, qty do + fallcheck(name, pos) + end + end) +end + +local oldpos = {} +local qtys = {} +minetest.register_globalstep(function(dtime) + for _, v in ipairs(minetest.get_connected_players()) do + local name = v:get_player_name() + + local pos = v:get_pos() + local old = oldpos[name] or pos + oldpos[name] = pos + + if v:get_player_control().sneak then return end + + local q = (qtys[name] or 0) + + vector.distance(pos, old) * 0.25 + + dtime * 0.05 + queuechecks(math_floor(q), name, pos) + qtys[name] = q - math_floor(q) + end + end) + +minetest.register_on_dignode(function(pos, _, digger) + local name = "(unknown)" + if digger and digger.get_player_name then name = digger:get_player_name() end + queuechecks(4, name, pos) + end) diff --git a/mods/nc_nodefall/init.lua b/mods/nc_nodefall/init.lua new file mode 100644 index 0000000..d14a0a5 --- /dev/null +++ b/mods/nc_nodefall/init.lua @@ -0,0 +1,9 @@ +-- LUALOCALS < --------------------------------------------------------- +local include, nodecore + = include, nodecore +-- LUALOCALS > --------------------------------------------------------- + +nodecore.amcoremod() + +include("disturb") +include("damage") diff --git a/mods/nc_nodefall/mod.conf b/mods/nc_nodefall/mod.conf new file mode 100644 index 0000000..33e84f3 --- /dev/null +++ b/mods/nc_nodefall/mod.conf @@ -0,0 +1,2 @@ +name = nc_nodefall +depends = nc_api diff --git a/mods/nc_optics/api.lua b/mods/nc_optics/api.lua new file mode 100644 index 0000000..901ac8e --- /dev/null +++ b/mods/nc_optics/api.lua @@ -0,0 +1,128 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore, pairs, vector + = minetest, nodecore, pairs, vector +-- LUALOCALS > --------------------------------------------------------- + +local optic_queue = {} + +local function dirname(pos) + if pos.x > 0 then return "e" end + if pos.x < 0 then return "w" end + if pos.y > 0 then return "u" end + if pos.y < 0 then return "d" end + if pos.z > 0 then return "n" end + if pos.z < 0 then return "s" end + return "" +end + +local function scan(pos, dir) + local p = {x = pos.x, y = pos.y, z = pos.z} + for _ = 1, 16 do + p = vector.add(p, dir) + local node = minetest.get_node(p) + if node.name == "ignore" then return false, node end + local def = minetest.registered_items[node.name] or {} + if not def.sunlight_propagates then return p, node end + end +end + +local function scan_recv(pos, dir) + local hit, node = scan(pos, dir) + if not hit then return hit, node end + local data = minetest.get_meta(hit):get_string("nc_optics") + if data == "" then return end + dir = dirname(vector.multiply(dir, -1)) + if not minetest.deserialize(data)[dir] then return end + return hit, node +end + +local function optic_check(pos) + optic_queue[minetest.hash_node_position(pos)] = pos +end +nodecore.optic_check = optic_check + +local function optic_trigger(start, dir) + local pos, node = scan(start, dir) + if not node then return end + local def = minetest.registered_items[node.name] or {} + if def and def.optic_check then return optic_check(pos) end +end + +local function optic_process(trans, pos) + local node = minetest.get_node(pos) + if node.name == "ignore" then return end + local def = minetest.registered_items[node.name] or {} + + local ignored + if def and def.optic_check then + local func = function(dir) + local hit, hnode = scan_recv(pos, dir) + ignored = ignored or hit == false + return hit, hnode + end + local nn, res = def.optic_check(pos, node, func, def) + if (not ignored) and nn then + trans[minetest.hash_node_position(pos)] = { + pos = pos, + nn = nn, + data = res or {} + } + end + end + + if not ignored then + for _, dir in pairs(nodecore.dirs()) do + optic_trigger(pos, dir) + end + end +end + +local function optic_commit(v) + local node = minetest.get_node(v.pos) + if node.name ~= v.nn then + node.name = v.nn + minetest.set_node(v.pos, node) + end + + local data = {} + for _, vv in pairs(v.data or {}) do + data[dirname(vv)] = 1 + end + + local meta = minetest.get_meta(v.pos) + + local old = meta:get_string("nc_optics") + old = old and minetest.deserialize(old) or {} + for _, dir in pairs(nodecore.dirs()) do + local dn = dirname(dir) + if old[dn] ~= data[dn] then + optic_trigger(v.pos, dir) + end + end + meta:set_string("nc_optics", minetest.serialize(data)) +end + +minetest.register_globalstep(function() + -- snapshot batch, as processing may write to queue + local batch = optic_queue + optic_queue = {} + + local trans = {} + for _, pos in pairs(batch) do + optic_process(trans, pos) + end + + for _, v in pairs(trans) do + optic_commit(v) + end + end) + +nodecore.register_limited_abm({ + label = "Optic Check", + interval = 1, + chance = 1, + limited_max = 100, + limited_alert = 100, + nodenames = {"group:optic_check"}, + action = nodecore.optic_check + }) diff --git a/mods/nc_optics/cooking.lua b/mods/nc_optics/cooking.lua new file mode 100644 index 0000000..a6fb3ed --- /dev/null +++ b/mods/nc_optics/cooking.lua @@ -0,0 +1,145 @@ +-- LUALOCALS < --------------------------------------------------------- +local math, minetest, nodecore + = math, minetest, nodecore +local math_random + = math.random +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +nodecore.register_craft({ + label = "melt sand to glass", + action = "cook", + touchgroups = { + coolant = 0, + flame = 3 + }, + duration = 20, + cookfx = true, + nodes = { + { + match = {groups = {sand = true}}, + replace = modname .. ":glass_hot_source" + } + } + }) + +nodecore.register_cook_abm({ + nodenames = {"group:sand"}, + neighbors = {"group:flame"} + }) + +local src = modname .. ":glass_hot_source" +local flow = modname .. ":glass_hot_flowing" + +local function near(pos, crit) + return #minetest.find_nodes_in_area( + {x = pos.x - 1, y = pos.y - 1, z = pos.z - 1}, + {x = pos.x + 1, y = pos.y, z = pos.z + 1}, + crit) > 0 +end + +nodecore.register_craft({ + label = "cool clear glass", + action = "cook", + priority = -1, + duration = 120, + cookfx = {smoke = true, hiss = true}, + check = function(pos) + return not near(pos, {flow}) + end, + nodes = { + { + match = src, + replace = modname .. ":glass" + } + } + }) + +nodecore.register_craft({ + label = "cool float glass", + action = "cook", + duration = 120, + cookfx = {smoke = true, hiss = true}, + check = function(pos) + return not near(pos, {flow}) + end, + nodes = { + { + match = src, + replace = modname .. ":glass_float" + }, + { + y = -1, + match = {groups = {lava = true}} + } + } + }) + +nodecore.register_craft({ + label = "quench opaque glass", + action = "cook", + cookfx = true, + check = function(pos) + return (not near(pos, {flow})) + and near(pos, {"group:coolant"}) + end, + nodes = { + { + match = src, + replace = modname .. ":glass_opaque" + } + } + }) +nodecore.register_craft({ + label = "quench crude glass", + action = "cook", + cookfx = true, + check = function(pos) + return near(pos, {flow}) + and near(pos, {"group:coolant"}) + end, + nodes = { + { + match = src, + replace = modname .. ":glass_crude" + } + } + }) + +nodecore.register_cook_abm({nodenames = {src}}) + +nodecore.register_limited_abm({ + label = "Molten Glass Flowing", + interval = 1, + chance = 4, + nodenames = {src}, + action = function(pos, node) + local meta = minetest.get_meta(pos) + local gen = meta:get_int("glassgen") + if gen >= 32 and math_random(1, 2) == 1 then + minetest.set_node(pos, {name = modname .. ":glass_crude"}) + minetest.sound_play("nc_api_craft_hiss", {gain = 1, pos = pos}) + return nodecore.smokefx(pos, 0.2, 80) + end + local miny = pos.y + local found = {} + nodecore.scan_flood(pos, 5, function(p) + local nn = minetest.get_node(p).name + if nn == src then return end + if nn ~= flow then return false end + if p.y > miny then return end + if p.y == miny then + found[#found + 1] = p + return + end + miny = p.y + found = {p} + end) + if #found < 1 then return end + local np = nodecore.pickrand(found) + minetest.set_node(np, node) + minetest.get_meta(np):set_int("glassgen", gen + 1) + minetest.set_node(pos, {name = flow, param2 = 7}) + end + }) diff --git a/mods/nc_optics/crafting.lua b/mods/nc_optics/crafting.lua new file mode 100644 index 0000000..a10bf63 --- /dev/null +++ b/mods/nc_optics/crafting.lua @@ -0,0 +1,71 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore + = minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +nodecore.register_craft({ + label = "hammer prism from glass", + action = "pummel", + toolgroups = {thumpy = 5}, + nodes = { + { + match = modname .. ":glass_opaque", + replace = modname .. ":prism" + } + } + }) + +nodecore.register_craft({ + label = "cleave lenses from glass", + action = "pummel", + toolgroups = {choppy = 5}, + nodes = { + { + match = modname .. ":glass_opaque", + replace = "air" + } + }, + items = { + {name = modname .. ":lens", count = 2, scatter = 5} + } + }) + +nodecore.register_craft({ + label = "hammer glass to crude", + action = "pummel", + priority = -1, + toolgroups = {thumpy = 3}, + nodes = { + { + match = {groups = {silica_clear = true}}, + replace = modname .. ":glass_crude" + } + } + }) + +nodecore.register_craft({ + label = "hammer glass back to sand", + action = "pummel", + priority = -2, + toolgroups = {thumpy = 3}, + nodes = { + { + match = {groups = {silica = true}}, + replace = "nc_terrain:sand_loose" + } + } + }) + +nodecore.register_craft({ + label = "hammer lenses back to sand", + action = "pummel", + toolgroups = {thumpy = 3}, + nodes = { + { + match = {groups = {silica_lens = true}, count = 2}, + replace = "nc_terrain:sand_loose" + } + } + }) diff --git a/mods/nc_optics/glass.lua b/mods/nc_optics/glass.lua new file mode 100644 index 0000000..7aff432 --- /dev/null +++ b/mods/nc_optics/glass.lua @@ -0,0 +1,122 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore + = minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +minetest.register_node(modname .. ":glass", { + description = "Clear Glass", + drawtype = "glasslike_framed_optional", + tiles = { + modname .. "_glass_glare.png^" .. modname .. "_glass_edges.png", + modname .. "_glass_glare.png" + }, + groups = { + silica = 1, + silica_clear = 1, + cracky = 3 + }, + sunlight_propagates = true, + paramtype = "light", + sounds = nodecore.sounds("nc_optics_glassy") + }) + +minetest.register_node(modname .. ":glass_opaque", { + description = "Chromatic Glass", + tiles = { modname .. "_glass_frost.png" }, + groups = { + silica = 1, + cracky = 3 + }, + paramtype = "light", + sounds = nodecore.sounds("nc_optics_glassy") + }) + +minetest.register_node(modname .. ":glass_crude", { + description = "Crude Glass", + drawtype = "glasslike_framed_optional", + tiles = { + modname .. "_glass_crude.png^" .. modname .. "_glass_edges.png", + modname .. "_glass_crude.png" + }, + paramtype = "light", + groups = { + silica = 1, + falling_node = 1, + crumbly = 2 + }, + sounds = nodecore.sounds("nc_terrain_crunchy") + }) + +minetest.register_node(modname .. ":glass_float", { + description = "Float Glass", + drawtype = "glasslike_framed_optional", + tiles = { + modname .. "_glass_float.png^" .. modname .. "_glass_edges.png", + modname .. "_glass_float.png" + }, + propagates_sunlight = true, + paramtype = "light", + groups = { + silica = 1, + silica_clear = 1, + cracky = 3 + }, + sounds = nodecore.sounds("nc_optics_glassy") + }) + +local molttxr = "nc_terrain_lava.png^nc_optics_glass_glare.png" +local moltdef = { + description = "Molten Glass", + drawtype = "liquid", + tiles = { molttxr }, + special_tiles = { molttxr, molttxr }, + paramtype = "light", + liquid_viscosity = 7, + liquid_renewable = false, + liquid_range = 2, + light_source = 4, + walkable = false, + diggable = false, + buildable_to = false, + drowning = 1, + on_punch = nodecore.node_punch_hurt, + damage_per_second = 4, + drop = "", + groups = { igniter = 1, silica = 1 }, + post_effect_color = {a = 191, r = 255, g = 64, b = 0}, + liquid_alternative_flowing = modname .. ":glass_hot_flowing", + liquid_alternative_source = modname .. ":glass_hot_source", + sounds = nodecore.sounds("nc_terrain_bubbly") +} + +minetest.register_node(modname .. ":glass_hot_source", + nodecore.underride({ + liquidtype = "source" + }, moltdef)) +minetest.register_node(modname .. ":glass_hot_flowing", + nodecore.underride({ + liquidtype = "flowing", + drawtype = "flowingliquid", + paramtype2 = "flowingliquid" + }, moltdef)) + +nodecore.register_ambiance({ + label = "Glass Source Ambiance", + nodenames = {modname .. ":glass_hot_source"}, + neigbors = {"air"}, + interval = 1, + chance = 10, + sound_name = "nc_terrain_bubbly", + sound_gain = 0.2 + }) +nodecore.register_ambiance({ + label = "Glass Flow Ambiance", + nodenames = {modname .. ":glass_hot_flowing"}, + neigbors = {"air"}, + interval = 1, + chance = 10, + sound_name = "nc_terrain_bubbly", + sound_gain = 0.2 + }) diff --git a/mods/nc_optics/init.lua b/mods/nc_optics/init.lua new file mode 100644 index 0000000..b9479b5 --- /dev/null +++ b/mods/nc_optics/init.lua @@ -0,0 +1,13 @@ +-- LUALOCALS < --------------------------------------------------------- +local include, nodecore + = include, nodecore +-- LUALOCALS > --------------------------------------------------------- + +nodecore.amcoremod() + +include("api") +include("glass") +include("lens") +include("prism") +include("cooking") +include("crafting") diff --git a/mods/nc_optics/lens.lua b/mods/nc_optics/lens.lua new file mode 100644 index 0000000..9853b6b --- /dev/null +++ b/mods/nc_optics/lens.lua @@ -0,0 +1,111 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore, vector + = minetest, nodecore, vector +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +local function lens_check(pos, node, check) + local face = nodecore.facedirs[node.param2] + + if check(face.k) then + return modname .. ":lens_glow" + end + + local fore = vector.add(pos, face.f) + local ll = minetest.get_node_light(fore) + if not ll then return end + local lt = 15 + if node and node.name == modname .. ":lens_on" then lt = 14 end + local on = ll >= lt and face.f.y == 1 + if not on then + local nnode = minetest.get_node(fore) + local def = minetest.registered_items[nnode.name] or {} + on = def.light_source and def.light_source > 4 + end + if on then + return modname .. ":lens_on", {face.k} + end + return modname .. ":lens" +end + +local txr = modname .. "_glass_frost.png" + +local basedef = { + description = "Lens", + drawtype = "nodebox", + node_box = nodecore.fixedbox( + {-0.5, -0.5, -3/8, 0.25, -0.25, 1/8}, + {-0.25, 0.25, -3/8, 0.5, 0.5, 1/8}, + {-0.5, -0.25, -3/8, -0.25, 0.5, 1/8}, + {0.25, -0.5, -3/8, 0.5, 0.25, 1/8}, + {-0.25, -0.25, -1/8, 0.25, 0.25, 0.25} + ), + selection_box = nodecore.fixedbox( + {-0.5, -0.5, -3/8, 0.5, 0.5, 1/8} + ), + tiles = { + txr, + txr, + txr, + txr, + txr .. "^" .. modname .. "_lens_out.png", + txr .. "^" .. modname .. "_lens_in.png", + }, + groups = { + silica = 1, + optic_check = 1, + cracky = 3 + }, + drop = modname .. ":lens", + on_construct = nodecore.optic_check, + on_destruct = nodecore.optic_check, + on_spin = nodecore.optic_check, + optic_check = lens_check, + paramtype = "light", + paramtype2 = "facedir", + on_rightclick = nodecore.node_spin_filtered(function(a, b) + return vector.equals(a.f, b.f) + end), + sounds = nodecore.sounds("nc_optics_glassy") +} + +local function reg(suff, def) + minetest.register_node(modname .. ":lens" .. suff, + nodecore.underride(def, basedef)) +end +reg("", {}) +reg("_on", { + description = "Active Lens", + light_source = 2 + }) +reg("_glow", { + description = "Shining Lens", + light_source = 12, + tiles = { + txr, + txr, + txr, + txr, + txr .. "^" .. modname .. "_lens_in.png", + txr .. "^" .. modname .. "_lens_out.png", + }, + }) + +nodecore.register_limited_abm({ + label = "Lens Fire Starting", + interval = 2, + chance = 2, + nodenames = {modname .. ":lens_on"}, + action = function(pos, node) + local face = nodecore.facedirs[node.param2] + local out = vector.add(face.k, pos) + local tn = minetest.get_node(out) + local tdef = minetest.registered_items[tn.name] or {} + local flam = tdef and (not tdef.sunlight_propagates) + and tdef.groups and tdef.groups.flammable + if flam then + return nodecore.fire_check_ignite(out, tn) + end + end + }) diff --git a/mods/nc_optics/mod.conf b/mods/nc_optics/mod.conf new file mode 100644 index 0000000..0fd026f --- /dev/null +++ b/mods/nc_optics/mod.conf @@ -0,0 +1,2 @@ +name = nc_optics +depends = nc_api, nc_api_craft, nc_fire, nc_terrain diff --git a/mods/nc_optics/prism.lua b/mods/nc_optics/prism.lua new file mode 100644 index 0000000..096c86d --- /dev/null +++ b/mods/nc_optics/prism.lua @@ -0,0 +1,72 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore, vector + = minetest, nodecore, vector +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +local function prism_check(_, node, check) + local face = nodecore.facedirs[node.param2] + + local power = (check(face.f) or check(face.r)) + and (not check(face.t)) and (not check(face.b)) + + if power then + return modname .. ":prism_on", {face.k, face.l} + end + return modname .. ":prism" +end + +local txr = modname .. "_glass_frost.png" + +local basedef = { + description = "Prism", + drawtype = "nodebox", + node_box = nodecore.fixedbox( + {-3/8, -3/8, -0.5, -0.25, 3/8, -3/8}, + {3/8, -3/8, 0.25, 0.5, 3/8, 3/8}, + {-3/8, -0.5, -0.5, 0.5, -3/8, 3/8}, + {-3/8, 3/8, -0.5, 0.5, 0.5, 3/8}, + {-3/8, -3/8, -3/8, 3/8, 3/8, 3/8}, + {-0.25, -0.25, 3/8, 0.25, 0.25, 0.5}, + {-0.5, -0.25, -0.25, -3/8, 0.25, 0.25} + ), + selection_box = nodecore.fixedbox( + {-3/8, -0.5, -0.5, 0.5, 0.5, 3/8} + ), + tiles = { + txr, + txr, + txr .. "^" .. modname .. "_prism_in.png", + txr .. "^" .. modname .. "_lens_out.png", + txr .. "^" .. modname .. "_lens_out.png", + txr .. "^(" .. modname .. "_prism_in.png^[transformFX)", + }, + groups = { + silica = 1, + optic_check = 1, + cracky = 3 + }, + drop = modname .. ":prism", + on_construct = nodecore.optic_check, + on_destruct = nodecore.optic_check, + on_spin = nodecore.optic_check, + optic_check = prism_check, + paramtype = "light", + paramtype2 = "facedir", + on_rightclick = nodecore.node_spin_filtered(function(a, b) + return vector.equals(a.f, b.r) + and vector.equals(a.r, b.f) + end), + sounds = nodecore.sounds("nc_optics_glassy") +} + +local function reg(suff, def) + minetest.register_node(modname .. ":prism" .. suff, + nodecore.underride(def, basedef)) +end +reg("", {}) +reg("_on", { + description = "Active Prism", + light_source = 2 + }) diff --git a/mods/nc_optics/sounds/nc_optics_glassy.0.ogg b/mods/nc_optics/sounds/nc_optics_glassy.0.ogg new file mode 100644 index 0000000..b627644 Binary files /dev/null and b/mods/nc_optics/sounds/nc_optics_glassy.0.ogg differ diff --git a/mods/nc_optics/sounds/nc_optics_glassy.1.ogg b/mods/nc_optics/sounds/nc_optics_glassy.1.ogg new file mode 100644 index 0000000..cfbb525 Binary files /dev/null and b/mods/nc_optics/sounds/nc_optics_glassy.1.ogg differ diff --git a/mods/nc_optics/sounds/nc_optics_glassy.2.ogg b/mods/nc_optics/sounds/nc_optics_glassy.2.ogg new file mode 100644 index 0000000..592a8d3 Binary files /dev/null and b/mods/nc_optics/sounds/nc_optics_glassy.2.ogg differ diff --git a/mods/nc_optics/sounds/nc_optics_glassy.3.ogg b/mods/nc_optics/sounds/nc_optics_glassy.3.ogg new file mode 100644 index 0000000..8b62358 Binary files /dev/null and b/mods/nc_optics/sounds/nc_optics_glassy.3.ogg differ diff --git a/mods/nc_optics/sounds/nc_optics_glassy.4.ogg b/mods/nc_optics/sounds/nc_optics_glassy.4.ogg new file mode 100644 index 0000000..fe719b4 Binary files /dev/null and b/mods/nc_optics/sounds/nc_optics_glassy.4.ogg differ diff --git a/mods/nc_optics/textures/nc_optics_glass_crude.png b/mods/nc_optics/textures/nc_optics_glass_crude.png new file mode 100644 index 0000000..151be75 Binary files /dev/null and b/mods/nc_optics/textures/nc_optics_glass_crude.png differ diff --git a/mods/nc_optics/textures/nc_optics_glass_edges.png b/mods/nc_optics/textures/nc_optics_glass_edges.png new file mode 100644 index 0000000..d4d07cb Binary files /dev/null and b/mods/nc_optics/textures/nc_optics_glass_edges.png differ diff --git a/mods/nc_optics/textures/nc_optics_glass_float.png b/mods/nc_optics/textures/nc_optics_glass_float.png new file mode 100644 index 0000000..769b47a Binary files /dev/null and b/mods/nc_optics/textures/nc_optics_glass_float.png differ diff --git a/mods/nc_optics/textures/nc_optics_glass_frost.png b/mods/nc_optics/textures/nc_optics_glass_frost.png new file mode 100644 index 0000000..9041ccd Binary files /dev/null and b/mods/nc_optics/textures/nc_optics_glass_frost.png differ diff --git a/mods/nc_optics/textures/nc_optics_glass_glare.png b/mods/nc_optics/textures/nc_optics_glass_glare.png new file mode 100644 index 0000000..e988dcc Binary files /dev/null and b/mods/nc_optics/textures/nc_optics_glass_glare.png differ diff --git a/mods/nc_optics/textures/nc_optics_lens_in.png b/mods/nc_optics/textures/nc_optics_lens_in.png new file mode 100644 index 0000000..a7e412e Binary files /dev/null and b/mods/nc_optics/textures/nc_optics_lens_in.png differ diff --git a/mods/nc_optics/textures/nc_optics_lens_out.png b/mods/nc_optics/textures/nc_optics_lens_out.png new file mode 100644 index 0000000..79d1c9d Binary files /dev/null and b/mods/nc_optics/textures/nc_optics_lens_out.png differ diff --git a/mods/nc_optics/textures/nc_optics_prism_in.png b/mods/nc_optics/textures/nc_optics_prism_in.png new file mode 100644 index 0000000..6e34144 Binary files /dev/null and b/mods/nc_optics/textures/nc_optics_prism_in.png differ diff --git a/mods/nc_player_gui/init.lua b/mods/nc_player_gui/init.lua new file mode 100644 index 0000000..7e52bb9 --- /dev/null +++ b/mods/nc_player_gui/init.lua @@ -0,0 +1,144 @@ +-- LUALOCALS < --------------------------------------------------------- +local ipairs, minetest, nodecore, pairs, table, type + = ipairs, minetest, nodecore, pairs, table, type +local table_concat, table_insert + = table.concat, table.insert +-- LUALOCALS > --------------------------------------------------------- + +nodecore.amcoremod() + +nodecore.register_inventory_tab, +nodecore.registered_inventory_tabs += nodecore.mkreg() + +local nct = nodecore.translate + +do + local version = nodecore.version + version = version and (nct("Version") .. " " .. version) + or nct("DEVELOPMENT VERSION") + + nodecore.register_inventory_tab({ + title = "About", + content = { + nct(nodecore.product) .. " - " .. version, + "", + "(C)2018-2019 by Aaron Suen ", + "MIT License (http://www.opensource.org/licenses/MIT)", + "See included LICENSE file for full details and credits", + "", + "https://content.minetest.net/packages/Warr1024/nodecore/", + "GitLab: https://gitlab.com/sztest/nodecore", + "Discord: https://discord.gg/SHq2tkb" + } + }) +end + +nodecore.register_inventory_tab({ + title = "Inventory", + content = { + "Player's Guide: Inventory Management", + "", + "- There is NO inventory screen.", + "- Drop items onto ground to create stack nodes. They do not decay.", + "- Sneak+drop to count out single items from stack.", + "- Items picked up try to fit into the current selected slot first.", + "- Crafting is done by building recipes in-world.", + "- Order and specific face of placement may matter for crafting." + } + }) + +nodecore.register_inventory_tab({ + title = "Pummel", + content = { + "Player's Guide: Pummeling Recipes", + "", + "- Some recipes require \"pummeling\" a node.", + "- To pummel, punch a node repeatedly, WITHOUT digging.", + "- You do not have to punch very fast (about 1 per second).", + "- Recipes are time-based, punching faster does not speed up.", + "- Wielded item, target face, and surrounding nodes may matter.", + "- Stacks may be pummeled, exact item count may matter.", + "- If a recipe exists, you will see a special particle effect." + } + }) + +nodecore.register_inventory_tab({ + title = "Tips", + content = { + "Player's Guide: Tips and Guidance", + "", + "- Stuck in a pit? Pummel surfaces barehanded to find places to climb.", + "- Can't dig trees or grass? Search for sticks in the canopy.", + "- Ores may be hidden, but revealed by subtle clues in terrain.", + "- \"Furnaces\" are not a thing; discover smelting with open flames.", + "- Trouble lighting a fire? Try using longer sticks, more tinder.", + "- The game is challenging by design, sometimes frustrating. DON'T GIVE UP!" + } + }) + +for _, v in pairs(nodecore.registered_inventory_tabs) do + nct(v.title) + for i = 1, #v.content do nct(v.content[i]) end +end + +local pad = " " +for _ = 1, 8 do pad = pad .. pad end + +local fse = minetest.formspec_escape +function nodecore.inventory_formspec(player, curtab) + local t = { + "bgcolor[#000000C0;true]", + "listcolors[#00000000;#00000000;#00000000;#000000FF;#FFFFFFFF]" + } + + local x = 0 + local y = 0 + local f + for i, v in ipairs(nodecore.registered_inventory_tabs) do + t[#t + 1] = "button[" .. x .. "," .. y + .. ";2.2,0.5;tab" .. i .. ";" .. fse(nct(v.title)) .. "]" + if curtab == i or (not curtab and i == 1) then + f = v.content + end + x = x + 2 + if x >= 12 then + x = 0 + y = y + 0.5 + end + end + if x > 0 then y = y + 0.5 end + + table_insert(t, 1, "size[12," .. 5.5 + y .. "]") + + if f then + if type(f) == "function" then f = f(player) end + for i = 1, #f do + t[#t + 1] = "label[0," .. (y + 0.25) .. ";" + .. fse(nct(f[i])) .. pad .. ".]" + y = y + 0.4 + end + end + + return table_concat(t) +end + +minetest.register_on_joinplayer(function(player) + player:set_inventory_formspec(nodecore.inventory_formspec(player)) + end) + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname == "" then + local tab + for i = 1, #nodecore.registered_inventory_tabs do + if fields["tab" .. i] then + tab = i + break + end + end + if tab then + minetest.show_formspec(player:get_player_name(), formname, + nodecore.inventory_formspec(player, tab)) + end + end + end) diff --git a/mods/nc_player_gui/mod.conf b/mods/nc_player_gui/mod.conf new file mode 100644 index 0000000..1e194d0 --- /dev/null +++ b/mods/nc_player_gui/mod.conf @@ -0,0 +1,2 @@ +name = nc_player_gui +depends = nc_api diff --git a/mods/nc_player_hand/hand.lua b/mods/nc_player_hand/hand.lua new file mode 100644 index 0000000..48a8ed6 --- /dev/null +++ b/mods/nc_player_hand/hand.lua @@ -0,0 +1,16 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore + = minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +minetest.register_item(":", { + ["type"] = "none", + wield_image = "nc_player_hand.png", + wield_scale = {x = 4, y = 8, z = 3}, + tool_capabilities = nodecore.toolcaps({ + uses = 0, + crumbly = 1, + snappy = 1, + thumpy = 1 + }) + }) diff --git a/mods/nc_player_hand/init.lua b/mods/nc_player_hand/init.lua new file mode 100644 index 0000000..bb503fc --- /dev/null +++ b/mods/nc_player_hand/init.lua @@ -0,0 +1,9 @@ +-- LUALOCALS < --------------------------------------------------------- +local include, nodecore + = include, nodecore +-- LUALOCALS > --------------------------------------------------------- + +nodecore.amcoremod() + +include("hand") +include("wieldsounds") diff --git a/mods/nc_player_hand/mod.conf b/mods/nc_player_hand/mod.conf new file mode 100644 index 0000000..41468f6 --- /dev/null +++ b/mods/nc_player_hand/mod.conf @@ -0,0 +1,2 @@ +name = nc_player_hand +depends = nc_api diff --git a/mods/nc_player_hand/textures/crack_anylength.png b/mods/nc_player_hand/textures/crack_anylength.png new file mode 100644 index 0000000..9e0b878 Binary files /dev/null and b/mods/nc_player_hand/textures/crack_anylength.png differ diff --git a/mods/nc_player_hand/textures/nc_player_hand.png b/mods/nc_player_hand/textures/nc_player_hand.png new file mode 100644 index 0000000..554fcbc Binary files /dev/null and b/mods/nc_player_hand/textures/nc_player_hand.png differ diff --git a/mods/nc_player_hand/textures/src/crack_anylength.svg b/mods/nc_player_hand/textures/src/crack_anylength.svg new file mode 100644 index 0000000..7f25335 --- /dev/null +++ b/mods/nc_player_hand/textures/src/crack_anylength.svg @@ -0,0 +1,789 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mods/nc_player_hand/wieldsounds.lua b/mods/nc_player_hand/wieldsounds.lua new file mode 100644 index 0000000..039365c --- /dev/null +++ b/mods/nc_player_hand/wieldsounds.lua @@ -0,0 +1,49 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, pairs + = minetest, pairs +-- LUALOCALS > --------------------------------------------------------- + +local function wieldsound(player, idx, gain) + local n = player:get_inventory():get_stack("main", idx):get_name() + local def = minetest.registered_items[n] + if def and def.sounds then + local t = {} + for k, v in pairs(def.sounds.dig) do t[k] = v end + t.object = player + t.gain = gain or 1 + if player:get_player_control().sneak then t.gain = t.gain / 4 end + return function() minetest.sound_play(t.name, t) end + end + return function() end +end + +local wields = {} +local pending = {} +minetest.register_globalstep(function(dtime) + for _, player in pairs(minetest.get_connected_players()) do + local pname = player:get_player_name() + + local pend = pending[pname] + if pend then + pend.t = pend.t - dtime + if pend.t <= 0 then + pend.f() + pending[pname] = nil + pend = nil + end + end + + local idx = player:get_wield_index() + local old = wields[pname] + if idx ~= old then + wields[pname] = idx + if old and not pend then + wieldsound(player, old, 0.07)() + end + pending[pname] = { + t = 0.15, + f = wieldsound(player, idx, 0.15) + } + end + end + end) diff --git a/mods/nc_player_health/damage.lua b/mods/nc_player_health/damage.lua new file mode 100644 index 0000000..ca19f7c --- /dev/null +++ b/mods/nc_player_health/damage.lua @@ -0,0 +1,28 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore + = minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +minetest.register_on_player_hpchange(function(player, hp) + local orig = player:get_hp() + if player:get_armor_groups().immortal then + return orig + end + if hp < 0 then + minetest.after(0, function() + local now = player:get_hp() + if now >= orig then return end + nodecore.sound_play_except("player_damage", { + pos = player:get_pos(), + gain = 0.5 + }, player) + end) + end + if hp + orig <= 0 then + hp = 1 - orig + player:get_meta():set_float("dhp", -1) + end + return hp + end, + true +) diff --git a/mods/nc_player_health/ejectinv.lua b/mods/nc_player_health/ejectinv.lua new file mode 100644 index 0000000..0e328d6 --- /dev/null +++ b/mods/nc_player_health/ejectinv.lua @@ -0,0 +1,79 @@ +-- LUALOCALS < --------------------------------------------------------- +local math, minetest, nodecore, pairs, table + = math, minetest, nodecore, pairs, table +local math_floor, math_random, table_remove + = math.floor, math.random, table.remove +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +local hand = minetest.registered_items[""] +local injured = modname .. ":injured" +minetest.register_craftitem(injured, { + description = "Injury", + stack_max = 1, + inventory_image = modname .. "_injured.png", + wield_image = hand.wield_image, + wield_scale = hand.wield_scale, + on_drop = function(stack) return stack end, + on_place = function(stack) return stack end, + virtual_item = true + }) + +local function pickend(q) + for i = q, 1, -1 do + if math_random() < 0.5 then return i end + end + return pickend(q) +end + +local function checkinv(player) + local inv = player:get_inventory() + local size = inv:get_size("main") + + local inj = {} + local reg = {} + for i = 1, size do + if inv:get_stack("main", i):get_name() == injured then + inj[#inj + 1] = i + else + reg[#reg + 1] = i + end + end + + local slots = math_floor(nodecore.getphealth(player) / 20 * (size - 2) + 0.5) + 2 + + if #reg > slots then + local pos = player:get_pos() + while #reg > slots do + local n = pickend(#reg) + local i = reg[n] + table_remove(reg, n) + local stack = inv:get_stack("main", i) + if not (stack:get_definition() or {}).virtual_item then + nodecore.item_eject(pos, stack, 5) + end + inv:set_stack("main", i, injured) + end + return + end + + local fill = size - slots + if #inj > fill then + for i = 1, #inj / 2 do + inj[i], inj[#inj + 1 - i] = inj[#inj + 1 - i], inj[i] + end + while #inj > fill do + local n = pickend(#inj) + local i = inj[n] + table_remove(inj, n) + inv:set_stack("main", i, "") + end + end +end + +minetest.register_globalstep(function() + for _, p in pairs(minetest.get_connected_players()) do + if p:get_hp() > 0 then checkinv(p) end + end + end) diff --git a/mods/nc_player_health/healing.lua b/mods/nc_player_health/healing.lua new file mode 100644 index 0000000..6eee602 --- /dev/null +++ b/mods/nc_player_health/healing.lua @@ -0,0 +1,88 @@ +-- LUALOCALS < --------------------------------------------------------- +local math, minetest, nodecore, pairs, vector + = math, minetest, nodecore, pairs, vector +local math_exp, math_random, math_sqrt + = math.exp, math.random, math.sqrt +-- LUALOCALS > --------------------------------------------------------- + +local ppos = {} +local cache = {} + +local function envcheck(player) + local pname = player:get_player_name() + + if player:get_breath() < 11 then return end + + local pos = player:get_pos() + local eyeheight = player:get_properties().eye_height or 1.625 + pos.y = pos.y + eyeheight + + local old = ppos[pname] or pos + ppos[pname] = pos + local moving = not vector.equals(pos, old) + + local stats = {} + + stats.light = minetest.get_node_light(pos) or 0 + + local target = vector.add(pos, { + x = math_random() * 128 - 64, + y = math_random() * 128 - 64, + z = math_random() * 128 - 64 + }) + local hit = minetest.raycast(pos, target, false)() + hit = hit and hit.under or target + + stats.space = vector.distance(pos, hit) + + local node = minetest.get_node(hit) + local def = minetest.registered_items[node.name] or {} + local groups = def.groups or {} + + stats.green = groups.green or 0 + stats.water = groups.water or 0 + stats.green / 5 + + local agg = cache[pname] + if not agg then + agg = {} + local raw = player:get_meta():get_string("healthenv") + if raw and raw ~= "" then + agg = minetest.deserialize(raw) + end + cache[pname] = agg + end + for k, v in pairs(stats) do + agg[k] = ((agg[k] or 0) * 99 + v) / 100 + end + agg.dirty = (agg.dirty or 0) + 1 + if agg.dirty >= 5 then + agg.dirty = nil + player:get_meta():set_string("healthenv", + minetest.serialize(agg)) + for k, v in pairs(agg) do + agg[k] = 1 - math_exp(-v) + end + local heal = 0.1 + + (agg.green * agg.green) * 4 + + (agg.water * agg.water) * 2 + + (agg.space * agg.space) + + (agg.light * agg.light) + heal = math_sqrt(heal) + if moving then heal = heal / 2 end + nodecore.addphealth(player, heal) + end + +end + +minetest.register_on_dieplayer(function(player) + player:get_meta():set_string("healthenv", "") + cache[player:get_player_name()] = nil + end) + +local function timer() + minetest.after(0.5, timer) + for _, p in pairs(minetest.get_connected_players()) do + if p:get_hp() > 0 then envcheck(p) end + end +end +timer() diff --git a/mods/nc_player_health/init.lua b/mods/nc_player_health/init.lua new file mode 100644 index 0000000..41527ee --- /dev/null +++ b/mods/nc_player_health/init.lua @@ -0,0 +1,10 @@ +-- LUALOCALS < --------------------------------------------------------- +local include, nodecore + = include, nodecore +-- LUALOCALS > --------------------------------------------------------- + +nodecore.amcoremod() + +include("healing") +include("ejectinv") +include("damage") diff --git a/mods/nc_player_health/mod.conf b/mods/nc_player_health/mod.conf new file mode 100644 index 0000000..451b2d0 --- /dev/null +++ b/mods/nc_player_health/mod.conf @@ -0,0 +1,2 @@ +name = nc_player_health +depends = nc_api, nc_player_hand diff --git a/mods/nc_player_health/sounds/player_damage.ogg b/mods/nc_player_health/sounds/player_damage.ogg new file mode 100644 index 0000000..5d172a1 Binary files /dev/null and b/mods/nc_player_health/sounds/player_damage.ogg differ diff --git a/mods/nc_player_health/textures/nc_player_health_injured.png b/mods/nc_player_health/textures/nc_player_health_injured.png new file mode 100644 index 0000000..2cdcab7 Binary files /dev/null and b/mods/nc_player_health/textures/nc_player_health_injured.png differ diff --git a/mods/nc_player_hud/init.lua b/mods/nc_player_hud/init.lua new file mode 100644 index 0000000..da335a4 --- /dev/null +++ b/mods/nc_player_hud/init.lua @@ -0,0 +1,10 @@ +-- LUALOCALS < --------------------------------------------------------- +local include, nodecore + = include, nodecore +-- LUALOCALS > --------------------------------------------------------- + +nodecore.amcoremod() + +include("setup") +include("touchtip") +include("pretrans") diff --git a/mods/nc_player_hud/mod.conf b/mods/nc_player_hud/mod.conf new file mode 100644 index 0000000..021bfe2 --- /dev/null +++ b/mods/nc_player_hud/mod.conf @@ -0,0 +1,2 @@ +name = nc_player_hud +depends = nc_api diff --git a/mods/nc_player_hud/pretrans.lua b/mods/nc_player_hud/pretrans.lua new file mode 100644 index 0000000..fd5eb6c --- /dev/null +++ b/mods/nc_player_hud/pretrans.lua @@ -0,0 +1,17 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore, pairs + = minetest, nodecore, pairs +-- LUALOCALS > --------------------------------------------------------- + +minetest.after(0, function() + for _, v in pairs(minetest.registered_items) do + if v.description then + nodecore.translate_inform(v.description) + end + if v.meta_descriptions then + for _, d in pairs(v.meta_descriptions) do + nodecore.translate_inform(d) + end + end + end + end) diff --git a/mods/nc_player_hud/setup.lua b/mods/nc_player_hud/setup.lua new file mode 100644 index 0000000..6c4ba8c --- /dev/null +++ b/mods/nc_player_hud/setup.lua @@ -0,0 +1,54 @@ +-- LUALOCALS < --------------------------------------------------------- +local math, minetest, pairs + = math, minetest, pairs +local math_floor + = math.floor +-- LUALOCALS > --------------------------------------------------------- + +local breath = {} + +local function breathimg(br) + local o = 255 * (1 - br / 11) + if o == 0 then return "" end + return "nc_player_hud_breath.png^[opacity:" + .. math_floor(o) +end + +minetest.register_on_joinplayer(function(player) + player:hud_set_flags({ + healthbar = false, + breathbar = false, + minimap = false, + minimap_radar = false + }) + player:hud_set_hotbar_itemcount(8) + player:hud_set_hotbar_image("nc_player_hud_bar.png") + player:hud_set_hotbar_selected_image("nc_player_hud_sel.png") + + local img = breathimg(player:get_breath()) + breath[player:get_player_name()] = { + id = player:hud_add({ + hud_elem_type = "image", + position = {x = 0.5, y = 0.5}, + text = img, + direction = 0, + scale = {x = -100, y = -100}, + offset = {x = 0, y = 0} + }), + val = img + } + end) + +local function breathhud(player) + local hud = breath[player:get_player_name()] + if not hud then return end + local i = breathimg(player:get_breath()) + if hud.val == i then return end + return player:hud_change(hud.id, "text", i) +end + +minetest.register_globalstep(function() + for _, player in pairs(minetest.get_connected_players()) do + breathhud(player) + end + end) diff --git a/mods/nc_player_hud/textures/nc_player_hud_bar.png b/mods/nc_player_hud/textures/nc_player_hud_bar.png new file mode 100644 index 0000000..7bb836c Binary files /dev/null and b/mods/nc_player_hud/textures/nc_player_hud_bar.png differ diff --git a/mods/nc_player_hud/textures/nc_player_hud_breath.png b/mods/nc_player_hud/textures/nc_player_hud_breath.png new file mode 100644 index 0000000..e6a0351 Binary files /dev/null and b/mods/nc_player_hud/textures/nc_player_hud_breath.png differ diff --git a/mods/nc_player_hud/textures/nc_player_hud_sel.png b/mods/nc_player_hud/textures/nc_player_hud_sel.png new file mode 100644 index 0000000..bc62589 Binary files /dev/null and b/mods/nc_player_hud/textures/nc_player_hud_sel.png differ diff --git a/mods/nc_player_hud/textures/src/font.svg b/mods/nc_player_hud/textures/src/font.svg new file mode 100644 index 0000000..6263c96 --- /dev/null +++ b/mods/nc_player_hud/textures/src/font.svg @@ -0,0 +1,540 @@ + + + + + + + + + + image/svg+xml + + + + + + + `1234567890-=qwertyuiop[]\asdfghjkl;'zxcvbnm,./~!@#$%^&*()_+QWERTYUIOP{}|ASDFGHJKL:"ZXCVBNM<>? + + diff --git a/mods/nc_player_hud/textures/src/huds.svg b/mods/nc_player_hud/textures/src/huds.svg new file mode 100644 index 0000000..097921b --- /dev/null +++ b/mods/nc_player_hud/textures/src/huds.svg @@ -0,0 +1,1908 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mods/nc_player_hud/touchtip.lua b/mods/nc_player_hud/touchtip.lua new file mode 100644 index 0000000..6a854f0 --- /dev/null +++ b/mods/nc_player_hud/touchtip.lua @@ -0,0 +1,92 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore, pairs + = minetest, nodecore, pairs +-- LUALOCALS > --------------------------------------------------------- + +local tips = {} + +local function show(player, text, ttl) + text = nodecore.translate(text) + ttl = ttl or 2 + local pname = player:get_player_name() + local tip = tips[pname] + if tip then + if text ~= tip.text then + player:hud_change(tip.id, "text", text) + tip.text = text + end + tip.ttl = ttl + return + end + tips[pname] = { + id = player:hud_add({ + hud_elem_type = "text", + position = {x = 0.5, y = 0.75}, + text = text, + number = 0xFFFFFF, + alignment = {x = 0, y = 0}, + offset = {x = 0, y = 0}, + }), + text = text, + ttl = ttl + } +end +nodecore.show_touchtip = show + +local wields = {} + +local function stack_desc(s) + if s:is_empty() then return "" end + + local t = s:get_meta():get_string("description") + if t and t ~= "" then return t end + + local n = s:get_name() + local d = minetest.registered_items[n] or {} + return d.description or n +end + +local function wield_name(player) + return stack_desc(player:get_wielded_item()) +end + +minetest.register_globalstep(function(dtime) + for _, player in pairs(minetest.get_connected_players()) do + local pname = player:get_player_name() + + local wn = wield_name(player) + if wn ~= wields[pname] then + wields[pname] = wn + show(player, wn) + end + + local tip = tips[pname] + if tip then + tip.ttl = tip.ttl - dtime + if tip.ttl <= 0 then + player:hud_remove(tip.id) + tips[pname] = nil + end + end + end + end) + +minetest.register_on_punchnode(function(pos, node, puncher) + node = node or minetest.get_node(pos) + local name = node.name + local def = minetest.registered_items[name] or {} + if def.air_equivalent or def.pointable == false then return end + if def.groups and def.groups.is_stack_only then + name = stack_desc(nodecore.stack_get(pos)) + elseif def.description then + name = def.description + end + + show(puncher, name) + end) + +minetest.register_on_joinplayer(function(player) + local pname = player:get_player_name() + tips[pname] = nil + wields[pname] = nil + end) diff --git a/mods/nc_player_model/init.lua b/mods/nc_player_model/init.lua new file mode 100644 index 0000000..e1dfaa2 --- /dev/null +++ b/mods/nc_player_model/init.lua @@ -0,0 +1,155 @@ +-- LUALOCALS < --------------------------------------------------------- +local math, minetest, nodecore, os, pairs, table + = math, minetest, nodecore, os, pairs, table +local math_floor, os_date, table_concat + = math.floor, os.date, table.concat +-- LUALOCALS > --------------------------------------------------------- + +nodecore.amcoremod() + +local modname = minetest.get_current_modname() + +local anim = { + stand = {x = 0, y = 0}, + sit = {x = 1, y = 1}, + walk = {x = 2, y = 42}, + mine = {x = 43, y = 57, speed = 0.85}, + lay = {x = 58, y = 58}, + walk_mine = {x = 59, y = 103}, + swim_up = {x = 105, y = 162, speed = 0.4}, + swim_down = {x = 163, y = 223, speed = 0.4}, + swim_mine = {x = 224, y = 281, speed = 0.5} +} + +local function setcached(func) + local cache = {} + return function(player, value) + local pname = player:get_player_name() + if cache[pname] == value then return end + cache[pname] = value + return func(player, value) + end +end +local setanim = setcached(function(player, x) + local a = anim[x] or anim.stand + player:set_animation({x = a.x, y = a.y}, + 72 * (a.speed or 1)) + end) +local setskin = setcached(function(player, x) + player:set_properties({textures = {x}}) + end) + +local skintimes = {} +local dayskins = { + day_2_14 = true, + day_3_17 = true, + day_4_1 = true, + day_10_31 = true +} + +local liquids = {} +minetest.after(0, function() + for k, v in pairs(minetest.registered_items) do + if v.liquidtype and v.liquidtype ~= "none" then + liquids[k] = true + end + end + end) +local function swimming(player) + local pos = player:get_pos() + local r = 0.6 + for dz = -r, r, r do + for dx = -r, r, r do + local p = { + x = pos.x + dx, + y = pos.y, + z = pos.z + dz + } + local node = minetest.get_node(p) + if (node.name == "air" or liquids[node.name]) then + p.y = p.y - 0.35 + node = minetest.get_node(p) + end + if not liquids[node.name] then return end + end + end + return true +end + +local function updatevisuals(player) + local hp = player:get_hp() + if hp <= 0 then + setanim(player, "lay") + else + local ctl = player:get_player_control() + local walk = ctl.up or ctl.down or ctl.right or ctl.left + local mine = ctl.LMB or ctl.RMB + + if not swimming(player) then + if walk and mine then + setanim(player, "walk_mine") + elseif walk then + setanim(player, "walk") + elseif mine then + setanim(player, "mine") + else + setanim(player, "stand") + end + else + local v = player:get_player_velocity() + + if mine then + setanim(player, "swim_mine") + elseif v and v.y >= -0.5 then + setanim(player, "swim_up") + else + setanim(player, "swim_down") + end + end + end + + local pname = player:get_player_name() + local now = minetest.get_us_time() / 1000000 + local last = skintimes[pname] or 0 + if now < last + 2 then return end + skintimes[pname] = now + + local layers = {"base.png"} + local date = os_date("!*t") + local bare = "day_" .. date.month .. "_" .. date.day + if dayskins[bare] then layers[#layers + 1] = bare .. ".png" end + local dmg = (1 - hp / 20) * 4 + local dmgi = math_floor(dmg) + local dmgf = dmg - dmgi + for i = 1, dmgi do + layers[#layers + 1] = "damage" .. i .. ".png" + end + if dmgf > 0 then + layers[#layers + 1] = "damage" .. (dmgi + 1) + .. ".png^[opacity:" .. math_floor(256 * dmgf) + end + local privs = minetest.get_player_privs(player:get_player_name()) + if not privs.interact then layers[#layers + 1] = "no_interact.png" end + if not privs.shout then layers[#layers + 1] = "no_shout.png" end + for k, v in pairs(layers) do + layers[k] = "(" .. modname .. "_" .. v .. ")" + end + setskin(player, table_concat(layers, "^") .. "^[makealpha:254,0,253") +end + +minetest.register_on_joinplayer(function(player) + player:set_properties({ + visual = "mesh", + visual_size = {x = 0.9, y = 0.9, z = 0.9}, + mesh = modname .. ".b3d" + }) + setskin(player, "dummy") + setanim(player, "dummy") + updatevisuals(player) + end) + +minetest.register_globalstep(function() + for _, player in pairs(minetest.get_connected_players()) do + updatevisuals(player) + end + end) diff --git a/mods/nc_player_model/mod.conf b/mods/nc_player_model/mod.conf new file mode 100644 index 0000000..260d7e1 --- /dev/null +++ b/mods/nc_player_model/mod.conf @@ -0,0 +1,2 @@ +name = nc_player_model +depends = nc_api diff --git a/mods/nc_player_model/models/nc_player_model.b3d b/mods/nc_player_model/models/nc_player_model.b3d new file mode 100644 index 0000000..2ecd248 Binary files /dev/null and b/mods/nc_player_model/models/nc_player_model.b3d differ diff --git a/mods/nc_player_model/models/src/nc_player_model.blend b/mods/nc_player_model/models/src/nc_player_model.blend new file mode 100644 index 0000000..9edef88 Binary files /dev/null and b/mods/nc_player_model/models/src/nc_player_model.blend differ diff --git a/mods/nc_player_model/textures/nc_player_model_base.png b/mods/nc_player_model/textures/nc_player_model_base.png new file mode 100644 index 0000000..11009a5 Binary files /dev/null and b/mods/nc_player_model/textures/nc_player_model_base.png differ diff --git a/mods/nc_player_model/textures/nc_player_model_damage1.png b/mods/nc_player_model/textures/nc_player_model_damage1.png new file mode 100644 index 0000000..a8ec05d Binary files /dev/null and b/mods/nc_player_model/textures/nc_player_model_damage1.png differ diff --git a/mods/nc_player_model/textures/nc_player_model_damage2.png b/mods/nc_player_model/textures/nc_player_model_damage2.png new file mode 100644 index 0000000..97f18fe Binary files /dev/null and b/mods/nc_player_model/textures/nc_player_model_damage2.png differ diff --git a/mods/nc_player_model/textures/nc_player_model_damage3.png b/mods/nc_player_model/textures/nc_player_model_damage3.png new file mode 100644 index 0000000..052ab73 Binary files /dev/null and b/mods/nc_player_model/textures/nc_player_model_damage3.png differ diff --git a/mods/nc_player_model/textures/nc_player_model_damage4.png b/mods/nc_player_model/textures/nc_player_model_damage4.png new file mode 100644 index 0000000..0c5ed7c Binary files /dev/null and b/mods/nc_player_model/textures/nc_player_model_damage4.png differ diff --git a/mods/nc_player_model/textures/nc_player_model_day_10_31.png b/mods/nc_player_model/textures/nc_player_model_day_10_31.png new file mode 100644 index 0000000..f4850b0 Binary files /dev/null and b/mods/nc_player_model/textures/nc_player_model_day_10_31.png differ diff --git a/mods/nc_player_model/textures/nc_player_model_day_2_14.png b/mods/nc_player_model/textures/nc_player_model_day_2_14.png new file mode 100644 index 0000000..ec89728 Binary files /dev/null and b/mods/nc_player_model/textures/nc_player_model_day_2_14.png differ diff --git a/mods/nc_player_model/textures/nc_player_model_day_3_17.png b/mods/nc_player_model/textures/nc_player_model_day_3_17.png new file mode 100644 index 0000000..f580d66 Binary files /dev/null and b/mods/nc_player_model/textures/nc_player_model_day_3_17.png differ diff --git a/mods/nc_player_model/textures/nc_player_model_day_4_1.png b/mods/nc_player_model/textures/nc_player_model_day_4_1.png new file mode 100644 index 0000000..4ae2979 Binary files /dev/null and b/mods/nc_player_model/textures/nc_player_model_day_4_1.png differ diff --git a/mods/nc_player_model/textures/nc_player_model_no_interact.png b/mods/nc_player_model/textures/nc_player_model_no_interact.png new file mode 100644 index 0000000..c9863da Binary files /dev/null and b/mods/nc_player_model/textures/nc_player_model_no_interact.png differ diff --git a/mods/nc_player_model/textures/nc_player_model_no_shout.png b/mods/nc_player_model/textures/nc_player_model_no_shout.png new file mode 100644 index 0000000..1afc5f9 Binary files /dev/null and b/mods/nc_player_model/textures/nc_player_model_no_shout.png differ diff --git a/mods/nc_player_names/init.lua b/mods/nc_player_names/init.lua new file mode 100644 index 0000000..8fa7bf0 --- /dev/null +++ b/mods/nc_player_names/init.lua @@ -0,0 +1,169 @@ +-- LUALOCALS < --------------------------------------------------------- +local math, minetest, nodecore, pairs, tonumber + = math, minetest, nodecore, pairs, tonumber +local math_sqrt + = math.sqrt +-- LUALOCALS > --------------------------------------------------------- + +nodecore.amcoremod() + +local modname = minetest.get_current_modname() + +-- Maximum distance at which custom nametags are visible. +local distance = tonumber(minetest.settings:get(modname .. "_distance")) or 16 + +-- Keep track of active player HUDs. +local huds = {} + +------------------------------------------------------------------------ +-- PLAYER JOIN/LEAVE + +-- On player joining, disable the built-in nametag by setting its +-- text to whitespace and color to transparent. +minetest.register_on_joinplayer(function(player) + player:set_nametag_attributes({ + text = " ", + color = {a = 0, r = 0, g = 0, b = 0} + }) + end) + +-- On player leaving, clean up any associated HUDs. +minetest.register_on_leaveplayer(function(player) + -- Garbage-collect player's own HUDs. + local pn = player:get_player_name() + huds[pn] = nil + + -- Remove HUDs for this player's name + -- from other players + for _, v in pairs(huds) do + local i = v[pn] + if i then + i.o:hud_remove(i.i) + v[pn] = nil + end + end + end) + +------------------------------------------------------------------------ +-- GLOBAL TICK HUD MANAGEMENT + +local function fluidmedium(pos) + local node = minetest.get_node(pos) + local def = minetest.registered_items[node.name] + if not def then return node.name end + if def.sunlight_propagates then return "CLEAR" end + return def.liquid_alternative_source or node.name +end + +-- Determine if player 1 can see player 2's face, including +-- checks for distance, line-of-sight, and facing direction. +local function canseeface(p1, p2) + if p1:get_hp() <= 0 or p2:get_hp() <= 0 then return end + if p1:get_attach() or p2:get_attach() then return end + + -- Players must be within max distance of one another, + -- determined by light level, but not too close. + local o1 = p1:get_pos() + local o2 = p2:get_pos() + local e1 = p1:get_properties().eye_height or 1.625 + local e2 = p2:get_properties().eye_height or 1.625 + local dx = o1.x - o2.x + local dy = o1.y - o2.y + local dz = o1.z - o2.z + local dsqr = (dx * dx + dy * dy + dz * dz) + if dsqr < 1 then return end + local ll = minetest.get_node_light({x = o2.x, y = o2.y + e2, z = o2.z}) + if not ll then return end + local ld = (ll / 15 * distance) + if dsqr > (ld * ld) then return end + + -- Make sure players' eyes are inside the same fluid. + o1.y = o1.y + e1 + o2.y = o2.y + e2 + local f1 = fluidmedium(o1) + local f2 = fluidmedium(o2) + if f1 ~= f2 then return end + + -- Check for line of sight from approximate eye level + -- of one player to the other. + for pt in minetest.raycast(o1, o2, true, true) do + if pt.type == "node" then + if fluidmedium(pt.under) ~= f1 then return end + elseif pt.type == "object" then + if pt.ref ~= p1 and pt.ref ~= p2 then return end + else + return + end + end + + -- Players must be facing each other; cannot identify another + -- player's face when their back is turned. Note that + -- minetest models don't show pitch, so ignore the y component. + + -- Compute normalized 2d vector from one player to another. + local d = dx * dx + dz * dz + if d == 0 then return end + d = math_sqrt(d) + dx = dx / d + dz = dz / d + + -- Compute normalized 2d facing direction vector for target player. + local l2 = p2:get_look_dir() + d = l2.x * l2.x + l2.z * l2.z + if d == 0 then return end + d = math_sqrt(d) + l2.x = l2.x / d + l2.z = l2.z / d + + -- Compare directions via dot product. + if (dx * l2.x + dz * l2.z) <= 0.5 then return end + + return true +end + +-- On each global step, check all player visibility, and create/remove/update +-- each player's HUDs accordingly. +minetest.register_globalstep(function() + local conn = minetest.get_connected_players() + for _, p1 in pairs(conn) do + local n1 = p1:get_player_name() + local h = huds[n1] + if not h then + h = {} + huds[n1] = h + end + for _, p2 in pairs(conn) do + if p2 ~= p1 then + local n2 = p2:get_player_name() + local i = h[n2] + if canseeface(p1, p2) then + local p = p2:get_pos() + p.y = p.y + 1.25 + + -- Create a new HUD if not present. + if not i then + i = {o = p1, p = p} + i.i = p1:hud_add({ + hud_elem_type = "waypoint", + world_pos = p, + name = n2, + text = "", + number = 0xffffff + }) + h[n2] = i + end + + -- Update HUD if outdated. + if p.x ~= i.p.x or p.y ~= i.p.y or p.z ~= i.p.z then + p1:hud_change(i.i, "world_pos", p) + i.p = p + end + elseif i then + -- Remove HUD if visibility lost. + p1:hud_remove(i.i) + h[n2] = nil + end + end + end + end + end) diff --git a/mods/nc_player_names/mod.conf b/mods/nc_player_names/mod.conf new file mode 100644 index 0000000..ab85b8b --- /dev/null +++ b/mods/nc_player_names/mod.conf @@ -0,0 +1,2 @@ +name = nc_player_names +depends = nc_api diff --git a/mods/nc_player_pickup/api.lua b/mods/nc_player_pickup/api.lua new file mode 100644 index 0000000..fe9e011 --- /dev/null +++ b/mods/nc_player_pickup/api.lua @@ -0,0 +1,33 @@ +-- LUALOCALS < --------------------------------------------------------- +local ItemStack, nodecore + = ItemStack, nodecore +-- LUALOCALS > --------------------------------------------------------- + +function nodecore.inv_walk(player, widx, inv, list) + widx = widx or player:get_wield_index() + list = list or "main" + inv = inv or player:get_inventory() + local size = inv:get_size(list) + local slots = {} + for i = widx, size do slots[#slots +1] = i end + for i = widx - 1, 1, -1 do slots[#slots +1] = i end + local idx = 0 + return function() + idx = idx + 1 + return slots[idx] + end +end + +function nodecore.give_item(player, stack, list, inv) + stack = ItemStack(stack) + if stack:is_empty() then return stack end + + inv = inv or player:get_inventory() + for idx in nodecore.inv_walk(player, nil, inv, list) do + local s = inv:get_stack(list, idx) + stack = nodecore.stack_merge(s, stack) + inv:set_stack(list, idx, s) + if stack:is_empty() then return stack end + end + return inv:add_item(list, stack) +end diff --git a/mods/nc_player_pickup/init.lua b/mods/nc_player_pickup/init.lua new file mode 100644 index 0000000..f4da7a6 --- /dev/null +++ b/mods/nc_player_pickup/init.lua @@ -0,0 +1,10 @@ +-- LUALOCALS < --------------------------------------------------------- +local include, nodecore + = include, nodecore +-- LUALOCALS > --------------------------------------------------------- + +nodecore.amcoremod() + +include("api") +include("intercept") +include("rearrange") diff --git a/mods/nc_player_pickup/intercept.lua b/mods/nc_player_pickup/intercept.lua new file mode 100644 index 0000000..39705ad --- /dev/null +++ b/mods/nc_player_pickup/intercept.lua @@ -0,0 +1,68 @@ +-- LUALOCALS < --------------------------------------------------------- +local ipairs, minetest, nodecore, setmetatable + = ipairs, minetest, nodecore, setmetatable +-- LUALOCALS > --------------------------------------------------------- + +local function wrapinv(inv, player) + if not inv then return inv end + local t = {} + setmetatable(t, {__index = inv}) + function t.add_item(_, list, stack) + return nodecore.give_item(player, stack, list, inv) + end + return t +end + +local function wrapplayer(player) + if not player then return player end + local t = {} + setmetatable(t, {__index = player}) + function t.get_inventory() + return wrapinv(player:get_inventory(), player) + end + return t +end + +local oldstackgive = nodecore.stack_giveto +nodecore.stack_giveto = function(a, whom, ...) + return oldstackgive(a, wrapplayer(whom), ...) +end + +local olddrops = minetest.handle_node_drops +function minetest.handle_node_drops(a, b, whom, ...) + return olddrops(a, b, wrapplayer(whom), ...) +end + +local oldeat = minetest.do_item_eat +function minetest.do_item_eat(a, b, c, whom, ...) + return oldeat(a, b, c, wrapplayer(whom), ...) +end + +local bii = minetest.registered_entities["__builtin:item"] +local item = { + on_punch = function(self, whom, ...) + return bii.on_punch(self, wrapplayer(whom), ...) + end +} +setmetatable(item, bii) +minetest.register_entity(":__builtin:item", item) + +for _, cmd in ipairs({"give", "giveme"}) do + local give = minetest.registered_chatcommands[cmd] or {} + local oldfunc = give.func or function() end + give.func = function(...) + local oldgpbn = minetest.get_player_by_name + local function helper(...) + minetest.get_player_by_name = oldgpbn + return ... + end + minetest.get_player_by_name = function(...) + local function helpest(p, ...) + p = wrapplayer(p) + return p, ... + end + return helpest(oldgpbn(...)) + end + return helper(oldfunc(...)) + end +end diff --git a/mods/nc_player_pickup/mod.conf b/mods/nc_player_pickup/mod.conf new file mode 100644 index 0000000..7eb6ecc --- /dev/null +++ b/mods/nc_player_pickup/mod.conf @@ -0,0 +1,2 @@ +name = nc_player_pickup +depends = nc_api diff --git a/mods/nc_player_pickup/rearrange.lua b/mods/nc_player_pickup/rearrange.lua new file mode 100644 index 0000000..6066824 --- /dev/null +++ b/mods/nc_player_pickup/rearrange.lua @@ -0,0 +1,82 @@ +-- LUALOCALS < --------------------------------------------------------- +local ItemStack, ipairs, minetest, nodecore + = ItemStack, ipairs, minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +local cache = {} + +local function handlepickups(player) + local inv = player:get_inventory() + local pname = player:get_player_name() + local cached = cache[pname] + if cached then + local snap = {} + for i = 1, #cached do snap[i] = ItemStack(cached[i]) end + + local excess = {} + local dirty + + local widx = player:get_wield_index() + for i in nodecore.inv_walk(player, widx, inv) do + local cur = inv:get_stack("main", i) + local old = snap[i] + if old:is_empty() or cur:peek_item(1):to_string() + == old:peek_item(1):to_string() then + local def = minetest.registered_items[cur:get_name()] + if not (def and def.virtual_item) then + local cc = cur:get_count() + local oc = old:get_count() + if cc > oc then + cur:set_count(cc - oc) + for j = 1, #excess do + cur = nodecore.stack_merge(excess[j], cur) + end + if not cur:is_empty() then + excess[#excess + 1] = cur + end + dirty = dirty or i ~= widx + else + snap[i] = cur + end + end + else + snap[i] = cur + end + end + + if dirty then + for i = 1, #excess do + local v = excess[i] + for j in nodecore.inv_walk(player, widx, inv) do + v = nodecore.stack_merge(snap[j], v) + end + if not v:is_empty() then + minetest.log("failed to reinsert item " + .. v:get_name() .. " " .. v:get_count() + .. " for " .. pname) + dirty = nil + end + end + end + + if dirty then + dirty = nil + for i = 1, #cached do + dirty = dirty or inv:get_stack("main", i) + :to_string() ~= snap[i]:to_string() + end + end + + if dirty then + minetest.log("inventory rearranged for " .. pname) + inv:set_list("main", snap) + end + end + cache[pname] = inv:get_list("main") +end + +minetest.register_globalstep(function() + for _, p in ipairs(minetest.get_connected_players()) do + handlepickups(p) + end + end) diff --git a/mods/nc_player_setup/hotpotato.lua b/mods/nc_player_setup/hotpotato.lua new file mode 100644 index 0000000..80c702c --- /dev/null +++ b/mods/nc_player_setup/hotpotato.lua @@ -0,0 +1,42 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, pairs + = minetest, pairs +-- LUALOCALS > --------------------------------------------------------- + +local function hotpotatoes(player) + local inv = player:get_inventory() + local hurt = 0 + local throw = {} + for i = 1, inv:get_size("main") do + local s = inv:get_stack("main", i) + local n = not s:is_empty() and s:get_name() + n = n and minetest.registered_items[n] + n = n and n.damage_per_second + if n and n > 0 then + hurt = hurt + n + inv:set_stack("main", i, "") + throw[#throw + 1] = s + end + end + if #throw > 0 then + local pname = player:get_player_name() + local pos = player:get_pos() + pos.y = pos.y + 1.2 + local dir = player:get_look_dir() + dir.x = dir.x * 5 + dir.y = dir.y * 5 + 3 + dir.z = dir.z * 5 + for _, v in pairs(throw) do + local obj = minetest.add_item(pos, v) + obj:set_velocity(dir) + obj:get_luaentity().dropped_by = pname + end + end + if hurt > 0 then player:set_hp(player:get_hp() - hurt) end +end + +minetest.register_globalstep(function() + for _, v in pairs(minetest.get_connected_players()) do + hotpotatoes(v) + end + end) diff --git a/mods/nc_player_setup/init.lua b/mods/nc_player_setup/init.lua new file mode 100644 index 0000000..bbe4716 --- /dev/null +++ b/mods/nc_player_setup/init.lua @@ -0,0 +1,9 @@ +-- LUALOCALS < --------------------------------------------------------- +local include, nodecore + = include, nodecore +-- LUALOCALS > --------------------------------------------------------- + +nodecore.amcoremod() + +include("setup") +include("hotpotato") diff --git a/mods/nc_player_setup/mod.conf b/mods/nc_player_setup/mod.conf new file mode 100644 index 0000000..fe9d528 --- /dev/null +++ b/mods/nc_player_setup/mod.conf @@ -0,0 +1,2 @@ +name = nc_player_setup +depends = nc_api diff --git a/mods/nc_player_setup/setup.lua b/mods/nc_player_setup/setup.lua new file mode 100644 index 0000000..90121ba --- /dev/null +++ b/mods/nc_player_setup/setup.lua @@ -0,0 +1,43 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, pairs + = minetest, pairs +-- LUALOCALS > --------------------------------------------------------- + +local footsteps = {} + +minetest.register_on_joinplayer(function(player) + local inv = player:get_inventory() + inv:set_size("main", 8) + inv:set_size("craft", 0) + inv:set_size("craftpreview", 0) + inv:set_size("craftresult", 0) + + player:set_physics_override({speed = 1.25}) + + player:set_properties({ + makes_footstep_sound = true, + + -- Allow slight zoom for screenshots + zoom_fov = 60 + }) + footsteps[player:get_player_name()] = true + end) + +minetest.register_allow_player_inventory_action(function(_, action) + return action == "move" and 0 or 1000000 + end) + +minetest.unregister_chatcommand("kill") + +minetest.register_globalstep(function() + for _, player in pairs(minetest.get_connected_players()) do + local name = player:get_player_name() + local value = not player:get_player_control().sneak + if footsteps[name] ~= value then + player:set_properties({ + makes_footstep_sound = value + }) + footsteps[name] = value + end + end + end) diff --git a/mods/nc_player_wield/init.lua b/mods/nc_player_wield/init.lua new file mode 100644 index 0000000..6922368 --- /dev/null +++ b/mods/nc_player_wield/init.lua @@ -0,0 +1,129 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore, table + = minetest, nodecore, table +local table_remove + = table.remove +-- LUALOCALS > --------------------------------------------------------- + +nodecore.amcoremod() + +local modname = minetest.get_current_modname() + +local function entprops(stack, conf) + local t = { + hp_max = 1, + physical = false, + collide_with_objects = false, + collisionbox = {0, 0, 0, 0, 0, 0}, + visual = "wielditem", + visual_size = {x = 0.1, y = 0.1, z = 0.1}, + textures = {""}, + spritediv = {x = 1, y = 1}, + initial_sprite_basepos = {x = 0, y = 0}, + is_visible = false, + static_save = false + } + if not stack then return t end + if stack:is_empty() then return t end + local def = minetest.registered_items[stack:get_name()] or {} + if def.virtual_item then return t end + t.is_visible = true + t.textures[1] = stack:get_name() + if conf and conf.slot == 0 then + t.visual_size = {x = 0.2, y = 0.2, z = 0.2} + end + return t +end + +local attq = {} + +minetest.register_entity(modname .. ":ent", { + initial_properties = entprops(), + on_step = function(self) + local conf = self.conf + if not conf then return self.object:remove() end + + local player = minetest.get_player_by_name(conf.pname) + if not player then return self.object:remove() end + + if not self.att then + self.att = true + return self.object:set_attach(player, + conf.bone, conf.apos, conf.arot) + end + + local inv = player:get_inventory() + local sz = inv:get_size("main") + local s = conf.slot + player:get_wield_index() + if s > sz then s = s - sz end + + local stack = inv:get_stack("main", s) + local sn = stack:get_name() + if sn ~= self.sn then + self.sn = sn + self.object:set_properties(entprops(stack, conf)) + end + end + }) + +minetest.register_globalstep(function() + local v = table_remove(attq, 1) + if not v then return end + + local player = minetest.get_player_by_name(v.pname) + if not player then return end + + if not minetest.get_node_or_nil(player:get_pos()) then + attq[#attq + 1] = v + return + end + + local obj = minetest.add_entity(v.pos, modname .. ":ent") + local ent = obj:get_luaentity() + ent.conf = v + end) + +minetest.register_on_joinplayer(function(player) + local pname = player:get_player_name() + local pos = player:get_pos() + + local function addslot(n, b, x, y, z, rx, ry, rz) + attq[#attq + 1] = { + pname = pname, + slot = n, + pos = pos, + bone = b, + apos = { + x = x, + y = y, + z = z + }, + arot = { + x = rx or 0, + y = ry or 0, + z = rz or 0 + } + } + end + + addslot(0, "Arm_Right", -2.5, 8, 0, 2, 178, 60) + + -- Show player's entire inventory as a "toolbelt". + -- This is very unstable and tends to break badly, + + --[[ + local function cslot(n, x, z) + return addslot(n, nil, x * 1.6, + 5.5 + x / 2, + z * 2.1) + end + + cslot(1, 1, 1) + cslot(2, 0, 1.2) + cslot(3, -1, 1) + cslot(4, -2, 0) + cslot(5, -1, -1) + cslot(6, 0, -1.2) + cslot(7, 1, -1) + --]] + end) diff --git a/mods/nc_player_wield/mod.conf b/mods/nc_player_wield/mod.conf new file mode 100644 index 0000000..ccef888 --- /dev/null +++ b/mods/nc_player_wield/mod.conf @@ -0,0 +1,2 @@ +name = nc_player_wield +depends = nc_api, nc_player_model diff --git a/mods/nc_scaling/init.lua b/mods/nc_scaling/init.lua new file mode 100644 index 0000000..050151b --- /dev/null +++ b/mods/nc_scaling/init.lua @@ -0,0 +1,226 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore, pairs, vector + = minetest, nodecore, pairs, vector +-- LUALOCALS > --------------------------------------------------------- + +nodecore.amcoremod() + +local modname = minetest.get_current_modname() + +minetest.register_node(modname .. ":steps", { + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + tiles = { + "nc_scaling_blank.png", + "nc_scaling_blank.png", + "nc_scaling_blank.png", + "nc_scaling_blank.png", + "nc_scaling_blank.png", + "nc_scaling_steps.png" + }, + use_texture_alpha = true, + drawtype = "nodebox", + node_box = nodecore.fixedbox(-0.5, -0.5, 31/64, 0.5, 0.5, 0.5), + walkable = false, + climbable = true, + pointable = false, + buildable_to = true, + air_equivalent = true, + light_source = 1, + groups = {[modname] = 1} + }) + +minetest.register_node(modname .. ":hang", { + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + drawtype = "airlike", + walkable = false, + climbable = true, + pointable = false, + buildable_to = true, + air_equivalent = true, + groups = {[modname] = 1} + }) + +minetest.register_node(modname .. ":see", { + paramtype = "light", + sunlight_propagates = true, + tiles = { + "nc_scaling_steps.png", + "nc_scaling_blank.png" + }, + use_texture_alpha = true, + drawtype = "nodebox", + node_box = nodecore.fixedbox(-0.5, -0.5, -0.5, 0.5, -31/64, 0.5), + walkable = false, + pointable = false, + buildable_to = true, + air_equivalent = true, + light_source = 1, + groups = {[modname] = 1} + }) + +local function closenough(pos, player) + local pp = player:get_pos() + pp.y = pp.y + 1 + return vector.distance(pos, pp) <= 5 +end + +nodecore.register_limited_abm({ + label = "Scaling Decay", + interval = 1, + chance = 1, + limited_max = 100, + nodenames = {"group:" .. modname}, + action = function(pos) + local data = minetest.get_meta(pos):get_string("data") + if (not data) or (data == "") then + return minetest.remove_node(pos) + end + data = minetest.deserialize(data) + if minetest.get_node(data.pos).name ~= data.node then + return minetest.remove_node(pos) + end + for _, p in pairs(minetest.get_connected_players()) do + if closenough(pos, p) then return end + end + return minetest.remove_node(pos) + end + }) + +local function stepcheck(pos, data) + if not closenough(pos, data.crafter) then return end + if not data.wield:is_empty() then return end + local node = minetest.get_node(pos) + local def = minetest.registered_nodes[node.name] + return not nodecore.toolspeed(data.wield, def.groups) +end + +local function setstep(pos, node, mdata, param2) + node = {name = modname .. ":" .. node} + if param2 then node.param2 = param2 end + minetest.set_node(pos, node) + minetest.get_meta(pos):set_string("data", + minetest.serialize(mdata)) +end + +local function hangcheck(pos, dx, dy, dz, mdata) + pos = { + x = pos.x + dx, + y = pos.y + dy, + z = pos.z + dz + } + if minetest.get_node(pos).name ~= "air" then return end + setstep(pos, "hang", mdata) +end + +local function stepafter(dx, dy, dz) + return function(pos, data) + local p = data.rel(dx, dy, dz) + + local d = vector.subtract(p, pos) + local fd = 0 + for i = 0, #nodecore.facedirs do + if vector.equals(nodecore.facedirs[i].f, d) then + fd = i + break + end + end + + nodecore.node_sound(pos, "place") + + local mdata = { + pos = pos, + node = data.node.name + } + setstep(p, "steps", mdata, fd) + + -- invisible support below to simulate hanging by fingertips + hangcheck(p, 0, -1, 0, mdata) + if dy ~= 0 then + -- invisible support to the sides to simulate swinging + -- outward to grab onto the side of an overhang when + -- hanging below it + hangcheck(p, 1, -1, 0, mdata) + hangcheck(p, -1, -1, 0, mdata) + hangcheck(p, 0, -1, 1, mdata) + hangcheck(p, 0, -1, -1, mdata) + end + end +end + +local pumparticles = { + minsize = 1, + maxsize = 5, + forcetexture = "nc_scaling_particle.png", + glow = 1 +} + +nodecore.register_craft({ + label = "scale sheer walls", + action = "pummel", + priority = -100, + pumparticles = pumparticles, + duration = 5, + normal = {x = 1}, + check = stepcheck, + nodes = { + { + match = {walkable = true} + }, + { + x = 1, + match = {any = {"air", modname .. ":hang"}} + } + }, + after = stepafter(1, 0, 0) + }) + +nodecore.register_craft({ + label = "scale sheer ceilings", + action = "pummel", + priority = -100, + pumparticles = pumparticles, + duration = 10, + normal = {y = -1}, + check = stepcheck, + nodes = { + { + match = {walkable = true} + }, + { + y = -1, + match = "air" + } + }, + after = stepafter(0, -1, 0) + }) + +nodecore.register_craft({ + label = "scale sheer floors", + action = "pummel", + priority = -100, + pumparticles = pumparticles, + duration = 5, + normal = {y = 1}, + check = stepcheck, + nodes = { + { + match = {walkable = true} + }, + { + y = 1, + match = {any = {"air", modname .. ":hang"}}, + replace = modname .. ":see" + } + }, + after = function(pos) + minetest.get_meta({x = pos.x, y = pos.y + 1, z = pos.z}) + :set_string("data", minetest.serialize({ + pos = pos, + node = minetest.get_node(pos).name + })) + end + }) diff --git a/mods/nc_scaling/mod.conf b/mods/nc_scaling/mod.conf new file mode 100644 index 0000000..81d90e6 --- /dev/null +++ b/mods/nc_scaling/mod.conf @@ -0,0 +1,2 @@ +name = nc_scaling +depends = nc_api, nc_api_craft diff --git a/mods/nc_scaling/textures/nc_scaling_blank.png b/mods/nc_scaling/textures/nc_scaling_blank.png new file mode 100644 index 0000000..2a7543c Binary files /dev/null and b/mods/nc_scaling/textures/nc_scaling_blank.png differ diff --git a/mods/nc_scaling/textures/nc_scaling_particle.png b/mods/nc_scaling/textures/nc_scaling_particle.png new file mode 100644 index 0000000..5ed6be5 Binary files /dev/null and b/mods/nc_scaling/textures/nc_scaling_particle.png differ diff --git a/mods/nc_scaling/textures/nc_scaling_steps.png b/mods/nc_scaling/textures/nc_scaling_steps.png new file mode 100644 index 0000000..07f2978 Binary files /dev/null and b/mods/nc_scaling/textures/nc_scaling_steps.png differ diff --git a/mods/nc_sieve/init.lua b/mods/nc_sieve/init.lua new file mode 100644 index 0000000..dba5a93 --- /dev/null +++ b/mods/nc_sieve/init.lua @@ -0,0 +1,8 @@ +-- LUALOCALS < --------------------------------------------------------- +local include, nodecore + = include, nodecore +-- LUALOCALS > --------------------------------------------------------- + +nodecore.amcoremod() + +include("sieve") diff --git a/mods/nc_sieve/mod.conf b/mods/nc_sieve/mod.conf new file mode 100644 index 0000000..e5aeefc --- /dev/null +++ b/mods/nc_sieve/mod.conf @@ -0,0 +1,2 @@ +name = nc_sieve +depends = nc_woodwork, nc_stonework, nc_terrain, nc_lode, nc_lux, nc_api diff --git a/mods/nc_sieve/sieve.lua b/mods/nc_sieve/sieve.lua new file mode 100644 index 0000000..af2741e --- /dev/null +++ b/mods/nc_sieve/sieve.lua @@ -0,0 +1,270 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore, pairs + = minetest, nodecore, pairs +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() +local wmodname = "nc_woodwork" + +local side = "nc_tree_tree_side.png" +local top = wmodname.. "_plank.png" +local top_sieve = wmodname .. "_plank.png^[mask:"..modname.."_sieve.png^nc_tree_leaves.png" + +local sside = "nc_terrain_stone.png" +local stop_sieve = "nc_terrain_stone.png^[mask:"..modname.."_sieve.png^nc_terrain_cobble.png" + +minetest.register_node(modname .. ":table", { + description = "Wooden Table", + drawtype = "nodebox", + node_box = nodecore.fixedbox( + {-0.5, 7/16, -0.5, 0.5, 0.5, 0.5}, + {-0.5, -0.5, -0.5, -7/16, 7/16, -7/16}, + {-0.5, -0.5, 7/16, -7/16, 7/16, 0.5}, + {7/16, -0.5, -0.5, 0.5, 7/16, -7/16}, + {7/16, -0.5, 7/16, 0.5, 7/16, 0.5} + ), + selection_box = nodecore.fixedbox(), + collision_box = nodecore.fixedbox(), + tiles = { top, top, side }, + groups = { + choppy = 1, + flammable = 2, + fire_fuel = 3, + }, + paramtype = "light", + sounds = nodecore.sounds("nc_tree_woody"), + }) + +minetest.register_node(modname .. ":table_broken", { + description = "Broken Wooden Table", + drawtype = "nodebox", + node_box = nodecore.fixedbox( + {-0.5, 7/16, -0.5, -0.5+4/16,0.5,0.5}, + {0.5-4/16, 7/16, -0.5, 0.5, 0.5, 0.5}, + {-8/32, 7/16, 8/32, 8/32, 0.5, 0.5}, + {-8/32, 7/16, -0.5, 8/32, 0.5, -8/32}, + {-0.5, -0.5, -0.5, -7/16, 7/16, -7/16}, + {-0.5, -0.5, 7/16, -7/16, 7/16, 0.5}, + {7/16, -0.5, -0.5, 0.5, 7/16, -7/16}, + {7/16, -0.5, 7/16, 0.5, 7/16, 0.5} + ), + selection_box = nodecore.fixedbox(), + collision_box = nodecore.fixedbox(), + tiles = { top, top, side }, + groups = { + choppy = 1, + flammable = 2, + fire_fuel = 3, + }, + paramtype = "light", + sounds = nodecore.sounds("nc_tree_woody"), + }) +minetest.register_node(modname .. ":sieve", { + description = "Wooden Sieve", + drawtype = "nodebox", + use_texture_alpha = true, + node_box = nodecore.fixedbox( + {-4/16,7/16,-4/16,4/16,0.5,4/16}, + {-0.5, 7/16, -0.5, -0.5+4/16,0.5,0.5}, + {0.5-4/16, 7/16, -0.5, 0.5, 0.5, 0.5}, + {-8/32, 7/16, 8/32, 8/32, 0.5, 0.5}, + {-8/32, 7/16, -0.5, 8/32, 0.5, -8/32}, + {-0.5, -0.5, -0.5, -7/16, 7/16, -7/16}, + {-0.5, -0.5, 7/16, -7/16, 7/16, 0.5}, + {7/16, -0.5, -0.5, 0.5, 7/16, -7/16}, + {7/16, -0.5, 7/16, 0.5, 7/16, 0.5} + ), + selection_box = nodecore.fixedbox(), + collision_box = nodecore.fixedbox(), + tiles = { top_sieve, top_sieve, side }, + groups = { + choppy = 1, + flammable = 2, + fire_fuel = 3, + }, + paramtype = "light", + sounds = nodecore.sounds("nc_tree_woody"), + }) +minetest.register_node(modname .. ":sieve_stone", { + description = "Stone Sieve", + drawtype = "nodebox", + use_texture_alpha = true, + node_box = nodecore.fixedbox( + {-4/16,7/16,-4/16,4/16,0.5,4/16}, + {-0.5, 7/16, -0.5, -0.5+4/16,0.5,0.5}, + {0.5-4/16, 7/16, -0.5, 0.5, 0.5, 0.5}, + {-8/32, 7/16, 8/32, 8/32, 0.5, 0.5}, + {-8/32, 7/16, -0.5, 8/32, 0.5, -8/32}, + {-0.5, -0.5, -0.5, -7/16, 7/16, -7/16}, + {-0.5, -0.5, 7/16, -7/16, 7/16, 0.5}, + {7/16, -0.5, -0.5, 0.5, 7/16, -7/16}, + {7/16, -0.5, 7/16, 0.5, 7/16, 0.5} + ), + selection_box = nodecore.fixedbox(), + collision_box = nodecore.fixedbox(), + tiles = { stop_sieve, stop_sieve, sside }, + groups = { + cracky = 2, + }, + paramtype = "light", + sounds = nodecore.sounds("nc_terrain_stony"), + }) + +minetest.register_craftitem(modname..":random_dust",{ + description = "Dust of random minerals", + inventory_image = modname.."_random_dust.png" +}) + +nodecore.register_craft({ + label = "break a table", + action = "pummel", + toolgroups = {choppy = 1}, + nodes = { + {match = modname .. ":table", replace = modname .. ":table_broken"} + }, + }) + +local dio = { + items={{name = "nc_stonework:chip", count = 4, scatter = 2}} +} + +local duo = { + items={{name = modname..":random_dust", count = 1, scatter = 2}} +} +local dio2 = { + items={{name = "nc_stonework:chip", count = 8, scatter = 2}} +} + +local duo2 = { + items={{name = modname..":random_dust", count = 2, scatter = 2}} +} +local dio3 = { + items={{name = "nc_stonework:chip", count = 16, scatter = 2}} +} + +local duo3 = { + items={{name = modname..":random_dust", count = 4, scatter = 2}} +} + +local dirts = { + ["nc_terrain:dirt"] = dio, + ["nc_terrain:dirt_loose"] = dio, + ["nc_tree:humus"] = dio2, + ["nc_tree:humus_loose"] = dio2, + ["nc_terrain:gravel"] = duo, + ["nc_terrain:gravel_loose"] = duo, + ["nc_terrain:sand"] = duo2, + ["nc_terrain:sand_loose"] = duo2, + ["nc_tree:leaves_loose"] = {node = "nc_terrain:water_source"} +} + +local dirtss = { + ["nc_terrain:dirt"] = dio2, + ["nc_terrain:dirt_loose"] = dio2, + ["nc_tree:humus"] = dio3, + ["nc_tree:humus_loose"] = dio3, + ["nc_terrain:gravel"] = duo2, + ["nc_terrain:gravel_loose"] = duo2, + ["nc_terrain:sand"] = duo3, + ["nc_terrain:sand_loose"] = duo3, + ["nc_tree:leaves_loose"] = {node = "nc_terrain:water_source"}, +} + +for k,v in pairs(dirts) do + +nodecore.register_craft({ + label = "use a sieve with "..k, + action = "pummel", + toolgroups = {crumbly = 1}, + nodes = { + {match = {name = k}, replace = v.node or "air"}, + {y=-1,match = modname .. ":sieve"} + }, + items = v.items + }) + +end + +for k,v in pairs(dirtss) do + +nodecore.register_craft({ + label = "use a stone sieve with "..k, + action = "pummel", + toolgroups = {crumbly = 1}, + nodes = { + {match = {name = k}, replace = v.node or "air"}, + {y=-1,match = modname .. ":sieve_stone"} + }, + items = v.items + }) + +end + +local ores = { + ["nc_lode:cobble_loose"] = 100, + ["nc_lux:cobble1_loose"] = 10, + ["nc_sponge:sponge_living"]=1 +} + +nodecore.register_craft({ + label = "pack random dust into cobble", + action = "pummel", + toolgroups = {thumpy = 2}, + nodes = { + {match = {name = modname..":random_dust",count=8},replace = "nc_terrain:cobble"} + }, + after = function(pos) + local chances = {} + local mc = 1 + for k,v in pairs(ores) do + for n=mc,mc-1+v do + chances[n] = k + end + mc=mc+v + end + local ore = chances[math.random(1,mc-1)] + minetest.set_node(pos,{name=ore}) + end + }) + +nodecore.register_craft({ + label = "assemble wood sieve", + norotate = true, + nodes = { + {y = -1, match = modname .. ":table_broken", replace = modname .. ":sieve"}, + {match = "nc_tree:leaves_loose", replace = "air"}, + } + }) + +nodecore.register_craft({ + label = "assemble stone sieve", + norotate = true, + nodes = { + {y = -1, match = modname .. ":table_broken", replace = modname .. ":sieve_stone"}, + {match = "nc_terrain:cobble_loose", replace = "air"}, + } + }) + +nodecore.register_craft({ + label = "assemble wood table", + norotate = true, + nodes = { + {match = wmodname .. ":plank", replace = modname .. ":table"}, + {x = -1, z = -1, match = wmodname .. ":staff", replace = "air"}, + {x = 1, z = -1, match = wmodname .. ":staff", replace = "air"}, + {x = -1, z = 1, match = wmodname .. ":staff", replace = "air"}, + {x = 1, z = 1, match = wmodname .. ":staff", replace = "air"}, + } + }) + +nodecore.register_craft({ + label = "assemble wood table", + norotate = true, + nodes = { + {match = wmodname .. ":plank", replace = modname .. ":table"}, + {x = 0, z = -1, match = wmodname .. ":staff", replace = "air"}, + {x = 0, z = 1, match = wmodname .. ":staff", replace = "air"}, + {x = -1, z = 0, match = wmodname .. ":staff", replace = "air"}, + {x = 1, z = 0, match = wmodname .. ":staff", replace = "air"}, + } + }) diff --git a/mods/nc_sieve/textures/nc_sieve_random_dust.png b/mods/nc_sieve/textures/nc_sieve_random_dust.png new file mode 100644 index 0000000..9165c65 Binary files /dev/null and b/mods/nc_sieve/textures/nc_sieve_random_dust.png differ diff --git a/mods/nc_sieve/textures/nc_sieve_sieve.png b/mods/nc_sieve/textures/nc_sieve_sieve.png new file mode 100644 index 0000000..61f20f8 Binary files /dev/null and b/mods/nc_sieve/textures/nc_sieve_sieve.png differ diff --git a/mods/nc_sky/init.lua b/mods/nc_sky/init.lua new file mode 100644 index 0000000..cbefea2 --- /dev/null +++ b/mods/nc_sky/init.lua @@ -0,0 +1,116 @@ +--nothing-- +local grass = "nc_terrain:dirt_with_grass" +local dirt = "nc_terrain:dirt" +local stone = "nc_terrain:stone" +local queue = {} + +minetest.register_globalstep(function(dt) + for f,_ in pairs(queue) do + if not coroutine.resume(f) then + queue[f]=nil + end + end +end) + +local function maxval(octaves,persistence,scale) + local m = scale + local poc = scale + if octaves > 1 then + for n=2,octaves do + poc = poc*persistence + m=m+poc + end + end + return m +end + +local function island(pos,r) + minetest.after(2,function()--queue[coroutine.create(function() + local noise = PerlinNoise({ + seed = math.random(10000), + octaves = 3, + spread = {x=r/2,y=r/2,z=r/2}, + lacunarity = 2, + persistence = 0.5, + flags = "absvalue" + }) + local n = 0 + local c = 0 + local cm = (r*2+1)^3 + local function geto(x,y,z) + local dist = (x*x+y*y+z*z)^0.5 + local uvdist = (y+r)/(r*2) + local hdist = (x*x+z*z)^0.5 + local uhdist = (math.max(0,r-hdist)/r)^((1-uvdist)^3*5) + local udist = math.max(0,r-dist)/r + if math.min(1,math.max(0,uhdist^2)) ~= uhdist^2 then + print(uhdist^2) + end + local m = ((math.max(r-(hdist),0)/r)^0.1*(uhdist^2))-uhdist*uvdist^3 + return m + end + for x=-r,r do + for z=-r,r do + for y=-r,r do + local xx,yy,zz = pos.x+x,pos.y+y,pos.z+z + o,o2 = geto(x,y,z),geto(x,y+1,z) + local oc = (o > 0.4) + local oc2 = o2 > 0.4 + local og = (o > 0.6) + if oc then + n=n+1 + local nam = dirt + if not og and not oc2 then + nam = grass + end + if og then + nam = stone + end + minetest.set_node({x=xx,y=yy,z=zz},{name=nam}) + else + n=n+0.01 + end + if n > 1000 then + n=0 + --coroutine.yield() + end + end + end + end + minetest.set_node({x=pos.x,y=pos.y+10,z=pos.z},{name="nc_tree:eggcorn_planted"}) + end)--end)] = true +end +local f = math.floor +local function spawn_island(name,pos) + local ref = minetest.get_player_by_name(name) + pos = {x=f(pos.x),y=f(pos.y),z=f(pos.z)} + island(pos,16,name) + ref:set_pos({x=pos.x,y=pos.y+30,z=pos.z}) +end +local store = minetest.get_mod_storage() +local function pid(x,z) + return "i"..x.."_"..z +end +local function checkpos(x,z) + if store:get_string(pid(x,z)) == "" then + return true + end +end +local function gen_island_pos(name) + local x,z = 0,0 + local ok = checkpos(x,z) + while not ok do + x,z = x+math.random(-1,1),z+math.random(-1,1) + ok = checkpos(x,z) + end + store:set_string(pid(x,z),name) + spawn_island(name,{x=x*128,y=256,z=z*128}) + return pid(x,z) +end +minetest.register_on_joinplayer(function(ref) + local meta = ref:get_meta() + local name = ref:get_player_name() + if meta:get_string("island") == "" then + meta:set_string("island",gen_island_pos(name)) + end +end) \ No newline at end of file diff --git a/mods/nc_sponge/abm.lua b/mods/nc_sponge/abm.lua new file mode 100644 index 0000000..63ab6b1 --- /dev/null +++ b/mods/nc_sponge/abm.lua @@ -0,0 +1,53 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore, pairs + = minetest, nodecore, pairs +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +nodecore.register_limited_abm({ + label = "Sponge Wettening", + interval = 1, + chance = 10, + limited_max = 100, + nodenames = {modname .. ":sponge"}, + neighbors = {"group:water"}, + action = function(pos) + minetest.set_node(pos, {name = modname .. ":sponge_wet"}) + nodecore.node_sound(pos, "place") + for _, p in pairs(minetest.find_nodes_in_area( + {x = pos.x - 1, y = pos.y - 1, z = pos.z - 1}, + {x = pos.x + 1, y = pos.y + 1, z = pos.z + 1}, + {"group:water"})) do + nodecore.node_sound(p, "dig") + minetest.remove_node(p) + end + end + }) + +nodecore.register_limited_abm({ + label = "Sponge Drying in Sunlight", + interval = 1, + chance = 100, + limited_max = 100, + nodenames = {modname .. ":sponge_wet", modname .. ":sponge_living"}, + action = function(pos) + if minetest.get_node_light({x = pos.x, y = pos.y + 1, z = pos.z}) >= 15 then + minetest.sound_play("nc_api_craft_hiss", {gain = 0.02, pos = pos}) + return minetest.set_node(pos, {name = modname .. ":sponge"}) + end + end + }) + +nodecore.register_limited_abm({ + label = "Sponge Drying near Fire", + interval = 1, + chance = 20, + limited_max = 100, + nodenames = {modname .. ":sponge_wet", modname .. ":sponge_living"}, + neighbors = {"group:igniter"}, + action = function(pos) + minetest.sound_play("nc_api_craft_hiss", {gain = 0.02, pos = pos}) + return minetest.set_node(pos, {name = modname .. ":sponge"}) + end + }) diff --git a/mods/nc_sponge/cultivate.lua b/mods/nc_sponge/cultivate.lua new file mode 100644 index 0000000..432bc48 --- /dev/null +++ b/mods/nc_sponge/cultivate.lua @@ -0,0 +1,87 @@ +-- LUALOCALS < --------------------------------------------------------- +local ItemStack, math, minetest, nodecore, pairs, vector + = ItemStack, math, minetest, nodecore, pairs, vector +local math_pow, math_random + = math.pow, math.random +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +local growdirs = nodecore.dirs() + +local living = modname .. ":sponge_living" + +nodecore.register_limited_abm({ + label = "Sponge Growth", + interval = 10, + chance = 1000, + limited_max = 100, + nodenames = {living}, + neighbors = {"group:water"}, + action = function(pos) + local total = 0 + if nodecore.scan_flood(pos, 6, + function(p, d) + if d >= 6 then return true end + if minetest.get_node(p).name ~= living then return false end + total = total + 1 + if total >= 20 then return true end + end + ) then return end + + pos = vector.add(pos, growdirs[math_random(1, #growdirs)]) + + local node = minetest.get_node_or_nil(pos) + local def = node and minetest.registered_nodes[node.name] + local grp = def and def.groups and def.groups.water + if (not grp) or (grp < 1) then return end + + local below = {x = pos.x, y = pos.y - 1, z = pos.z} + node = minetest.get_node(below) + if (math_random() > 0.1) or (node.name ~= living) then + def = minetest.registered_nodes[node.name] + grp = def and def.groups and def.groups.sand + if (not grp) or (grp < 1) then return end + end + minetest.set_node(pos, {name = living}) + end + }) + +-- A living sponge can be dug intact, RARELY, and ONLY if surrounded +-- on all sides and edges (X/Z plane) by other living sponges. + +local digpos +local old_node_dig = minetest.node_dig +minetest.node_dig = function(pos, node, ...) + if (node and node.name) ~= living then + return old_node_dig(pos, node, ...) + end + local function helper(...) + digpos = nil + return ... + end + digpos = pos + return helper(old_node_dig(pos, node, ...)) +end +local old_get_node_drops = minetest.get_node_drops +minetest.get_node_drops = function(...) + local drops = old_get_node_drops(...) + if not digpos then return drops end + local neighbors = #minetest.find_nodes_in_area( + {x = digpos.x - 1, y = digpos.y - 1, z = digpos.z - 1}, + {x = digpos.x + 1, y = digpos.y + 1, z = digpos.z + 1}, + {living}) + if neighbors >= 5 then + local prob = math_pow(2, neighbors - 5) * 0.005 + if math_random() <= prob then return drops end + end + drops = drops or {} + for k, v in pairs(drops) do + v = ItemStack(v) + if v:get_name() == living then + v:set_name(modname .. ":sponge_wet") + end + drops[k] = v + end + return drops +end diff --git a/mods/nc_sponge/gen.lua b/mods/nc_sponge/gen.lua new file mode 100644 index 0000000..3934624 --- /dev/null +++ b/mods/nc_sponge/gen.lua @@ -0,0 +1,58 @@ +-- LUALOCALS < --------------------------------------------------------- +local math, minetest, nodecore + = math, minetest, nodecore +local math_floor, math_random + = math.floor, math.random +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +local maxy = -8 +local miny = maxy - 8 + +local c_sand = minetest.get_content_id("nc_terrain:sand") +local c_water = minetest.get_content_id("nc_terrain:water_source") +local c_sponge = minetest.get_content_id(modname .. ":sponge_living") + +local function spawn(area, data, x, y, z) + local total = 0 + nodecore.scan_flood({x = x, y = y, z = z}, 5, function(p) + if math_random() < 0.01 then return true end + if p.y > y and math_random() > 0.1 then return false end + local idx = area:index(p.x, p.y - 1, p.z) + if data[idx] ~= c_sponge and data[idx] ~= c_sand then return false end + idx = area:index(p.x, p.y, p.z) + if data[idx] ~= c_water then return false end + data[idx] = c_sponge + total = total + 1 + if total >= 20 then return true end + end) +end + +nodecore.register_mapgen_shared(function(minp, maxp, area, data) + if minp.y > maxy or maxp.y < miny then return end + + local qty = math_floor(math_random() * (maxp.x - minp.x) + * (maxp.z - minp.z) / (64 * 64)) + for _ = 1, qty do + local x = math_floor(math_random() * (maxp.x - minp.x)) + minp.x + local z = math_floor(math_random() * (maxp.z - minp.z)) + minp.z + local starty = maxp.y + if starty > (maxy + 1) then starty = (maxy + 1) end + local endy = minp.y + if endy < miny then endy = miny end + local waterabove = nil + for y = starty, endy, -1 do + local idx = area:index(x, y, z) + local cur = data[idx] + if cur == c_water then + waterabove = true + elseif cur == c_sand and waterabove then + spawn(area, data, x, y + 1, z) + break + else + break + end + end + end + end) diff --git a/mods/nc_sponge/init.lua b/mods/nc_sponge/init.lua new file mode 100644 index 0000000..e9bdca8 --- /dev/null +++ b/mods/nc_sponge/init.lua @@ -0,0 +1,12 @@ +-- LUALOCALS < --------------------------------------------------------- +local include, nodecore + = include, nodecore +-- LUALOCALS > --------------------------------------------------------- + +nodecore.amcoremod() + +include("node") +include("abm") +include("gen") +include("cultivate") +include("squeeze") diff --git a/mods/nc_sponge/mod.conf b/mods/nc_sponge/mod.conf new file mode 100644 index 0000000..3f88fa8 --- /dev/null +++ b/mods/nc_sponge/mod.conf @@ -0,0 +1,2 @@ +name = nc_sponge +depends = nc_api, nc_api_craft, nc_terrain diff --git a/mods/nc_sponge/node.lua b/mods/nc_sponge/node.lua new file mode 100644 index 0000000..f5b2783 --- /dev/null +++ b/mods/nc_sponge/node.lua @@ -0,0 +1,49 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore + = minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +minetest.register_node(modname .. ":sponge", { + description = "Sponge", + drawtype = "allfaces_optional", + tiles = {modname ..".png"}, + paramtype = "light", + groups = { + crumbly = 2, + flammable = 3, + fire_fuel = 3, + sponge = 1 + }, + sounds = nodecore.sounds("nc_terrain_swishy") + }) + +minetest.register_node(modname .. ":sponge_wet", { + description = "Wet Sponge", + drawtype = "allfaces_optional", + tiles = {modname ..".png^(nc_terrain_water.png^[opacity:96)"}, + paramtype = "light", + groups = { + crumbly = 2, + coolant = 1, + falling_node = 1, + moist = 1, + sponge = 1 + }, + sounds = nodecore.sounds("nc_terrain_swishy") + }) + +minetest.register_node(modname .. ":sponge_living", { + description = "Living Sponge", + drawtype = "allfaces_optional", + tiles = {modname ..".png^(nc_terrain_water.png^[opacity:96)"}, + paramtype = "light", + groups = { + crumbly = 2, + coolant = 1, + moist = 1, + sponge = 1 + }, + sounds = nodecore.sounds("nc_terrain_swishy") + }) diff --git a/mods/nc_sponge/squeeze.lua b/mods/nc_sponge/squeeze.lua new file mode 100644 index 0000000..593bb5e --- /dev/null +++ b/mods/nc_sponge/squeeze.lua @@ -0,0 +1,81 @@ +-- LUALOCALS < --------------------------------------------------------- +local math, minetest, nodecore, pairs, vector + = math, minetest, nodecore, pairs, vector +local math_random + = math.random +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +minetest.register_entity(modname .. ":waterguard", { + initial_properties = { + physical = false, + collide_with_objects = false, + collisionbox = {0, 0, 0, 0, 0, 0}, + textures = {""}, + is_visible = false, + static_save = true + }, + on_activate = function(self, data) + self.data = minetest.deserialize(data) + end, + get_staticdata = function(self) + return minetest.serialize(self.data) + end, + on_step = function(self, dtime) + local pos = self.object:get_pos() + local node = minetest.get_node(pos) + if node.name ~= "nc_terrain:water_source" then + return self.object:remove() + end + self.data.ttl = self.data.ttl - dtime + if (self.data.ttl <= 0) then + return minetest.set_node(pos, { + name = "nc_terrain:water_flowing", + param2 = 7 + }) + end + end + }) + +local spongedirs = { + {x = 1, y = 0, z = 0}, + {x = -1, y = 0, z = 0}, + {x = 0, y = 0, z = 1}, + {x = 0, y = 0, z = -1} +} + +nodecore.register_craft({ + label = "squeeze sponge", + action = "pummel", + toolgroups = {thumpy = 1}, + nodes = { + { + match = modname .. ":sponge_wet", + replace = modname .. ":sponge" + }, + { + x = 1, + match = "air" + } + }, + after = function(pos) + local dirs = {} + for _, d in pairs(spongedirs) do + local p = vector.add(pos, d) + if minetest.get_node(p).name == "air" then + dirs[#dirs + 1] = p + end + end + local p = dirs[math_random(1, #dirs)] + + if minetest.get_node(p).name ~= "air" + or minetest.find_node_near(p, 2, {"nc_terrain:water_source"}) + then return end + + minetest.set_node(p, {name = "nc_terrain:water_source"}) + nodecore.node_sound(p, "place") + minetest.add_entity(p, modname .. ":waterguard", + minetest.serialize({ttl = 3})) + end + }) diff --git a/mods/nc_sponge/textures/nc_sponge.png b/mods/nc_sponge/textures/nc_sponge.png new file mode 100644 index 0000000..fd73104 Binary files /dev/null and b/mods/nc_sponge/textures/nc_sponge.png differ diff --git a/mods/nc_stats/init.lua b/mods/nc_stats/init.lua new file mode 100644 index 0000000..a384cc2 --- /dev/null +++ b/mods/nc_stats/init.lua @@ -0,0 +1,265 @@ +-- LUALOCALS < --------------------------------------------------------- +local math, minetest, nodecore, os, pairs, table, type, vector + = math, minetest, nodecore, os, pairs, table, type, vector +local math_random, os_date, table_remove + = math.random, os.date, table.remove +-- LUALOCALS > --------------------------------------------------------- + +nodecore.amcoremod() + +local modname = minetest.get_current_modname() +local modstore = minetest.get_mod_storage() + +------------------------------------------------------------------------ +-- DATABASE SETUP + +local statsdb = {} +nodecore.statsdb = statsdb + +local function load_check(s) + s = s and s ~= "" and minetest.deserialize(s) + return type(s) == "table" and s or {} +end +do + local s = load_check(modstore:get_string(modname)) + statsdb[false] = s + s.firstseen = s.firstseen or os_date("!*t") + s.startup = (s.startup or 0) + 1 +end + +local function dbadd_nav(qty, dirty, db, root, key, ...) + local v = db[root] + if key then + if not v or type(v) ~= "table" then + v = {} + db[root] = v + end + if dirty then v.dirty = true end + return dbadd_nav(qty, nil, v, key, ...) + else + v = v and type(v) == "number" and v or 0 + db[root] = v + qty + end +end +local function dbadd(qty, root, ...) + if qty == 0 then return end + return dbadd_nav(qty, true, statsdb, root, ...) +end + +local function playeradd(qty, player, ...) + if not player then return end + local pname = (type(player) == "string") and player or player:get_player_name() + if not pname then return end + local data = statsdb[pname] + if not data then + if type(player) == "string" then player = minetest.get_player_by_name(player) end + if (not player) or (not player.is_player) or (not player:is_player()) then return end + data = load_check(player:get_meta():get_string(modname)) + statsdb[pname] = data + end + dbadd(qty, pname, ...) + if not statsdb[pname].firstseen then + statsdb[pname].firstseen = os_date("!*t") + end + dbadd(qty, false, "players", ...) +end +nodecore.player_stat_add = playeradd + +------------------------------------------------------------------------ +-- PLAYER EVENTS + +local function reghook(func, stat, pwhom, npos) + return func(function(...) + local t = {...} + local whom = t[pwhom] + local n = npos and t[npos].name or nil + return playeradd(1, whom, stat, n) + end) +end +reghook(minetest.register_on_punchnode, "punch", 3, 2) +reghook(minetest.register_on_dignode, "dig", 3, 2) +reghook(minetest.register_on_placenode, "place", 3, 2) +reghook(minetest.register_on_dieplayer, "die", 1) +reghook(minetest.register_on_respawnplayer, "spawn", 1) +reghook(minetest.register_on_joinplayer, "join", 1) +reghook(minetest.register_on_leaveplayer, "leave", 1) + +local function unpackreason(reason) + if type(reason) ~= "table" then return reason or "?" end + if reason.from then return reason.from, reason.type or nil end + return reason.type or "?" +end + +minetest.register_on_player_hpchange(function(whom, change, reason) + if change < 0 then + return playeradd(-change, whom, "hurt", unpackreason(reason)) + else + return playeradd(change, whom, "heal", unpackreason(reason)) + end + end) + +minetest.register_on_cheat(function(player, reason) + playeradd(1, player, "cheat", unpackreason(reason)) + end) + +minetest.register_on_chat_message(function(name, msg) + dbadd(1, name, "chat", (msg:sub(1, 1) == "/") and "command" or "message") + end) + +minetest.register_on_shutdown(function() + for _, player in pairs(minetest.get_connected_players()) do + playeradd(1, player, "shutdown") + end + end) + +------------------------------------------------------------------------ +-- PLAYER INVENTORY SCAN + +local function invscan(dt, player) + local inv = player:get_inventory() + local t = {} + for i = 1, inv:get_size("main") do + local stack = inv:get_stack("main", i) + if not stack:is_empty() then + t[stack:get_name()] = true + end + end + for k in pairs(t) do + playeradd(dt, player, "inv", k) + end +end + +------------------------------------------------------------------------ +-- PLAYER MOVEMENT/IDLE HOOKS + +local playdb = { } +local idlemin = 5 +local function movement(dt, player) + if not player or not player:is_player() then return end + local pn = player:get_player_name() + + local pd = playdb[pn] + if not pd then + pd = {} + playdb[pn] = pd + end + + local pos = player:get_pos() + local dir = player:get_look_dir() + local cur = { pos.x, pos.y, pos.z, dir.x, dir.y, dir.z } + local moved + if pd.last then + for i = 1, 6 do + moved = moved or pd.last[i] ~= cur[i] + end + if moved then + playeradd(vector.distance(pos, + {x = pd.last[1], y = pd.last[2], z = pd.last[3]}), + player, "distance") + end + end + pd.last = cur + + local t = pd.t or 0 + if moved then + pd.t = 0 + if t >= idlemin then + playeradd(t, player, "idle") + return playeradd(dt, player, "move") + else + return playeradd(t + dt, player, "move") + end + else + if t >= idlemin then + return playeradd(dt, player, "idle") + else + pd.t = t + dt + if (t + dt) >= idlemin then + return playeradd(t + dt, player, "idle") + end + end + end +end +minetest.register_globalstep(function(dt) + for _, player in pairs(minetest.get_connected_players()) do + invscan(dt, player) + movement(dt, player) + end + end) + +------------------------------------------------------------------------ +-- DATABASE FLUSH CYCLE + +local opq = {} + +local function flushkey(k) + local v = statsdb[k] + if not v or not v.dirty then return end + v.dirty = nil + + v.datafix = v.datafix or 0 + if v.datafix < 1 then + v.datafix = 1 + + local q = k and v or v.players + for _, n in pairs({"hurt", "heal", "cheat"}) do + local old = q[n] + if old then + q[n] = {} + for xk, xv in pairs(old) do + if type(xv) == "number" then + dbadd_nav(xv, nil, q[n], unpackreason(xk)) + else + q[n][xk] = xv + end + end + end + end + end + + if k == false then + return modstore:set_string(modname, minetest.serialize(v)) + end + + local player = minetest.get_player_by_name(k) + if player then + return player:get_meta():set_string(modname, minetest.serialize(v)) + end +end + +local function flushop() + local k = table_remove(opq) + if k == nil then return end + minetest.after(0, flushop) + return flushkey(k) +end + +local function flushenq() + minetest.after(20, flushenq) + if #opq > 0 then return end + for k in pairs(statsdb) do + opq[#opq + 1] = k + end + for i = 1, #opq do + local j = math_random(1, #opq) + opq[i], opq[j] = opq[j], opq[i] + end + minetest.after(0, flushop) +end +flushenq() + +minetest.register_globalstep(function(dt) + dbadd(dt, false, "elapsed") + dbadd(1, false, "tick") + end) + +minetest.register_on_leaveplayer(function(player) + return flushkey(player:get_player_name()) + end) +minetest.register_on_shutdown(function() + dbadd(1, false, "shutdown") + flushkey(false) + for _, player in pairs(minetest.get_connected_players()) do + flushkey(player:get_player_name()) + end + end) diff --git a/mods/nc_stats/mod.conf b/mods/nc_stats/mod.conf new file mode 100644 index 0000000..d2b8f50 --- /dev/null +++ b/mods/nc_stats/mod.conf @@ -0,0 +1,2 @@ +name = nc_stats +depends = nc_api diff --git a/mods/nc_stonework/chip.lua b/mods/nc_stonework/chip.lua new file mode 100644 index 0000000..2479db6 --- /dev/null +++ b/mods/nc_stonework/chip.lua @@ -0,0 +1,80 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore + = minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +minetest.register_craftitem(modname .. ":chip", { + description = "Stone Chip", + inventory_image = modname .. "_stone.png", + wield_image = "[combine:16x16:0,2=" .. modname .. "_stone.png", + wield_scale = {x = 1.25, y = 1.25, z = 1.75}, + sounds = nodecore.sounds("nc_terrain_stony") + }) + +nodecore.register_craft({ + label = "break cobble to chips", + action = "pummel", + nodes = { + {match = "nc_terrain:cobble_loose", replace = "nc_terrain:gravel"} + }, + items = { + {name = modname .. ":chip", count = 4, scatter = 5} + }, + toolgroups = {cracky = 2}, + itemscatter = 5 + }) + +nodecore.register_craft({ + label = "break packed cobble to chips", + action = "pummel", + nodes = { + {match = "nc_terrain:cobble", replace = "nc_terrain:gravel"} + }, + items = { + {name = modname .. ":chip", count = 4, scatter = 5} + }, + toolgroups = {cracky = 4}, + itemscatter = 5 + }) + +nodecore.register_craft({ + label = "repack chips to cobble", + action = "pummel", + nodes = { + { + match = {name = modname .. ":chip", count = 8}, + replace = "nc_terrain:cobble_loose" + } + }, + toolgroups = {thumpy = 2} + }) + + + +nodecore.register_craft({ + label = "break gravel to chips", + action = "pummel", + nodes = { + {match = "nc_terrain:gravel_loose", replace = "nc_terrain:sand"} + }, + items = { + {name = modname .. ":chip", count = 4, scatter = 5} + }, + toolgroups = {cracky = 2}, + itemscatter = 5 + }) + +nodecore.register_craft({ + label = "break packed gravel to chips", + action = "pummel", + nodes = { + {match = "nc_terrain:gravel", replace = "nc_terrain:sand"} + }, + items = { + {name = modname .. ":chip", count = 2, scatter = 5} + }, + toolgroups = {cracky = 2}, + itemscatter = 5 + }) \ No newline at end of file diff --git a/mods/nc_stonework/init.lua b/mods/nc_stonework/init.lua new file mode 100644 index 0000000..0bff295 --- /dev/null +++ b/mods/nc_stonework/init.lua @@ -0,0 +1,9 @@ +-- LUALOCALS < --------------------------------------------------------- +local include, nodecore + = include, nodecore +-- LUALOCALS > --------------------------------------------------------- + +nodecore.amcoremod() + +include("chip") +include("tools") diff --git a/mods/nc_stonework/mod.conf b/mods/nc_stonework/mod.conf new file mode 100644 index 0000000..e36b997 --- /dev/null +++ b/mods/nc_stonework/mod.conf @@ -0,0 +1,2 @@ +name = nc_stonework +depends = nc_terrain, nc_woodwork diff --git a/mods/nc_stonework/textures/nc_stonework_stone.png b/mods/nc_stonework/textures/nc_stonework_stone.png new file mode 100644 index 0000000..6d78d54 Binary files /dev/null and b/mods/nc_stonework/textures/nc_stonework_stone.png differ diff --git a/mods/nc_stonework/textures/nc_stonework_tip_hatchet.png b/mods/nc_stonework/textures/nc_stonework_tip_hatchet.png new file mode 100644 index 0000000..fb45e89 Binary files /dev/null and b/mods/nc_stonework/textures/nc_stonework_tip_hatchet.png differ diff --git a/mods/nc_stonework/textures/nc_stonework_tip_mallet.png b/mods/nc_stonework/textures/nc_stonework_tip_mallet.png new file mode 100644 index 0000000..8b0ab13 Binary files /dev/null and b/mods/nc_stonework/textures/nc_stonework_tip_mallet.png differ diff --git a/mods/nc_stonework/textures/nc_stonework_tip_pick.png b/mods/nc_stonework/textures/nc_stonework_tip_pick.png new file mode 100644 index 0000000..afb550a Binary files /dev/null and b/mods/nc_stonework/textures/nc_stonework_tip_pick.png differ diff --git a/mods/nc_stonework/textures/nc_stonework_tip_spade.png b/mods/nc_stonework/textures/nc_stonework_tip_spade.png new file mode 100644 index 0000000..356b39f Binary files /dev/null and b/mods/nc_stonework/textures/nc_stonework_tip_spade.png differ diff --git a/mods/nc_stonework/tools.lua b/mods/nc_stonework/tools.lua new file mode 100644 index 0000000..adfd598 --- /dev/null +++ b/mods/nc_stonework/tools.lua @@ -0,0 +1,66 @@ +-- LUALOCALS < --------------------------------------------------------- +local ipairs, minetest, nodecore + = ipairs, minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +nodecore.register_stone_tip_tool, +nodecore.registered_stone_tip_tools += nodecore.mkreg() + +local stoned = nodecore.sounds("nc_terrain_stony").place + +local chip = modname .. ":chip" +nodecore.extend_item(chip, function(copy, orig) + copy.on_place = function(itemstack, placer, pointed_thing, ...) + if not nodecore.interact(placer) then return end + if itemstack:get_name() == chip and pointed_thing.type == "node" then + local pos = pointed_thing.under + for _, v in ipairs(nodecore.registered_stone_tip_tools) do + if nodecore.match(pos, { + name = v.from, + wear = 0.05 + }) then + minetest.remove_node(pos) + nodecore.item_eject(pos, v.to) + stoned.pos = pos + minetest.sound_play(stoned.name, stoned) + itemstack:set_count(itemstack:get_count() - 1) + if placer then + nodecore.player_stat_add(1, placer, "craft", + "assemble " .. v.to) + end + return itemstack + end + end + end + return orig.on_place(itemstack, placer, pointed_thing, ...) + end + end) + +local function tooltip(name, group) + local tool = modname .. ":tool_" .. name:lower() + local wood = "nc_woodwork:tool_" .. name:lower() + minetest.register_tool(tool, { + description = "Stone-Tipped " .. name, + inventory_image = "nc_woodwork_tool_" .. name:lower() .. ".png^" + .. modname .. "_tip_" .. name:lower() .. ".png", + tool_wears_to = wood, + groups = { + flammable = 2 + }, + tool_capabilities = nodecore.toolcaps({ + uses = 0.25, + [group] = 3 + }), + on_ignite = modname .. ":chip", + sounds = nodecore.sounds("nc_terrain_stony") + }) + nodecore.register_stone_tip_tool({from = wood, to = tool}) +end + +tooltip("Mallet", "thumpy") +tooltip("Spade", "crumbly") +tooltip("Hatchet", "choppy") +tooltip("Pick", "cracky") diff --git a/mods/nc_terrain/ambiance.lua b/mods/nc_terrain/ambiance.lua new file mode 100644 index 0000000..2b7ad9d --- /dev/null +++ b/mods/nc_terrain/ambiance.lua @@ -0,0 +1,42 @@ +-- LUALOCALS < --------------------------------------------------------- +local nodecore + = nodecore +-- LUALOCALS > --------------------------------------------------------- + +nodecore.register_ambiance({ + label = "Water Source Ambiance", + nodenames = {"nc_terrain:water_source"}, + neigbors = {"air"}, + interval = 1, + chance = 1000, + sound_name = "nc_terrain_watery", + sound_gain = 0.05 + }) +nodecore.register_ambiance({ + label = "Water Flow Ambiance", + nodenames = {"nc_terrain:water_flowing"}, + neigbors = {"air"}, + interval = 1, + chance = 50, + sound_name = "nc_terrain_watery", + sound_gain = 0.15 + }) + +nodecore.register_ambiance({ + label = "Lava Source Ambiance", + nodenames = {"nc_terrain:lava_source"}, + neigbors = {"air"}, + interval = 1, + chance = 250, + sound_name = "nc_terrain_bubbly", + sound_gain = 0.2 + }) +nodecore.register_ambiance({ + label = "Lava Flow Ambiance", + nodenames = {"nc_terrain:lava_flowing"}, + neigbors = {"air"}, + interval = 1, + chance = 10, + sound_name = "nc_terrain_bubbly", + sound_gain = 0.2 + }) diff --git a/mods/nc_terrain/api.lua b/mods/nc_terrain/api.lua new file mode 100644 index 0000000..f6af9c2 --- /dev/null +++ b/mods/nc_terrain/api.lua @@ -0,0 +1,24 @@ +-- LUALOCALS < --------------------------------------------------------- +local math, minetest, nodecore + = math, minetest, nodecore +local math_floor, math_sqrt + = math.floor, math.sqrt +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +nodecore.hard_stone_strata = 7 + +function nodecore.hard_stone_tile(n) + local o = math_floor(math_sqrt(n or 0) * 96) + if o <= 0 then + return modname .. "_stone.png" + end + if o >= 255 then + return modname .. "_stone.png^" + .. modname .. "_stone_hard.png" + end + return modname .. "_stone.png^(" + .. modname .. "_stone_hard.png^[opacity:" + .. o .. ")" +end diff --git a/mods/nc_terrain/biome.lua b/mods/nc_terrain/biome.lua new file mode 100644 index 0000000..0cb0d0e --- /dev/null +++ b/mods/nc_terrain/biome.lua @@ -0,0 +1,34 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest + = minetest +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +minetest.register_biome({ + name = "unknown", + node_top = modname .. ":dirt_with_grass", + depth_top = 1, + node_filler = modname .. ":dirt", + depth_filler = 1, + node_riverbed = modname .. ":sand", + depth_riverbed = 2, + y_min = 6, + y_max = 31000, + heat_point = 0, + humidity_point = 0, + }) + +minetest.register_biome({ + name = "seabed", + node_top = modname .. ":sand", + depth_top = 1, + node_filler = modname .. ":sand", + depth_filler = 1, + node_riverbed = modname .. ":sand", + depth_riverbed = 2, + y_min = -31000, + y_max = 5, + heat_point = 0, + humidity_point = 0, + }) diff --git a/mods/nc_terrain/grasslife.lua b/mods/nc_terrain/grasslife.lua new file mode 100644 index 0000000..33be402 --- /dev/null +++ b/mods/nc_terrain/grasslife.lua @@ -0,0 +1,64 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore + = minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +local dirt = "nc_terrain:dirt" +local grass = "nc_terrain:dirt_with_grass" + +local breathable = { + airlike = true, + allfaces = true, + allfaces_optional = true, + torchlike = true, + signlike = true, + plantlike = true, + firelike = true, + raillike = true, + nodebox = true, + mesh = true, + plantlike_rooted = true +} + +-- nil = stay, false = die, true = grow +local function grassable(above) + local node = minetest.get_node(above) + if node.name == "ignore" then return end + + local def = minetest.registered_items[node.name] or {} + + if (not def.drawtype) or (not breathable[def.drawtype]) + or (def.damage_per_second and def.damage_per_second > 0) + then return false end + + local ln = minetest.get_node_light(above) or 0 + if ln >= 10 then return true end + local ld = minetest.get_node_light(above, 0.5) or 0 + if ld >= 10 then return end +end + +nodecore.register_limited_abm({ + label = "Grass Spread", + nodenames = {"group:soil"}, + neighbors = {grass}, + interval = 6, + chance = 50, + action = function(pos, node) + if node.name == grass then return end + local above = {x = pos.x, y = pos.y + 1, z = pos.z} + if not grassable(above) then return end + return minetest.set_node(pos, {name = grass}) + end + }) + +nodecore.register_limited_abm({ + label = "Grass Decay", + nodenames = {grass}, + interval = 8, + chance = 50, + action = function(pos) + local above = {x = pos.x, y = pos.y + 1, z = pos.z} + if grassable(above) ~= false then return end + return minetest.set_node(pos, {name = dirt}) + end + }) diff --git a/mods/nc_terrain/init.lua b/mods/nc_terrain/init.lua new file mode 100644 index 0000000..156c55a --- /dev/null +++ b/mods/nc_terrain/init.lua @@ -0,0 +1,14 @@ +-- LUALOCALS < --------------------------------------------------------- +local include, nodecore + = include, nodecore +-- LUALOCALS > --------------------------------------------------------- + +nodecore.amcoremod() + +include('api') +include('node') +include('biome') +include('strata') +include('ore') +include('grasslife') +include('ambiance') diff --git a/mods/nc_terrain/mod.conf b/mods/nc_terrain/mod.conf new file mode 100644 index 0000000..7c8a47f --- /dev/null +++ b/mods/nc_terrain/mod.conf @@ -0,0 +1,2 @@ +name = nc_terrain +depends = nc_api diff --git a/mods/nc_terrain/node.lua b/mods/nc_terrain/node.lua new file mode 100644 index 0000000..c87a8cc --- /dev/null +++ b/mods/nc_terrain/node.lua @@ -0,0 +1,353 @@ +-- LUALOCALS < --------------------------------------------------------- +local ipairs, minetest, nodecore, pairs, type + = ipairs, minetest, nodecore, pairs, type +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +local function regterrain(def) + def.name = def.name or def.description:gsub("%W", "_"):lower() + def.fullname = modname .. ":" .. def.name + + def.tiles = def.tiles or { def.fullname:gsub("%W", "_") .. ".png" } + def.is_ground_content = true + + if def.liquidtype then + def.liquid_alternative_flowing = def.fullname .. "_flowing" + def.liquid_alternative_source = def.fullname .. "_source" + def.fullname = def.fullname .. "_" .. def.liquidtype + def.special_tiles = def.special_tiles or { def.tiles[1], def.tiles[1] } + end + + def.mapgen = def.mapgen or { def.name } + + minetest.register_node(def.fullname, def) + + for _, v in pairs(def.mapgen) do + minetest.register_alias("mapgen_" .. v, def.fullname) + end +end + +local function clone(t) + local c = minetest.deserialize(minetest.serialize(t)) + for k, v in pairs(t) do + if type(v) == "function" then c[k] = v end + end + return c +end + +local function regliquid(def) + local t = clone(def) + t.drawtype = "liquid" + t.liquidtype = "source" + regterrain(t) + + t = clone(def) + t.mapgen = { } + t.drawtype = "flowingliquid" + t.liquidtype = "flowing" + t.paramtype2 = "flowingliquid" + regterrain(t) +end + +local strata = {} +regterrain({ + description = "Stone", + mapgen = { + "stone", + "stone_with_coal", + "stone_with_iron", + "desert_stone", + "sandstone", + "mese", + }, + silktouch = false, + groups = { + stone = 1, + rock = 1, + cracky = 2 + }, + drop_in_place = modname .. ":cobble", + strata = strata, + sounds = nodecore.sounds("nc_terrain_stony") + }) +strata[1] = modname .. ":stone" +for i = 1, nodecore.hard_stone_strata do + regterrain({ + name = "hard_stone_" .. i, + description = "Stone", + tiles = { nodecore.hard_stone_tile(i) }, + silktouch = false, + groups = { + stone = i, + rock = i, + cracky = i + 2, + hard_stone = i + }, + drop_in_place = modname .. ((i > 1) + and (":hard_stone_" .. (i - 1)) or ":stone"), + sounds = nodecore.sounds("nc_terrain_stony") + }) + strata[i + 1] = modname .. ":hard_stone_" .. i +end + +regterrain({ + description = "Cobble", + tiles = { modname .. "_gravel.png^" .. modname .. "_cobble.png" }, + mapgen = { + "sandstonebrick", + "stair_sandstone_block", + "cobble", + "stair_cobble", + "stair_desert_stone", + "mossycobble" + }, + groups = { + cobble = 1, + rock = 1, + cracky = 1 + }, + alternate_loose = { + repack_level = 2, + groups = { + cracky = 0, + crumbly = 2, + falling_repose = 3 + }, + sounds = nodecore.sounds("nc_terrain_chompy") + }, + crush_damage = 2, + sounds = nodecore.sounds("nc_terrain_stony") + }) + +for _, v in ipairs({ + "snow", + "snowblock", + "junglegrass", + "tree", + "jungletree", + "pine_tree", + "leaves", + "apple", + "jungleleaves", + "pine_needles" + }) do + minetest.register_alias("mapgen_" .. v, "air") +end + +regterrain({ + description = "Dirt", + alternate_loose = { + groups = { + dirt_loose = 1, + falling_repose = 2, + soil = 2 + } + }, + mapgen = { + "dirt", + "ice", + }, + groups = { + dirt = 1, + crumbly = 1, + soil = 1 + }, + crush_damage = 1, + sounds = nodecore.sounds("nc_terrain_crunchy") + }) +regterrain({ + name = "dirt_with_grass", + description = "Grass", + tiles = { + modname .. "_grass_top.png", + modname .. "_dirt.png", + modname .. "_dirt.png^" .. modname .. "_grass_side.png" + }, + mapgen = { + "dirt_with_grass", + "dirt_with_snow" + }, + groups = { + crumbly = 2, + soil = 1, + green = 1 + }, + drop_in_place = modname .. ":dirt", + sounds = nodecore.sounds("nc_terrain_grassy") + }) +regterrain({ + description = "Gravel", + alternate_loose = { + groups = { + crumbly = 2, + falling_repose = 2 + } + }, + groups = { + gravel = 1, + crumbly = 1, + falling_node = 1 + }, + crush_damage = 1, + sounds = nodecore.sounds("nc_terrain_chompy") + }) +regterrain({ + description = "Sand", + alternate_loose = { + groups = { + falling_repose = 1 + } + }, + groups = { + sand = 1, + crumbly = 1, + falling_node = 1 + }, + mapgen = { + "sand", + "clay", + "desert_sand" + }, + crush_damage = 0.5, + sounds = nodecore.sounds("nc_terrain_swishy") + }) + +regliquid({ + description = "Water", + mapgen = { "river_water_source", "water_source" }, + paramtype = "light", + liquid_viscosity = 1, + liquid_renewable = false, + alpha = 160, + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + drowning = 1, + drop = "", + groups = { coolant = 1, water = 2, moist = 2 }, + post_effect_color = {a = 103, r = 30, g = 76, b = 90}, + sounds = nodecore.sounds("nc_terrain_watery") + }) +regliquid({ + name = "lava", + description = "Molten Rock", + mapgen = { "lava_source" }, + paramtype = "light", + liquid_viscosity = 7, + liquid_renewable = false, + light_source = 13, + walkable = false, + diggable = false, + buildable_to = true, + drowning = 1, + damage_per_second = 8, + on_punch = nodecore.node_punch_hurt, + drop = "", + groups = { igniter = 1, lava = 2 }, + post_effect_color = {a = 191, r = 255, g = 64, b = 0}, + sounds = nodecore.sounds("nc_terrain_bubbly") + }) + +local src = modname..":water_source" +local flow = modname..":water_flowing" + + +nodecore.register_limited_abm({ + label = "Water Renew", + interval = 1, + chance = 1, + nodenames = {flow}, + neirbours = {src}, + action = function(pos, node) + local n2 = minetest.get_node({x=pos.x,y=pos.y-1,z=pos.z}).name + if n2 == flow then + local count = 0 + for x=-1,1 do + for y=0,1 do + for z=-1,1 do + if (x*x+y*y+z*z)^0.5 == 1 and minetest.get_node({x=pos.x+x,y=pos.y+y,z=pos.z+z}) == src then + count = count + 1 + end + end + end + end + if count >= 2 then + minetest.set_node(pos,{name=src}) + end + end + end + }) + + +nodecore.register_limited_abm({ + label = "Water Flowing", + interval = 1, + chance = 2, + nodenames = {src}, + action = function(pos, node) + local miny = pos.y + local found = {} + nodecore.scan_flood(pos, 5, function(p) + local nn = minetest.get_node(p).name + if nn == src then return end + if nn ~= flow then return false end + if p.y > miny then return end + if p.y == miny then + found[#found + 1] = p + return + end + miny = p.y + found = {p} + end) + if #found < 1 then return end + local np = nodecore.pickrand(found) + minetest.set_node(np, node) + minetest.set_node(pos, {name = flow, param2 = 7}) + end + }) + +nodecore.register_craft({ + label = "melt cobble to lava", + action = "cook", + touchgroups = {flame = 3}, + duration = 30, + cookfx = true, + nodes = { + { + match = modname .. ":cobble", + replace = modname .. ":lava_source" + } + } + }) + +local src2 = modname..":lava_source" +local flow2 = modname..":lava_flowing" + +nodecore.register_limited_abm({ + label = "Lava Flowing", + interval = 2, + chance = 2, + nodenames = {src2}, + action = function(pos, node) + local miny = pos.y + local found = {} + nodecore.scan_flood(pos, 5, function(p) + local nn = minetest.get_node(p).name + if nn == src2 then return end + if nn ~= flow2 then return false end + if p.y > miny then return end + if p.y == miny then + found[#found + 1] = p + return + end + miny = p.y + found = {p} + end) + if #found < 1 then return end + local np = nodecore.pickrand(found) + minetest.set_node(np, node) + minetest.set_node(pos, {name = flow2, param2 = 7}) + end + }) diff --git a/mods/nc_terrain/ore.lua b/mods/nc_terrain/ore.lua new file mode 100644 index 0000000..e2de1c4 --- /dev/null +++ b/mods/nc_terrain/ore.lua @@ -0,0 +1,26 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest + = minetest +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +minetest.register_ore({ + name = "gravel", + ore_type = "blob", + ore = modname .. ":gravel", + wherein = modname .. ":stone", + clust_size = 5, + clust_scarcity = 8 * 8 * 8, + random_factor = 0, + noise_params = { + offset = 0, + scale = 3, + spread = {x=10, y=25, z=10}, + seed = 34654, + octaves = 3, + persist = 0.5, + flags = "eased", + }, + noise_threshold = 1.2 + }) diff --git a/mods/nc_terrain/sounds/nc_terrain_bubbly.0.ogg b/mods/nc_terrain/sounds/nc_terrain_bubbly.0.ogg new file mode 100644 index 0000000..89b3b82 Binary files /dev/null and b/mods/nc_terrain/sounds/nc_terrain_bubbly.0.ogg differ diff --git a/mods/nc_terrain/sounds/nc_terrain_bubbly.1.ogg b/mods/nc_terrain/sounds/nc_terrain_bubbly.1.ogg new file mode 100644 index 0000000..81e916a Binary files /dev/null and b/mods/nc_terrain/sounds/nc_terrain_bubbly.1.ogg differ diff --git a/mods/nc_terrain/sounds/nc_terrain_bubbly.2.ogg b/mods/nc_terrain/sounds/nc_terrain_bubbly.2.ogg new file mode 100644 index 0000000..be8e925 Binary files /dev/null and b/mods/nc_terrain/sounds/nc_terrain_bubbly.2.ogg differ diff --git a/mods/nc_terrain/sounds/nc_terrain_chompy.0.ogg b/mods/nc_terrain/sounds/nc_terrain_chompy.0.ogg new file mode 100644 index 0000000..74247bf Binary files /dev/null and b/mods/nc_terrain/sounds/nc_terrain_chompy.0.ogg differ diff --git a/mods/nc_terrain/sounds/nc_terrain_chompy.1.ogg b/mods/nc_terrain/sounds/nc_terrain_chompy.1.ogg new file mode 100644 index 0000000..c5d9d08 Binary files /dev/null and b/mods/nc_terrain/sounds/nc_terrain_chompy.1.ogg differ diff --git a/mods/nc_terrain/sounds/nc_terrain_crunchy.0.ogg b/mods/nc_terrain/sounds/nc_terrain_crunchy.0.ogg new file mode 100644 index 0000000..023c433 Binary files /dev/null and b/mods/nc_terrain/sounds/nc_terrain_crunchy.0.ogg differ diff --git a/mods/nc_terrain/sounds/nc_terrain_crunchy.1.ogg b/mods/nc_terrain/sounds/nc_terrain_crunchy.1.ogg new file mode 100644 index 0000000..cdf1956 Binary files /dev/null and b/mods/nc_terrain/sounds/nc_terrain_crunchy.1.ogg differ diff --git a/mods/nc_terrain/sounds/nc_terrain_crunchy.2.ogg b/mods/nc_terrain/sounds/nc_terrain_crunchy.2.ogg new file mode 100644 index 0000000..338e936 Binary files /dev/null and b/mods/nc_terrain/sounds/nc_terrain_crunchy.2.ogg differ diff --git a/mods/nc_terrain/sounds/nc_terrain_grassy.0.ogg b/mods/nc_terrain/sounds/nc_terrain_grassy.0.ogg new file mode 100644 index 0000000..5c1ac1f Binary files /dev/null and b/mods/nc_terrain/sounds/nc_terrain_grassy.0.ogg differ diff --git a/mods/nc_terrain/sounds/nc_terrain_grassy.1.ogg b/mods/nc_terrain/sounds/nc_terrain_grassy.1.ogg new file mode 100644 index 0000000..bfd2633 Binary files /dev/null and b/mods/nc_terrain/sounds/nc_terrain_grassy.1.ogg differ diff --git a/mods/nc_terrain/sounds/nc_terrain_grassy.2.ogg b/mods/nc_terrain/sounds/nc_terrain_grassy.2.ogg new file mode 100644 index 0000000..cf25fd3 Binary files /dev/null and b/mods/nc_terrain/sounds/nc_terrain_grassy.2.ogg differ diff --git a/mods/nc_terrain/sounds/nc_terrain_stony.0.ogg b/mods/nc_terrain/sounds/nc_terrain_stony.0.ogg new file mode 100644 index 0000000..9283582 Binary files /dev/null and b/mods/nc_terrain/sounds/nc_terrain_stony.0.ogg differ diff --git a/mods/nc_terrain/sounds/nc_terrain_stony.1.ogg b/mods/nc_terrain/sounds/nc_terrain_stony.1.ogg new file mode 100644 index 0000000..d1b73f9 Binary files /dev/null and b/mods/nc_terrain/sounds/nc_terrain_stony.1.ogg differ diff --git a/mods/nc_terrain/sounds/nc_terrain_stony.2.ogg b/mods/nc_terrain/sounds/nc_terrain_stony.2.ogg new file mode 100644 index 0000000..2229a3a Binary files /dev/null and b/mods/nc_terrain/sounds/nc_terrain_stony.2.ogg differ diff --git a/mods/nc_terrain/sounds/nc_terrain_swishy.0.ogg b/mods/nc_terrain/sounds/nc_terrain_swishy.0.ogg new file mode 100644 index 0000000..4f30438 Binary files /dev/null and b/mods/nc_terrain/sounds/nc_terrain_swishy.0.ogg differ diff --git a/mods/nc_terrain/sounds/nc_terrain_swishy.1.ogg b/mods/nc_terrain/sounds/nc_terrain_swishy.1.ogg new file mode 100644 index 0000000..f8d3f76 Binary files /dev/null and b/mods/nc_terrain/sounds/nc_terrain_swishy.1.ogg differ diff --git a/mods/nc_terrain/sounds/nc_terrain_swishy.2.ogg b/mods/nc_terrain/sounds/nc_terrain_swishy.2.ogg new file mode 100644 index 0000000..642a81a Binary files /dev/null and b/mods/nc_terrain/sounds/nc_terrain_swishy.2.ogg differ diff --git a/mods/nc_terrain/sounds/nc_terrain_watery.0.ogg b/mods/nc_terrain/sounds/nc_terrain_watery.0.ogg new file mode 100644 index 0000000..7940fdc Binary files /dev/null and b/mods/nc_terrain/sounds/nc_terrain_watery.0.ogg differ diff --git a/mods/nc_terrain/sounds/nc_terrain_watery.1.ogg b/mods/nc_terrain/sounds/nc_terrain_watery.1.ogg new file mode 100644 index 0000000..b36c23b Binary files /dev/null and b/mods/nc_terrain/sounds/nc_terrain_watery.1.ogg differ diff --git a/mods/nc_terrain/sounds/nc_terrain_watery.2.ogg b/mods/nc_terrain/sounds/nc_terrain_watery.2.ogg new file mode 100644 index 0000000..e3192ff Binary files /dev/null and b/mods/nc_terrain/sounds/nc_terrain_watery.2.ogg differ diff --git a/mods/nc_terrain/strata.lua b/mods/nc_terrain/strata.lua new file mode 100644 index 0000000..eb6166e --- /dev/null +++ b/mods/nc_terrain/strata.lua @@ -0,0 +1,67 @@ +-- LUALOCALS < --------------------------------------------------------- +local error, ipairs, math, minetest, nodecore, pairs + = error, ipairs, math, minetest, nodecore, pairs +local math_floor, math_random + = math.floor, math.random +-- LUALOCALS > --------------------------------------------------------- + +local thickness = 128 + +nodecore.stratadata = nodecore.memoize(function() + local data = {} + data.stratbyid = {} + data.altsbyid = {} + for k, v in pairs(minetest.registered_nodes) do + if v.strata then + local sn + for s, n in ipairs(v.strata) do + if n == k then sn = s end + end + if not sn then error(k .. " not found in own strata") end + local cid = minetest.get_content_id(k) + data.stratbyid[cid] = sn + data.altsbyid[cid] = {} + for s, n in ipairs(v.strata) do + data.altsbyid[cid][s] = minetest.get_content_id(n) + end + end + end + return data + end) + +nodecore.register_mapgen_shared(function(minp, maxp, area, data) + if minp.y > -64 then return end + + local ai = area.index + local t = nodecore.hard_stone_strata + local sd = nodecore.stratadata() + local byid = sd.stratbyid + local alts = sd.altsbyid + + for z = minp.z, maxp.z do + for y = minp.y, maxp.y do + local raw = y / -thickness + local strat = math_floor(raw) + local dither = raw - strat + if strat > t then + strat = t + dither = nil + elseif dither > (4 / thickness) then + dither = nil + else + dither = (dither * thickness + 1)/5 + end + for x = minp.x, maxp.x do + local i = ai(area, x, y, z) + if byid[data[i]] then + if dither and math_random() >= dither then + data[i] = alts[data[i]][strat] + else + data[i] = alts[data[i]][strat + 1] + end + end + end + end + end + end, + -100) diff --git a/mods/nc_terrain/textures/nc_terrain_cobble.png b/mods/nc_terrain/textures/nc_terrain_cobble.png new file mode 100644 index 0000000..205258a Binary files /dev/null and b/mods/nc_terrain/textures/nc_terrain_cobble.png differ diff --git a/mods/nc_terrain/textures/nc_terrain_dark.png b/mods/nc_terrain/textures/nc_terrain_dark.png new file mode 100644 index 0000000..e959668 Binary files /dev/null and b/mods/nc_terrain/textures/nc_terrain_dark.png differ diff --git a/mods/nc_terrain/textures/nc_terrain_dirt.png b/mods/nc_terrain/textures/nc_terrain_dirt.png new file mode 100644 index 0000000..7cd1b9c Binary files /dev/null and b/mods/nc_terrain/textures/nc_terrain_dirt.png differ diff --git a/mods/nc_terrain/textures/nc_terrain_grass_side.png b/mods/nc_terrain/textures/nc_terrain_grass_side.png new file mode 100644 index 0000000..2c97b00 Binary files /dev/null and b/mods/nc_terrain/textures/nc_terrain_grass_side.png differ diff --git a/mods/nc_terrain/textures/nc_terrain_grass_top.png b/mods/nc_terrain/textures/nc_terrain_grass_top.png new file mode 100644 index 0000000..d7b1dfe Binary files /dev/null and b/mods/nc_terrain/textures/nc_terrain_grass_top.png differ diff --git a/mods/nc_terrain/textures/nc_terrain_gravel.png b/mods/nc_terrain/textures/nc_terrain_gravel.png new file mode 100644 index 0000000..55d44ba Binary files /dev/null and b/mods/nc_terrain/textures/nc_terrain_gravel.png differ diff --git a/mods/nc_terrain/textures/nc_terrain_lava.png b/mods/nc_terrain/textures/nc_terrain_lava.png new file mode 100644 index 0000000..1a730ff Binary files /dev/null and b/mods/nc_terrain/textures/nc_terrain_lava.png differ diff --git a/mods/nc_terrain/textures/nc_terrain_sand.png b/mods/nc_terrain/textures/nc_terrain_sand.png new file mode 100644 index 0000000..7bca609 Binary files /dev/null and b/mods/nc_terrain/textures/nc_terrain_sand.png differ diff --git a/mods/nc_terrain/textures/nc_terrain_stone.png b/mods/nc_terrain/textures/nc_terrain_stone.png new file mode 100644 index 0000000..e497acf Binary files /dev/null and b/mods/nc_terrain/textures/nc_terrain_stone.png differ diff --git a/mods/nc_terrain/textures/nc_terrain_stone_hard.png b/mods/nc_terrain/textures/nc_terrain_stone_hard.png new file mode 100644 index 0000000..d8c1f88 Binary files /dev/null and b/mods/nc_terrain/textures/nc_terrain_stone_hard.png differ diff --git a/mods/nc_terrain/textures/nc_terrain_water.png b/mods/nc_terrain/textures/nc_terrain_water.png new file mode 100644 index 0000000..b5985cf Binary files /dev/null and b/mods/nc_terrain/textures/nc_terrain_water.png differ diff --git a/mods/nc_torch/abm.lua b/mods/nc_torch/abm.lua new file mode 100644 index 0000000..40db8fd --- /dev/null +++ b/mods/nc_torch/abm.lua @@ -0,0 +1,54 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore, pairs, vector + = minetest, nodecore, pairs, vector +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +nodecore.register_limited_abm({ + label = "Torch Igniting", + interval = 6, + chance = 1, + nodenames = {modname .. ":torch_lit"}, + neighbors = {"group:flammable"}, + action = function(pos) + local check = { + {x = 1, y = 0, z = 0}, + {x = -1, y = 0, z = 0}, + {x = 0, y = 0, z = 1}, + {x = 0, y = 0, z = -1}, + {x = 0, y = 1, z = 0} + } + for _, ofst in pairs(check) do + local npos = vector.add(pos, ofst) + local nbr = minetest.get_node(npos) + if minetest.get_item_group(nbr.name, "flammable") > 0 and not nodecore.quenched(npos) then + nodecore.fire_check_ignite(npos, nbr) + end + end + end + }) + +nodecore.register_limited_abm({ + label = "Torch Extinguishing", + interval = 1, + chance = 1, + nodenames = {modname .. ":torch_lit"}, + action = function(pos) + if nodecore.quenched(pos) or + minetest.get_gametime() > minetest.get_meta(pos):get_float("expire") then + minetest.remove_node(pos) + minetest.add_item(pos, {name = "nc_fire:lump_ash"}) + minetest.sound_play("nc_fire_snuff", {gain = 1, pos = pos}) + end + end + }) + +nodecore.register_ambiance({ + label = "Flame Ambiance", + nodenames = {modname .. ":torch_lit"}, + interval = 1, + chance = 1, + sound_name = "nc_fire_flamy", + sound_gain = 0.1 + }) diff --git a/mods/nc_torch/init.lua b/mods/nc_torch/init.lua new file mode 100644 index 0000000..1ee693f --- /dev/null +++ b/mods/nc_torch/init.lua @@ -0,0 +1,10 @@ +-- LUALOCALS < --------------------------------------------------------- +local include, nodecore + = include, nodecore +-- LUALOCALS > --------------------------------------------------------- + +nodecore.amcoremod() + +include("node") +include("abm") +include("wield") diff --git a/mods/nc_torch/mod.conf b/mods/nc_torch/mod.conf new file mode 100644 index 0000000..12f7d47 --- /dev/null +++ b/mods/nc_torch/mod.conf @@ -0,0 +1,2 @@ +name = nc_torch +depends = nc_api, nc_api_craft, nc_fire, nc_woodwork diff --git a/mods/nc_torch/models/nc_torch_torch.obj b/mods/nc_torch/models/nc_torch_torch.obj new file mode 100644 index 0000000..0eb38a1 --- /dev/null +++ b/mods/nc_torch/models/nc_torch_torch.obj @@ -0,0 +1,85 @@ +# Blender v2.81 (sub 8) OBJ File: 'nc_torch_torch.blend' +# www.blender.org +mtllib nc_torch_torch.mtl +o Cube +v -0.062500 -0.500000 0.062500 +v -0.062500 0.375000 0.062500 +v -0.062500 -0.500000 -0.062500 +v -0.062500 0.375000 -0.062500 +v 0.062500 -0.500000 0.062500 +v 0.062500 0.375000 0.062500 +v 0.062500 -0.500000 -0.062500 +v 0.062500 0.375000 -0.062500 +v -0.093750 0.000000 0.093750 +v -0.093750 0.500000 0.093750 +v -0.093750 0.000000 -0.093750 +v -0.093750 0.500000 -0.093750 +v 0.093750 0.000000 0.093750 +v 0.093750 0.500000 0.093750 +v 0.093750 0.000000 -0.093750 +v 0.093750 0.500000 -0.093750 +vt 0.437500 0.437500 +vt 0.562500 0.437500 +vt 0.562500 0.562500 +vt 0.437500 0.562500 +vt 0.562500 0.562500 +vt 0.437500 0.562500 +vt 0.437500 0.437500 +vt 0.562500 0.437500 +vt 0.562500 -0.000000 +vt 0.562500 1.000000 +vt 0.437500 1.000000 +vt 0.437500 -0.000000 +vt 0.562500 -0.000000 +vt 0.562500 1.000000 +vt 0.437500 1.000000 +vt 0.437500 -0.000000 +vt 0.562500 -0.000000 +vt 0.562500 1.000000 +vt 0.437500 1.000000 +vt 0.437500 -0.000000 +vt 0.562500 -0.000000 +vt 0.562500 1.000000 +vt 0.437500 1.000000 +vt 0.437500 -0.000000 +vt 1.000000 0.000000 +vt 1.000000 1.000000 +vt 0.000000 1.000000 +vt 0.000000 0.000000 +vt 1.000000 0.000000 +vt 1.000000 1.000000 +vt 0.000000 1.000000 +vt 0.000000 0.000000 +vt 1.000000 0.000000 +vt 1.000000 1.000000 +vt 0.000000 1.000000 +vt 0.000000 0.000000 +vt 1.000000 0.000000 +vt 1.000000 1.000000 +vt 0.000000 1.000000 +vt 0.000000 0.000000 +vn 0.0000 1.0000 0.0000 +vn 0.0000 -1.0000 0.0000 +vn -1.0000 0.0000 0.0000 +vn 0.0000 0.0000 -1.0000 +vn 1.0000 0.0000 0.0000 +vn 0.0000 0.0000 1.0000 +g Cube_Cube_top +usemtl top +s off +f 8/1/1 4/2/1 2/3/1 6/4/1 +g Cube_Cube_bottom +usemtl bottom +f 3/5/2 7/6/2 5/7/2 1/8/2 +g Cube_Cube_side +usemtl side +f 1/9/3 2/10/3 4/11/3 3/12/3 +f 3/13/4 4/14/4 8/15/4 7/16/4 +f 7/17/5 8/18/5 6/19/5 5/20/5 +f 5/21/6 6/22/6 2/23/6 1/24/6 +g Cube_Cube_flame +usemtl flame +f 9/25/3 10/26/3 12/27/3 11/28/3 +f 11/29/4 12/30/4 16/31/4 15/32/4 +f 15/33/5 16/34/5 14/35/5 13/36/5 +f 13/37/6 14/38/6 10/39/6 9/40/6 diff --git a/mods/nc_torch/models/src/nc_torch_torch.blend b/mods/nc_torch/models/src/nc_torch_torch.blend new file mode 100644 index 0000000..2a8330b Binary files /dev/null and b/mods/nc_torch/models/src/nc_torch_torch.blend differ diff --git a/mods/nc_torch/node.lua b/mods/nc_torch/node.lua new file mode 100644 index 0000000..0283e0e --- /dev/null +++ b/mods/nc_torch/node.lua @@ -0,0 +1,97 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore + = minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +minetest.register_node(modname .. ":torch", { + description = "Torch", + drawtype = "mesh", + mesh = "nc_torch_torch.obj", + tiles = { + "nc_fire_coal_4.png", + "nc_tree_tree_top.png", + "nc_fire_coal_4.png^[lowpart:50:nc_tree_tree_side.png", + "[combine:1x1" + }, + selection_box = nodecore.fixedbox(-1/16, -0.5, -1/16, 1/16, 6/16, 1/16), + collision_box = nodecore.fixedbox(-1/16, -0.5, -1/16, 1/16, 6/16, 1/16), + paramtype = "light", + sunlight_propagates = true, + groups = { + snappy = 1, + falling_repose = 1, + flammable = 1, + firestick = 3, + stack_as_node = 1 + }, + sounds = nodecore.sounds("nc_tree_sticky"), + on_ignite = function(pos) + minetest.set_node(pos, {name = modname .. ":torch_lit"}) + minetest.sound_play("nc_fire_ignite", {gain = 1, pos = pos}) + local expire = minetest.get_gametime() + nodecore.boxmuller() * 5 + 60 + minetest.get_meta(pos):set_float("expire", expire) + return true + end + }) + +nodecore.register_craft({ + label = "assemble torch", + normal = {y = 1}, + nodes = { + {match = "nc_fire:lump_coal", replace = "air"}, + {y = -1, match = "nc_woodwork:staff", replace = modname .. ":torch"}, + } + }) + +-- Note: Torch dropped as item is sort of unrealistic, perhaps drop as node in future +minetest.register_node(modname .. ":torch_lit", { + description = "Lit Torch", + drawtype = "mesh", + mesh = "nc_torch_torch.obj", + tiles = { + "nc_fire_coal_4.png^nc_fire_ember_4.png", + "nc_tree_tree_top.png", + "nc_fire_coal_4.png^nc_fire_ember_4.png^[lowpart:50:nc_tree_tree_side.png", + { + name = "nc_torch_flame.png", + animation = { + ["type"] = "vertical_frames", + aspect_w = 3, + aspect_h = 8, + length = 0.6 + } + } + }, + selection_box = nodecore.fixedbox(-1/16, -0.5, -1/16, 1/16, 6/16, 1/16), + collision_box = nodecore.fixedbox(-1/16, -0.5, -1/16, 1/16, 6/16, 1/16), + paramtype = "light", + sunlight_propagates = true, + light_source = 8, + groups = { + snappy = 1, + falling_repose = 1, + stack_as_node = 1 + }, + stack_max = 1, + sounds = nodecore.sounds("nc_tree_sticky"), + preserve_metadata = function(_, _, oldmeta, drops) + drops[1]:get_meta():set_float("expire", oldmeta.expire) + end, + after_place_node = function(pos, _, itemstack) + minetest.get_meta(pos):set_float("expire", + itemstack:get_meta():get_float("expire")) + end + }) + +minetest.register_node(modname .. ":wield_light", { + drawtype = "airlike", + paramtype = "light", + light_source = 8, + pointable = false, + walkable = false, + on_timer = function(pos) + minetest.set_node(pos, {name = "air"}) + end, + }) diff --git a/mods/nc_torch/textures/nc_torch_flame.png b/mods/nc_torch/textures/nc_torch_flame.png new file mode 100644 index 0000000..19a1d07 Binary files /dev/null and b/mods/nc_torch/textures/nc_torch_flame.png differ diff --git a/mods/nc_torch/wield.lua b/mods/nc_torch/wield.lua new file mode 100644 index 0000000..c5ac52c --- /dev/null +++ b/mods/nc_torch/wield.lua @@ -0,0 +1,92 @@ +-- LUALOCALS < --------------------------------------------------------- +local ItemStack, minetest, pairs, setmetatable, vector + = ItemStack, minetest, pairs, setmetatable, vector +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +local function islit(stack) + return stack and stack:get_name() == modname .. ":torch_lit" +end + +local function snuffinv(player, inv, i) + minetest.sound_play("nc_fire_snuff", {object = player, gain = 0.5}) + inv:set_stack("main", i, "nc_fire:lump_ash") +end + +local function wieldlight(pos) + local cur = minetest.get_node(pos).name + if cur ~= "air" and cur ~= modname .. ":wield_light" then return end + minetest.set_node(pos, {name = modname .. ":wield_light"}) + return minetest.get_node_timer(pos):start(0.3) +end + +local now +local wltimers = {} +local ambtimers = {} +minetest.register_globalstep(function(dt) + now = now or minetest.get_gametime() + now = now + dt + for _, player in pairs(minetest.get_connected_players()) do + local inv = player:get_inventory() + local ppos = player:get_pos() + + -- Snuff all torches if doused in water. + local hpos = vector.add(ppos, {x = 0, y = 1, z = 0}) + local head = minetest.get_node(hpos).name + if minetest.get_item_group(head, "water") > 0 then + for i = 1, inv:get_size("main") do + local stack = inv:get_stack("main", i) + if islit(stack) then snuffinv(player, inv, i) end + end + else + -- Snuff torches that have expired. + for i = 1, inv:get_size("main") do + local stack = inv:get_stack("main", i) + if islit(stack) and now > stack:get_meta() + :get_float("expire") then snuffinv(player, inv, i) end + end + + if islit(player:get_wielded_item()) then + -- Wield light + local name = player:get_player_name() + local t = wltimers[name] or 0 + if t <= now then + wltimers[name] = now + 0.2 + wieldlight(hpos) + end + + -- Wield ambiance + t = ambtimers[name] or 0 + if t <= now then + ambtimers[name] = now + 1 + minetest.sound_play("nc_fire_flamy", + {object = player, gain = 0.1}) + end + end + end + end + end) + +-- Apply wield light to entities as well. +local function entlight(self, dtime, ...) + local stack = ItemStack(self.node and self.node.name or self.itemstring or "") + if not islit(stack) then return ... end + local wltime = (self.wltime or 0) - dtime + if wltime <= 0 then + wltime = 0.2 + wieldlight(self.object:get_pos()) + end + self.wltime = wltime + return ... +end +for _, name in pairs({"item", "falling_node"}) do + local def = minetest.registered_entities["__builtin:" .. name] + local ndef = { + on_step = function(self, dtime, ...) + return entlight(self, dtime, def.on_step(self, dtime, ...)) + end + } + setmetatable(ndef, def) + minetest.register_entity(":__builtin:" .. name, ndef) +end diff --git a/mods/nc_tote/init.lua b/mods/nc_tote/init.lua new file mode 100644 index 0000000..fbe7542 --- /dev/null +++ b/mods/nc_tote/init.lua @@ -0,0 +1,137 @@ +-- LUALOCALS < --------------------------------------------------------- +local ItemStack, ipairs, minetest, nodecore, pairs, type + = ItemStack, ipairs, minetest, nodecore, pairs, type +-- LUALOCALS > --------------------------------------------------------- + +nodecore.amcoremod() + +local modname = minetest.get_current_modname() + +local metadescs = { + "Tote (1 Slot)", + "Tote (2 Slots)", + "Tote (3 Slots)", + "Tote (4 Slots)", + "Tote (5 Slots)", + "Tote (6 Slots)", + "Tote (7 Slots)", + "Tote (8 Slots)", +} + +local function totedug(pos, _, _, digger) + local dump + for dx = -1, 1 do + for dz = -1, 1 do + local p = {x = pos.x + dx, y = pos.y, z = pos.z + dz} + local n = minetest.get_node(p) + local d = minetest.registered_items[n.name] or {} + if d and d.groups and d.groups.totable then + local m = minetest.get_meta(p):to_table() + for _, v1 in pairs(m.inventory or {}) do + for k2, v2 in pairs(v1) do + if type(v2) == "userdata" then + v1[k2] = v2:to_string() + end + end + end + dump = dump or {} + dump[#dump + 1] = { + x = dx, + z = dz, + n = n, + m = m + } + minetest.remove_node(p) + end + end + end + local drop = ItemStack(modname .. ":handle") + if dump then + local meta = drop:get_meta() + meta:set_string("carrying", minetest.serialize(dump)) + meta:set_string("description", metadescs[#dump]) + end + minetest.handle_node_drops(pos, {drop}, digger) +end + +local function toteplace(stack, _, pointed) + local pos = nodecore.buildable_to(pointed.under) and pointed.under + or nodecore.buildable_to(pointed.above) and pointed.above + if not pos then return stack end + + stack = ItemStack(stack) + local inv = stack:get_meta():get_string("carrying") + inv = inv and (inv ~= "") and minetest.deserialize(inv) + if not inv then + minetest.set_node(pos, {name = stack:get_name()}) + stack:set_count(stack:get_count() - 1) + return stack + end + + local commit = {{pos, {name = stack:get_name()}, {}}} + for _, v in ipairs(inv) do + if commit then + local p = {x = pos.x + v.x, y = pos.y, z = pos.z + v.z} + if not nodecore.buildable_to(p) then + commit = nil + else + commit[#commit + 1] = {p, v.n, v.m} + end + end + end + if commit then + for _, v in ipairs(commit) do + minetest.set_node(v[1], v[2]) + minetest.get_meta(v[1]):from_table(v[3]) + end + stack:set_count(stack:get_count() - 1) + end + return stack +end + +minetest.register_node(modname .. ":handle", { + description = "Tote Handle", + meta_descriptions = metadescs, + drawtype = "nodebox", + node_box = nodecore.fixedbox( + {-0.5, -0.5, -0.5, 0.5, -3/8, 0.5}, + {-0.5, -3/8, -0.5, -3/8, 3/8, -3/8}, + {-0.5, -3/8, 3/8, -3/8, 3/8, 0.5}, + {3/8, -3/8, -0.5, 0.5, 3/8, -3/8}, + {3/8, -3/8, 3/8, 0.5, 3/8, 0.5}, + {-0.5, 1/4, -0.5, -3/8, 3/8, 0.5}, + {3/8, 1/4, -0.5, 0.5, 3/8, 0.5}, + {-0.5, 3/8, -1/8, 0.5, 0.5, 1/8} + ), + selection_box = nodecore.fixedbox(), + paramtype = "light", + tiles = { + "nc_lode_annealed.png", + "nc_lode_annealed.png", + "nc_lode_annealed.png^[lowpart:75:nc_tree_tree_side.png" + .. "^[lowpart:12.5:nc_lode_annealed.png" + }, + groups = { + snappy = 1, + container = 1, + fire_fuel = 5 + }, + stack_max = 1, + after_dig_node = totedug, + on_place = toteplace, + drop = "", + sounds = nodecore.sounds("nc_lode_annealed") + }) + +nodecore.register_craft({ + label = "craft tote handle", + norotate = true, + nodes = { + {match = "nc_woodwork:frame", replace = "air"}, + {y = -1, match = "nc_lode:block_annealed", replace = modname .. ":handle"}, + {y = -1, x = 1, match = "nc_woodwork:shelf"}, + {y = -1, x = -1, match = "nc_woodwork:shelf"}, + {y = -1, z = 1, match = "nc_woodwork:shelf"}, + {y = -1, z = -1, match = "nc_woodwork:shelf"}, + } + }) diff --git a/mods/nc_tote/mod.conf b/mods/nc_tote/mod.conf new file mode 100644 index 0000000..97258f5 --- /dev/null +++ b/mods/nc_tote/mod.conf @@ -0,0 +1,2 @@ +name = nc_tote +depends = nc_api, nc_api_craft, nc_lode, nc_tree, nc_woodwork diff --git a/mods/nc_tree/ambiance.lua b/mods/nc_tree/ambiance.lua new file mode 100644 index 0000000..05af390 --- /dev/null +++ b/mods/nc_tree/ambiance.lua @@ -0,0 +1,20 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore + = minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +nodecore.register_ambiance({ + label = "Tree Leaves Ambiance", + nodenames = {"nc_tree:leaves"}, + neigbors = {"air"}, + interval = 1, + chance = 100, + sound_name = "nc_tree_breeze", + check = function(pos) + pos.y = pos.y + 1 + if pos.y <= 0 then return end + return minetest.get_node(pos).name == "air" + and minetest.get_node_light(pos, 0.5) == 15 + and { gain = nodecore.windiness(pos.y) / 20 } + end + }) diff --git a/mods/nc_tree/api.lua b/mods/nc_tree/api.lua new file mode 100644 index 0000000..c94e883 --- /dev/null +++ b/mods/nc_tree/api.lua @@ -0,0 +1,45 @@ +-- LUALOCALS < --------------------------------------------------------- +local ipairs, math, minetest, nodecore + = ipairs, math, minetest, nodecore +local math_sqrt + = math.sqrt +-- LUALOCALS > --------------------------------------------------------- + +nodecore.register_leaf_drops, nodecore.registered_leaf_drops += nodecore.mkreg() + +function nodecore.leaf_decay(pos, node) + node = node or minetest.get_node(pos) + local t = {} + for _, v in ipairs(nodecore.registered_leaf_drops) do + t = v(pos, node, t) or t + end + local p = nodecore.pickrand(t, function(x) return x.prob end) + if not p then return end + minetest.set_node(pos, p) + if p.item then nodecore.item_eject(pos, p.item) end + return nodecore.fallcheck(pos) +end + +function nodecore.tree_growth_rate(pos) + local d = 1 + local w = 1 + nodecore.scan_flood(pos, 3, function(p, r) + if r < 1 then return end + local nn = minetest.get_node(p).name + local def = minetest.registered_items[nn] or {} + if not def.groups then + return false + end + if def.groups.soil then + d = d + def.groups.soil + w = w + 0.2 + elseif def.groups.moist then + w = w + def.groups.moist + return false + else + return false + end + end) + return math_sqrt(d * w)*100 +end diff --git a/mods/nc_tree/compost.lua b/mods/nc_tree/compost.lua new file mode 100644 index 0000000..964af0d --- /dev/null +++ b/mods/nc_tree/compost.lua @@ -0,0 +1,68 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore + = minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +minetest.register_node(modname .. ":humus", { + description = "Humus", + tiles = {modname .. "_humus.png"}, + groups = { + dirt = 2, + crumbly = 1, + soil = 4 + }, + alternate_loose = { + groups = { + dirt_loose = 2, + soil = 5 + } + }, + crush_damage = 1, + sounds = nodecore.sounds("nc_terrain_crunchy") + }) + +minetest.register_node(modname .. ":peat", { + description = "Peat", + tiles = {modname .. "_humus.png^" .. modname .. "_peat.png^nc_api_loose.png"}, + groups = { + falling_repose = 1, + crumbly = 1, + flammable = 1, + fire_fuel = 3, + moist = 1, + green = 1 + }, + crush_damage = 1, + sounds = nodecore.sounds("nc_terrain_swishy") + }) + +nodecore.register_craft({ + label = "compress peat block", + action = "pummel", + toolgroups = {crumbly = 1}, + nodes = { + { + match = {name = modname .. ":leaves_loose", count = 8}, + replace = modname .. ":peat" + } + } + }) + +nodecore.register_soaking_abm({ + label = "Composting Growing", + nodenames = {modname .. ":peat"}, + neighbors = {"group:soil"}, + interval = 10, + chance = 1, + limited_max = 100, + limited_alert = 1000, + soakrate = nodecore.tree_growth_rate, + soakcheck = function(data, pos) + if data.total < 2500 then return end + minetest.get_meta(pos):from_table({}) + minetest.set_node(pos, {name = modname .. ":humus"}) + nodecore.node_sound(pos, "place") + end + }) diff --git a/mods/nc_tree/cultivation.lua b/mods/nc_tree/cultivation.lua new file mode 100644 index 0000000..3eb18e0 --- /dev/null +++ b/mods/nc_tree/cultivation.lua @@ -0,0 +1,158 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore, pairs, vector + = minetest, nodecore, pairs, vector +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +local ldname = "nc_terrain:dirt_loose" +local epname = modname .. ":eggcorn_planted" + +minetest.register_node(modname .. ":eggcorn", { + description = "Eggcorn", + drawtype = "plantlike", + paramtype = "light", + visual_scale = 0.5, + wield_scale = {x = 0.75, y = 0.75, z = 1.5}, + collision_box = nodecore.fixedbox(-3/16, -0.5, -3/16, 3/16, 0, 3/16), + selection_box = nodecore.fixedbox(-3/16, -0.5, -3/16, 3/16, 0, 3/16), + inventory_image = "[combine:24x24:4,4=" .. modname .. "_eggcorn.png", + tiles = { modname .. "_eggcorn.png" }, + groups = { + snappy = 1, + flammable = 3, + attached_node = 1, + }, + node_placement_prediction = "", + place_as_item = true, + sounds = nodecore.sounds("nc_tree_corny"), + stack_rightclick = function(pos, _, whom, stack) + if nodecore.stack_get(pos):get_count() ~= 1 then return end + local def = minetest.registered_items[stack:get_name()] + if (not def) or (not def.groups) or (not def.groups.dirt_loose) then return end + + minetest.set_node(pos, {name = epname}) + nodecore.node_sound(pos, "place") + + if nodecore.player_stat_add then + nodecore.player_stat_add(1, whom, "craft", "eggcorn planting") + end + minetest.log((whom and whom:get_player_name() or "unknown") + .. " planted an eggcorn at " .. minetest.pos_to_string(pos)) + + stack:set_count(stack:get_count() - 1) + return stack + end + }) + +nodecore.register_limited_abm({ + interval = 1, + chance = 1, + nodenames = {modname .. ":eggcorn"}, + action = function(pos) + minetest.remove_node(pos) + return nodecore.place_stack(pos, modname .. ":eggcorn") + end + }) + +nodecore.register_leaf_drops(function(_, node, list) + list[#list + 1] = { + name = "air", + item = modname .. ":eggcorn", + prob = 0.05 * (node.param2 + 1)} + end) + +local epdef = nodecore.underride({drop = ldname}, minetest.registered_items[ldname] or {}) +epdef.groups.soil = nil +minetest.register_node(epname, epdef) + +local function growthcheck(pos) + local anode = minetest.get_node({x = pos.x, y = pos.y + 1, z = pos.z}) + if anode.name ~= "air" then return 0 end + return nodecore.tree_growth_rate(pos) +end + +local function growtree(pos) + minetest.sound_play("nc_tree_woody", {pos = pos, gain = 5}) + for _ = 1, 4 do + minetest.sound_play("nc_terrain_swishy", {pos = pos, gain = 3}) + end + local leaves = {} + for i = 1, 8 do + local p = {x = pos.x, y = pos.y + i, z = pos.z} + local n = minetest.get_node(p) + if n.name == modname .. ":leaves" then + leaves[p] = n + minetest.remove_node(p) + else + local def = minetest.registered_nodes[n.name] + if def and def.buildable_to then + leaves[p] = n + minetest.remove_node(p) + end + end + end + local place = {x = pos.x - 2, y = pos.y, z = pos.z - 2} + minetest.get_meta(pos):from_table({}) + minetest.place_schematic(place, nodecore.tree_schematic, + "random", {}, false) + for p, n in pairs(leaves) do + if minetest.get_node(p).name == "air" then + minetest.set_node(p, n) + end + end +end + +minetest.register_chatcommand("growtrees", { + description = "Instantly grow nearby trees", + privs = { ["debug"] = true }, + func = function(pname) + local player = minetest.get_player_by_name(pname) + if not player then return end + local pos = player:get_pos() + local range = {x = 5, y = 5, z = 5} + local min = vector.subtract(pos, range) + local max = vector.add(pos, range) + for _, p in pairs(minetest.find_nodes_in_area(min, max, {epname})) do + local r = growthcheck(p) + if r and r > 0 then growtree(p) end + end + end + }) + +nodecore.register_soaking_abm({ + label = "EggCorn Growing", + nodenames = {epname}, + interval = 10, + chance = 1, + limited_max = 100, + limited_alert = 1000, + qtyfield = "growth", + timefield = "start", + soakrate = growthcheck, + soakcheck = function(data, pos) + if data.total >= 5000 then return growtree(pos) end + local zero = {x = 0, y = 0, z = 0} + nodecore.digparticles(minetest.registered_items[modname .. ":leaves"], + { + amount = data.rate, + time = 10, + minpos = { + x = pos.x - 0.3, + y = pos.y + 33/64, + z = pos.z - 0.3 + }, + maxpos = { + x = pos.x + 0.3, + y = pos.y + 33/64, + z= pos.z + 0.3 + }, + minvel = zero, + maxvel = zero, + minexptime = 0.1, + maxexptime = 0.5, + minsize = 1, + maxsize = 3, + }) + end + }) diff --git a/mods/nc_tree/decor.lua b/mods/nc_tree/decor.lua new file mode 100644 index 0000000..bb62bb9 --- /dev/null +++ b/mods/nc_tree/decor.lua @@ -0,0 +1,25 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore + = minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +minetest.register_decoration({ + deco_type = "schematic", + place_on = {"nc_terrain:dirt_with_grass"}, + sidelen = 16, + noise_params = { + offset = -0.008, + scale = 0.016, + spread = {x = 120, y = 120, z = 120}, + seed = 2, + octaves = 3, + persist = 0.66 + }, + biomes = {"unknown"}, + y_min = 1, + y_max = 31000, + schematic = nodecore.tree_schematic, + flags = "place_center_x, place_center_z", + rotation = "random", + replacements = { } + }) diff --git a/mods/nc_tree/init.lua b/mods/nc_tree/init.lua new file mode 100644 index 0000000..ab8c70b --- /dev/null +++ b/mods/nc_tree/init.lua @@ -0,0 +1,19 @@ +-- LUALOCALS < --------------------------------------------------------- +local include, nodecore + = include, nodecore +-- LUALOCALS > --------------------------------------------------------- + +nodecore.amcoremod() + +include("api") +include("node") +include("leafdecay") +include("compost") + +include("stick") + +include("schematic") +include("decor") +include("cultivation") + +include("ambiance") diff --git a/mods/nc_tree/leafdecay.lua b/mods/nc_tree/leafdecay.lua new file mode 100644 index 0000000..1749b1d --- /dev/null +++ b/mods/nc_tree/leafdecay.lua @@ -0,0 +1,31 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore + = minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +nodecore.register_limited_abm({ + label = "Leaf Decay", + interval = 1, + chance = 10, + limited_max = 100, + limited_alert = 1000, + nodenames = {modname .. ":leaves"}, + action = function(pos) + if not nodecore.scan_flood(pos, 5, function(p) + local n = minetest.get_node(p).name + if n == modname .. ":tree" + or n == "ignore" then + return true + end + if n == modname .. ":leaves" then + return + end + return false + end + ) then + nodecore.leaf_decay(pos) + end + end + }) diff --git a/mods/nc_tree/mod.conf b/mods/nc_tree/mod.conf new file mode 100644 index 0000000..3cccab3 --- /dev/null +++ b/mods/nc_tree/mod.conf @@ -0,0 +1,2 @@ +name = nc_tree +depends = nc_api, nc_api_craft, nc_items, nc_terrain diff --git a/mods/nc_tree/node.lua b/mods/nc_tree/node.lua new file mode 100644 index 0000000..e236393 --- /dev/null +++ b/mods/nc_tree/node.lua @@ -0,0 +1,73 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore + = minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +minetest.register_node(modname .. ":root", { + description = "Stump", + tiles = { + modname .. "_tree_top.png", + "nc_terrain_dirt.png", + "nc_terrain_dirt.png^" .. modname .. "_roots.png" + }, + silktouch = false, + groups = { + flammable = 50, + fire_fuel = 4, + choppy = 4 + }, + drop = "nc_tree:stick 8", + sounds = nodecore.sounds("nc_tree_woody") + }) + +minetest.register_node(modname .. ":tree", { + description = "Tree Trunk", + tiles = { + modname .. "_tree_top.png", + modname .. "_tree_top.png", + modname .. "_tree_side.png" + }, + groups = { + choppy = 2, + flammable = 8, + fire_fuel = 6 + }, + sounds = nodecore.sounds("nc_tree_woody") + }) + +minetest.register_node(modname .. ":leaves", { + description = "Leaves", + drawtype = "allfaces_optional", + paramtype = "light", + tiles = { modname .. "_leaves.png" }, + waving = 1, + groups = { + snappy = 1, + flammable = 3, + fire_fuel = 2, + green = 3 + }, + alternate_loose = { + tiles = { modname .. "_leaves_dry.png" }, + walkable = false, + groups = { + flammable = 1, + falling_repose = 1, + green = 1, + stack_as_node = 1 + } + }, + alternate_solid = { + after_dig_node = function(...) + return nodecore.leaf_decay(...) + end, + node_dig_prediction = "air" + }, + sounds = nodecore.sounds("nc_terrain_swishy") + }) +nodecore.register_leaf_drops(function(_, _, list) + list[#list + 1] = {name = modname .. ":leaves_loose", prob = 0.5} + list[#list + 1] = {name = "air"} + end) diff --git a/mods/nc_tree/schematic.lua b/mods/nc_tree/schematic.lua new file mode 100644 index 0000000..26cb3bd --- /dev/null +++ b/mods/nc_tree/schematic.lua @@ -0,0 +1,83 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore + = minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +local root = { + ".....", + ".....", + "..r..", + ".....", + ".....", +} +local trunk = { + ".....", + ".....", + "..t..", + ".....", + ".....", +} +local bot = { + ".....", + ".ebe.", + ".btb.", + ".ebe.", + ".....", +} +local low = { + ".lll.", + "lebel", + "lbtbl", + "lebel", + ".lll.", +} +local hi = { + ".lll.", + "llell", + "lebel", + "llell", + ".lll.", +} +local top = { + ".....", + ".lll.", + ".lll.", + ".lll.", + ".....", +} + +nodecore.tree_schematic = nodecore.ezschematic( + { + ["."] = {name = "air", prob = 0}, + r = {name = modname .. ":root", prob = 255, force_place = true}, + t = {name = modname .. ":tree", prob = 255}, + b = {name = modname .. ":leaves", param2 = 2, prob = 255}, + e = {name = modname .. ":leaves", param2 = 1,prob = 255}, + l = {name = modname .. ":leaves", prob = 240}, + }, + { + root, + trunk, + trunk, + trunk, + bot, + low, + low, + hi, + top + }, + { + yslice_prob = { + {ypos = 1, prob = 255}, + {ypos = 2, prob = 160}, + {ypos = 3, prob = 160}, + {ypos = 4, prob = 160}, + {ypos = 5, prob = 255}, + {ypos = 6, prob = 160}, + {ypos = 7, prob = 160}, + {ypos = 8, prob = 255}, + } + } +) diff --git a/mods/nc_tree/sounds/nc_tree_breeze.0.ogg b/mods/nc_tree/sounds/nc_tree_breeze.0.ogg new file mode 100644 index 0000000..326be9a Binary files /dev/null and b/mods/nc_tree/sounds/nc_tree_breeze.0.ogg differ diff --git a/mods/nc_tree/sounds/nc_tree_breeze.1.ogg b/mods/nc_tree/sounds/nc_tree_breeze.1.ogg new file mode 100644 index 0000000..ac49b91 Binary files /dev/null and b/mods/nc_tree/sounds/nc_tree_breeze.1.ogg differ diff --git a/mods/nc_tree/sounds/nc_tree_breeze.2.ogg b/mods/nc_tree/sounds/nc_tree_breeze.2.ogg new file mode 100644 index 0000000..1df5b83 Binary files /dev/null and b/mods/nc_tree/sounds/nc_tree_breeze.2.ogg differ diff --git a/mods/nc_tree/sounds/nc_tree_corny.0.ogg b/mods/nc_tree/sounds/nc_tree_corny.0.ogg new file mode 100644 index 0000000..6a0e431 Binary files /dev/null and b/mods/nc_tree/sounds/nc_tree_corny.0.ogg differ diff --git a/mods/nc_tree/sounds/nc_tree_corny.1.ogg b/mods/nc_tree/sounds/nc_tree_corny.1.ogg new file mode 100644 index 0000000..7871763 Binary files /dev/null and b/mods/nc_tree/sounds/nc_tree_corny.1.ogg differ diff --git a/mods/nc_tree/sounds/nc_tree_corny.2.ogg b/mods/nc_tree/sounds/nc_tree_corny.2.ogg new file mode 100644 index 0000000..6e6dc93 Binary files /dev/null and b/mods/nc_tree/sounds/nc_tree_corny.2.ogg differ diff --git a/mods/nc_tree/sounds/nc_tree_sticky.0.ogg b/mods/nc_tree/sounds/nc_tree_sticky.0.ogg new file mode 100644 index 0000000..07f3944 Binary files /dev/null and b/mods/nc_tree/sounds/nc_tree_sticky.0.ogg differ diff --git a/mods/nc_tree/sounds/nc_tree_sticky.1.ogg b/mods/nc_tree/sounds/nc_tree_sticky.1.ogg new file mode 100644 index 0000000..910a66e Binary files /dev/null and b/mods/nc_tree/sounds/nc_tree_sticky.1.ogg differ diff --git a/mods/nc_tree/sounds/nc_tree_woody.0.ogg b/mods/nc_tree/sounds/nc_tree_woody.0.ogg new file mode 100644 index 0000000..75e7e49 Binary files /dev/null and b/mods/nc_tree/sounds/nc_tree_woody.0.ogg differ diff --git a/mods/nc_tree/sounds/nc_tree_woody.1.ogg b/mods/nc_tree/sounds/nc_tree_woody.1.ogg new file mode 100644 index 0000000..dd94ddb Binary files /dev/null and b/mods/nc_tree/sounds/nc_tree_woody.1.ogg differ diff --git a/mods/nc_tree/sounds/nc_tree_woody.2.ogg b/mods/nc_tree/sounds/nc_tree_woody.2.ogg new file mode 100644 index 0000000..11c4488 Binary files /dev/null and b/mods/nc_tree/sounds/nc_tree_woody.2.ogg differ diff --git a/mods/nc_tree/sounds/nc_tree_woody.3.ogg b/mods/nc_tree/sounds/nc_tree_woody.3.ogg new file mode 100644 index 0000000..7f65b7a Binary files /dev/null and b/mods/nc_tree/sounds/nc_tree_woody.3.ogg differ diff --git a/mods/nc_tree/stick.lua b/mods/nc_tree/stick.lua new file mode 100644 index 0000000..6e1f85b --- /dev/null +++ b/mods/nc_tree/stick.lua @@ -0,0 +1,33 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore + = minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +minetest.register_node(modname .. ":stick", { + description = "Stick", + drawtype = "nodebox", + node_box = nodecore.fixedbox(-1/16, -0.5, -1/16, 1/16, 0, 1/16), + tiles = { + modname .. "_tree_top.png", + modname .. "_tree_top.png", + modname .. "_tree_side.png" + }, + paramtype = "light", + sunlight_propagates = true, + groups = { + firestick = 1, + snappy = 1, + flammable = 2, + falling_repose = 1, + stack_as_node = 1 + }, + sounds = nodecore.sounds("nc_tree_sticky") + }) + +nodecore.register_leaf_drops(function(_, node, list) + list[#list + 1] = { + name = modname .. ":stick", + prob = 0.2 * (node.param2 * node.param2)} + end) diff --git a/mods/nc_tree/textures/nc_tree_eggcorn.png b/mods/nc_tree/textures/nc_tree_eggcorn.png new file mode 100644 index 0000000..479b515 Binary files /dev/null and b/mods/nc_tree/textures/nc_tree_eggcorn.png differ diff --git a/mods/nc_tree/textures/nc_tree_humus.png b/mods/nc_tree/textures/nc_tree_humus.png new file mode 100644 index 0000000..9e2c9f2 Binary files /dev/null and b/mods/nc_tree/textures/nc_tree_humus.png differ diff --git a/mods/nc_tree/textures/nc_tree_leaves.png b/mods/nc_tree/textures/nc_tree_leaves.png new file mode 100644 index 0000000..b9a07c5 Binary files /dev/null and b/mods/nc_tree/textures/nc_tree_leaves.png differ diff --git a/mods/nc_tree/textures/nc_tree_leaves_dry.png b/mods/nc_tree/textures/nc_tree_leaves_dry.png new file mode 100644 index 0000000..ab91dff Binary files /dev/null and b/mods/nc_tree/textures/nc_tree_leaves_dry.png differ diff --git a/mods/nc_tree/textures/nc_tree_peat.png b/mods/nc_tree/textures/nc_tree_peat.png new file mode 100644 index 0000000..124896b Binary files /dev/null and b/mods/nc_tree/textures/nc_tree_peat.png differ diff --git a/mods/nc_tree/textures/nc_tree_roots.png b/mods/nc_tree/textures/nc_tree_roots.png new file mode 100644 index 0000000..1daff94 Binary files /dev/null and b/mods/nc_tree/textures/nc_tree_roots.png differ diff --git a/mods/nc_tree/textures/nc_tree_tree_side.png b/mods/nc_tree/textures/nc_tree_tree_side.png new file mode 100644 index 0000000..a874efa Binary files /dev/null and b/mods/nc_tree/textures/nc_tree_tree_side.png differ diff --git a/mods/nc_tree/textures/nc_tree_tree_top.png b/mods/nc_tree/textures/nc_tree_tree_top.png new file mode 100644 index 0000000..a92907a Binary files /dev/null and b/mods/nc_tree/textures/nc_tree_tree_top.png differ diff --git a/mods/nc_woodwork/adze.lua b/mods/nc_woodwork/adze.lua new file mode 100644 index 0000000..3b606fc --- /dev/null +++ b/mods/nc_woodwork/adze.lua @@ -0,0 +1,30 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore + = minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +minetest.register_tool(modname .. ":adze", { + description = "Wooden Adze", + inventory_image = modname .. "_adze.png", + groups = { + flammable = 2 + }, + tool_capabilities = nodecore.toolcaps({ + choppy = 1 + }), + sounds = nodecore.sounds("nc_tree_sticky") + }) + +nodecore.register_craft({ + label = "assemble wood adze", + normal = {y = 1}, + nodes = { + {match = "nc_tree:stick", replace = "air"}, + {y = -1, match = modname .. ":staff", replace = "air"}, + }, + items = { + {y = -1, name = modname .. ":adze"} + } + }) diff --git a/mods/nc_woodwork/init.lua b/mods/nc_woodwork/init.lua new file mode 100644 index 0000000..b0f5ec1 --- /dev/null +++ b/mods/nc_woodwork/init.lua @@ -0,0 +1,13 @@ +-- LUALOCALS < --------------------------------------------------------- +local include, nodecore + = include, nodecore +-- LUALOCALS > --------------------------------------------------------- + +nodecore.amcoremod() + +include("adze") +include("plank") +include("staff") +include("tools") +include("ladder") +include("shelf") diff --git a/mods/nc_woodwork/ladder.lua b/mods/nc_woodwork/ladder.lua new file mode 100644 index 0000000..79fae3e --- /dev/null +++ b/mods/nc_woodwork/ladder.lua @@ -0,0 +1,75 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore + = minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +local lt = 1/16 +local lw = 3/16 +local ll = 1/2 + +local tt = "nc_tree_tree_side.png^(nc_tree_tree_top.png^[mask:nc_woodwork_ladder_mask.png)" + +minetest.register_node(modname .. ":ladder", { + description = "Wooden Ladder", + drawtype = "nodebox", + node_box = nodecore.fixedbox( + {-lt, -ll, -lt, lt, ll, lt}, + {-lw, -lt, -lt, lw, lt, lt}, + {-lt, -lt, -lw, lt, lt, lw} + ), + tiles = {tt}, + groups = { + snappy = 1, + flammable = 2, + fire_fuel = 1, + falling_node = 1, + stack_as_node = 1 + }, + crush_damage = 0.25, + paramtype = "light", + sunlight_propagates = true, + climbable = true, + sounds = nodecore.sounds("nc_tree_sticky") + + }) + +nodecore.register_craft({ + label = "assemble wood ladder", + normal = {x = 1}, + nodes = { + {match = "nc_tree:stick", replace = "air"}, + {x = -1, match = modname .. ":staff", replace = modname .. ":ladder"}, + } + }) + +minetest.register_node(modname .. ":frame", { + description = "Wooden Frame", + drawtype = "nodebox", + node_box = nodecore.fixedbox( + {-lt, -ll, -lt, lt, ll, lt}, + {-ll, -lt, -lt, ll, lt, lt}, + {-lt, -lt, -ll, lt, lt, ll} + ), + tiles = {tt}, + groups = { + snappy = 1, + flammable = 2, + fire_fuel = 1, + stack_as_node = 1 + }, + paramtype = "light", + climbable = true, + sunlight_propagates = true, + sounds = nodecore.sounds("nc_tree_sticky") + }) + +nodecore.register_craft({ + label = "assemble wood frame", + normal = {x = 1}, + nodes = { + {match = modname .. ":staff", replace = "air"}, + {x = -1, match = modname .. ":staff", replace = modname .. ":frame"}, + } + }) diff --git a/mods/nc_woodwork/mod.conf b/mods/nc_woodwork/mod.conf new file mode 100644 index 0000000..f26972d --- /dev/null +++ b/mods/nc_woodwork/mod.conf @@ -0,0 +1,2 @@ +name = nc_woodwork +depends = nc_api, nc_api_craft, nc_items, nc_tree diff --git a/mods/nc_woodwork/plank.lua b/mods/nc_woodwork/plank.lua new file mode 100644 index 0000000..e8ae501 --- /dev/null +++ b/mods/nc_woodwork/plank.lua @@ -0,0 +1,44 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore + = minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +local plank = modname .. ":plank" +minetest.register_node(plank, { + description = "Wooden Plank", + tiles = { modname .. "_plank.png" }, + groups = { + choppy = 1, + flammable = 2, + fire_fuel = 5 + }, + sounds = nodecore.sounds("nc_tree_woody") + }) + +nodecore.register_craft({ + label = "split tree to planks", + action = "pummel", + toolgroups = {choppy = 1}, + normal = {y = 1}, + nodes = { + {match = "nc_tree:tree", replace = "air"} + }, + items = { + {name = plank, count = 4, scatter = 5} + } + }) + +nodecore.register_craft({ + label = "bash planks to sticks", + action = "pummel", + toolgroups = {thumpy = 3}, + normal = {y = 1}, + nodes = { + {match = plank, replace = "air"} + }, + items = { + {name = "nc_tree:stick 2", count = 4, scatter = 5} + } + }) diff --git a/mods/nc_woodwork/shelf.lua b/mods/nc_woodwork/shelf.lua new file mode 100644 index 0000000..67d891f --- /dev/null +++ b/mods/nc_woodwork/shelf.lua @@ -0,0 +1,103 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore + = minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +local side = "nc_tree_tree_side.png" +local top = side .. "^(" .. modname .. "_plank.png^[mask:" +.. modname .. "_shelf.png)" + +local function doplace(stack, clicker, pointed_thing, ...) + local function helper(left, ok, ...) + if ok then nodecore.node_sound(pointed_thing.above, "place") end + return left, ok, ... + end + return helper(minetest.item_place_node(stack, clicker, pointed_thing, ...)) +end + +minetest.register_node(modname .. ":shelf", { + description = "Wooden Shelf", + drawtype = "nodebox", + node_box = nodecore.fixedbox( + {-0.5, -0.5, -0.5, 0.5, -7/16, 0.5}, + {-0.5, 7/16, -0.5, 0.5, 0.5, 0.5}, + {-0.5, -7/16, -0.5, -7/16, 7/16, -7/16}, + {-0.5, -7/16, 7/16, -7/16, 7/16, 0.5}, + {7/16, -7/16, -0.5, 0.5, 7/16, -7/16}, + {7/16, -7/16, 7/16, 0.5, 7/16, 0.5} + ), + selection_box = nodecore.fixedbox(), + collision_box = nodecore.fixedbox(), + tiles = { top, top, side }, + groups = { + choppy = 1, + visinv = 1, + flammable = 2, + fire_fuel = 3, + container = 1, + totable = 1 + }, + paramtype = "light", + sounds = nodecore.sounds("nc_tree_woody"), + on_construct = function(pos) + local inv = minetest.get_meta(pos):get_inventory() + inv:set_size("solo", 1) + nodecore.visinv_update_ents(pos) + end, + on_rightclick = function(pos, _, clicker, stack, pointed_thing) + if not nodecore.interact(clicker) then return end + if pointed_thing.above.y ~= pointed_thing.under.y then + return doplace(stack, clicker, pointed_thing) + end + if not stack or stack:is_empty() then return end + local def = minetest.registered_items[stack:get_name()] or {} + if def.groups and def.groups.container then + return doplace(stack, clicker, pointed_thing) + end + return nodecore.stack_add(pos, stack) + end, + on_punch = function(pos, node, puncher, pointed_thing, ...) + minetest.node_punch(pos, node, puncher, pointed_thing, ...) + if not nodecore.interact(puncher) then return end + if pointed_thing.above.y ~= pointed_thing.under.y then return end + return nodecore.stack_giveto(pos, puncher) + end, + on_dig = function(pos, node, digger, ...) + if nodecore.stack_giveto(pos, digger) then + return minetest.node_dig(pos, node, digger, ...) + end + end, + on_ignite = function(pos) + return nodecore.stack_get(pos) + end, + stack_allow = function(_, _, stack) + local def = minetest.registered_items[stack:get_name()] or {} + if def.groups and def.groups.container then return false end + end + }) + +nodecore.register_craft({ + label = "assemble wood shelf", + norotate = true, + nodes = { + {match = modname .. ":plank", replace = "air"}, + {x = -1, z = -1, match = modname .. ":frame", replace = modname .. ":shelf"}, + {x = 1, z = -1, match = modname .. ":frame", replace = modname .. ":shelf"}, + {x = -1, z = 1, match = modname .. ":frame", replace = modname .. ":shelf"}, + {x = 1, z = 1, match = modname .. ":frame", replace = modname .. ":shelf"}, + } + }) + +nodecore.register_craft({ + label = "assemble wood shelf", + norotate = true, + nodes = { + {match = modname .. ":plank", replace = "air"}, + {x = 0, z = -1, match = modname .. ":frame", replace = modname .. ":shelf"}, + {x = 0, z = 1, match = modname .. ":frame", replace = modname .. ":shelf"}, + {x = -1, z = 0, match = modname .. ":frame", replace = modname .. ":shelf"}, + {x = 1, z = 0, match = modname .. ":frame", replace = modname .. ":shelf"}, + } + }) diff --git a/mods/nc_woodwork/staff.lua b/mods/nc_woodwork/staff.lua new file mode 100644 index 0000000..8ede182 --- /dev/null +++ b/mods/nc_woodwork/staff.lua @@ -0,0 +1,37 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore + = minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +minetest.register_node(modname .. ":staff", { + description = "Staff", + drawtype = "nodebox", + node_box = nodecore.fixedbox(-1/16, -0.5, -1/16, 1/16, 0.5, 1/16), + oldnames = {"nc_tree:staff"}, + tiles = { + "nc_tree_tree_top.png", + "nc_tree_tree_top.png", + "nc_tree_tree_side.png" + }, + paramtype = "light", + sunlight_propagates = true, + groups = { + firestick = 2, + snappy = 1, + flammable = 2, + falling_repose = 2, + stack_as_node = 1 + }, + sounds = nodecore.sounds("nc_tree_sticky") + }) + +nodecore.register_craft({ + label = "assemble staff", + normal = {y = 1}, + nodes = { + {match = "nc_tree:stick", replace = "air"}, + {y = -1, match = "nc_tree:stick", replace = modname .. ":staff"} + } + }) diff --git a/mods/nc_woodwork/textures/nc_woodwork_adze.png b/mods/nc_woodwork/textures/nc_woodwork_adze.png new file mode 100644 index 0000000..0a3efcb Binary files /dev/null and b/mods/nc_woodwork/textures/nc_woodwork_adze.png differ diff --git a/mods/nc_woodwork/textures/nc_woodwork_ladder_mask.png b/mods/nc_woodwork/textures/nc_woodwork_ladder_mask.png new file mode 100644 index 0000000..5b9e501 Binary files /dev/null and b/mods/nc_woodwork/textures/nc_woodwork_ladder_mask.png differ diff --git a/mods/nc_woodwork/textures/nc_woodwork_plank.png b/mods/nc_woodwork/textures/nc_woodwork_plank.png new file mode 100644 index 0000000..2062d7b Binary files /dev/null and b/mods/nc_woodwork/textures/nc_woodwork_plank.png differ diff --git a/mods/nc_woodwork/textures/nc_woodwork_shelf.png b/mods/nc_woodwork/textures/nc_woodwork_shelf.png new file mode 100644 index 0000000..f854028 Binary files /dev/null and b/mods/nc_woodwork/textures/nc_woodwork_shelf.png differ diff --git a/mods/nc_woodwork/textures/nc_woodwork_tool_hatchet.png b/mods/nc_woodwork/textures/nc_woodwork_tool_hatchet.png new file mode 100644 index 0000000..2a2c8e8 Binary files /dev/null and b/mods/nc_woodwork/textures/nc_woodwork_tool_hatchet.png differ diff --git a/mods/nc_woodwork/textures/nc_woodwork_tool_mallet.png b/mods/nc_woodwork/textures/nc_woodwork_tool_mallet.png new file mode 100644 index 0000000..7a44e57 Binary files /dev/null and b/mods/nc_woodwork/textures/nc_woodwork_tool_mallet.png differ diff --git a/mods/nc_woodwork/textures/nc_woodwork_tool_pick.png b/mods/nc_woodwork/textures/nc_woodwork_tool_pick.png new file mode 100644 index 0000000..b4a8baf Binary files /dev/null and b/mods/nc_woodwork/textures/nc_woodwork_tool_pick.png differ diff --git a/mods/nc_woodwork/textures/nc_woodwork_tool_spade.png b/mods/nc_woodwork/textures/nc_woodwork_tool_spade.png new file mode 100644 index 0000000..c1f9896 Binary files /dev/null and b/mods/nc_woodwork/textures/nc_woodwork_tool_spade.png differ diff --git a/mods/nc_woodwork/textures/nc_woodwork_toolhead_hatchet.png b/mods/nc_woodwork/textures/nc_woodwork_toolhead_hatchet.png new file mode 100644 index 0000000..1bfb48e Binary files /dev/null and b/mods/nc_woodwork/textures/nc_woodwork_toolhead_hatchet.png differ diff --git a/mods/nc_woodwork/textures/nc_woodwork_toolhead_mallet.png b/mods/nc_woodwork/textures/nc_woodwork_toolhead_mallet.png new file mode 100644 index 0000000..6350064 Binary files /dev/null and b/mods/nc_woodwork/textures/nc_woodwork_toolhead_mallet.png differ diff --git a/mods/nc_woodwork/textures/nc_woodwork_toolhead_pick.png b/mods/nc_woodwork/textures/nc_woodwork_toolhead_pick.png new file mode 100644 index 0000000..af2b04e Binary files /dev/null and b/mods/nc_woodwork/textures/nc_woodwork_toolhead_pick.png differ diff --git a/mods/nc_woodwork/textures/nc_woodwork_toolhead_spade.png b/mods/nc_woodwork/textures/nc_woodwork_toolhead_spade.png new file mode 100644 index 0000000..1161369 Binary files /dev/null and b/mods/nc_woodwork/textures/nc_woodwork_toolhead_spade.png differ diff --git a/mods/nc_woodwork/tools.lua b/mods/nc_woodwork/tools.lua new file mode 100644 index 0000000..7491c05 --- /dev/null +++ b/mods/nc_woodwork/tools.lua @@ -0,0 +1,73 @@ +-- LUALOCALS < --------------------------------------------------------- +local minetest, nodecore + = minetest, nodecore +-- LUALOCALS > --------------------------------------------------------- + +local modname = minetest.get_current_modname() + +local function toolhead(name, from, group, sticks) + local n + if name then + n = modname .. ":toolhead_" .. name:lower() + local t = n:gsub(":", "_") .. ".png" + minetest.register_craftitem(n, { + description = "Wooden " .. name .. " Head", + inventory_image = t, + stack_max = 1, + groups = { + choppy = 1, + flammable = 2 + }, + sounds = nodecore.sounds("nc_tree_woody") + }) + local m = modname .. ":tool_" .. name:lower() + local u = m:gsub(":", "_") .. ".png" + minetest.register_tool(m, { + description = "Wooden " .. name, + inventory_image = u, + groups = { + flammable = 2 + }, + tool_capabilities = nodecore.toolcaps({ + [group] = 2 + }), + sounds = nodecore.sounds("nc_tree_woody") + }) + nodecore.register_craft({ + label = "assemble wood " .. name:lower(), + normal = {y = 1}, + nodes = { + {match = n, replace = "air"}, + {y = -1, match = modname .. ":staff", replace = "air"}, + }, + items = { + {y = -1, name = m}, + } + }) + end + + nodecore.register_craft({ + label = "carve " .. from, + action = "pummel", + toolgroups = {choppy = 1}, + nodes = { + {match = from, replace = "air"} + }, + items = { + n and {name = n} or nil, + sticks and {name = "nc_tree:stick", + count = sticks, scatter = 5} or nil + } + }) +end + +toolhead("Mallet", modname .. ":plank", + "thumpy", 2) +toolhead("Spade", modname .. ":toolhead_mallet", + "crumbly", 1) +toolhead("Hatchet", modname .. ":toolhead_spade", + "choppy", 1) +toolhead("Pick", modname .. ":toolhead_hatchet", + "cracky", 2) +toolhead(nil, modname.. ":toolhead_pick", + nil, 2) diff --git a/mods/nc_writing/assetsrc/nodian-alphabet.svg b/mods/nc_writing/assetsrc/nodian-alphabet.svg new file mode 100644 index 0000000..5d7a972 --- /dev/null +++ b/mods/nc_writing/assetsrc/nodian-alphabet.svg @@ -0,0 +1,216 @@ + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mods/nc_writing/init.lua b/mods/nc_writing/init.lua new file mode 100644 index 0000000..af6b607 --- /dev/null +++ b/mods/nc_writing/init.lua @@ -0,0 +1,194 @@ +-- LUALOCALS < --------------------------------------------------------- +local ItemStack, math, minetest, nodecore, pairs, table, tonumber, + vector + = ItemStack, math, minetest, nodecore, pairs, table, tonumber, + vector +local math_floor, math_random, table_sort + = math.floor, math.random, table.sort +-- LUALOCALS > --------------------------------------------------------- + +nodecore.amcoremod() + +local modname = minetest.get_current_modname() + +local glyphs = { + modname .. "_ava.png", + modname .. "_del.png", + modname .. "_enz.png", + modname .. "_enz.png^[transformFX", + modname .. "_san.png", + modname .. "_tef.png", + modname .. "_tef.png^[transformFX", + modname .. "_yut.png", + modname .. "_geq.png", + modname .. "_geq.png^[transformFX", + modname .. "_rex.png", + modname .. "_rex.png^[transformFX" +} +local glyph_next = {} +local glyph_alts = {} +for i = 2, #glyphs do + glyph_next[i - 1] = i + if #glyphs[i] > #glyphs[1] then + glyph_next[i - 1] = (i < #glyphs) and i + 1 or 1 + glyph_alts[i] = i - 1 + glyph_alts[i - 1] = i + end + glyph_next[#glyphs] = 1 +end + +local spinmap +do + local rots = {} + for i = 0, 23 do + local f = nodecore.facedirs[i] + local r = rots[f.t.n] + if not r then + r = {} + rots[f.t.n] = r + end + r[f.f.n] = i + end + spinmap = {} + for _, v in pairs(rots) do + local t = {} + for _, x in pairs(v) do t[#t + 1] = x end + table_sort(t) + for i = 1, #t - 1 do + spinmap[t[i] ] = t[i + 1] + end + spinmap[t[#t]] = t[1] + end +end + +local nodepref = modname .. ":glyph" +local coallump = "nc_fire:lump_coal" + +for i = 1, #glyphs do + minetest.register_node(nodepref .. i, { + description = "Charcoal Glyph", + tiles = { + glyphs[i], + modname .. "_blank.png" + }, + drawtype = "nodebox", + node_box = nodecore.fixedbox( + {-0.5, -0.5, -0.5, 0.5, -7/16, 0.5} + ), + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + walkable = false, + buildable_to = true, + pointable = false, + groups = { + alpha_glyph = 1, + snappy = 1 + }, + drop = coallump, + floodable = true + }) +end + +local function writable(pos, node) + node = node or minetest.get_node_or_nil(pos) + if not node then return end + local def = minetest.registered_nodes[node.name] + return not nodecore.toolspeed(ItemStack(""), def.groups) +end + +local oldcsff = minetest.check_single_for_falling +function minetest.check_single_for_falling(pos, ...) + local node = minetest.get_node_or_nil(pos) + if not node then return oldcsff(pos, ...) end + if minetest.get_item_group(node.name, "alpha_glyph") ~= 0 then + local dp = vector.add(pos, nodecore.facedirs[node.param2].b) + if not writable(dp) then + minetest.remove_node(pos) + return true + end + end + return oldcsff(pos, ...) +end + +minetest.register_on_punchnode(function(pos, node, puncher, pointed) + if (not puncher) or (not puncher:is_player()) then return end + + local wield = puncher:get_wielded_item() + if wield:get_name() ~= coallump then return end + + if not writable(pos, node) then return end + + local above = pointed.above + local anode = minetest.get_node_or_nil(above) + if not anode then return end + + if minetest.get_item_group(anode.name, "alpha_glyph") ~= 0 then + if anode.name:sub(1, #nodepref) ~= nodepref then return end + local g = tonumber(anode.name:sub(#nodepref + 1)) + if g and glyph_next[g] then + anode.name = nodepref .. glyph_next[g] + end + minetest.swap_node(above, anode) + local def = minetest.registered_items[anode.name] or {} + if def.on_spin then def.on_spin(above, anode) end + end + end) + +local old_place = minetest.item_place +function minetest.item_place(itemstack, placer, pointed_thing, param2, ...) + if not nodecore.interact(placer) or (itemstack:get_name() ~= "nc_fire:lump_coal") then + return old_place(itemstack, placer, pointed_thing, param2, ...) + end + + local above = pointed_thing.above + local anode = minetest.get_node_or_nil(above) + if (not anode) or (minetest.get_item_group(anode.name, "alpha_glyph") <= 0) + or (not vector.equals(nodecore.facedirs[anode.param2].t, + vector.subtract(pointed_thing.above, pointed_thing.under))) then + return old_place(itemstack, placer, pointed_thing, param2, ...) + end + + if anode.name:sub(1, #nodepref) ~= nodepref then return end + local np2 = spinmap[anode.param2] or 0 + if np2 < anode.param2 then + local g = tonumber(anode.name:sub(#nodepref + 1)) + if g and glyph_alts[g] then + anode.name = nodepref .. glyph_alts[g] + end + end + anode.param2 = np2 + minetest.swap_node(above, anode) + local def = minetest.registered_items[anode.name] or {} + if def.on_spin then def.on_spin(above, anode) end +end + +nodecore.register_craft({ + label = "charcoal writing", + action = "pummel", + pumparticles = { + minsize = 1, + maxsize = 5, + forcetexture = "nc_fire_coal_4.png^[mask:[combine\\:16x16\\:" + .. math_floor(math_random() * 12) .. "," + .. math_floor(math_random() * 12) .. "=nc_api_pummel.png" + }, + duration = 2, + wield = {name = "nc_fire:lump_coal", count = false}, + consumewield = 1, + check = function(pos, data) + return writable(pos) and minetest.get_node(data.pointed.above).name == "air" + end, + nodes = { { match = {walkable = true} } }, + after = function(pos, data) + local dir = vector.subtract(pos, data.pointed.above) + for i = 1, #nodecore.facedirs do + if vector.equals(nodecore.facedirs[i].b, dir) then + return minetest.set_node(data.pointed.above, { + name = nodepref .. 1, + param2 = i + }) + end + end + end + }) diff --git a/mods/nc_writing/mod.conf b/mods/nc_writing/mod.conf new file mode 100644 index 0000000..c1eb9fd --- /dev/null +++ b/mods/nc_writing/mod.conf @@ -0,0 +1,2 @@ +name = nc_writing +depends = nc_api, nc_fire, nc_items diff --git a/mods/nc_writing/textures/nc_writing_ava.png b/mods/nc_writing/textures/nc_writing_ava.png new file mode 100644 index 0000000..c672695 Binary files /dev/null and b/mods/nc_writing/textures/nc_writing_ava.png differ diff --git a/mods/nc_writing/textures/nc_writing_blank.png b/mods/nc_writing/textures/nc_writing_blank.png new file mode 100644 index 0000000..ada6be5 Binary files /dev/null and b/mods/nc_writing/textures/nc_writing_blank.png differ diff --git a/mods/nc_writing/textures/nc_writing_del.png b/mods/nc_writing/textures/nc_writing_del.png new file mode 100644 index 0000000..e145b49 Binary files /dev/null and b/mods/nc_writing/textures/nc_writing_del.png differ diff --git a/mods/nc_writing/textures/nc_writing_enz.png b/mods/nc_writing/textures/nc_writing_enz.png new file mode 100644 index 0000000..d638360 Binary files /dev/null and b/mods/nc_writing/textures/nc_writing_enz.png differ diff --git a/mods/nc_writing/textures/nc_writing_geq.png b/mods/nc_writing/textures/nc_writing_geq.png new file mode 100644 index 0000000..a4304df Binary files /dev/null and b/mods/nc_writing/textures/nc_writing_geq.png differ diff --git a/mods/nc_writing/textures/nc_writing_rex.png b/mods/nc_writing/textures/nc_writing_rex.png new file mode 100644 index 0000000..c615a1f Binary files /dev/null and b/mods/nc_writing/textures/nc_writing_rex.png differ diff --git a/mods/nc_writing/textures/nc_writing_san.png b/mods/nc_writing/textures/nc_writing_san.png new file mode 100644 index 0000000..6315e65 Binary files /dev/null and b/mods/nc_writing/textures/nc_writing_san.png differ diff --git a/mods/nc_writing/textures/nc_writing_tef.png b/mods/nc_writing/textures/nc_writing_tef.png new file mode 100644 index 0000000..1d1f8ad Binary files /dev/null and b/mods/nc_writing/textures/nc_writing_tef.png differ diff --git a/mods/nc_writing/textures/nc_writing_yut.png b/mods/nc_writing/textures/nc_writing_yut.png new file mode 100644 index 0000000..28155f7 Binary files /dev/null and b/mods/nc_writing/textures/nc_writing_yut.png differ diff --git a/screenshot.png b/screenshot.png new file mode 100644 index 0000000..0349065 Binary files /dev/null and b/screenshot.png differ