Merge branch 'dev' into fancy_hotbar_9271_fixed

This commit is contained in:
Aaron Suen 2020-09-04 12:29:08 -04:00
commit 5b2e61be75
498 changed files with 10815 additions and 3997 deletions

BIN
.cdb-alpha.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 414 KiB

7
.cdb-alpha.md Normal file
View File

@ -0,0 +1,7 @@
*This package is the **development edition** of the **NodeCore** game. It may include cutting-edge or experimental new features. It may also be unstable or buggy.*
Updates are released automatically, tracking the [NodeCore Dev Branch](https://gitlab.com/sztest/nodecore/commits/dev). Note that there may be some releases that don't include *any* functionality changes, since the automated process may pick up changes to embedded documentation or other things that don't end up in the game.
Alternatively, check out the [Official Release Edition of NodeCore](/packages/Warr1024/nodecore/).
Join the Discord [https://discord.gg/NNYeF6f](https://discord.gg/NNYeF6f) or IRC at **#nodecore** on [freenode](https://freenode.net/)

BIN
.cdb-release.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 KiB

15
.cdb-release.md Normal file
View File

@ -0,0 +1,15 @@
**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!
Note that NodeCore is a _complete_ game, but new features are still actively developed. If you're looking for the latest experimental stuff, and don't mind a little instability or a few bugs, check out the [NodeCore ALPHA](/packages/Warr1024/nodecore_alpha/) early-access releases.
Join the Discord [https://discord.gg/NNYeF6f](https://discord.gg/NNYeF6f) or IRC at **#nodecore** on [freenode](https://freenode.net/)

View File

@ -3,9 +3,34 @@ local dofile
= dofile
-- LUALOCALS > ---------------------------------------------------------
-- luacheck: push
-- luacheck: globals config readtext readbinary
local alpha = config and config.branch == "dev"
readtext = readtext or function() end
readbinary = readbinary or function() end
return {
user = "Warr1024",
pkg = "nodecore",
min = "5.0",
version = dofile("./mods/nc_api/version.lua")
pkg = alpha and "nodecore_alpha" or "nodecore",
min = "5.2",
version = dofile("./mods/nc_api/version.lua"),
path = ".",
type = "game",
title = "NodeCore" .. (alpha and " ALPHA" or ""),
short_desc = (alpha
and "Experimental early-access release of NodeCore."
or "Original, immersive puzzle/adventure game with NO popup GUIs, minimal HUDs."),
tags = "building, crafting, environment, inventory, machines, player vs env, puzzle",
license = "mit",
desc = alpha and readtext('.cdb-alpha.md') or readtext('.cdb-release.md'),
repo = "https://gitlab.com/sztest/nodecore",
website = "https://nodecore.mine.nu",
issueTracker = "https://discord.gg/NNYeF6f",
forums = "https://forum.minetest.net/viewtopic.php?f=15&t=24857",
screenshots = alpha
and {readbinary('.cdb-alpha.jpg'), readbinary('.cdb-release.jpg')}
or {readbinary('.cdb-release.jpg')}
}
-- luacheck: pop

3
.gitattributes vendored
View File

@ -1,5 +1,4 @@
version.lua export-subst
.git* export-ignore
.lua* export-ignore
.* export-ignore
docs export-ignore
src export-ignore

View File

@ -1,3 +1,13 @@
globals = {"minetest", "ItemStack", "VoxelArea", "vector", "nodecore", "include", "SecureRandom"}
globals = {
"minetest",
"ItemStack",
"VoxelArea",
"vector",
"nodecore",
"include",
"SecureRandom",
"PcgRandom",
"profiler"
}
color = false
quiet = 1

View File

@ -6,3 +6,5 @@ vector
nodecore
include
SecureRandom
PcgRandom
profiler

View File

@ -29,6 +29,11 @@ contribution.
Other Guidelines:
- Please do not use the nc_* namespace for projects you will be
releasing directly to the public, e.g. via ContentDB, Forums, etc.
This namespace should only be for things that will be included in
the base game.
- 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

View File

@ -1,9 +1,12 @@
Copyright (C)2018-2019 Aaron Suen <warr1024@gmail.com>
Copyright (C)2018-2020 Aaron Suen <warr1024@gmail.com>
Portions Copyright (C)2019 LoneWolfHT <lonewolf04361@gmail.com>
Portions Copyright (C)2019 Magik Eh
Portions Copyright (C)2019 Terifo <terifo1590@gmail.com>
Portions Copyright (C)2019 GreenXenith
Portions Copyright (C)2019 Kimapr
Portions Copyright (C)2019 Dmitriy Tillyaev (Kimapr) <dmitriy.tillyaev@gmail.com>
Portions Copyright (C)2019 Elkien
Portions Copyright (C)2020 WintersKnight94 <wintersknight94@gmail.com>
Portions Copyright (C)2019 Avicennia G
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

4
README
View File

@ -45,7 +45,7 @@ Features:
------------------------------------------------------------------------
NodeCore is (C)2018-2019 by Aaron Suen <warr1024@gmail.com>
NodeCore is (C)2018-2020 by Aaron Suen <warr1024@gmail.com>
MIT License (http://www.opensource.org/licenses/MIT)
See included LICENSE file for full details and credits
@ -56,7 +56,7 @@ GitLab:
https://gitlab.com/sztest/nodecore
Discord:
https://discord.gg/SHq2tkb
https://discord.gg/NNYeF6f
IRC:
#nodecore on chat.freenode.net

View File

@ -4,6 +4,8 @@
Remember, check out the CONTRIBUTING file for guidelines on contributing
to the project!
- Testing and bug reports!
- Translations:
- NodeCore is running Weblate:
https://nodecore.mine.nu/trans/projects/nodecore/core/
@ -11,23 +13,61 @@ to the project!
want to contribute translations.
- Help (PRs and/or advocacy) with Minetest engine issues:
- #9934: This bug is causing us to maintain a workaround in
NodeCore which is fragile and keeps breaking, leading to
significant network load for some clients.
- #9377: This causes some annoyances when handling lux tools,
and makes a certain mechanic blatant when it's intended to be
subtle.
- #7245: This is blocking making navigation challenges and
distinguishing nodes with similar appearance into gameplay
elements. Current open PR is #9315.
- #7876: Causes a damage flash when a new player joins, or a
player from before 2020-02-19 when max HP was changed.
- TBD: It would be nice to be able to make the player neutrally
buoyant (disable slow downward drift) in water/liquids. This
probably needs to be supported explicitly by the MT client.
- TBD: Bone attachment axes invert if there is any animation on
that bone/axis. This is blocking the visible inventory
feature. (MTG #2547, but it's probably an engine bug)
- #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.
- #9043: This bug requires NodeCore to maintain a workaround for
the engine in its own code.
- #9048: Causes player inventory sounds to be played at the wrong
volume.
- TBD: Engine should provide a standard way to make digparticles
through walls when ent/player transfer distance is high; when
low, instead it causes players/ents to be invisible even when
terrain is loaded and visible, causing distant player activity
to look like poltergeists.
- #9912: Engine should provide a standard way to make digparticles
that doesn't depend on using [combine and knowing exact source
texture size (breaks texturepacks).
- #6963: If this is implemented, we may have a more efficient
way to handle "visinv" nodes, i.e. stacks, storage boxes,
and other container nodes.
- Help with documentation
- Improvements to the in-game guidance, esp. for onboarding new
players, are wanted. Ideally we want to offer a spoiler-free
experience by default, but want players to have options/resources
in the event they can't figure something out.
- Advising players where they can find external resources, or other
sources of help, such as wikis, youtube, chatrooms, multiplayer
servers, etc.
- Work on improving the nodecore wiki itself.
- Improved versions of any art assets (sounds, textures, models).
- All textures for base inclusion should be 16x (keep
high-def textures to texture packs). Note that textures
larger than 16x are allowed (and already used) in the game
for textures that "spill over" into neighoring spaces, but
the spatial resolution of 16 pixels per node is maintained.
- It must be practical to maintain a consistent style for
other assets, including future related ones, or the content
being reworked should be mature and stable, independent of
other content areas, and the new textures should mesh
reasonably well with the existing style.
- Alternatively, publish your mods, texturepacks, or soundpacks
directly to the community, via ContentDB.
- Replacements for nodeboxes and meshes that render faster (i.e.
better FPS preservation when tons of them are around) on most
or all systems are wanted.
- Publicity and player content:
- Help spread NodeCore! Share your experiences, screenshots,
@ -35,32 +75,5 @@ to the project!
- Let the developers know if you have shared something about
NodeCore, or would like guidance creating something to share.
- Improved versions of any art assets (sounds, textures, models).
- 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.
- Alternatively, publish your mods, texturepacks, or soundpacks
directly to the community, via ContentDB.
- Nodebox replacements with significantly lower poly count
are wanted. Pull in outer faces by 1/256 to avoid z-fighting
under water.
- 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.
- Door animations.
- These need to be relatively efficient, i.e. not involve
a ton of node manipulation or spawning lots of entities.
Of particular concern is network packet load on clients.
- Something using animated entities (which could represent
multiple nodes sharing an axis) could work well.
- Alternatively, a reasonable particle effect? Something
abstract is fine too, as long as it conveys a sense of
movement to help players visualize what's moving and in
what direction.
........................................................................
========================================================================

View File

@ -1,78 +0,0 @@
========================================================================
ICEBOX: Low-Priority Ideas
------------------------------------------------------------------------
#### ##### #### # # ###### ##### ####
# # # # # # # # # # #
#### # # # # # # ##### # # ####
# ##### # # # # # ##### #
# # # # # # # # # # # #
#### # #### # ###### ###### # # ####
- Rebuild falling_node and item entity from the ground up.
- Refactor item_entity's scan method into scan_tunnel API for
use by both item_entity and falling_node.
- Add methods to settle as node or settle as stacks.
- Add flags to force stack/item settlement.
- Add method to try to settle item/node first, create ent only
if settling fails.
- On anything settling and a node being created, check space above
for entities to early-settle.
- Make falling_node try to find somewhere to place itself instead
of displacing the node it landed on, convert to an item as a
fallback.
- Standardize collision detection, i.e. ignore node collision boxes
and settle early based on full-node size.
- API for recursing through embedded inventories, e.g. in totes.
- Lux reaction cannot sense other lux inside totes.
- Player APIs:
- Physics/acceleration, for waterflow, conveyors, etc.
- When can we remove the issue7020 workaround?
- Lens strobing rate limiting of some kind?
- Require cool-downs after a lot of toggling?
- Could this be an accessibility issue?
- "Smart" optics placement?
- Pick initial rotation automatically to have the most utility
according to some heuristics.
- May involve expanding or redesigning the optics API
significantly...?
- 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.
........................................................................
========================================================================

271
docs/ideas.txt Normal file
View File

@ -0,0 +1,271 @@
========================================================================
IDEAS: Possible future additions/improvements to the game
------------------------------------------------------------------------
#### ##### #### # # ###### ##### ####
# # # # # # # # # # #
#### # # # # # # ##### # # ####
# ##### # # # # # ##### #
# # # # # # # # # # # #
#### # #### # ###### ###### # # ####
- Visual "subtitles" for sounds?
- Use new image_waypoint HUD type; it works in new versions,
invisible in old versions (graceful fallback).
- An icon for each sound type.
- Separate air vs. node cursor?
- Like the node vs. entity cursor, can we hide the cursor when
pointing only at air?
- Would server lag be too much?
- This would integrate really well with a WAILA sort of thing.
- Could totally revamp touchtips, and dynamic feel Lightning.
- Use an image HUD so we can force mobile to display it too, so
mobile players can use look dir too?
- Buff igniting
- Make hot lode and other heated materials able to ignite
- This was probably not already done just because we
didn't have AISMs at the time, but we do now.
- Reconsider lux fluid ignition again.
- Maybe have rare "spark" events that can ignite?
- Maybe have it involve proximity to other materials?
- Water? Lava?
- Optic beams?
- Chop frames, ladders, staves back down into sticks?
- Can we use glasslike_framed for shelves?
- Alternate 2 versions of the registration based on y coord
so it forces top/bottom faces to show
- More lode bar crafts:
- Frames
- Ladders?
- Adzes?
- chop+crumb -1 relative tier
- cracky -2 relative tier
- full durability
- Should these be full lode or wood handle?
- Rakes?
- Return some prills after construction?
- Make wear carry across heating/cooling recipes
- Allow full-lode tools to be tempered
- All these need to be recyclable.
- Piezo node for optics detects sounds?
- Sounds emitted by mod stuff?
- Footsteps?
- Can be used as a BUD
- Lode tongs?
- Craft from bars/rods (or lode adzes?).
- Add an API to hot potato
- Scan for all hot potato items and produce a list of slot->bool
- If any items found with an on_hot_potato callback, pass them
that list (and player, inv, etc) to be modified.
- If slot is marked "safe" then no hot potato if items are in
a slot adjacent to tongs.
- If slot is not marked safe, mark it safe if tongs or any tool
are wielded item.
- Unmark safe any slots that don't contain hot things after
hot potato check.
- Allow frame loose ends to be chopped off when placed next to other
frames, so custom shapes can be made.
- Dungeon loot
- Add recipe hints (prearranged nodes) as decorations?
- Rows of shelves against walls. Very rarely lode crates.
- Loot items in shelves, weighted pickrand(). Add a "margin" pick
result with value of proportion of where in range the picked value
was, and vary tool durability or stack count non-linearly by it.
- Scattered items on floor. Most are from loot tables, some are
crates or storeboxes.
- A lode "mace" tool with all dig groups?
- Would require reevaluatng recipe priority, or tool modality.
- Make lava easier to find at a distance visually
- Particles, like cherenkov?
- New Darkness feature:
- Keep track of queue of recent "safe spots" for player:
in sunlight, on solid ground or climbable etc.
- Also check for being completely entombed in solid non-climbables.
- Track player darkness, search for nearby light. Keep track of recent hit/miss (ring/queue).
- If player is in TOTAL darkness for long enough to be certain, then do "fugue" teleportation.
- Fade screen to black slowly via HUD (maybe have an API for this for skyrealms).
- Drop all items.
- Apply a temporary debuff...?
- Teleport player back to recent safe spots until we find one, or run out.
- Fade screen back from black.
- Should tool appearance vary based on wear?
- Make "fresh" vs. "worn" tools (for purposes of their usability
in crafts) have a distinct look?
- Tree sap
- Stumps with air above exude, become dry stumps.
- Use as a glue/resin in recipes.
- Make longer-life torches?
- Stick optics in place to prevent rotating?
- Straw/thatch?
- Domain Wall Sensor
- Adapt from sztest?
- Field Generator?
- Power an annealed lode block from 2 opposite faces.
- Generates particle effect at mapblock boundary.
- Particle effect with lux fluid and/or cobble?
- Create particle effect around player while carrying lux in
inventory?
- Maybe only if the lux is higher activation tier?
- Should ash and derivatives have a fertilizing effect?
- Maybe wet/tacky stuccos?
- Optic locking
- Prevent accidental rotation.
- Use tree sap / glue?
- Make "glued" optic node?
- Detect adjacent glue node?
- Apply frame, make framed optics?
- Hammer into place with certain tool?
- Door Automation
- Should have press recipes for stickcraft, i.e. staves,
frames, ladders.
- Press tools (or tool heads) into nodes to activate other
pummel recipes like chopping.
- Mount tool heads on frames to make machine tools?
- Press recipes for digging.
- If pushing a node (or toolhead backed by node) and there
is a climbable walkable behind it, or a storebox, dig the
node and push it through climable as catapult, or into
storebox if it fits.
- Pressing stack of 1 node places it, instead of pummeling it.
Can pummel on the second push.
- Should doors trigger place recipes when blocked?
- Push players?
- Need more door materials: lode, glasses
- Renewability Gap
- Renewable but not generatable
- Sponges: Sprout under water from peat+sand?
- Lode
- Lux
- Water sources.
- Sustainable but not renewable
- Not sustainable
- Lava sources.
- Surround stone with lava to melt?
- Threats
- Visceral
- Flammable/toxic gas?
- Monsters: stone-lurkers, mimics.
- Complex multi-node mimic that eats tools you try to dig it with,
stores them in core node(s) inside somewhere to be recovered.
- Lightning, meteor strikes?
- Creeping
- Cellular automata hazards.
- From exploration, delving too deep, leaving things to rot, etc.
- Blights, Fungi
- Termites, carpenter ants, other wood-eating inflictions?
- 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.
- New materials to craft with.
- Dungeon materials, stonework?
- Decorations for dungeons
- 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?
- Things that cannot ever be dug, and must be moved only
by in-world machinery?
- Vary player walking speed based on nodes under feet?
- Visual "craft guide" system?
- Build a 3x3 work space out of wood/logs, place center node
last and it will convert to a workbench node.
- Workbench node will scan for potential recipe matches
centered on the space above based on what's present
and matches at least 1 non-air node, picks one.
- Create display "ghost" entities representing items that
can be placed to complete the recipe.
- Should tree growth rate start out faster but slow down?
- This could make the decision to harvest trees early vs
wait for them to mature more nuanced.
- Social features
- Randomize player appearance/colors.
- Shirt/pants, possibly w/ stripes/patterns
- Skin color, hair color, eye color?
- Add a "cloak" layer for cloaks, capes, over entire body
- Make some control states / anims last a little longer, e.g.
extend mining or waving anims to a second or so to make sure
they're visible and not just flicker.
- Drop-in recipes, triggered on thrown or falling items settling?
- Good for dangerous stuff, maybe?
- Compact signage via concrete/writing/stylus
- Draw glyphs on a wall.
- Place a lens focusing light from the wall onto a spot.
- Put pliant concrete in that spot.
- Make sure wall is adequately lit.
- Etch the lens-facing side of the pliant concrete with stylus.
- Create a "custom patterned" concrete sign block with letters etched
onto it. Store in metadata, use ents to render, etc.
- Allow metalworking with wood tools?
- Eat a lot of extra durability?
- Door animations.
- These need to be relatively efficient, i.e. not involve
a ton of node manipulation or spawning lots of entities.
Of particular concern is network packet load on clients.
- Something using animated entities (which could represent
multiple nodes sharing an axis) could work well.
- Alternatively, a reasonable particle effect? Something
abstract is fine too, as long as it conveys a sense of
movement to help players visualize what's moving and in
what direction.
- Visual in-world hotbar
- GreenXenith's visualbar mod
- Replace hotbar, merge it with both bandolier and YCTIWY?
- Players could be "pickpocketed" during normal gameplay.
- Make a sound/visual to warn player.
- Jordach's new first-person-attached entities feature?
........................................................................
========================================================================

136
docs/issues-code.txt Normal file
View File

@ -0,0 +1,136 @@
========================================================================
ISSUES-CODE: Issues related to code quality and APIs
------------------------------------------------------------------------
#### ##### #### # # ###### ##### ####
# # # # # # # # # # #
#### # # # # # # ##### # # ####
# ##### # # # # # ##### #
# # # # # # # # # # # #
#### # #### # ###### ###### # # ####
- Look into game default settings.
- Change default ABM budget
(https://github.com/minetest/minetest/pull/10290)
- Make door pusheability customizable
- door_can_push or door_cannot_push groups/flags or something.
- Allow override of standard falling_node check.
- Overhaul player health to work entirely virtual
- Raise max up a lot to make room for fine grained falling
damage so we can raise threshold
- Consider falling damage add percent to all nodes?
- Add API for doing fake damage effect using set hp
- Allow optics pending transaction to be flushed early
- Optics interacting with doors are out of sync
- May need to commit the optic state immediately when triggering
doors so they get the correct current state.
- Consider full eversion of event handlers
- Disallow (or automatically convert) traditional single-hanlders
on all definitions
- Use a register_on_something() method to hook pretty much
everything
- Unify mkreg
- Add validation/modifying and order comparison funcs
- Use for recipes, mapgen_shared, playerstep, etc.
- Consider replacing with register_generic():
- Allow lazy registration, i.e. a register method that can
register for things not yet defined, and allow later registration
of the registration definition that will pick up those missed.
- Define order for inv tabs
- Hint System Refactor
- Move stats into an api layer to ensure availability
- Simplify stats, track less detail, limit data growth.
- Break up hints into each individual mod.
- Add shortcuts for hint registrations, e.g. integrated with recipes.
- Transactional api ref localization
- For certain large computations, like an optic processing, it may be
worthwhile to capture some often-repeated functions like minetest.get_node
as locals.
- May need to test performance on a non-JIT build, where this is expected
to have a larger impact, since JIT probably optimizes the difference away.
- Continue to chisel away at ABM perf issues.
- Simplify or optimize existing ABMs
- Convert things to DNTs.
- Some time-integral processes are not resetting when prereqs removed
- Cooking resumes instead of resetting when fire removed.
- Leaching resumes instead of resetting when water removed.
- Take advantage of the fact that players/inventories use a single shared
metatable for player inventory arrangement hooks in nc_player_pickup,
like we did for entity:set_properties.
- Currently inv pickup logic isn't working and we're relying on
rearrangement; need to resolve this one way or another.
- Make leaf decay group-driven for mod applicability.
- Switch some extended attributes to first-class support instead of modifying
definition at registration time.
- e.g. drop_in_place should hook the engine's dig event instead of
registering an on_dig on the node, so inheritance works.
- Add a nodecore.inherit_node() helper that registers a node as a
modified copy of another definition, e.g. for planted eggcorns copying
dirt, door panels copying original materials, etc.
- Add an on_falling_check handler to replace check_single_for_falling custom
hook in writing, and possibly other places.
- Should we create "recipe groups" to make it easier to specify
equivalent recipes for hint purposes?
- Need to find a way to make AISMs work with falling_node.
- Create ItemStack, run hooks, try to convert back to node
(assume node and item meta map 1:1) and if it fails then
spawn an item_ent.
- Need this for amalgamation remelting.
- Would it make sense to unify the item and falling_node ents?
- API for map-seed-deterministic scatter.
- Given minp, maxp, seed and density, find all positions.
- Use for sponges, lava/water springs, etc.
- Unify sponge growth logic so it can be used for mapgen, to ensure
that spawned sponges match naturally-grown ones?
- Easier recipe API:
- Use ascii art like ezschematic?
- Aliases like "sides"/"corners"?
- Make 3x3 recipes easier to define.
- Standardize visinv access API
- stack_access(pos, node, dirfrom) - return booly
whether access to inside stack is allowed.
- Use for shelf API.
- Use for touchtips inv access.
- Genericize sponge logic using stack_access API
- Wandering fluids API for concrete, glass?
- Configurable setting for generation count multiplier.
- API for recursing through embedded inventories, e.g. in totes.
- Lux reaction cannot sense other lux inside totes.
- Scripts to validate dependency graph.
- Tag deps directly in code at place of use.
- Auto-generate mod.conf / depends.txt
- API Cleanup
- Further nc_api break-up, clean up util functions.
- Heat API
- Quenched, Flames as numbers or nil?
- Unify nc_items and visinv API.
- Stack nodes are "special", get first-class support.
- APIs for different kinds of "neighbor" scans
- Face, edge, corner touching
........................................................................
========================================================================

25
docs/issues-docs.txt Normal file
View File

@ -0,0 +1,25 @@
========================================================================
ISSUES-DOCS: Issues related to documentation
------------------------------------------------------------------------
#### ##### #### # # ###### ##### ####
# # # # # # # # # # #
#### # # # # # # ##### # # ####
# ##### # # # # # ##### #
# # # # # # # # # # # #
#### # #### # ###### ###### # # ####
- Add a code of conduct to project
- Cover chat rules from discord, servers?
- Add a credits file with more extensive/specific credits, including
non-copyrightable contributions to core project...?
- Design doc needs another shakedown.
- Expecially: what has "nodecorian" come to mean?
- Need to clean out issues in wishlist.
- Put some issues unlikely to be resolved on ice.
........................................................................
========================================================================

155
docs/issues-game.txt Normal file
View File

@ -0,0 +1,155 @@
========================================================================
ISSUES-GAME: Gameplay-affecting issues
------------------------------------------------------------------------
#### ##### #### # # ###### ##### ####
# # # # # # # # # # #
#### # # # # # # ##### # # ####
# ##### # # # # # ##### #
# # # # # # # # # # # #
#### # #### # ###### ###### # # ####
- Infuse rakes.
- Larger radius?
- Dig more types of stuff?
- Silk touch?
- Stone softening rates feel off.
- Once first stage of stone softens, others follow really
quicky (exponential runaway basically).
- If you leave stone soaking for a while, it looks like it
basically softens all or nothing.
- Can we smooth this out and make it less jarring?
- Buff wall scaling
- Allow 1n lateral movement along wall
- Makes outer wall corners navigable
- Silk Touch needs a review, possible nerf.
- Review what materials are silk toucheable and which are not
at this point, make adjustments if needed.
- Maybe require some preparatory step, like a pummel into a
prepped material before dig?
- Make a way to prevent crafting on place
- Sneak? Aux?
- Buff lux burns significantly when touching lux.
- Change lux burn model to operate like radiant heat instead?
- Genericize radiant damage check to check a hook for damage
applicability from nodes found
- Maybe retire classic damage per second entirely
- Maybe replace all normal damage with lux burns?
- May need a hack to play damage effects when not altering hp.
- Set hp lower and use 1+ delta, then let damage normalizer
reset it?
- Consider changing wet/dry stack splitting
- Currently, original stack remains in place, wetted/dried
stack jumps out to new spot.
- Instead, maybe wetted/dried stays in place and original
jumps out (unless there's an adjacent wetted/dried stack to
reuse).
- More similar to the way flammable stack ignition works
- Just meaner overall
- Consider largely retiring offline time-integral mechanics
- Keepers:
- Tree growth
- Compost
- Losers:
- Sponge expiration
- Torch expiration
- Leaching
- Repacking
- Concrete
- Lux renew
- Logic: Action by a living thing (i.e. presence of player or
microorganisms) is what keeps time ticking...?
- Be more consistent with some non-offline mechanics like
fire fuel consumption
- "Fairness" issues, e.g. when sponge expiration happens before
squeezer DNTs have had a chance to fire.
- When we did torches via expiration metadata, the reason at the
time was that there was no way to get them to tick reliably like
we can with nodes; with AISMs this is no longer the case.
- Repose changes
- Staves/rods should repose a lot less or not at all.
- Rework repose to be based on amount of loose material below, not
amount of distance available to fall? repose only needs to have a
particular angle as measured on flat land?
- Hint system
- Updates for everything since renewable ores (read changelog)
- Agg may have been broken by concrete overhaul
- Consider removing redundant or reverse paths, i.e. recycling
or artificial resource recipes.
- They complicate maintenance.
- They are distracting for players (e.g. Emerald feeling
COMPELLED to chop up a lode crate unnecessarily for the
hint completion)
- Hints could be re-expanded by 3rd party mods
- Delay lens full brightess?
- Propagate optic signals immediately
- Reach full brightness a few seconds later, to reduce map
update work and prevent rapid strobes.
- Strobes can cause excess lighting recalcs and block
transfers, and can cause seizure problems for users
- Consider doing looktips and using a custom HUD to force crosshair
for mobile as well.
- Looktips can re-show any time lookdir changes, not just on
change of target node name, so rejiggling the view can
give more time to read tip.
- Don't allow looktip if the "above" node is below a certain
light level
- Consider separating wieldtips and punch/looktips again.
- falling_node pillars settle out of order!
- Also anectodal issues with falling nodes sometimes
tunneling WAY upwards now, as observed with BXS's
mine on NCC where gravel tunneled all the way up
the ladder
- Tote issues:
- Consider updating tote recipe.
- Totes should do face-connected search for totables; don't pick up
shelves only touching via a corner.
- Flammables should respond via AISM when bathed in fire or igniting
liquids like molten glass or rock.
- Import YCTIWY as part of the base game.
- Setting to disable entirely
- Setting to disable compact mode
- Setting for fresh/stale like bones; items become accessible
only after time has passed since last login
- Make the priv just to override any protections
- Shelf recipe reform
- Add a "shelf frame" node made from wooden frames
- Add appropriate material to shelf frame to make shelf
- 2-stage construction should make it easier to discover
- Shelf frame can gain its own distinct uses
- e.g. some things can fall through it but not others.
Items? Players? Fluids?
- Should there be pockets of softer stone at depth, like there is gravel?
- Register ores for softer stone of each level
- Maybe some ores for cobble and/or loose cobble?
- Consider checking for a nearby active player before running
"fast-evolving" ABMs that don't normally work offline, like fire
extinguishing/spreading?
- This would make gameplay more fair for those who tend to
go AFK suddenly and can't return for a long time.
- This would reduce the gap between things that support the offline
mechanic and those that don't between MP and SP.
- Make separate walkable/non-walkable stack nodes.
- Should sticks and eggcorns be non-walkable?
........................................................................
========================================================================

View File

@ -1,56 +0,0 @@
========================================================================
ISSUES: Bugs, Cleanup and Refinements
------------------------------------------------------------------------
#### ##### #### # # ###### ##### ####
# # # # # # # # # # #
#### # # # # # # ##### # # ####
# ##### # # # # # ##### #
# # # # # # # # # # # #
#### # #### # ###### ###### # # ####
- Hint updates:
- Press recipe witnessing?
- Rake.
- Glass tank.
- Optics states, e.g. active, shining, gated.
- Injury/burns?
- Full tote?
- Dirt->sand leeching
- Time for an audit again...
- Can we preserve non-buildable_to liquid sources when squashed,
e.g. lava or glass clobbered by falling_node or item?
- Flammables should respond via AISM when bathed in fire or igniting
liquids like molten glass or rock.
- Consider checking for a nearby active player before running
"fast-evolving" ABMs that don't normally work offline, like fire
extinguishing/spreading?
- This would make gameplay more fair for those who tend to
go AFK suddenly and can't return for a long time.
- Offline tick logic for spreading nodes
- Use soaking API, calculate time to spread.
- If actual time exceeds time to spread, pass soak depth on to
new node that's been created, and trigger respread check.
- Will have to do a lot of performance testing.
- Probably should be using hash_node_position insted of pos_to_string
in many places where we don't support non-integer positions anyway
- CDB screenshot out of date.
- Update nc_reative dependencies!
- New optics
- Full tote
- Glass tank, lode crates
- Lux
- Torches
- Design doc needs another shakedown.
- Consider updating tote recipe.
........................................................................
========================================================================

56
docs/nonideas.txt Normal file
View File

@ -0,0 +1,56 @@
========================================================================
NONIDEAS: Ideas already considered and rejected
------------------------------------------------------------------------
#### ##### #### # # ###### ##### ####
# # # # # # # # # # #
#### # # # # # # ##### # # ####
# ##### # # # # # ##### #
# # # # # # # # # # # #
#### # #### # ###### ###### # # ####
- Anything Already Added
- If something already exists in the game then it will not
be added.
- Please play though the game enough to understand what is
already in the game before making suggestions.
- Mobs/Animals
- Things that are "off-grid" are discouraged. Node-based
"staybs" could at least fit the mechanics, but entity-based
creatures that move freely do not. Use of /clearobjects
should not remove key gameplay elements as long as the game
is allowed to "quiesce" first.
- Monsters that are easy to understand and deal with would not
fit the games theme or play style. Threats need to be subtle,
insidious, and indirect. Threats that offer no direct
cathartic response (i.e. bashing it to death) also fit the
theme better, as well as threats that can be turned around and
exploited as resources once mastered (but remain a threat if
handled carelessly).
- NodeCore pacing requires that dangers to a player should be
consequences of the player's own decisions, and not something
that can be blamed on environment or chance. Having monsters
spawn spontaneously and stalk the player would be problematic.
- NodeCore "conservation" mechanics discourage having things
spawn spontaneously at all, and they would need to be part of
mapgen.
- Food/Hunger
- Players are like ethereal beings who visit the world only
temporarily and are not subject to injury or survival
mechanics within the world.
- Things that focus a mechanic on/through the player do not
fit the world-centric/node-centric theme of the game.
- Using food items to provide things like temporary buffs is
likely to be a lot of effort and likely to be skipped by most
players.
- Beds
- There is no night to skip, and players have no need for sleep.
- Bed-like structures can be made out of existing nodes. Purely
decorative elements that are not fungible do not fit the
game's design.
........................................................................
========================================================================

68
docs/releng.txt Normal file
View File

@ -0,0 +1,68 @@
========================================================================
RELENG: Release engineering and version support
------------------------------------------------------------------------
#### ##### #### # # ###### ##### ####
# # # # # # # # # # #
#### # # # # # # ##### # # ####
# ##### # # # # # ##### #
# # # # # # # # # # # #
#### # #### # ###### ###### # # ####
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
VERSION POLICY
--------------
Version support should go as far back as:
- One official minor release (e.g. #.#) prior to the latest across all
platforms.
- The latest officially supported release for each platform.
This means that during the 5.2 release, we support 5.2, 5.1, and 5.0
(because android is stuck on 5.0). When 5.3 is released and brings
back current android support, we will drop 5.0 and 5.1, since all
platforms will be at 5.3, and thus 5.2 will be the earliest.
Version support should go as far forward as:
Support the current latest release at all times. Test the game out on
dev versions so we can be prepared to support the next release as soon
as it happens.
ENGINE/FORK POLICY
------------------
NodeCore is only designed to fully support the official minetest.net
game engine at this time, on all supported desktop and mobile
platforms.
Forks may be unofficially supported if they are 100% API-compatible
with an officially-supported engine, or if there is benefit to
supporting them and they require only negligible changes/maintenance
to get working.
Compatible forks will not explicitly be blocked from running NodeCore
if they are capable of running it. Nags/warnings may be added for
such engines, but only if they have the potential to cause significant
disruption, such as generating excessive frivolous support issues,
allowing cheating, or providing an altered game experience without
indication that it does not represent the original.
NEW MT RELEASE PROCESS
----------------------
- Wait for a grace period (standard 1 week) after new MT release before
evaluating EOS for previous versions.
- Reevaluate the policy and decide which version(s) need EOS
- Check CDB for version strings and update .cdbrelease.lua
- Check this doc for special TODO items related to release
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
- After 5.2 EOS:
- Change bandolier slot items back to upright_sprite
- Consider switching touchtips to waypoint HUDs now that
hiding distance is an options.
- Switch ents to using on_step moveresult for collision
detection instead of checking nodes directly.
........................................................................
========================================================================

View File

@ -1,160 +0,0 @@
========================================================================
ROADMAP: Large New Development Projects
------------------------------------------------------------------------
#### ##### #### # # ###### ##### ####
# # # # # # # # # # #
#### # # # # # # ##### # # ####
# ##### # # # # # ##### #
# # # # # # # # # # # #
#### # #### # ###### ###### # # ####
- Consider upstreaming nc_stucco, maybe into nc_concrete?
- Credit Avicennia G a.k.a. Tereno Johnson
- Stylus from stick+chip, stick+prill, etc. using "scratchy" group.
- Add materials for mud+ash, sand+ash, add coal lump to agg.
- All materials work like concrete, falling, liquefy with water.
- All of them cure to a tacky state first, then to dry.
- Become tacky if molded, cure to lower material otherwise.
- Use soaking. Etching allowed to reset timer?
- Include a few etched patterns. Separate mask and noise layers.
- bricky, meshy, barry, icebox, enol, bordythin, gkey, bindy
- Not relocatable
- dry digs to cobble, dirt, sand, etc.
- tacky undiggable until it cures (like a liquid)
- Cheaper materials have shorter liquid, longer tacky phase
- Standardize wandering liquid API?
- Wander frequency, dist limit
- Generation limit params
- Curing time
- Curing check (e.g. for quenching)
- Time and gen cure methods
- Make stone bricks or other building materials?
- Pummel stone w/ lux+ pick?
- Door Automation
- Should have press recipes for stickcraft, i.e. staves,
frames, ladders.
- Press tools (or tool heads) into nodes to activate other
pummel recipes like chopping.
- Mount tool heads on frames to make machine tools?
- Press recipes for digging.
- If pushing a node (or toolhead backed by node) and there
is a climbable walkable behind it, or a storebox, dig the
node and push it through climable as catapult, or into
storebox if it fits.
- Pressing stack of 1 node places it, instead of pummeling it.
Can pummel on the second push.
- Should doors trigger place recipes when blocked?
- Push players?
- Need more door materials: lode, glasses
- Standardize visinv access API
- stack_access(pos, node, dirfrom) - return booly
whether access to inside stack is allowed.
- Use for shelf API.
- Use for touchtips inv access.
- Genericize sponge logic using stack_access API
- Wandering fluids API for concrete, glass, lava?
- Configurable setting for generation count multiplier.
- Lava quenching, new material?
- Seepstone?
- Lava wandering.
- Concentrations of lava should melt nearyby stone
- Dependent on hardness of stone
- Lava near fringes should spontaneously quench.
- Should there be pockets of softer stone at depth, like there is gravel?
- Domain Wall Sensor
- Adapt from sztest?
- Field Generator?
- Power an annealed lode block from 2 opposite faces.
- Generates particle effect at mapblock boundary.
- Particle effect with lux fluid and/or cobble?
- Water and lava surface springs.
- Access to water for forges.
- Access to lava for lighting, firestarting, glass?
- Renewability Gap
- Renewable but not generatable
- Sponges: Sprout under water from peat+sand?
- Water sources.
- Sustainable but not renewable
- Lode: Infuse lode into eggcorns -> lodecorns -> tree-farming for lode?
- Lux: Infuse lode cobble to make lux cobble?
- Lava sources.
- Completely lossy
- Hard stone: harden using nearby heat sources?
- 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
- 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.
- Social features
- Randomize player appearance/colors.
- Shirt/pants, possibly w/ stripes/patterns
- Skin color, hair color, eye color?
- 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?
- Things that cannot ever be dug, and must be moved only
by in-world machinery?
- Fancy hotbar.
- Build hotbar texture dynamically from pieces and texturemods.
- Inventory items can have a hotbar_texture associated with them to
override the default for that slot.
- Make virtual items invisible on their own, use hotbar texture for them.
- Injuries show torn/cracked slot.
- Lux burns show partially melted slot.
- Need to also alter the selection texture based on wield index.
- Tick delay...
- Vary player walking speed based on nodes under feet?
- Use gravity vector to make flowing water push the player?
........................................................................
========================================================================

View File

@ -6,4 +6,5 @@ mod_storage
players.*
players
nc_api.template.tr
texturepack_override.template.txt
world.mt

View File

@ -0,0 +1,22 @@
------------------------------------------------------------------------
This world is maintained as a "standard" screenshot to show a visual
example of a plausible game scene, including a variety of in-game
elements. It can be used freely (MIT licensed like the rest of the
game) for making screenshots for texture packs.
How To Use:
- Copy or symlink this dir into ~/.minetest/worlds, or wherever your
minetest worlds are stored.
- Copy the world.mt.dist file to world.mt.
- Enter the world (singleplayer or "host game"; either is fine).
- Do NOT move the mouse or any other controls; keep your exact position
and looking angle. If you mess up, leave and rejoin.
- Hide the chat (F2) and wait for on-screen messages to fade.
- Select the "empty" hotbar slot #6.
- Resize your window to the largest size possible, with a ~16:9 or
~16:10 aspect ratio.
- Hold the zoom key (and no other key).
- Capture an in-game screenshot (F12).
------------------------------------------------------------------------

Binary file not shown.

View File

@ -38,37 +38,15 @@ mgv7_np_cavern = {
octaves = 5
persistence = 0.63
}
mgv7_cave_width = 0.09
mg_biome_np_heat = {
mgv7_np_floatland = {
flags = defaults
lacunarity = 2
offset = 50
scale = 50
spread = (1000,1000,1000)
seed = 5349
octaves = 3
persistence = 0.5
}
mgv7_lava_depth = -256
mgv7_np_mount_height = {
flags = defaults
lacunarity = 2
offset = 256
scale = 112
spread = (1000,1000,1000)
seed = 72449
octaves = 3
persistence = 0.6
}
mg_biome_np_humidity_blend = {
flags = defaults
lacunarity = 2
lacunarity = 1.618
offset = 0
scale = 1.5
spread = (8,8,8)
seed = 90003
octaves = 2
persistence = 1
scale = 0.7
spread = (384,96,384)
seed = 1009
octaves = 4
persistence = 0.75
}
mgv7_np_ridge = {
flags = defaults
@ -80,28 +58,61 @@ mgv7_np_ridge = {
octaves = 4
persistence = 0.75
}
mgv7_large_cave_depth = -33
mg_biome_np_humidity = {
mgv7_np_mountain = {
flags = defaults
lacunarity = 2
offset = 50
scale = 50
spread = (1000,1000,1000)
seed = 842
octaves = 3
persistence = 0.5
offset = -0.6
scale = 1
spread = (250,350,250)
seed = 5333
octaves = 5
persistence = 0.63
}
mg_biome_np_heat_blend = {
mgv7_floatland_ymax = 4096
mgv7_np_ridge_uwater = {
flags = defaults
lacunarity = 2
offset = 0
scale = 1
spread = (1000,1000,1000)
seed = 85039
octaves = 5
persistence = 0.6
}
mgv7_mount_zero_level = 0
mg_biome_np_humidity_blend = {
flags = defaults
lacunarity = 2
offset = 0
scale = 1.5
spread = (8,8,8)
seed = 13
seed = 90003
octaves = 2
persistence = 1
}
mgv7_floatland_level = 1280
mgv7_small_cave_num_min = 0
mgv7_large_cave_flooded = 0.5
mg_biome_np_heat = {
flags = defaults
lacunarity = 2
offset = 50
scale = 50
spread = (1000,1000,1000)
seed = 5349
octaves = 3
persistence = 0.5
}
mgv7_np_mount_height = {
flags = defaults
lacunarity = 2
offset = 256
scale = 112
spread = (1000,1000,1000)
seed = 72449
octaves = 3
persistence = 0.6
}
mgv7_small_cave_num_max = 0
mgv7_np_terrain_base = {
flags = defaults
lacunarity = 2
@ -112,19 +123,8 @@ mgv7_np_terrain_base = {
octaves = 5
persistence = 0.6
}
mgv7_np_float_base_height = {
flags = defaults
lacunarity = 2
offset = 48
scale = 24
spread = (300,300,300)
seed = 907
octaves = 4
persistence = 0.7
}
seed = 14531853857515683775
water_level = 1
mapgen_limit = 31000
mg_name = v7
mgv7_cavern_threshold = 0.7
mgv7_dungeon_ymin = -31000
@ -140,19 +140,36 @@ mgv7_np_height_select = {
octaves = 6
persistence = 0.7
}
mgv7_np_mountain = {
mg_biome_np_heat_blend = {
flags = defaults
lacunarity = 2
offset = -0.6
scale = 1
spread = (250,350,250)
seed = 5333
octaves = 5
persistence = 0.63
offset = 0
scale = 1.5
spread = (8,8,8)
seed = 13
octaves = 2
persistence = 1
}
mgv7_shadow_limit = 1024
mgv7_float_mount_height = 128
mgv7_float_mount_exponent = 0.75
mgv7_floatland_density = -0.6
mgv7_cave_width = 0.09
mg_biome_np_humidity = {
flags = defaults
lacunarity = 2
offset = 50
scale = 50
spread = (1000,1000,1000)
seed = 842
octaves = 3
persistence = 0.5
}
mgv7_floatland_taper = 256
mgv7_floatland_ywater = -31000
mgv7_large_cave_depth = -33
mgv7_floatland_ymin = 1024
mapgen_limit = 31000
mgv7_float_taper_exp = 2
mgv7_large_cave_num_min = 0
mgv7_large_cave_num_max = 2
mgv7_np_terrain_persist = {
flags = defaults
lacunarity = 2
@ -166,7 +183,6 @@ mgv7_np_terrain_persist = {
mgv7_cavern_limit = -256
mgv7_cavern_taper = 256
mgv7_dungeon_ymax = 31000
mgv7_float_mount_density = 0.6
mgv7_np_terrain_alt = {
flags = defaults
lacunarity = 2
@ -188,25 +204,4 @@ mgv7_np_filler_depth = {
octaves = 3
persistence = 0.7
}
mgv7_mount_zero_level = 0
mgv7_np_ridge_uwater = {
flags = defaults
lacunarity = 2
offset = 0
scale = 1
spread = (1000,1000,1000)
seed = 85039
octaves = 5
persistence = 0.6
}
mgv7_np_floatland_base = {
flags = defaults
lacunarity = 2
offset = -0.6
scale = 1.5
spread = (600,600,600)
seed = 114
octaves = 5
persistence = 0.6
}
[end_of_params]

View File

@ -1,3 +1,2 @@
gameid = nodecore
backend = sqlite3
load_mod_nc_reative = true

View File

@ -0,0 +1,18 @@
-- LUALOCALS < ---------------------------------------------------------
local nodecore
= nodecore
-- LUALOCALS > ---------------------------------------------------------
local txr
nodecore.register_playerstep({
label = "skyrealm skybox",
priority = -1000,
action = function(_, data)
if not txr then
if not (data.sky and data.sky.textures) then return end
txr = data.sky.textures[1]
txr = {txr, txr, txr, txr, txr, txr}
end
data.sky.textures = txr
end
})

View File

@ -0,0 +1 @@
depends = nc_api_all

View File

@ -0,0 +1,73 @@
-- LUALOCALS < ---------------------------------------------------------
local ItemStack, minetest, nodecore, pairs, vector
= ItemStack, minetest, nodecore, pairs, vector
-- LUALOCALS > ---------------------------------------------------------
local modname = minetest.get_current_modname();
local setinv = {
{"nc_stonework:tool_pick", 1, 0.7},
{"nc_stonework:tool_spade", 1, 0.8},
{"nc_stonework:tool_hatchet", 1, 0.4},
{"nc_stonework:tool_mallet", 1, 0.2},
{"nc_stonework:chip", 54},
{"air", 1, nil, "[combine:1x1"},
{"nc_terrain:sand_loose", 14},
{"nc_terrain:dirt_loose", 47}
}
for _, v in pairs(setinv) do
local n = modname .. ":" .. v[1]:gsub(":", "_")
if not minetest.registered_items[n] then
local def = minetest.registered_items[v[1]]
minetest.register_item(n, {
["type"] = def["type"],
tiles = def.tiles,
inventory_image = v[4] or def.inventory_image,
wield_image = v[4] or def.wield_image,
on_drop = function() return ItemStack("") end,
on_place = function() end,
on_use = function() end
})
end
v[1] = n
end
local startpos = {}
local function setup(p)
local inv = p:get_inventory()
for i, v in pairs(setinv) do
if v then
local s = ItemStack(v[1])
s:set_count(v[2])
if v[3] then s:set_wear(65535 * v[3]) end
inv:set_stack("main", i, s)
end
end
local pname = p:get_player_name()
minetest.after(0, function()
p = minetest.get_player_by_name(pname)
if not p then return end
startpos[pname] = p:get_pos()
end)
end
nodecore.register_on_joinplayer(setup)
nodecore.register_on_respawnplayer(setup)
nodecore.register_playerstep({
label = "mock inv clear",
action = function(p)
local pname = p:get_player_name()
local pos = p:get_pos()
local spos = startpos[pname]
if not spos or vector.distance(pos, spos) < 1 then return end
startpos[pname] = nil
local inv = p:get_inventory()
for i = 1, inv:get_size("main") do
local sn = inv:get_stack("main", i):get_name()
if sn:sub(1, #modname + 1) == modname .. ":" then
inv:set_stack("main", i, "")
end
end
end
})

View File

@ -0,0 +1 @@
depends = nc_api_all, nc_terrain, nc_stonework

View File

@ -0,0 +1,7 @@
-- LUALOCALS < ---------------------------------------------------------
local include
= include
-- LUALOCALS > ---------------------------------------------------------
include("wield")
include("model")

View File

@ -0,0 +1 @@
depends = nc_api_all, nc_player_model, nc_player_wield

View File

@ -0,0 +1,71 @@
-- LUALOCALS < ---------------------------------------------------------
local minetest, nodecore, pairs, vector
= minetest, nodecore, pairs, vector
-- LUALOCALS > ---------------------------------------------------------
local modname = minetest.get_current_modname()
local anims = {}
do
local raw = {0, 53, 165}
raw[#raw + 1] = raw[1]
for i = 1, #raw - 1 do
anims[raw[i]] = raw[i + 1]
end
end
minetest.register_entity(modname .. ":ent", {
initial_properties = {
visual = "mesh",
visual_size = {x = 0.9, y = 0.9, z = 0.9},
mesh = "nc_player_model.b3d",
textures = {"nc_player_model_base.png"},
collisionbox = {-0.25, 0, -0.25, 0.25, 2, 0.25},
physical = true
},
get_staticdata = function(self)
return minetest.serialize(self.data)
end,
on_activate = function(self, data)
self.data = data and minetest.deserialize(data) or {}
local obj = self.object
obj:set_acceleration({x = 0, y = -10, z = 0})
local anim = self.data.anim or 0
obj:set_animation({x = anim, y = anim}, 1)
nodecore.mock_player_wieldview(self)
end,
on_punch = function(self, whom)
if not whom then return end
local obj = self.object
local ctl = whom:get_player_control()
if ctl.RMB and ctl.sneak then
return obj:remove()
end
if ctl.RMB then
local pos = obj:get_pos()
if not pos then return end
pos = vector.add(pos, vector.multiply(vector.direction(
whom:get_pos(), pos), 0.25))
pos.y = pos.y + 1
return obj:set_pos(pos)
end
if ctl.sneak then
self.data.wield = {
inv = whom:get_inventory():get_list("main"),
widx = whom:get_wield_index()
}
for k, v in pairs(self.data.wield.inv) do
self.data.wield.inv[k] = v:get_name()
end
nodecore.mock_player_wieldview(self)
return
end
local pos = obj:get_pos()
if not pos then return end
local dir = vector.direction(pos, whom:get_pos())
obj:set_yaw(minetest.dir_to_yaw(dir))
local anim = anims[self.data.anim or 0]
self.data.anim = anim
obj:set_animation({x = anim, y = anim}, 1)
end
})

View File

@ -0,0 +1,134 @@
-- LUALOCALS < ---------------------------------------------------------
local minetest, nodecore, pairs
= minetest, nodecore, pairs
-- LUALOCALS > ---------------------------------------------------------
nodecore.amcoremod()
local modname = minetest.get_current_modname()
local xyz = function(n) return {x = n, y = n, z = n} end
local size_w_item = xyz(0.2)
local size_w_tool = xyz(0.3)
local size_slot = xyz(0.075)
local size_item = xyz(0.1)
local hidden = {is_visible = false}
local selslot = {is_visible = true, visual_size = size_slot, textures = {"nc_player_wield:sel"}}
local emptyslot = {is_visible = true, visual_size = size_slot, textures = {"nc_player_wield:slot"}}
local function calcprops(itemname, iswield)
local def = minetest.registered_items[itemname]
if def and def.virtual_item then return hidden end
if itemname == "" then return iswield and hidden or emptyslot end
return {
is_visible = true,
visual_size = iswield and (def and def.type == "tool" and size_w_tool
or size_w_item) or (itemname == "" and size_slot) or size_item,
textures = {itemname},
glow = def and (def.light_source or def.glow or 0)
}
end
local propcache_item = {}
local propcache_wield = {}
local function itemprops(itemname, iswield)
local cache = iswield and propcache_wield or propcache_item
local found = cache[itemname]
if found then return found end
found = calcprops(itemname, iswield)
cache[itemname] = found
return found
end
local entname = modname .. ":wv"
local entdef
entdef = {
initial_properties = {
hp_max = 1,
physical = false,
collide_with_objects = false,
collisionbox = {0, 0, 0, 0, 0, 0},
visual = "wielditem",
textures = {""},
is_visible = false,
static_save = false,
glow = 0
},
on_activate = function(self)
self.on_step = entdef.on_step
end,
on_step = function(self)
local conf = self.conf
if not conf then return self.object:remove() end
local pdata = self.conf.ent.data.wield
if pdata == nil then return self.object:remove() end
if not pdata then return self.object:set_properties(hidden) end
if not self.att then
self.att = true
return self.object:set_attach(self.conf.ent.object,
conf.bone, conf.apos, conf.arot)
end
local widx = pdata.widx
if conf.slot == widx then
return self.object:set_properties(selslot)
end
return self.object:set_properties(itemprops(
pdata.inv[conf.slot or widx],
not conf.slot))
end
}
minetest.register_entity(entname, entdef)
function nodecore.mock_player_wieldview(ent)
local pos = ent.object:get_pos()
if not pos then return end
for _, wv in pairs(minetest.luaentities) do
if wv.name == entname and wv.conf.ent == ent then
wv.object:remove()
end
end
local function addslot(n, b, x, y, z, rx, ry, rz)
local obj = minetest.add_entity(pos, entname)
obj:get_luaentity().conf = {
ent = ent,
slot = n,
pos = pos,
bone = b,
apos = {
x = x,
y = y,
z = z
},
arot = {
x = rx or 0,
y = ry or 180,
z = rz or 0
}
}
end
addslot(nil, "Arm_Right", 0, 7, 2, -90, 200, 90)
local function cslot(n, x, y, z)
return addslot(n, "Bandolier", x * 0.8,
0.75 + y * 1.6,
-0.25 + z)
end
cslot(1, 1.75, 0, 0)
cslot(2, -1, 1, 0.05)
cslot(3, 1, 2, 0.1)
cslot(4, -1.75, 3, 0.02)
cslot(5, 1.75, 3, 0.02)
cslot(6, -1, 2, 0.1)
cslot(7, 1, 1, 0.05)
cslot(8, -1.75, 0, 0)
end

View File

@ -0,0 +1,26 @@
-- LUALOCALS < ---------------------------------------------------------
local math, minetest, nodecore
= math, minetest, nodecore
local math_pi
= math.pi
-- LUALOCALS > ---------------------------------------------------------
local function setup(p)
local n = p:get_player_name()
local r = minetest.get_player_privs(n)
r.fly = true
r.fast = true
r.give = true
r.interact = true
r.nc_reative = true
minetest.set_player_privs(n, r)
p:set_pos({x = -112.6, y = 5, z = -92.6})
p:set_look_horizontal(163.8 * math_pi / 180)
p:set_look_vertical(9 * math_pi / 180)
p:hud_set_flags({crosshair = false})
end
nodecore.register_on_joinplayer(setup)
nodecore.register_on_respawnplayer(setup)

View File

@ -0,0 +1 @@
depends = nc_api_all

View File

@ -1,70 +0,0 @@
-- LUALOCALS < ---------------------------------------------------------
local ItemStack, math, minetest, pairs
= ItemStack, math, minetest, pairs
local math_pi
= math.pi
-- LUALOCALS > ---------------------------------------------------------
local modname = minetest.get_current_modname();
minetest.settings:set("time_speed", 0)
minetest.after(0, function() minetest.set_timeofday(0.5) end)
local setinv = {
{"nc_stonework:tool_pick", 1, 0.7},
{"nc_stonework:tool_spade", 1, 0.8},
{"nc_stonework:tool_hatchet", 1, 0.4},
{"nc_stonework:tool_mallet", 1, 0.2},
{"nc_stonework:chip", 54},
false,
{"nc_terrain:sand_loose", 14},
{"nc_terrain:dirt_loose", 47}
}
for _, v in pairs(setinv) do
if v then
local n = modname .. ":" .. v[1]:gsub(":", "_")
if not minetest.registered_items[n] then
print(v[1])
local def = minetest.registered_items[v[1]]
minetest.register_item(n, {
["type"] = def["type"],
tiles = def.tiles,
inventory_image = def.inventory_image,
wield_image = def.wield_image,
on_drop = function() return ItemStack("") end,
on_place = function() end,
on_use = function() end
})
end
v[1] = n
end
end
local function setup(p)
local n = p:get_player_name()
local r = minetest.get_player_privs(n)
r.fly = true
r.fast = true
r.give = true
r.interact = true
r.nc_reative = true
minetest.set_player_privs(n, r)
p:set_pos({x = -112.6, y = 5, z = -92.6})
p:set_look_horizontal(163.8 * math_pi / 180)
p:set_look_vertical(9 * math_pi / 180)
local inv = p:get_inventory()
for i, v in pairs(setinv) do
if v then
local s = ItemStack(v[1])
s:set_count(v[2])
if v[3] then s:set_wear(65535 * v[3]) end
inv:set_stack("main", i, s)
end
end
end
minetest.register_on_joinplayer(setup)
minetest.register_on_respawnplayer(setup)

View File

@ -1 +0,0 @@
depends = nc_terrain, nc_stonework

View File

@ -0,0 +1,23 @@
-- LUALOCALS < ---------------------------------------------------------
local minetest, nodecore, pairs, rawset, type
= minetest, nodecore, pairs, rawset, type
-- LUALOCALS > ---------------------------------------------------------
local function noanim(t)
if type(t) ~= "table" then return t end
if t.animation then
rawset(t.animation, "length", 1000000)
end
for _, v in pairs(t) do noanim(v) end
return t
end
for _, v in pairs(minetest.registered_nodes) do
noanim(v.tiles)
noanim(v.special_tiles)
end
nodecore.register_on_register_item(function(_, def)
noanim(def.tiles)
noanim(def.special_tiles)
end)

View File

@ -0,0 +1 @@
depends = nc_api_all

View File

@ -0,0 +1,60 @@
-- LUALOCALS < ---------------------------------------------------------
local PcgRandom, minetest, nodecore
= PcgRandom, minetest, nodecore
-- LUALOCALS > ---------------------------------------------------------
local modname = minetest.get_current_modname()
local genname = modname .. ":gen"
minetest.register_node(genname, {
description = "Smoke Generator",
inventory_image = "nc_api_craft_smoke.png",
wield_image = "nc_api_craft_smoke.png",
drawtype = "airlike",
paramtype = "light",
sunlight_propagates = true,
walkable = false,
groups = {snappy = 1}
})
nodecore.register_dnt({
name = genname,
nodenames = {genname},
time = 2,
loop = true,
ignore_stasis = true,
action = function(pos)
local pcg = PcgRandom(minetest.hash_node_position(pos))
local rng = function() return pcg:next() / 2 ^ 32 + 0.5 end
for _ = 1, 10 do
local p = {
x = pos.x + rng() - 0.5,
y = pos.y + rng() * 2 - 0.5,
z = pos.z + rng() - 0.5,
}
minetest.add_particle({
pos = p,
texture = "nc_api_craft_smoke.png",
size = rng() * 2 + 1,
expirationtime = 2.1
})
end
end
})
nodecore.register_abm({
label = "smokegen",
nodenames = {genname},
interval = 1,
chance = 1,
ignore_stasis = true,
action = function(pos) return nodecore.dnt_set(pos, genname) end
})
nodecore.register_lbm({
name = genname,
nodenames = {genname},
run_at_every_load = true,
action = function(pos) return nodecore.dnt_reset(pos, genname, 0.01) end
})

View File

@ -0,0 +1 @@
depends = nc_api_all

View File

@ -0,0 +1,6 @@
-- LUALOCALS < ---------------------------------------------------------
local nodecore
= nodecore
-- LUALOCALS > ---------------------------------------------------------
nodecore.stasis = true

View File

@ -0,0 +1 @@
depends = nc_api_all

View File

@ -0,0 +1,35 @@
-- LUALOCALS < ---------------------------------------------------------
local getmetatable, minetest, pairs
= getmetatable, minetest, pairs
-- LUALOCALS > ---------------------------------------------------------
local publicfields = {
formspec = true,
infotext = true
}
local function hook(meta)
for k, v in pairs(meta) do
if k:sub(1, 4) == "set_" then
meta[k] = function(data, name, ...)
if not publicfields[name] then
data:mark_as_private(name)
end
return v(data, name, ...)
end
end
end
end
local rawmeta = minetest.get_meta
function minetest.get_meta(...)
local raw = rawmeta(...)
if raw then
local meta = getmetatable(raw)
if meta then
hook(meta)
minetest.get_meta = rawmeta
end
end
return raw
end

View File

@ -0,0 +1,8 @@
-- LUALOCALS < ---------------------------------------------------------
local minetest
= minetest
-- LUALOCALS > ---------------------------------------------------------
minetest.register_entity("nc_api:stackent", {
on_activate = function(self) return self.object:remove() end
})

View File

@ -1,22 +0,0 @@
-- LUALOCALS < ---------------------------------------------------------
local math, vector
= math, vector
local math_atan2
= math.atan2
-- LUALOCALS > ---------------------------------------------------------
vector.dot = vector.dot or function(a, b)
return a.x * b.x + a.y * b.y + a.z * b.z
end
vector.cross = vector.cross or function(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
vector.angle = vector.angle or function(a, b)
return math_atan2(vector.length(vector.cross(a, b)), vector.dot(a, b))
end

View File

@ -20,7 +20,7 @@ function nodecore.digparticles(nodedef, partdef)
elseif nodedef.inventory_image then
img[1] = nodedef.inventory_image
end
if #img < 1 then return minetest.log("no pummel tile images found!") end
if #img < 1 then return nodecore.log("warning", "no pummel tile images found!") end
img = nodecore.pickrand(img)
if img.name then img = img.name end

View File

@ -1,11 +1,11 @@
-- 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
local dofile, error, ipairs, minetest, pairs, rawget, rawset,
setmetatable, table, tostring, type
= dofile, error, ipairs, minetest, pairs, rawget, rawset,
setmetatable, table, tostring, type
local table_concat, table_insert, table_sort
= table.concat, table.insert, table.sort
-- LUALOCALS > ---------------------------------------------------------
local nodecore = rawget(_G, "nodecore") or {}
@ -42,11 +42,58 @@ setmetatable(nodecore, {
end
})
include("compat_vector")
include("issue7020")
include("issue9043")
minetest.register_on_mods_loaded(function()
for _, n in pairs(minetest.get_modnames()) do
if n == "default" then
error(nodecore.product
.. " cannot be loaded on top of another game!")
error()
end
end
end)
local levels = {none = true, error = true, warning = true, action = true, info = true, verbose = true}
function nodecore.log(level, ...)
if not level or not levels[level] then error("invalid log level " .. tostring(level)) end
return minetest.log(level, ...)
end
nodecore.log("action", nodecore.product .. (nodecore.version and (" Version " .. nodecore.version)
or " DEVELOPMENT VERSION"))
do
local ticked = 0
local function regreport()
ticked = ticked + 1
if ticked < 5 then return minetest.after(0, regreport) end
local reg = "registered_"
local t = {}
for k, v in pairs(nodecore) do
if k:sub(1, #reg) == reg and type(v) == "table" then
local qty = 0
for _ in pairs(v) do qty = qty + 1 end
t[#t + 1] = "#" .. k .. " = " .. qty
end
end
table_sort(t)
for _, x in ipairs(t) do nodecore.log("action", x) end
end
minetest.after(0, regreport)
end
minetest.register_on_joinplayer(function(player)
local pname = player:get_player_name()
local pinfo = minetest.get_player_information(pname)
if pinfo.protocol_version < 39 then
return minetest.kick_player(pname, "Outdated client")
end
end)
include("compat_issue10127")
include("compat_legacyent")
include("util_misc")
include("util_hookmeta")
include("util_falling")
include("util_scan_flood")
include("util_node_is")
@ -58,27 +105,29 @@ include("util_sound")
include("util_translate")
include("util_ezschematic")
include("util_gametime")
include("util_settlescan")
include("util_texturemod")
include("match")
include("fx_digparticles")
include("register_limited_abm")
include("register_aism")
include("register_soaking")
include("register_ambiance")
include("register_mods")
include("register_entlabels")
include("mapgen_limits")
include("mapgen_shared")
include("item_on_register")
include("item_drop_in_place")
include("item_falling_repose")
include("item_falling_settle")
include("item_alternate_loose")
include("item_group_visinv")
include("item_oldnames")
include("item_tool_wears_to")
include("item_tool_break")
include("item_tool_sounds")
include("item_tool_rakes")
include("item_punch_sounds")
include("item_sound_pitch")
include("item_nodebox_zfighting")
include("item_virtual")
include("item_stackmax")
include("item_touch_hurt")
include("item_txp_overlay")
include("item_tiledump")

View File

@ -1,22 +0,0 @@
-- 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)

View File

@ -1,30 +0,0 @@
-- LUALOCALS < ---------------------------------------------------------
local minetest, rawset
= minetest, rawset
-- LUALOCALS > ---------------------------------------------------------
-- minetest.rotate_node uses sneak to invert the wall/floor orientation
-- direction, but REMOVES the use of sneak to prevent right-click on the
-- underlying node, which is a far more important function.
minetest.rotate_node = function(itemstack, placer, pointed_thing)
local invert_wall = placer and placer:get_player_control().sneak or false
local function commit()
return minetest.rotate_and_place(itemstack, placer, pointed_thing, false,
{invert_wall = invert_wall}, true)
end
if not invert_wall then return commit() end
local node = minetest.get_node_or_nil(pointed_thing.under)
if not node then return end
local def = minetest.registered_nodes[node.name]
if not def.on_rightclick then return commit() end
local oldrc = def.on_rightclick
local function helper(...)
rawset(def, "on_rightclick", oldrc)
return ...
end
rawset(def, "on_rightclick", nil)
return helper(commit())
end

View File

@ -13,7 +13,9 @@ nodecore.register_on_register_item(function(_, def)
local dip = def.drop_in_place
if dip then
if type(dip) ~= "table" then dip = {name = dip} end
def.drop = def.drop or ""
def.drop_non_silktouch = def.drop_non_silktouch
or def.drop ~= "" and def.drop
def.drop = ""
def.node_dig_prediction = def.node_dig_prediction or dip.name
local st = def.silktouch
if st == nil then
@ -29,10 +31,16 @@ nodecore.register_on_register_item(function(_, def)
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
return nodecore.item_eject(pos, stack)
end
dip.param2 = node.param2
minetest.set_node(pos, dip)
if def.drop_non_silktouch then
local stack = digger:get_inventory():add_item("main",
def.drop_non_silktouch)
if stack:is_empty() then return end
nodecore.item_eject(pos, stack)
end
end
end
end)

View File

@ -1,59 +0,0 @@
-- LUALOCALS < ---------------------------------------------------------
local minetest, nodecore, pairs, setmetatable, vector
= minetest, nodecore, pairs, setmetatable, vector
-- LUALOCALS > ---------------------------------------------------------
local function signal(pos, ...)
pos = vector.round(pos)
pos.y = pos.y + 1
for _, obj in pairs(minetest.get_objects_inside_radius(pos, 2)) do
if vector.equals(vector.round(obj:get_pos()), pos) then
obj = obj.get_luaentity and obj:get_luaentity()
if obj and obj.on_force_settle then
obj:on_force_settle(pos)
return signal(pos, ...)
end
end
end
return ...
end
local bifn = minetest.registered_entities["__builtin:falling_node"]
local falling = {
on_force_settle = function(self, pos)
local oldnode = minetest.get_node(pos)
if oldnode.name == "ignore" then
return self.object:remove()
end
if oldnode.name ~= "air" then
local olddef = minetest.registered_nodes[oldnode.name]
if olddef and (not olddef.buildable_to)
and (olddef.liquidtype ~= "none") then
for _, item in pairs(minetest.get_node_drops(oldnode, "")) do
minetest.add_item(pos, item)
end
end
end
local def = minetest.registered_nodes[self.node.name]
minetest.set_node(pos, def and self.node or {name = "air"})
if self.meta then minetest.get_meta(pos):from_table(self.meta) end
nodecore.node_sound(pos, "place")
self.object:remove()
minetest.check_for_falling(pos)
end,
on_step = function(self, ...)
local oldnode = minetest.add_node
minetest.add_node = function(pos, node, ...)
minetest.add_node = oldnode
return signal(self.object:get_pos(),
oldnode(pos, node, ...))
end
local function helper(...)
minetest.add_node = oldnode
return ...
end
return helper(bifn.on_step(self, ...))
end
}
setmetatable(falling, bifn)
minetest.register_entity(":__builtin:falling_node", falling)

View File

@ -1,197 +0,0 @@
-- 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, ss)
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 = ss and true or 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()
if ratio > 1 then ratio = 1 end
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, true)
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

View File

@ -10,5 +10,6 @@ nodecore.register_on_register_item(function(name, def)
minetest.register_alias(v, name)
end
end
def.oldnames = nil
end
end)

View File

@ -1,11 +1,34 @@
-- LUALOCALS < ---------------------------------------------------------
local minetest, nodecore
= minetest, nodecore
local minetest, nodecore, vector
= minetest, nodecore, vector
-- LUALOCALS > ---------------------------------------------------------
local lasthit = {}
minetest.register_on_punchnode(function(pos, node, puncher)
local function wearfx(puncher, wield)
nodecore.sound_play("nc_api_toolwear",
{object = puncher, gain = 0.5})
local ppos = puncher:get_pos()
if not ppos then return end
ppos.y = ppos.y + puncher:get_properties().eye_height - 0.1
local look = puncher:get_look_dir()
for _ = 1, 3 do
nodecore.digparticles(wield:get_definition(), {
time = 0.05,
amount = 1,
minpos = ppos,
maxpos = ppos,
minvel = vector.add(look, {x = -1, y = -1, z = -1}),
maxvel = vector.add(look, {x = 1, y = 1, z = 1}),
minacc = {x = 0, y = -8, z = 0},
maxacc = {x = 0, y = -8, z = 0},
minexptime = 0.25,
maxexptime = 1
})
end
end
nodecore.register_on_punchnode("node punch sounds", function(pos, node, puncher)
if not nodecore.player_visible(puncher) then return end
local pname = puncher:get_player_name()
@ -25,19 +48,37 @@ minetest.register_on_punchnode(function(pos, node, puncher)
end
if wield:get_wear() >= (65536 * 0.95) then
minetest.sound_play("nc_api_toolwear",
{object = puncher, gain = 0.5})
wearfx(puncher, wield)
end
end)
minetest.register_on_dignode(function(pos, node, digger)
nodecore.register_on_dignode("other player dig sounds", function(pos, node, digger)
if not nodecore.player_visible(digger) then return end
return nodecore.node_sound(pos, "dug",
{node = node, except = digger})
end)
minetest.register_on_placenode(function(pos, node, placer)
nodecore.register_on_placenode("other player place sounds", function(pos, node, placer)
if not nodecore.player_visible(placer) then return end
return nodecore.node_sound(pos, "place",
{node = node, except = placer})
end)
-- Work around 5.2 making dig/place sounds redundant,
-- but not backporting support to 5.0.
local function block_builtin_sounds(func)
return function(...)
local old_sound = minetest.sound_play
function minetest.sound_play(spec, param, ephem, ...)
if ephem and param.exclude_player then return end
return old_sound(spec, param, ephem, ...)
end
local function helper(...)
minetest.sound_play = old_sound
return ...
end
return helper(func(...))
end
end
minetest.item_place_node = block_builtin_sounds(minetest.item_place_node)
minetest.node_dig = block_builtin_sounds(minetest.node_dig)

View File

@ -0,0 +1,37 @@
-- LUALOCALS < ---------------------------------------------------------
local nodecore, pairs
= nodecore, pairs
-- LUALOCALS > ---------------------------------------------------------
local soundadj = {
nc_optics_glassy = -3,
nc_lode_annealed = -3,
nc_lode_tempered = -3
}
local toolgroups = {
cracky = true,
thumpy = true,
choppy = true,
crumbly = true,
snappy = true,
scratchy = true
}
nodecore.register_on_register_item(function(_, def)
if def.type ~= "node" then return end
local grp = def.groups
if not grp then return end
local snd = def.sounds
if (not snd) or snd.no_level_pitch then return end
local level = 0
for k in pairs(toolgroups) do
local l = grp[k]
if l and l > level then level = l end
end
if level <= 0 then return end
for _, v in pairs(snd) do
local l = level + (v.name and soundadj[v.name] or 0)
if l > 0 then v.pitch = (v.pitch or 1) * (1 + 0.1 * l) end
end
snd.no_level_pitch = true
end)

View File

@ -0,0 +1,99 @@
-- LUALOCALS < ---------------------------------------------------------
local io, ipairs, minetest, nodecore, pairs, table, tostring, type
= io, ipairs, minetest, nodecore, pairs, table, tostring, type
local io_open, table_concat, table_insert, table_sort
= io.open, table.concat, table.insert, table.sort
-- LUALOCALS > ---------------------------------------------------------
if not nodecore.infodump() then return end
local faces = {
"top",
"bottom",
"left",
"right",
"front",
"back"
}
local function tilize(tiles, max)
if not tiles then return end
tiles = minetest.deserialize(minetest.serialize(tiles))
if not tiles then return end
for k2, v2 in pairs(tiles) do
tiles[k2] = (type(v2) == "table" and v2.name or v2.image) or v2
end
while max and #tiles > max do tiles[#tiles] = nil end
while (#tiles > 1) and (tiles[#tiles] == tiles[#tiles - 1]) do
tiles[#tiles] = nil
end
return tiles
end
minetest.after(0, function()
local function noblank(s) return s and tostring(s):match("%S") and tostring(s) or nil end
local data = {}
for k, v in pairs(minetest.registered_items) do
local key = noblank(v.description) or k
key = key:gsub("%W+", "_"):lower()
data[key] = data[key] or {}
data[key][#data[key] + 1] = {
technical_name = k,
drawtype = v.drawtype,
description = v.description,
tiles = tilize(v.tiles, #faces),
inventory_image = noblank(v.inventory_image),
wield_image = noblank(v.wield_image),
special_tiles = tilize(v.special_tiles),
}
end
local ents = {}
for _, v in pairs(data) do
local curent = {}
local function writeln(s) curent[#curent + 1] = s end
table_sort(v, function(a, b) return a.technical_name < b.technical_name end)
local mesh
for _, t in ipairs(v) do
mesh = mesh or t.drawtype == "mesh"
local tn = t.technical_name
if t.tiles then
local tt = t.tiles
for i = #tt, 1, -1 do
if i == #tt and i ~= #faces then
writeln(tn .. " * " .. tt[i])
else
writeln(tn .. " " .. faces[i] .. " " .. tt[i])
end
end
end
if t.special_tiles then
for i, st in pairs(t.special_tiles) do
writeln(tn .. " special_" .. i .. " " .. st)
end
end
if noblank(t.inventory_image) then
writeln(tn .. " inventory " .. t.inventory_image)
end
if noblank(t.wield_image) then
writeln(tn .. " wield " .. t.wield_image)
end
end
if #curent > 0 then
if mesh then
table_insert(curent, 1, "# <!> MESH DRAWTYPE; FACES MAY"
.. " MISMATCH NAMES")
end
if noblank(v[1].description) then
table_insert(curent, 1, "# " .. v[1].description)
end
ents[#ents + 1] = table_concat(curent, "\n")
end
end
table_sort(ents)
local f = io_open(minetest.get_worldpath() .. "/texturepack_override.template.txt", "wb")
f:write(table_concat(ents, "\n\n"))
f:close()
end)

View File

@ -0,0 +1,43 @@
-- LUALOCALS < ---------------------------------------------------------
local ItemStack, nodecore, vector
= ItemStack, nodecore, vector
-- LUALOCALS > ---------------------------------------------------------
local function breakfx(who, def)
if def.sound and def.sound.breaks then
nodecore.sound_play(def.sound.breaks,
{object = who, gain = 0.5})
end
local pos = who:get_pos()
if pos then
pos.y = pos.y + who:get_properties().eye_height - 0.1
local look = vector.multiply(who:get_look_dir(), 2)
for _ = 1, 5 do
nodecore.digparticles(def, {
time = 0.05,
amount = 10,
minpos = pos,
maxpos = pos,
minvel = vector.add(look, {x = -2, y = -2, z = -2}),
maxvel = vector.add(look, {x = 2, y = 2, z = 2}),
minacc = {x = 0, y = -8, z = 0},
maxacc = {x = 0, y = -8, z = 0},
minexptime = 0.25,
maxexptime = 1
})
end
end
end
nodecore.register_on_register_item(function(_, def)
if def.tool_wears_to or def.type == "tool" then
def.after_use = def.after_use or function(what, who, _, dp)
what:add_wear(dp.wear)
if what:get_count() == 0 then
breakfx(who, def)
return ItemStack(def.tool_wears_to or "")
end
return what
end
end
end)

View File

@ -0,0 +1,125 @@
-- LUALOCALS < ---------------------------------------------------------
local ipairs, math, minetest, nodecore, pairs, table, vector
= ipairs, math, minetest, nodecore, pairs, table, vector
local math_abs, math_max, table_sort
= math.abs, math.max, table.sort
-- LUALOCALS > ---------------------------------------------------------
-- To register a tool as a rake, provie a callback:
-- on_rake(pos, node, user) returns volume, checkfunc
-- volume: ordered array of relative positions to be dug by rake
-- checkfunc(pos, node, rel): determine if item can be dug
-- rel: relative vector taken from volume array
-- returns true to dig, nil to not dig, false to abort loop
local volcache = {}
function nodecore.rake_volume(dxmax, dymax, dzmax)
dzmax = dzmax or dxmax
local key = minetest.pos_to_string({x = dxmax, y = dymax, z = dzmax})
local rakepos = volcache[key]
if rakepos then return rakepos end
rakepos = {}
for dy = -dymax, dymax do
for dx = -dxmax, dxmax do
for dz = -dzmax, dzmax do
local v = {x = dx, y = dy, z = dz}
v.d = vector.length(v)
v.rxz = math_max(math_abs(dx), math_abs(dz))
v.ry = math_abs(dy)
rakepos[#rakepos + 1] = v
end
end
end
table_sort(rakepos, function(a, b) return a.d < b.d end)
volcache[key] = rakepos
return rakepos
end
function nodecore.rake_index(filterfunc)
local rakable = {}
minetest.after(0, function()
for k, v in pairs(minetest.registered_nodes) do
if filterfunc(v, k) then
rakable[k] = true
end
end
end)
return function(_, node) return rakable[node.name] end
end
local function deferfall(func, ...)
local oldfall = minetest.check_for_falling
minetest.check_for_falling = nodecore.fallcheck
local function helper(...)
minetest.check_for_falling = oldfall
return ...
end
return helper(func(...))
end
local laststack
local lastraking
local old_node_dig = minetest.node_dig
minetest.node_dig = function(pos, node, user, ...)
laststack = nodecore.stack_get(pos)
local wield = user and user:is_player() and user:get_wielded_item()
lastraking = wield and (wield:get_definition() or {}).on_rake
if lastraking then return deferfall(old_node_dig, pos, node, user, ...) end
return old_node_dig(pos, node, user, ...)
end
local stackonly = {}
minetest.after(0, function()
for k, v in pairs(minetest.registered_nodes) do
if v.groups.is_stack_only then stackonly[k] = true end
end
end)
local function matching(_, na, pb, nb)
if stackonly[na.name] then
if not stackonly[nb.name] then return end
return (laststack and laststack:get_name()) == nodecore.stack_get(pb):get_name()
end
return na.name == nb.name
end
local function dorake(volume, check, pos, node, user, ...)
local sneak = user:get_player_control().sneak
local objpos = {}
for _, rel in ipairs(volume) do
local p = vector.add(pos, rel)
local n = minetest.get_node(p)
local allow = (rel.d > 0 or nil) and check(p, n, rel)
if allow == false then break end
if allow and ((not sneak) or matching(pos, node, p, n)) then
minetest.node_dig(p, n, user, ...)
objpos[minetest.hash_node_position(p)] = true
end
end
for _, lua in pairs(minetest.luaentities) do
if lua.name == "__builtin:item" then
local p = lua.object and lua.object:get_pos()
if p and objpos[minetest.hash_node_position(
vector.round(p))] then
lua.object:set_pos(pos)
end
end
end
end
local rakelock = {}
nodecore.register_on_dignode("rake handling", function(pos, node, user, ...)
local nowraking = lastraking
if not nowraking then return end
lastraking = nil
if not (pos and node and user and user:is_player()) then return end
local volume, check = nowraking(pos, node, user, ...)
if not (volume and check) then return end
local pname = user:get_player_name()
if rakelock[pname] then return end
rakelock[pname] = true
deferfall(dorake, volume, check, pos, node, user, ...)
rakelock[pname] = nil
end)

View File

@ -1,20 +0,0 @@
-- 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)

View File

@ -0,0 +1,41 @@
-- LUALOCALS < ---------------------------------------------------------
local ItemStack, minetest, nodecore
= ItemStack, minetest, nodecore
-- LUALOCALS > ---------------------------------------------------------
local function toolcandig(wield, node)
if (not wield) or wield:is_empty() then return end
local def = node and node.name and minetest.registered_items[node.name]
if not (def and def.groups) then return end
local toolspeed = nodecore.toolspeed(wield, def.groups)
if not toolspeed then return end
local handspeed = nodecore.toolspeed(ItemStack(""), def.groups)
return handspeed and (toolspeed < handspeed)
end
nodecore.register_on_register_item(function(_, def)
local dmg = def.pointable ~= false and def.groups
and def.groups.damage_touch
if not (dmg and dmg > 0) then return end
def.on_punch = def.on_punch or function(pos, node, puncher, ...)
if puncher and puncher:is_player()
and (not toolcandig(puncher:get_wielded_item(), node)) then
nodecore.addphealth(puncher, -dmg, {
nc_type = "node_touch_hurt",
node = node
})
end
return minetest.node_punch(pos, node, puncher, ...)
end
def.on_scaling = def.on_scaling or function(_, _, player, node)
if player and player:is_player() then
nodecore.addphealth(player, -dmg, {
nc_type = "node_touch_hurt",
node = node
})
end
return true
end
end)

View File

@ -0,0 +1,58 @@
-- LUALOCALS < ---------------------------------------------------------
local io, minetest, nodecore, pairs, table, tostring, type
= io, minetest, nodecore, pairs, table, tostring, type
local io_open, table_concat, table_sort
= io.open, table.concat, table.sort
-- LUALOCALS > ---------------------------------------------------------
local missing = {}
minetest.after(0, function()
local t = {}
for k in pairs(missing) do t[#t + 1] = k end
if #t < 1 then
return nodecore.log("action", "txp override images ok")
end
table_sort(t)
nodecore.log("warning", "missing txp override images:\n\t"
.. table_concat(t, "\n\t"))
end)
local function overlay(name, img, imgtype, force)
if type(img) == "table" then
local t = {}
for k, v in pairs(img) do
if type(k) == "number" then
t[k] = overlay(name, v, imgtype .. tostring(k), force)
elseif k == "name" then
t[k] = overlay(name, v, imgtype, force)
else
t[k] = v
end
end
return t
end
if (not img) or (img == "") or (type(img) ~= "string")
or (not (force or img:match("%^"))) or img:match("%^txp_") then return img end
local tpath = "txp_" .. name:gsub("^%W+", "")
:gsub("%W+", "_") .. "_" .. imgtype .. ".png"
local fullpath = minetest.get_modpath(minetest.get_current_modname())
.. "/textures/" .. tpath
local f = io_open(fullpath, "rb")
if not f then
missing[fullpath] = img
return img
end
f:close()
return tostring(nodecore.tmod(img):add(tpath):makealpha(255, 254, 2))
end
nodecore.register_on_register_item(function(name, def)
def.inventory_image = overlay(name, def.inventory_image, "inv")
def.wield_image = overlay(name, def.wield_image, "wield")
def.special_tiles = overlay(name, def.special_tiles, "special", true)
end)

View File

@ -1,6 +1,6 @@
-- LUALOCALS < ---------------------------------------------------------
local ItemStack, minetest, nodecore, setmetatable
= ItemStack, minetest, nodecore, setmetatable
local ItemStack, minetest, nodecore
= ItemStack, minetest, nodecore
-- LUALOCALS > ---------------------------------------------------------
local function isvirtual(item)
@ -17,13 +17,3 @@ local function guard(func)
end
minetest.spawn_item = guard(minetest.spawn_item)
minetest.add_item = guard(minetest.add_item)
local bii = minetest.registered_entities["__builtin:item"]
local newbii = {
on_activate = function(self, ...)
bii.on_activate(self, ...)
if isvirtual(self.itemstring) then return self.object:remove() end
end
}
setmetatable(newbii, bii)
minetest.register_entity(":__builtin:item", newbii)

View File

@ -1,4 +1,4 @@
# textdomain: nc_api
(C)2018-2019 by Aaron Suen <warr1024@@gmail.com>=(C)2018-2019 から Aaron Suen <warr1024@@gmail.com>
(C)2018-2020 by Aaron Suen <warr1024@@gmail.com>=(C)2018-2020 から Aaron Suen <warr1024@@gmail.com>
(and 1 more hint)=(さらに1つのヒント)
(and @1 more hints)=(さらに@1つのヒント)

View File

@ -1,8 +1,9 @@
# textdomain: nc_api
(C)2018-2019 by Aaron Suen <warr1024@@gmail.com>=(C)2018-2019 por Aaron Suen <war1024@@gmail.com>
(C)2018-2020 by Aaron Suen <warr1024@@gmail.com>=(C)2018-2020 por Aaron Suen <war1024@@gmail.com>
(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.
- Drop items onto ground to create stack nodes. They do not decay.=- Solte itens no chão para criar um node de itens amontoados. Eles não desaparecem.
- 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.
@ -10,10 +11,64 @@
- 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.
- Stuck in a pit? Pummel surfaces barehanded to find places to climb.=[REMOVED].
- 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).
...and 1 more hint...=...e mais 1 dica...
...and @1 more hints...=...e mais @1 dicas...
...have you activated a lens yet?=...você já ativou uma lente?
...have you assembled a staff from sticks yet?=...você já montou um bastão usando gravetos?
...have you assembled a wooden frame yet?=...você já montou um estrutura de madeira?
...have you assembled a wooden ladder yet?=...você já montou uma escada de madeira?
...have you assembled a wooden shelf yet?=...você já montou uma estante de madeira?
...have you assembled a wooden tool yet?=...você já montou uma ferramenta de madeira?
...have you assembled an adze out of sticks yet?=...você já montou um enxó usando gravetos?
...have you assembled an annealed lode tote handle yet?=...você já montou uma alça de bolsa recozida?
...have you bashed a plank into sticks yet?=...você já quebrou uma tábua em gravetos batendo nela?
...have you broken cobble into chips yet?=...você já quebrou pedregulho em pedaços?
...have you carved a wooden plank completely yet?=...você já entalhou completamente uma tábua de madeira?
...have you carved wooden tool heads from planks yet?=...você já transformou uma tábua em cabeças de ferramentas, entalhando a madeira?
...have you chipped chromatic glass into prisms yet?=...você já quebrou um vidro cromático em prismas, lascando o vidro?
...have you chopped a lode cube into prills yet?=...você já quebrou um veio mineral em lascas, usando um machado?
...have you chopped chromatic glass into lenses yet?=...você já quebrou vidro cromático em lentes, usando um machado?
...have you chopped up charcoal yet?=...você já quebrou carvão usando um machado?
...have you cold-forged an annealed lode tool head yet?=...você já fez uma forja fria de uma cabeça de ferramenta de veio mineral?
...have you cold-forged lode down completely yet?=...você já fez uma forja fria de um veio mineral?
...have you cooled molten glass into crude glass yet?=...você já esfriou vidro derretido para que este virasse vidro cru?
...have you cut down a tree yet?=...você já cortou uma árvore?
...have you dug up a tree stump yet?=...você já desenterrou um toco de árvore?
...have you dug up dirt yet?=...você já cavou terra?
...have you dug up gravel yet?=...você já cavou cascalho?
...have you dug up lode ore yet?=...você já desenterrou um veio mineral?
...have you dug up sand yet?=...você já cavou areia?
...have you dug up stone yet?=...você já cavou pedra?
...have you found a lode stratum yet?=...você já encontrou um estrato de veio mineral?
...have you found ash yet?=...você já encontrou cinzas?
...have you found charcoal yet?=...você já encontrou carvão?
...have you found deep stone strata yet?=...você já encontrou um estrato de pedra profunda?
...have you found dry leaves yet?=...você já encontrou folhas secas?
...have you found eggcorns yet?=...você já encontrou semente de carvalho?
...have you found lode ore yet?=...você já encontrou um veio mineral?
...have you found molten rock yet?=...você já encontrou pedra derretida (lava)?
...have you found sponges yet?=...você já encontrou esponjas?
...have you found sticks yet?=...você já encontrou gravetos?
...have you made fire by rubbing sticks together yet?=...você já fez fogo esfregando gravetos?
...have you melted down lode metal yet?=...você já derreteu um veio mineral?
...have you melted sand into glass yet?=...você já transformou areia em vidro, derretendo a areia?
...have you molded molten glass into clear glass yet?=...você já moldou vidro derretido em vidro transparente?
...have you packed high-quality charcoal yet?=...você já juntou carvão de alta qualidade?
...have you packed stone chips back into cobble yet?=...você já juntou pedaços de pedra para que virassem pedregulho?
...have you planted an eggcorn yet?=...você já plantou uma semente de carvalho?
...have you produced light from a lens yet?=...você já gerou luz a partir de uma lente?
...have you put a stone tip onto a tool yet?=...você já colocou uma ponta de pedra em uma ferramenta?
...have you quenched molten glass into chromatic glass yet?=...você já temperou vidro derretido para que virasse vidro cromático?
...have you sintered glowing lode into a cube yet?=...você já moldou veio mineral incandescente em um cubo?
...have you split a tree trunk into planks yet?=...você já fez tábuas quebrando troncos de madeira?
...have you tempered a lode anvil yet?=...você já fez uma bigorna temperando veio mineral?
...have you tempered a lode tool head yet?=...você já fez uma cabeça de ferramenta temperando veio mineral?
...have you welded a lode pick and spade together yet?=...você já soldou uma picareta de veio mineral com uma pá de veio mineral?
About=Sobre
Active Lens=Lente Ativa
Active Prism=Prisma Ativo
@ -78,8 +133,7 @@ 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
Not all game content is covered by hints. Explore!=As dicas não cobrem todo o conteúdo do jogo. Explore!
Prism=Prisma
Progress: @1 complete, @2 current, @3 future=Progresso: @1 completo(s), @2 atual(is), @3 futuro(s)
Pummel=Esmurrar

View File

@ -1,32 +1,93 @@
# textdomain: nc_api
(C)2018-2019 by Aaron Suen <warr1024@@gmail.com>=(C)2018-2019 por Aaron Suen <war1024@@gmail.com>
(C)2018-2020 by Aaron Suen <warr1024@@gmail.com>=(C)2018-2020 por Aaron Suen <war1024@@gmail.com>
(and 1 more hint)=(e mais 1 dica)
(and @1 more hints)=(e mais @1 dica)
- "Furnaces" are not a thing; discover smelting with open flames.=-"Fornalhas" não existem; descubra como cozinhar com chamas à céu aberto.
- Can't dig trees or grass? Search for sticks in the canopy.=- Não consegue quebrar árvores ou cavar? Procure por gravetos na cobertura.
- Crafting is done by building recipes in-world.=- A Criação de Itens é feita construindo as receitas pelo mundo.
- Do not use F5 debug info; it will mislead you!=- Não use as informações de debug do F5; Apenas irão lhe confundir!
- Drop items onto ground to create stack nodes. They do not decay.=- Solte itens no chão para criar um node de itens amontoados. Eles não desaparecem.
- Drop items onto ground to create stack nodes. They do not decay.=- Derrube itens no chão para criar pilhas de nodes. Eles não somem.
- Hold/repeat right-click on walls/ceilings barehanded to climb.=- Segure/repita o clique direito em paredes/tetos para escalar com mãos nuas.
- 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.
- Larger recipes are usually more symmetrical.=- Receitas maiores geralmente são mais simétricas.
- 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.
- Ores may be hidden, but revealed by subtle clues in terrain.=sutis pelo terreno.
- 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.
- Some recipes use a 3x3 "grid", laid out flat on the ground.=- Algumas receitas usam uma "grade" 3x3, disposta diretamente sobre o chão.
- 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.
- Stuck in a pit? Hold right-click on surfaces barehanded to climb.=mãos nuas para escalar.
- Stuck in a pit? Pummel surfaces barehanded to find places to climb.=[REMOVED].
- The game is challenging by design, sometimes frustrating. DON'T GIVE UP!=- O jogo é feito para ser desafiante, algumas fezes frustrante. NÃO DESISTA!
- 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.
- Trouble lighting a fire? Try using longer sticks, more tinder.=inflamáveis.
- 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).
...and 1 more hint...=...e mais 1 dica...
...and @1 more hints...=...e mais @1 dicas...
...have you activated a lens yet?=...você já ativou uma lente?
...have you assembled a staff from sticks yet?=...você já montou um bastão usando gravetos?
...have you assembled a wooden frame yet?=...você já montou um estrutura de madeira?
...have you assembled a wooden ladder yet?=...você já montou uma escada de madeira?
...have you assembled a wooden shelf yet?=...você já montou uma estante de madeira?
...have you assembled a wooden tool yet?=...você já montou uma ferramenta de madeira?
...have you assembled an adze out of sticks yet?=...você já montou um enxó usando gravetos?
...have you assembled an annealed lode tote handle yet?=...você já montou uma alça de bolsa recozida?
...have you bashed a plank into sticks yet?=...você já quebrou uma tábua em gravetos batendo nela?
...have you broken cobble into chips yet?=...você já quebrou pedregulho em pedaços?
...have you carved a wooden plank completely yet?=...você já entalhou completamente uma tábua de madeira?
...have you carved wooden tool heads from planks yet?=...você já transformou uma tábua em cabeças de ferramentas, entalhando a madeira?
...have you chipped chromatic glass into prisms yet?=...você já quebrou um vidro cromático em prismas, lascando o vidro?
...have you chopped a lode cube into prills yet?=...você já quebrou um veio mineral em lascas, usando um machado?
...have you chopped chromatic glass into lenses yet?=...você já quebrou vidro cromático em lentes, usando um machado?
...have you chopped up charcoal yet?=...você já quebrou carvão usando um machado?
...have you cold-forged an annealed lode tool head yet?=...você já fez uma forja fria de uma cabeça de ferramenta de veio mineral?
...have you cold-forged lode down completely yet?=...você já fez uma forja fria de um veio mineral?
...have you cooled molten glass into crude glass yet?=...você já esfriou vidro derretido para que este virasse vidro cru?
...have you cut down a tree yet?=...você já cortou uma árvore?
...have you dug up a tree stump yet?=...você já desenterrou um toco de árvore?
...have you dug up dirt yet?=...você já cavou terra?
...have you dug up gravel yet?=...você já cavou cascalho?
...have you dug up lode ore yet?=...você já desenterrou um veio mineral?
...have you dug up sand yet?=...você já cavou areia?
...have you dug up stone yet?=...você já cavou pedra?
...have you found a lode stratum yet?=...você já encontrou um estrato de veio mineral?
...have you found ash yet?=...você já encontrou cinzas?
...have you found charcoal yet?=...você já encontrou carvão?
...have you found deep stone strata yet?=...você já encontrou um estrato de pedra profunda?
...have you found dry leaves yet?=...você já encontrou folhas secas?
...have you found eggcorns yet?=...você já encontrou semente de carvalho?
...have you found lode ore yet?=...você já encontrou um veio mineral?
...have you found molten rock yet?=...você já encontrou pedra derretida (lava)?
...have you found sponges yet?=...você já encontrou esponjas?
...have you found sticks yet?=...você já encontrou gravetos?
...have you made fire by rubbing sticks together yet?=...você já fez fogo esfregando gravetos?
...have you melted down lode metal yet?=...você já derreteu um veio mineral?
...have you melted sand into glass yet?=...você já transformou areia em vidro, derretendo a areia?
...have you molded molten glass into clear glass yet?=...você já moldou vidro derretido em vidro transparente?
...have you packed high-quality charcoal yet?=...você já juntou carvão de alta qualidade?
...have you packed stone chips back into cobble yet?=...você já juntou pedaços de pedra para que virassem pedregulho?
...have you planted an eggcorn yet?=...você já plantou uma semente de carvalho?
...have you produced light from a lens yet?=...você já gerou luz a partir de uma lente?
...have you put a stone tip onto a tool yet?=...você já colocou uma ponta de pedra em uma ferramenta?
...have you quenched molten glass into chromatic glass yet?=...você já temperou vidro derretido para que virasse vidro cromático?
...have you sintered glowing lode into a cube yet?=...você já moldou veio mineral incandescente em um cubo?
...have you split a tree trunk into planks yet?=...você já fez tábuas quebrando troncos de madeira?
...have you tempered a lode anvil yet?=...você já fez uma bigorna temperando veio mineral?
...have you tempered a lode tool head yet?=...você já fez uma cabeça de ferramenta temperando veio mineral?
...have you welded a lode pick and spade together yet?=...você já soldou uma picareta de veio mineral com uma pá de veio mineral?
About=Sobre
Active Lens=Lente Ativa
Active Prism=Prisma Ativo
Adobe Mix=Mistura de Adobe
Adze=Enxó
Aggregate=Agregar
Aggregate=Agregado
Air=Ar
Amalgamation=Amalgamação
Annealed Lode=Veio Mineral Recozido
Annealed Lode Bar=Barra de Veio Mineral Recozida
Annealed Lode Hatchet=Machado de Veio Mineral Recozida
@ -41,12 +102,32 @@ 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
Artificial Water=Água Artificial
Ash=Cinza
Ash Lump=Nódulo de Cinzas
Bindy=Liguento
Bindy Adobe=Adobe Liguento
Bindy Pliant Adobe=Adobe Flexível Liguenta
Bindy Pliant Sandstone=Arenito Flexível Liguento
Bindy Pliant Stone=Pedra Flexível Liguenta
Bindy Pliant Tarstone=Pedra de Alcatrão Flexível Liguenta
Bindy Sandstone=Arenito Liguento
Bindy Stone=Pedra Liguenta
Bindy Tarstone=Pedra de Alcatrão Liguenta
Blank=Vazio(Em Branco)
Bonded Stone Bricks=Tijolos de Pedra Ligados
Boxy=Quadradão
Boxy Adobe=Adobe Quadrado
Boxy Pliant Adobe=Adobe Flexível Quadrado
Boxy Pliant Sandstone=Arenito Flexível Quadrado
Boxy Pliant Stone=Pedra Flexível Quadrada
Boxy Pliant Tarstone=Pedra de Alcatrão Flexível Quadrada
Boxy Sandstone=Arenito Quadrada
Boxy Stone=Pedra Quadrada
Boxy Tarstone=Pedra de Alcatrão Quadrada
Burn=Queimadura
Burning Embers=Brasa Quente
Charcoal=Carvão Vegetal
Charcoal Glyph=Glifo de Carvão Vegetal
Charcoal Lump=Nódulo de Carvão Vegetal
Chromatic Glass=Vidro Cromático
Clear Glass=Vidro Transparente
@ -107,11 +188,9 @@ Lux Flow=Fluxo de Lux
MIT License (http://www.opensource.org/licenses/MIT)=Licença MIT (http://www.opensource.org/licenses/MIT)
Molten Glass=Vidro Derretido
Molten Rock=Pedra Derretida
Not all game content is covered by hints. Explore!=As dicas não cobrem todo o conteúdo do jogo. Explore!
Not all game content is covered by hints. Explore!=Nem todo o conteúdo do jogo é coberto pelas dicas. Explore!
Peat=Turfa
Player's Guide: Inventory Management=Guia do Jogador: Gerenciamento de Inventário
Player's Guide: Pummeling Recipes=Guia do Jogador: Receitas por Esmurrada
Player's Guide: Tips and Guidance=Guia do Jogador: Dicas e Orientações
Prism=Prisma
Progress: @1 complete, @2 current, @3 future=Progresso: @1 completo(s), @2 atual(is), @3 futuro(s)
Pummel=Esmurrar
@ -193,8 +272,6 @@ chop a lode crate back apart=quebre uma caixa de veio mineral
chop a lode rod back into bars=martele uma haste de veio mineral de volta em barras
chop chromatic glass into lenses=martele vidro cromático tornando-o lentes
chop up charcoal=martele carvão mineral
cold-forge annealed lode prills into a tool head=faça uma cabeça de ferramenta forjando friamente granulado de filão recozido
cold-forge lode down completely=forge filão completamente, de forma fria
cool molten glass into crude glass=esfrie vidro derretido em vidro bruto
craft a torch from staff and coal lump=construa uma tocha a partir de um bastão e um nódulo de carvão
cut down a tree=corte uma árvore
@ -207,7 +284,6 @@ dig up sand=cave areia
dig up stone=escave pedra
dry out a sponge=drene uma esponja
ferment peat into humus=fermente turga em húmus
find a lode stratum=encontre um estrato de filão
find a sponge=encontre esponja
find a stick=encontre um graveto
find an eggcorn=encontre uma pinha
@ -227,7 +303,6 @@ insert metal rod into a cobble panel=insira uma haste de metal em um painel de p
insert wooden pin into wooden door panel=insira um pino de madeira em um painel de porta de madeira
light a torch=acenda uma tocha
lux-infuse a lode tool=infusa uma ferramenta de filão com lux
make an anvil by tempering a lode cube=faça uma forja temperando um cubo de filão
make fire by rubbing sticks together=faça fogo esfregando gravetos
make wet aggregate=faça agregado úmido
melt down lode metal from lode cobble=derreta filão metálico a partir de pedregulho de filão

View File

@ -1,33 +1,92 @@
# textdomain: nc_api
(C)2018-2019 by Aaron Suen <warr1024@@gmail.com>=(C)2018-2019 Аарон Суэн <warr1024@@gmail.com>
(C)2018-2020 by Aaron Suen <warr1024@@gmail.com>=(C)2018-2020 Аарон Суэн <warr1024@@gmail.com>
(and 1 more hint)=(и еще 1 подсказка)
(and @1 more hints)=(и еще @1 подсказок)
- "Furnaces" are not a thing; discover smelting with open flames.=- "Печек" тут нет; откройте для себя плавку открытым огнём.
- Can't dig trees or grass? Search for sticks in the canopy.=- Не можете копать деревья или траву? Ищите палки в сени.
- Crafting is done by building recipes in-world.=- Крафтинг совершается постройкой рецептов в мире.
- DONE: @1=- ЗАВЕРШЕНО: @1
- Do not use F5 debug info; it will mislead you!=- Не используйте отладочную информацию F5; Она введет вас в заблуждение!
- Drop items onto ground to create stack nodes. They do not decay.=[УДАЛЕНО].
- Drop items onto ground to create stack nodes. They do not decay.=- Бросайте вещи на землю чтобы создать стак-ноды. Они не исчезают.
- If a recipe exists, you will see a special particle effect.=- Если рецепт существует, вы увидите спец-эффект.
- Items picked up try to fit into the current selected slot first.=- Подобранные предметы пытаются поместиться в выделенный слот.
- Larger recipes are usually more symmetrical.=- Большие рецепты обычно более симметричны.
- Order and specific face of placement may matter for crafting.=- Порядок и грань размещения может может иметь значение.
- Ores may be hidden, but revealed by subtle clues in terrain.=- Может руды и спрятаны, но их раскрывают тонкие подсказки на местности.
- Recipes are time-based, punching faster does not speed up.=- Рецепты зависят от времени, учащенные удары ничего не ускоряют.
- Sneak+drop to count out single items from stack.=- Присесть+бросок чтобы отсчитывать отдельные предметы из стака.
- Some recipes require "pummeling" a node.=- Некоторые рецепты требуют "избивать" ноду.
- Some recipes use a 3x3 "grid", laid out flat on the ground.=- Некоторые рецепты используют "сетку" 3x3, разложенную плоско на земле.
- Stacks may be pummeled, exact item count may matter.=- Стаки тоже могут быть избиты, количество предметов может иметь значение.
- Stuck in a pit? Hold right-click on surfaces barehanded to climb.=- Застряли? Удерживайте ПКМ на поверхностях с голыми руками чтобы лазать.
- Stuck in a pit? Pummel surfaces barehanded to find places to climb.=[УДАЛЕНО].
- The game is challenging by design, sometimes frustrating. DON'T GIVE UP!=- Игра сложная по задумке, иногда разочаровывает. НЕ СДАВАЙТЕСЬ!
- There is NO inventory screen.=- Экрана инвентаря НЕТ.
- To pummel, punch a node repeatedly, WITHOUT digging.=- Чтобы избивать, повторно ударяйте ноду, НЕ КОПАЯ ЕЁ.
- Trouble lighting a fire? Try using longer sticks, more tinder.=- Проблемы с разведением огня? Попробуйте использовать палки подлиннее.
- Wielded item, target face, and surrounding nodes may matter.=- Предмет в руках, целевая грань и окружающие ноды могут иметь значение.
- You do not have to punch very fast (about 1 per second).=- Ударять нужно не так часто (около 1 удара в секунду).
...and 1 more hint...=[УДАЛЕНО].
...and @1 more hints...=[УДАЛЕНО].
...have you activated a lens yet?=[УДАЛЕНО]?
...have you assembled a staff from sticks yet?=[УДАЛЕНО]?
...have you assembled a wooden frame yet?=[УДАЛЕНО]?
...have you assembled a wooden ladder yet?=[УДАЛЕНО]?
...have you assembled a wooden shelf yet?=[УДАЛЕНО]?
...have you assembled a wooden tool yet?=[УДАЛЕНО]?
...have you assembled an adze out of sticks yet?=[УДАЛЕНО]?
...have you assembled an annealed lode tote handle yet?=[УДАЛЕНО]?
...have you bashed a plank into sticks yet?=[УДАЛЕНО]?
...have you broken cobble into chips yet?=[УДАЛЕНО]?
...have you carved a wooden plank completely yet?=[УДАЛЕНО]?
...have you carved wooden tool heads from planks yet?=[УДАЛЕНО]?
...have you chipped chromatic glass into prisms yet?=[УДАЛЕНО]?
...have you chopped a lode cube into prills yet?=[УДАЛЕНО]?
...have you chopped chromatic glass into lenses yet?=[УДАЛЕНО]?
...have you chopped up charcoal yet?=[УДАЛЕНО]?
...have you cold-forged an annealed lode tool head yet?=[УДАЛЕНО]?
...have you cold-forged lode down completely yet?=[УДАЛЕНО]?
...have you cooled molten glass into crude glass yet?=[УДАЛЕНО]?
...have you cut down a tree yet?=[УДАЛЕНО]?
...have you dug up a tree stump yet?=[УДАЛЕНО]?
...have you dug up dirt yet?=[УДАЛЕНО]?
...have you dug up gravel yet?=[УДАЛЕНО]?
...have you dug up lode ore yet?=[УДАЛЕНО]?
...have you dug up sand yet?=[УДАЛЕНО]?
...have you dug up stone yet?=[УДАЛЕНО]?
...have you found a lode stratum yet?=[УДАЛЕНО]?
...have you found ash yet?=[УДАЛЕНО]?
...have you found charcoal yet?=[УДАЛЕНО]?
...have you found deep stone strata yet?=[УДАЛЕНО]?
...have you found dry leaves yet?=[УДАЛЕНО]?
...have you found eggcorns yet?=[УДАЛЕНО]?
...have you found lode ore yet?=[УДАЛЕНО]?
...have you found molten rock yet?=[УДАЛЕНО]?
...have you found sponges yet?=[УДАЛЕНО]?
...have you found sticks yet?=[УДАЛЕНО]?
...have you made fire by rubbing sticks together yet?=[УДАЛЕНО]?
...have you melted down lode metal yet?=[УДАЛЕНО]?
...have you melted sand into glass yet?=[УДАЛЕНО]?
...have you molded molten glass into clear glass yet?=[УДАЛЕНО]?
...have you packed high-quality charcoal yet?=[УДАЛЕНО]?
...have you packed stone chips back into cobble yet?=[УДАЛЕНО]?
...have you planted an eggcorn yet?=[УДАЛЕНО]?
...have you produced light from a lens yet?=[УДАЛЕНО]?
...have you put a stone tip onto a tool yet?=[УДАЛЕНО]?
...have you quenched molten glass into chromatic glass yet?=[УДАЛЕНО]?
...have you sintered glowing lode into a cube yet?=[УДАЛЕНО]?
...have you split a tree trunk into planks yet?=[УДАЛЕНО]?
...have you tempered a lode anvil yet?=[УДАЛЕНО]?
...have you tempered a lode tool head yet?=[УДАЛЕНО]?
...have you welded a lode pick and spade together yet?=[УДАЛЕНО]?
About=Об игре
Active Lens=Активная Линза
Active Prism=Активная Призма
Adze=Тесло
Aggregate=Цемент
Air=Воздух
Amalgamation=Амальгамация
Annealed Lode=Обожжёный Металл
Annealed Lode Bar=Обожжёный Металлический Брусок
Annealed Lode Hatchet=Обожжёный Металлический Топорик
@ -42,12 +101,12 @@ Annealed Lode Prill=Обожжёный Металлический Самород
Annealed Lode Rod=Обожжёный Металлический Стержень
Annealed Lode Spade=Обожжёный Металлический Заступ
Annealed Lode Spade Head=Обожжёный Металлический Обух Заступа
Artificial Water=Искуственная вода
Ash=Пепел
Ash Lump=Комок Пепла
Burn=Ожог
Burning Embers=Горящие Угли
Charcoal=Уголь
Charcoal Glyph=Угольный Символ
Charcoal Lump=Комок Угля
Chromatic Glass=Хроматическое Стекло
Clear Glass=Прозрачное Стекло
@ -74,6 +133,8 @@ Glowing Lode Rod=Раскалённый Металлический Стерже
Glowing Lode Spade Head=Раскалённый Металлический Обух Заступа
Grass=Трава
Gravel=Гравий
Growing Leaves=Растущие Листья
Growing Tree Trunk=Растущий Ствол Дерева
Hints=Подсказки
Humus=Гумус
Ignore=Не обращайте внимания
@ -97,6 +158,7 @@ Lode Cobble=Булыжник с Металлом
Lode Crate=Металлический Ящик
Lode Ore=Металлическая Руда
Log=Бревно
Loose Amalgamation=Рыхлая Амальгамация
Loose Cobble=Рыхлый Булыжник
Loose Dirt=Рыхлая Грязь
Loose Gravel=Насыпной Гравий
@ -110,11 +172,9 @@ Lux Flow=Поток Люкса
MIT License (http://www.opensource.org/licenses/MIT)=Лицензия MIT (http://www.opensource.org/licenses/MIT)
Molten Glass=Расплавленное Стекло
Molten Rock=Расплавленный Камень
Not all game content is covered by hints. Explore!=[УДАЛЕНО]!
Not all game content is covered by hints. Explore!=Не вся игра покрыта подсказками. Исследуйте!
Peat=Торф
Player's Guide: Inventory Management=Руководсво Игрока: Управление Инвентарём
Player's Guide: Pummeling Recipes=Руководство Игрока: Рецепты Избиения
Player's Guide: Tips and Guidance=Руководство Игрока: Советы и Направление
Prism=Призма
Progress: @1 complete, @2 current, @3 future=Прогресс: @1 готовы, @2 сейчас, @3 в будущем
Pummel=Избиение
@ -123,6 +183,7 @@ Sand=Песок
See included LICENSE file for full details and credits=См. детали и кредиты в файле LICENSE
Shining Lens=Сияющая Линза
Sponge=Губка
Sprout=Росток
Staff=Жезл
Stick=Палка
Stone=Камень
@ -177,6 +238,9 @@ Wooden Shelf=Деревянная Полка
Wooden Spade=Деревянный Заступ
Wooden Spade Head=Деревянный Обух Заступа
activate a lens=активируйте линзу
activate a prism=активируйте призму
assemble a glass tank=соберите стеклянный танк
assemble a rake from adzes and a stick=соберите грабли из тесел и палки
assemble a staff from sticks=соберите жезл из палок
assemble a wooden frame from staves=соберите деревянный каркас из жезлов
assemble a wooden ladder from sticks=соберите деревянную лестницу из палок
@ -188,6 +252,7 @@ bash a plank into sticks=разбейте доску на палки
break cobble into chips=разбейте булыжник на кусочки
carve a wooden plank completely=вырежте доску до конца
carve wooden tool heads from planks=вырежте обухи из досок
catapult an item with a hinged panel=катапультируйте предмет с помощью приклепленной панели
chip chromatic glass into prisms=выстрогайте призмы из хроматического стекла
chisel a hinge groove into a wooden plank=высеките выемку для петли в доске
chisel a hinge groove into cobble=высеките выемку для петли в булыжнике
@ -196,8 +261,8 @@ chop a lode crate back apart=разрубите металлический ящ
chop a lode rod back into bars=разрубите металлический стержень обратно на бруски
chop chromatic glass into lenses=разрубите хроматическое стекло на линзы
chop up charcoal=нарежте уголь
cold-forge annealed lode prills into a tool head=выкуйте обух инструмента из холодных обожжённых металлический самородков
cold-forge lode down completely=выкуйте холодный металл до конца
cold-forge annealed lode on a tempered anvil=выкуйте отожженный металл холодной ковкой на закаленной наковальне
compress something with a hinged panel=сожмите что-нибудь прикрепленной панелью
cool molten glass into crude glass=остудите расплавленное стекло в рыхлое стекло
craft a torch from staff and coal lump=скрафтите факел из жезла и кусочка угля
cut down a tree=срубите дерево
@ -210,7 +275,6 @@ dig up sand=выкопайте песок
dig up stone=выкопайте камень
dry out a sponge=высушите губку
ferment peat into humus=ферментируйте торф в гумус
find a lode stratum=найдите слой металла
find a sponge=найдите губку
find a stick=найдите палку
find an eggcorn=найдите яйцезерно
@ -221,6 +285,7 @@ find dry (loose) leaves=найдите сухие (опавшие) листья
find lode ore=найдите железную руду
find lux=найдите люкс
find molten rock=найдите расплавленный камень
forge lode down completely on an anvil=выкуйте металл до конца
grind leaves into peat=измельчите листья в торф
hammer a lode bar back to a prill=выкуйте металлический брусок обратно в самородок
hammer a lode prill into a bar=выкуйте металлический брусок из самородка
@ -230,7 +295,6 @@ insert metal rod into a cobble panel=вставьте металлический
insert wooden pin into wooden door panel=вставьте деревянную булаву в деревянную дверную панель
light a torch=зажгите факел
lux-infuse a lode tool=зарядите металлический инструмент люксом
make an anvil by tempering a lode cube=сделайте наковальню закалив металлический куб
make fire by rubbing sticks together=разведите огонь потерев палки друг о друга
make wet aggregate=сделайте влажный цемент
melt down lode metal from lode cobble=выплавьте металл из булыжника с металлом
@ -254,6 +318,5 @@ solder lode rods into crates=спаяйте металлические стер
split a tree trunk into planks=разрубите ствол дерева на доски
squeeze out a sponge=выжмите губку
temper a lode tool head=закалите обух металлического инструмента
traverse a dark floor by feel=перейдите темный пол наощупь
weld glowing lode pick and spade heads together=сварите раскаленные обухи кирки и заступа вместе
write on a surface with a charcoal lump=напишите углем на поверхности

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2019-10-04 22:59+0000\n"
"Last-Translator: Terifo <none@example.org>\n"
"PO-Revision-Date: 2020-01-12 16:26+0000\n"
"Last-Translator: Weblate Admin <warr1024@gmail.com>\n"
"Language-Team: Japanese <http://nodecore.mine.nu/trans/projects/nodecore/"
"core/ja/>\n"
"Language: ja\n"
@ -19,3 +19,6 @@ msgstr "(さらに1つのヒント)"
msgid "(C)2018-2019 by Aaron Suen <warr1024@@gmail.com>"
msgstr "(C)2018-2019 から Aaron Suen <warr1024@@gmail.com>"
msgid "(C)2018-2020 by Aaron Suen <warr1024@@gmail.com>"
msgstr "(C)2018-2020 から Aaron Suen <warr1024@@gmail.com>"

View File

@ -3,7 +3,7 @@ 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-11-23 14:35+0000\n"
"PO-Revision-Date: 2020-04-21 13:55+0000\n"
"Last-Translator: Weblate Admin <warr1024@gmail.com>\n"
"Language-Team: Portuguese <http://nodecore.mine.nu/trans/projects/nodecore/"
"core/pt/>\n"
@ -636,7 +636,10 @@ msgid "pack leaves into peat"
msgstr "[REMOVED]"
msgid "- Stuck in a pit? Pummel surfaces barehanded to find places to climb."
msgstr "[REMOVED]"
msgstr "[REMOVED]."
msgid "Adze"
msgstr "Enxó"
msgid "(C)2018-2020 by Aaron Suen <warr1024@@gmail.com>"
msgstr "(C)2018-2020 por Aaron Suen <war1024@@gmail.com>"

View File

@ -3,8 +3,8 @@ 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-11-23 14:35+0000\n"
"Last-Translator: Weblate Admin <warr1024@gmail.com>\n"
"PO-Revision-Date: 2020-09-02 12:25+0000\n"
"Last-Translator: Terifo <none@example.org>\n"
"Language-Team: Portuguese (Brazil) <http://nodecore.mine.nu/trans/projects/"
"nodecore/core/pt_BR/>\n"
"Language: pt_BR\n"
@ -12,7 +12,7 @@ msgstr ""
"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"
"X-Generator: Weblate 4.0.4\n"
msgid "(C)2018-2019 by Aaron Suen <warr1024@@gmail.com>"
msgstr "(C)2018-2019 por Aaron Suen <war1024@@gmail.com>"
@ -225,7 +225,7 @@ msgid "Active Prism"
msgstr "Prisma Ativo"
msgid "Aggregate"
msgstr "Agregar"
msgstr "Agregado"
msgid "Air"
msgstr "Ar"
@ -631,7 +631,7 @@ msgstr ""
"- O jogo é feito para ser desafiante, algumas fezes frustrante. NÃO DESISTA!"
msgid "- Stuck in a pit? Pummel surfaces barehanded to find places to climb."
msgstr "[REMOVED]"
msgstr "[REMOVED]."
msgid "- Ores may be hidden, but revealed by subtle clues in terrain."
msgstr ""
@ -950,3 +950,167 @@ msgstr "[REMOVED]"
msgid "Adze"
msgstr "Enxó"
msgid "(C)2018-2020 by Aaron Suen <warr1024@@gmail.com>"
msgstr "(C)2018-2020 por Aaron Suen <war1024@@gmail.com>"
msgid "+"
msgstr "+"
msgid "Artificial Water"
msgstr "Água Artificial"
msgid "Amalgamation"
msgstr "Amalgamação"
msgid "Adobe Mix"
msgstr "Mistura de Adobe"
msgid "Adobe"
msgstr "Adobe"
msgid "@1 |||||"
msgstr "@1 |||||"
msgid "@1 ||||."
msgstr "@1 ||||."
msgid "@1 |||.."
msgstr "@1 |||.."
msgid "@1 ||..."
msgstr "@1 ||..."
msgid "@1 |...."
msgstr "@1 |...."
msgid "@1 ....."
msgstr "@1 ....."
msgid "@1 (90@2)"
msgstr "@1 (90@2)"
msgid "@1 (9)"
msgstr "@1 (9)"
msgid "@1 (80@2)"
msgstr "@1 (80@2)"
msgid "@1 (8)"
msgstr "@1 (8)"
msgid "@1 (70@2)"
msgstr "@1 (70@2)"
msgid "@1 (7)"
msgstr "@1 (7)"
msgid "@1 (60@2)"
msgstr "@1 (60@2)"
msgid "@1 (6)"
msgstr "@1 (6)"
msgid "@1 (50@2)"
msgstr "@1 (50@2)"
msgid "@1 (5)"
msgstr "@1 (5)"
msgid "@1 (40@2)"
msgstr "@1 (40@2)"
msgid "@1 (4)"
msgstr "@1 (4)"
msgid "@1 (30@2)"
msgstr "@1 (30@2)"
msgid "@1 (3)"
msgstr "@1 (3)"
msgid "@1 (20@2)"
msgstr "@1 (20@2)"
msgid "@1 (2)"
msgstr "@1 (2)"
msgid "@1 (10@2)"
msgstr "@1 (10@2)"
msgid "@1 (100@2)"
msgstr "@1 (100@2)"
msgid "- Some recipes use a 3x3 "grid", laid out flat on the ground."
msgstr ""
"- Algumas receitas usam uma \"grade\" 3x3, disposta diretamente sobre o chão."
msgid "- Larger recipes are usually more symmetrical."
msgstr "- Receitas maiores geralmente são mais simétricas."
msgid "- Hold/repeat right-click on walls/ceilings barehanded to climb."
msgstr ""
"- Segure/repita o clique direito em paredes/tetos para escalar com mãos nuas."
msgid "- Do not use F5 debug info; it will mislead you!"
msgstr "- Não use as informações de debug do F5; Apenas irão lhe confundir!"
msgid "Bindy Pliant Tarstone"
msgstr "Pedra de Alcatrão Flexível Liguenta"
msgid "Bindy Pliant Stone"
msgstr "Pedra Flexível Liguenta"
msgid "Bindy Pliant Sandstone"
msgstr "Arenito Flexível Liguento"
msgid "Bindy Pliant Adobe"
msgstr "Adobe Flexível Liguenta"
msgid "Bindy Adobe"
msgstr "Adobe Liguento"
msgid "Bindy"
msgstr "Liguento"
msgid "Bindy Tarstone"
msgstr "Pedra de Alcatrão Liguenta"
msgid "Bindy Stone"
msgstr "Pedra Liguenta"
msgid "Bindy Sandstone"
msgstr "Arenito Liguento"
msgid "Boxy Tarstone"
msgstr "Pedra de Alcatrão Quadrada"
msgid "Boxy Stone"
msgstr "Pedra Quadrada"
msgid "Boxy Pliant Tarstone"
msgstr "Pedra de Alcatrão Flexível Quadrada"
msgid "Boxy Sandstone"
msgstr "Arenito Quadrada"
msgid "Boxy Pliant Stone"
msgstr "Pedra Flexível Quadrada"
msgid "Boxy Pliant Sandstone"
msgstr "Arenito Flexível Quadrado"
msgid "Boxy Pliant Adobe"
msgstr "Adobe Flexível Quadrado"
msgid "Boxy Adobe"
msgstr "Adobe Quadrado"
msgid "Boxy"
msgstr "Quadradão"
msgid "Bonded Stone Bricks"
msgstr "Tijolos de Pedra Ligados"
msgid "Blank"
msgstr "Vazio(Em Branco)"

View File

@ -1,7 +1,7 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2019-12-19 04:08+0000\n"
"Last-Translator: Kimapr <none2@example.org>\n"
"PO-Revision-Date: 2020-04-20 13:07+0000\n"
"Last-Translator: Weblate Admin <warr1024@gmail.com>\n"
"Language-Team: Russian <http://nodecore.mine.nu/trans/projects/nodecore/core/"
"ru/>\n"
"Language: ru\n"
@ -175,40 +175,40 @@ msgid "About"
msgstr "Об игре"
msgid "...have you broken cobble into chips yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you bashed a plank into sticks yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you assembled an annealed lode tote handle yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you assembled an adze out of sticks yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you assembled a wooden tool yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you assembled a wooden shelf yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you assembled a wooden ladder yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you assembled a wooden frame yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you assembled a staff from sticks yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you activated a lens yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...and @1 more hints..."
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]."
msgid "...and 1 more hint..."
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]."
msgid "- You do not have to punch very fast (about 1 per second)."
msgstr "- Ударять нужно не так часто (около 1 удара в секунду)."
@ -230,7 +230,7 @@ msgid "- The game is challenging by design, sometimes frustrating. DON'T GIVE UP
msgstr "- Игра сложная по задумке, иногда разочаровывает. НЕ СДАВАЙТЕСЬ!"
msgid "- Stuck in a pit? Pummel surfaces barehanded to find places to climb."
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]."
msgid "- Stuck in a pit? Hold right-click on surfaces barehanded to climb."
msgstr ""
@ -266,7 +266,7 @@ msgid "- Drop items onto ground to create stack nodes. They do not decay."
msgstr "- Бросайте вещи на землю чтобы создать стак-ноды. Они не исчезают."
msgid "- Drop items onto ground to create stack nodes. They do not decay."
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]."
msgid "- DONE: @1"
msgstr "- ЗАВЕРШЕНО: @1"
@ -293,40 +293,40 @@ msgid "(C)2018-2019 by Aaron Suen <warr1024@@gmail.com>"
msgstr "(C)2018-2019 Аарон Суэн <warr1024@@gmail.com>"
msgid "...have you carved a wooden plank completely yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you carved wooden tool heads from planks yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you chipped chromatic glass into prisms yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you chopped a lode cube into prills yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you chopped chromatic glass into lenses yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you made fire by rubbing sticks together yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you chopped up charcoal yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you put a stone tip onto a tool yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you cold-forged an annealed lode tool head yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you cold-forged lode down completely yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "Loose Humus"
msgstr "Рыхлый Гумус"
msgid "...have you cooled molten glass into crude glass yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "Loose Lode Cobble"
msgstr "Рыхлый Булыжник с Металлом"
@ -335,97 +335,97 @@ msgid "MIT License (http://www.opensource.org/licenses/MIT)"
msgstr "Лицензия MIT (http://www.opensource.org/licenses/MIT)"
msgid "...have you cut down a tree yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "Not all game content is covered by hints. Explore!"
msgstr "Не вся игра покрыта подсказками. Исследуйте!"
msgid "...have you dug up a tree stump yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you dug up dirt yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you dug up gravel yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you dug up lode ore yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you dug up sand yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you dug up stone yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you found a lode stratum yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you found ash yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you found charcoal yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you found deep stone strata yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you found dry leaves yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you found eggcorns yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you found lode ore yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you found molten rock yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you found sponges yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you found sticks yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you melted down lode metal yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you melted sand into glass yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you molded molten glass into clear glass yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you packed high-quality charcoal yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you packed stone chips back into cobble yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you planted an eggcorn yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you produced light from a lens yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you quenched molten glass into chromatic glass yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you sintered glowing lode into a cube yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you split a tree trunk into planks yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you tempered a lode anvil yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you tempered a lode tool head yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "...have you welded a lode pick and spade together yet?"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]?"
msgid "Discord: https://discord.gg/SHq2tkb"
msgstr "[УДАЛЕНО]"
@ -639,7 +639,7 @@ msgid "Molten Rock"
msgstr "Расплавленный Камень"
msgid "Not all game content is covered by hints. Explore!"
msgstr "[УДАЛЕНО]"
msgstr "[УДАЛЕНО]!"
msgid "Peat"
msgstr "Торф"
@ -1015,3 +1015,119 @@ msgstr "сварите раскаленные обухи кирки и заст
msgid "write on a surface with a charcoal lump"
msgstr "напишите углем на поверхности"
msgid "Artificial Water"
msgstr "Искуственная вода"
msgid "@1 (90@2)"
msgstr "@1 (90@2)"
msgid "@1 (9)"
msgstr "@1 (9)"
msgid "@1 (80@2)"
msgstr "@1 (80@2)"
msgid "@1 (8)"
msgstr "@1 (8)"
msgid "@1 (70@2)"
msgstr "@1 (70@2)"
msgid "@1 (7)"
msgstr "@1 (7)"
msgid "@1 (60@2)"
msgstr "@1 (60@2)"
msgid "@1 (6)"
msgstr "@1 (6)"
msgid "@1 (50@2)"
msgstr "@1 (50@2)"
msgid "@1 (5)"
msgstr "@1 (5)"
msgid "@1 (40@2)"
msgstr "@1 (40@2)"
msgid "@1 (4)"
msgstr "@1 (4)"
msgid "@1 (30@2)"
msgstr "@1 (30@2)"
msgid "@1 (3)"
msgstr "@1 (3)"
msgid "@1 (20@2)"
msgstr "@1 (20@2)"
msgid "@1 (2)"
msgstr "@1 (2)"
msgid "@1 (10@2)"
msgstr "@1 (10@2)"
msgid "@1 (100@2)"
msgstr "@1 (100@2)"
msgid "+"
msgstr "+"
msgid "(C)2018-2020 by Aaron Suen <warr1024@@gmail.com>"
msgstr "(C)2018-2020 Аарон Суэн <warr1024@@gmail.com>"
msgid "forge lode down completely on an anvil"
msgstr "выкуйте металл до конца"
msgid "compress something with a hinged panel"
msgstr "сожмите что-нибудь прикрепленной панелью"
msgid "cold-forge annealed lode on a tempered anvil"
msgstr "выкуйте отожженный металл холодной ковкой на закаленной наковальне"
msgid "catapult an item with a hinged panel"
msgstr "катапультируйте предмет с помощью приклепленной панели"
msgid "assemble a rake from adzes and a stick"
msgstr "соберите грабли из тесел и палки"
msgid "assemble a glass tank"
msgstr "соберите стеклянный танк"
msgid "activate a prism"
msgstr "активируйте призму"
msgid "Sprout"
msgstr "Росток"
msgid "Loose Amalgamation"
msgstr "Рыхлая Амальгамация"
msgid "Growing Tree Trunk"
msgstr "Растущий Ствол Дерева"
msgid "Growing Leaves"
msgstr "Растущие Листья"
msgid "Cheat Torch"
msgstr "Читерский Факел"
msgid "Amalgamation"
msgstr "Амальгамация"
msgid "- Some recipes use a 3x3 "grid", laid out flat on the ground."
msgstr ""
"- Некоторые рецепты используют \"сетку\" 3x3, разложенную плоско на земле."
msgid "- Larger recipes are usually more symmetrical."
msgstr "- Большие рецепты обычно более симметричны."
msgid "- Hold/repeat right-click on walls/ceilings barehanded to climb."
msgstr ""
msgid "- Do not use F5 debug info; it will mislead you!"
msgstr ""
"- Не используйте отладочную информацию F5; Она введет вас в заблуждение!"

View File

@ -0,0 +1,18 @@
-- LUALOCALS < ---------------------------------------------------------
local math, minetest, nodecore, string, tonumber
= math, minetest, nodecore, string, tonumber
local math_floor, string_format
= math.floor, string.format
-- LUALOCALS > ---------------------------------------------------------
local limit = tonumber(minetest.get_mapgen_setting("mapgen_limit")) or 31000
local chunksize = tonumber(minetest.get_mapgen_setting("chunksize")) or 5
chunksize = chunksize * 16
local limitchunks = math_floor(limit / chunksize)
nodecore.map_limit_min = (-limitchunks + 0.5) * chunksize + 7.5
nodecore.map_limit_max = (limitchunks - 0.5) * chunksize + 7.5
nodecore.log("action", string_format("mapgen limit: %d, chunk: %d, bounds: %0.1f to %0.1f",
limit, chunksize, nodecore.map_limit_min, nodecore.map_limit_max))

View File

@ -1,39 +1,70 @@
-- LUALOCALS < ---------------------------------------------------------
local VoxelArea, ipairs, math, minetest, nodecore, table
= VoxelArea, ipairs, math, minetest, nodecore, table
local math_floor, table_insert
= math.floor, table.insert
local PcgRandom, VoxelArea, ipairs, math, minetest, nodecore, table
= PcgRandom, VoxelArea, ipairs, math, minetest, nodecore, table
local math_floor, math_random, table_insert
= math.floor, math.random, table.insert
-- LUALOCALS > ---------------------------------------------------------
local mapgens = {}
nodecore.registered_mapgen_shared = mapgens
local prios = {}
local singlenode = minetest.get_mapgen_setting("mg_name") == "singlenode"
function nodecore.register_mapgen_shared(func, prio)
prio = prio or 0
local counters = {}
function nodecore.register_mapgen_shared(def)
local label = def.label
if not label then
label = minetest.get_current_modname()
local i = (counters[label] or 0) + 1
counters[label] = i
label = label .. ":" .. i
end
local prio = def.priority or 0
def.priority = prio
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
local oldp = mapgens[try].priority
if (prio < oldp) or (prio == oldp and label > mapgens[try].label) then
min = try + 1
else
max = try
end
end
table_insert(mapgens, min, func)
table_insert(prios, min, prio)
table_insert(mapgens, min, def)
end
minetest.register_on_generated(function(minp, maxp)
local mapperlin
minetest.after(0, function() mapperlin = minetest.get_perlin(0, 1, 0, 1) end)
nodecore.register_on_generated("mapgen shared", 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)
local rng = math_random
if PcgRandom then
local seed = mapperlin:get_3d({x = minp.x, y = minp.y, z = minp.z})
seed = math_floor((seed - math_floor(seed)) * 2 ^ 32 - 2 ^ 31)
local pcg = PcgRandom(seed)
rng = function(a, b)
if b then
return pcg:next(a, b)
elseif a then
return pcg:next(1, a)
end
return (pcg:next() + 2 ^ 31) / 2 ^ 32
end
end
for _, def in ipairs(mapgens) do
local en = def.enabled
if en == nil then en = not singlenode end
if en then
def.func(minp, maxp, area, data, vm, emin, emax, rng)
end
end
vm:set_data(data)

View File

@ -1 +0,0 @@
name = nc_api

View File

@ -1,134 +0,0 @@
-- LUALOCALS < ---------------------------------------------------------
local ItemStack, math, minetest, nodecore, pairs, setmetatable, string
= ItemStack, math, minetest, nodecore, pairs, setmetatable, string
local math_random, string_format
= math.random, string.format
-- LUALOCALS > ---------------------------------------------------------
-- Active ItemStack Modifiers
-- Definition:
--- itemnames: {"mod:itemname", "group:name"}
--- interval: integer,
--- chance: integer,
--- func: function(stack, data) end
-- Data:
--- {pos, node}
--- {player, inv, list, slot}
nodecore.register_aism,
nodecore.registered_aisms
= nodecore.mkreg()
local aismidx = {}
local function defadd(key, def)
aismidx[key] = aismidx[key] or {}
aismidx[key][def] = true
end
minetest.after(0, function()
for _, def in pairs(nodecore.registered_aisms) do
for _, name in pairs(def.itemnames) do
if name:sub(1, 6) == "group:" then
for k, v in pairs(minetest.registered_items) do
if v and v.groups and v.groups[name:sub(7)] then
defadd(k, def)
end
end
else
defadd(name, def)
end
end
end
local keys = 0
local defs = 0
local peak = 0
for _, v in pairs(aismidx) do
keys = keys + 1
local n = 0
for _ in pairs(v) do n = n + 1 end
defs = defs + n
if n > peak then peak = n end
end
minetest.log(string_format("register_aism: %d keys, %d defs, %d peak", keys, defs, peak))
end)
local function checkrun(def, stack, data)
if def.chance and def.chance > 1 and math_random(1, def.chance) ~= 1 then return end
if def.interval and def.interval > 1 and (minetest.get_gametime() % def.interval) ~= 0 then return end
stack = def.action(stack, data)
if stack and data.set then data.set(ItemStack(stack)) end
end
local function checkstack(stack, data)
if (not stack) or stack:is_empty() then return end
local name = stack:get_name()
local defs = aismidx[name]
if not defs then return end
for def in pairs(defs) do
checkrun(def, stack, data)
end
end
nodecore.aism_check_stack = checkstack
nodecore.register_limited_abm({
label = "AISM Scheduler",
nodenames = {"group:visinv"},
interval = 1,
chance = 1,
action = function(pos, node)
return checkstack(nodecore.stack_get(pos), {
pos = pos,
node = node,
set = function(s)
return nodecore.stack_set(pos, s)
end
})
end
})
local function invtick()
minetest.after(1, invtick)
for _, player in pairs(minetest.get_connected_players()) do
local pos = player:get_pos()
pos.y = pos.y + player:get_properties().eye_height
local inv = player:get_inventory()
for lname, list in pairs(inv:get_lists()) do
for slot, stack in pairs(list) do
checkstack(stack, {
pos = pos,
player = player,
inv = inv,
list = lname,
slot = slot,
set = function(s)
return inv:set_stack(lname, slot, s)
end
})
end
end
end
end
invtick()
local bii = minetest.registered_entities["__builtin:item"]
local newbii = {
on_step = function(self, dtime, ...)
local t = (self.aismtimer or 0) + dtime
while t >= 1 do
t = t - 1
checkstack(ItemStack(self.itemstring), {
pos = self.object:get_pos(),
obj = self.object,
ent = self,
set = function(s)
if s:is_empty() then return self.object:remove() end
self.itemstring = s:to_string()
end
})
end
self.aismtimer = t
return bii.on_step(self, dtime, ...)
end
}
setmetatable(newbii, bii)
minetest.register_entity(":__builtin:item", newbii)

View File

@ -0,0 +1,10 @@
-- LUALOCALS < ---------------------------------------------------------
local minetest
= minetest
-- LUALOCALS > ---------------------------------------------------------
local oldfunc = minetest.register_entity
function minetest.register_entity(name, def, ...)
def.label = def.label or name
return oldfunc(name, def, ...)
end

View File

@ -1,74 +0,0 @@
-- 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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 429 B

View File

@ -1,6 +1,6 @@
-- LUALOCALS < ---------------------------------------------------------
local minetest, nodecore, pairs
= minetest, nodecore, pairs
local minetest, nodecore, pairs, vector
= minetest, nodecore, pairs, vector
-- LUALOCALS > ---------------------------------------------------------
local queue
@ -15,5 +15,6 @@ function nodecore.fallcheck(pos)
queue = nil
end)
end
queue[minetest.pos_to_string(pos)] = pos
pos = vector.round(pos)
queue[minetest.hash_node_position(pos)] = pos
end

View File

@ -5,16 +5,16 @@ local math_abs
= math.abs
-- LUALOCALS > ---------------------------------------------------------
minetest.register_globalstep(function(dtime)
nodecore.register_globalstep("gametime", function(dtime)
local mtt = minetest.get_gametime()
local nct = nodecore.gametime
if not nct then
minetest.log("nodecore.gametime: init to " .. mtt)
nodecore.log("action", "nodecore.gametime: init to " .. mtt)
nct = mtt
end
nct = nct + dtime
if math_abs(nct - mtt) >= 2 then
minetest.log("nodecore.gametime: excess drift; nct="
nodecore.log("warning", "nodecore.gametime: excess drift; nct="
.. nct .. ", mtt=" .. mtt)
nct = mtt
end

View File

@ -0,0 +1,52 @@
-- LUALOCALS < ---------------------------------------------------------
local minetest, nodecore, pairs, setmetatable, type, unpack
= minetest, nodecore, pairs, setmetatable, type, unpack
-- LUALOCALS > ---------------------------------------------------------
local function mkdef(...)
local def = {}
local ext = {}
for _, v in pairs({...}) do
if type(v) == "function" then
def.func = v
elseif type(v) == "string" then
def.label = v
elseif type(v) == "table" then
for tk, tv in pairs(v) do
def[tk] = tv
end
else
ext[#ext + 1] = v
end
end
setmetatable(def, {__call = function(_, ...) return def.func(...) end})
return def, unpack(ext)
end
for k in pairs({
register_globalstep = true,
register_playerevent = true,
register_on_placenode = true,
register_on_dignode = true,
register_on_punchnode = true,
register_on_generated = true,
register_on_newplayer = true,
register_on_dieplayer = true,
register_on_respawnplayer = true,
register_on_prejoinplayer = true,
register_on_joinplayer = true,
register_on_leaveplayer = true,
register_on_cheat = true,
register_on_chat_message = true,
register_on_player_receive_fields = true,
register_on_craft = true,
register_craft_predict = true,
register_on_protection_violation = true,
register_on_item_eat = true,
register_on_punchplayer = true,
register_on_player_hpchange = true,
register_on_shutdown = true
}) do
local base = minetest[k]
nodecore[k] = function(...) return base(mkdef(...)) end
end

View File

@ -3,10 +3,12 @@ local ItemStack, ipairs, math, minetest, nodecore, pairs, string,
tonumber, tostring, type, unpack, vector
= ItemStack, ipairs, math, minetest, nodecore, pairs, string,
tonumber, tostring, type, unpack, vector
local math_cos, math_floor, math_log, math_pi, math_random, math_sin,
math_sqrt, string_gsub, string_lower
= math.cos, math.floor, math.log, math.pi, math.random, math.sin,
math.sqrt, string.gsub, string.lower
local math_abs, math_cos, math_floor, math_log, math_pi, math_pow,
math_random, math_sin, math_sqrt, string_format, string_gsub,
string_lower
= math.abs, math.cos, math.floor, math.log, math.pi, math.pow,
math.random, math.sin, math.sqrt, string.format, string.gsub,
string.lower
-- LUALOCALS > ---------------------------------------------------------
for k, v in pairs(minetest) do
@ -159,11 +161,12 @@ function nodecore.tool_digs(what, groups)
end
function nodecore.interval(after, func)
local function go()
minetest.after(after, go)
return func()
end
minetest.after(after, go)
local go
local setnext = (type(after) == "function")
and function() return minetest.after(after(), go) end
or function() return minetest.after(after, go) end
go = function() setnext() return func() end
minetest.after(0, go)
end
function nodecore.wear_wield(player, groups, qty)
@ -179,7 +182,7 @@ function nodecore.wear_wield(player, groups, qty)
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,
nodecore.sound_play(wdef.sound.breaks,
{object = player, gain = 0.5})
end
end
@ -218,60 +221,6 @@ function nodecore.node_group(name, pos, node)
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
do
local stddirs = {}
for _, v in pairs(nodecore.dirs()) do
if v.y <= 0 then stddirs[#stddirs + 1] = v end
end
function nodecore.item_disperse(pos, name, qty, outdirs)
if qty < 1 then return end
local dirs = {}
for _, d in pairs(outdirs or stddirs) do
local p = vector.add(pos, d)
if nodecore.buildable_to(p) then
dirs[#dirs + 1] = {pos = p, qty = 0}
end
end
if #dirs < 1 then
return nodecore.item_eject(pos, name .. " " .. qty)
end
for _ = 1, qty 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, name .. " " .. v.qty)
end
end
end
end
function nodecore.find_nodes_around(pos, spec, r, s)
r = r or 1
if type(r) == "number" then
@ -302,10 +251,11 @@ function nodecore.node_spin_custom(...)
local qty = #arr
return function(pos, node, clicker, itemstack)
if nodecore.protection_test(pos, clicker) then return end
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 "
nodecore.log("action", clicker:get_player_name() .. " spins "
.. node.name .. " at " .. minetest.pos_to_string(pos)
.. " to param2 " .. node.param2 .. " ("
.. qty .. " total)")
@ -333,11 +283,6 @@ function nodecore.node_spin_filtered(func)
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
local function scrubkey(s)
return string_lower(string_gsub(tostring(s), "%W+", "_"))
end
@ -354,6 +299,11 @@ function nodecore.rate_adjustment(...)
return rate
end
local infodump_key = scrubkey(nodecore.product) .. "_infodump"
function nodecore.infodump()
return minetest.settings:get_bool(infodump_key)
end
function nodecore.obstructed(minpos, maxpos)
if not maxpos then
maxpos = {x = minpos.x + 0.5, y = minpos.y + 0.5, z = minpos.z + 0.5}
@ -363,16 +313,211 @@ function nodecore.obstructed(minpos, maxpos)
local radius = 4 + vector.distance(minpos, maxpos) / 2
for _, obj in pairs(minetest.get_objects_inside_radius(avgpos, radius)) do
local op = obj:get_pos()
local cb = obj:get_properties().collisionbox
if maxpos.x > op.x + cb[1] and minpos.x < op.x + cb[4]
local props = obj:get_properties()
local cb = props.collisionbox
if props.static_save
and maxpos.x > op.x + cb[1] and minpos.x < op.x + cb[4]
and maxpos.y > op.y + cb[2] and minpos.y < op.y + cb[5]
and maxpos.z > op.z + cb[3] and minpos.z < op.z + cb[6]
then
local lua = obj.get_luaentity and obj:get_luaentity()
if not ((lua and lua.is_stack) or (not nodecore.interact(obj))
or (not nodecore.player_visible(obj))) then
return obj
end
and obj.get_luaentity and obj:get_luaentity() then
return obj
end
end
end
local gravity = tonumber(minetest.settings:get("movement_gravity")) or 9.81
local friction = tonumber(minetest.settings:get("nodecore_air_friction")) or 0.0004
local function air_accel_factor(v)
local q = (friction * v * v) * 2 - 1
return q > 0 and q or 0
end
function nodecore.grav_air_physics_player(v)
if v.y > 0 then return 1 end
return 1 - air_accel_factor(v.y)
end
local function air_accel_net(v)
return v == 0 and 0 or v / -math_abs(v) * gravity * air_accel_factor(v)
end
function nodecore.grav_air_accel(v)
return {
x = air_accel_net(v.x),
y = air_accel_net(v.y) - gravity,
z = air_accel_net(v.z)
}
end
function nodecore.grav_air_accel_ent(obj)
local cur = obj:get_acceleration()
local new = nodecore.grav_air_accel(obj:get_velocity())
if vector.equals(cur, new) then return end
return obj:set_acceleration(new)
end
function nodecore.near_unloaded(pos, radius)
return minetest.find_node_near(pos, radius or 1, {"ignore"}, true)
end
function nodecore.get_objects_at_pos(pos)
pos = vector.round(pos)
local t = {}
-- get_objects_inside_radius just loops over these and does a euclidian
-- distance check anyway, which we can skip
for _, obj in pairs(minetest.object_refs) do
local p = obj:get_pos()
if p and vector.equals(vector.round(p), pos) then
t[#t + 1] = obj
end
end
return t
end
function nodecore.get_depth_light(y, qty)
qty = qty or 4/5
if y < 0 then qty = qty * math_pow(2, y / 64) end
return qty
end
nodecore.light_sun = 15
nodecore.light_sky = math_floor(0.5 + nodecore.light_sun * nodecore.get_depth_light(0))
function nodecore.is_full_sun(pos)
return pos.y >= 0 and minetest.get_node_light(pos, 0.5) == nodecore.light_sun
end
function nodecore.get_node_light(pos)
local artificial = minetest.get_node_light(pos, 0)
if not artificial then return end
local natural = math_floor(0.5 + minetest.get_node_light(pos, 0.5)
* nodecore.get_depth_light(pos.y))
return artificial > natural and artificial or natural
end
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] = v
end
end
end)
nodecore.registered_liquids = liquids
local player_was_swimming = {}
function nodecore.player_swimming(player)
local pname = player:get_player_name()
local pos = player:get_pos()
local r = 0.6
local swimming = true
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 node.name == "air" then swimming = nil
elseif not liquids[node.name] then
player_was_swimming[pname] = nil
return
end
end
end
if swimming then
player_was_swimming[pname] = true
return true
end
return player_was_swimming[pname]
end
local function mismatch(a, b)
if type(a) == "table" then
if type(b) ~= "table" then return true end
for k, v in pairs(a) do
if mismatch(v, b[k]) then return true end
end
return
end
if type(a) == "number" and type(b) == "number" then
local ratio = a / b
-- Floating point rounding...
if ratio > 0.99999 and ratio < 1.00001 then return end
end
return a ~= b
end
nodecore.prop_mismatch = mismatch
function nodecore.item_matching_index(items, getnames, idxname, asarray, keymod)
local index = {}
local function itemadd(key, item)
local t = index[key]
if not t then
t = {}
index[key] = t
end
if asarray then
t[#t + 1] = item
else
t[item] = true
end
end
keymod = keymod or function(x) return x end
local report_pending
local function rebuild()
for k in pairs(index) do index[k] = nil end
for _, item in pairs(items) do
for _, name in pairs(getnames(item)) do
if name == true then
for k in pairs(minetest.registered_items) do
itemadd(keymod(k, item), item)
end
elseif type(name) == "string" and name:sub(1, 6) == "group:" then
for k, v in pairs(minetest.registered_items) do
if v and v.groups and v.groups[name:sub(7)] then
itemadd(keymod(k, item), item)
end
end
else
itemadd(keymod(name, item), item)
end
end
end
if idxname and not report_pending then
report_pending = true
minetest.after(0, function()
report_pending = nil
local keys = 0
local defs = 0
local peak = 0
for _, v in pairs(index) do
keys = keys + 1
local n = 0
for _ in pairs(v) do n = n + 1 end
defs = defs + n
if n > peak then peak = n end
end
nodecore.log("action", string_format(
"%s %s: %d keys, %d defs, %d peak",
"item_matching_index",
idxname, keys, defs, peak))
end)
end
end
minetest.after(0, rebuild)
return index, rebuild
end
function nodecore.protection_test(pos, player)
if not player then return end
if type(player) ~= "string" then
if not player:is_player() then return end
player = player:get_player_name()
end
if minetest.is_protected(pos, player) then
minetest.record_protection_violation(pos, player)
return true
end
end

View File

@ -17,3 +17,22 @@ nodecore.buildable_to = defprop("buildable_to")
nodecore.walkable = defprop("walkable")
nodecore.climbable = defprop("climbable")
nodecore.sunlight_propagates = defprop("sunlight_propagates")
local airpass_drawtypes = {
airlike = true,
torchlike = true,
signlike = true,
firelike = true,
fencelike = true,
raillike = true,
nodebox = true,
mesh = true,
plantlike = true
}
function nodecore.air_pass(thing)
local name = type(thing) == "string" and thing or thing.name
or minetest.get_node(thing).name
local def = minetest.registered_items[name] or {}
if def.air_pass ~= nil then return def.air_pass end
return airpass_drawtypes[def.drawtype or false] or false
end

View File

@ -1,6 +1,6 @@
-- LUALOCALS < ---------------------------------------------------------
local math, minetest, nodecore
= math, minetest, nodecore
local math, nodecore, type
= math, nodecore, type
local math_ceil
= math.ceil
-- LUALOCALS > ---------------------------------------------------------
@ -10,25 +10,29 @@ local function getphealth(player)
end
nodecore.getphealth = getphealth
local function setphealth(player, hp)
if hp > 20 then hp = 20 end
local function setphealth(player, hp, reason, minwhole)
local hpmax = player:get_properties().hp_max
if hp > hpmax then hp = hpmax end
if hp < 0 then hp = 0 end
local whole = math_ceil(hp)
if whole == 0 then whole = 1 end
if minwhole and whole < minwhole then whole = minwhole end
local dhp = hp - whole
player:get_meta():set_float("dhp", dhp)
local old = player:get_hp()
player:set_hp(whole)
if type(reason) ~= "table" then reason = {nc_type = reason} end
reason = reason or {}
reason.from = "mod"
reason.type = "set_hp"
player:set_hp(whole, reason)
return old ~= whole
end
nodecore.setphealth = setphealth
local function addphealth(player, hp)
return setphealth(player, getphealth(player) + hp)
local function addphealth(player, hp, reason)
return setphealth(player,
getphealth(player) + hp,
reason,
hp >= 0 and player:get_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

View File

@ -20,7 +20,8 @@ function nodecore.scan_flood(pos, range, func)
local np = {
x = p.x + v.x,
y = p.y + v.y,
z = p.z + v.z
z = p.z + v.z,
prev = p
}
local nk = minetest.hash_node_position(np)
if not seen[nk] then

View File

@ -0,0 +1,69 @@
-- LUALOCALS < ---------------------------------------------------------
local math, nodecore, pairs, table, vector
= math, nodecore, pairs, table, vector
local math_random, table_sort
= math.random, table.sort
-- LUALOCALS > ---------------------------------------------------------
local settleorder = {}
local groups = {}
local keys = {}
for x = -5, 5 do
for y = -5, 5 do
for z = -5, 5 do
local p = {
x = x,
y = y,
z = z,
}
local d = vector.length(p)
if d <= 5 then
p.v = d + p.y / 100
local g = groups[p.v]
if not g then
g = {}
groups[p.v] = g
keys[#keys + 1] = p.v
end
g[#g + 1] = p
end
end
end
end
table_sort(keys)
for _, k in pairs(keys) do
local stamp = 0
local t = groups[k]
settleorder[#settleorder + 1] = function()
if stamp == nodecore.gametime then return t end
local n = #t
if n < 2 then return t end
for i = 1, n do
local j = math_random(1, n)
local x = t[i]
t[i] = t[j]
t[j] = x
end
stamp = nodecore.gametime
return t
end
end
function nodecore.settlescan()
local i = 0
local grp = {}
local j = 0
return function()
if j >= #grp then
if i >= #settleorder then
return
end
i = i + 1
grp = settleorder[i]()
j = 0
end
j = j + 1
return grp[j]
end
end

View File

@ -8,48 +8,18 @@ local 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))
function nodecore.sound_play(name, spec, ephem, ...)
if spec and type(spec) == "table" then
spec.pitch = (spec.pitch or 1) * 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(nodecore.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}
}
if ephem == nil then ephem = not spec.not_ephemeral end
return oldplay(name, spec, ephem, ...)
end
function nodecore.sound_play_except(name, def, pname)
if not pname then
return minetest.sound_play(name, def)
return nodecore.sound_play(name, def)
end
if type(pname) ~= "string" then
pname = pname:get_player_name()
@ -59,18 +29,72 @@ function nodecore.sound_play_except(name, def, pname)
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)
nodecore.sound_play(name, def)
end
end
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(nodecore.gametime / 5))
end
function nodecore.stack_sounds(pos, kind, stack, except)
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
if except then return nodecore.sound_play_except(t.name, t, except) end
return nodecore.sound_play(t.name, t)
end
function nodecore.stack_sounds_delay(...)
local t = {...}
minetest.after(0, function()
nodecore.stack_sounds(unpack(t))
end)
end
local gains_base = {
footstep = 0.2,
dig = 0.5,
dug = 1,
place = 1,
place_failed = 0.2,
fall = 0.1
}
function nodecore.sounds(name, gains, pitch)
local t = {}
for k, v in pairs(gains_base) do
t[k] = {
name = name,
gain = (gains and gains[k] or 1) * v,
pitch = pitch
}
end
return t
end
function nodecore.node_sound(pos, kind, opts)
nodecore.stack_sounds(pos, kind)
local node = opts and opts.node or minetest.get_node(pos)
local def = minetest.registered_items[node.name] or {}
if def.groups and def.groups.visinv then
nodecore.stack_sounds(pos, kind)
end
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
function nodecore.set_loud(pos, node, opts)
minetest.set_node(pos, node)
opts = opts or {}
opts.node = node
return nodecore.node_sound(pos, "place", opts)
end

View File

@ -1,14 +1,39 @@
-- LUALOCALS < ---------------------------------------------------------
local ItemStack, ipairs, minetest, nodecore
= ItemStack, ipairs, minetest, nodecore
local ItemStack, getmetatable, math, minetest, nodecore, pairs, string,
vector
= ItemStack, getmetatable, math, minetest, nodecore, pairs, string,
vector
local math_cos, math_floor, math_pi, math_random, math_sin,
string_format
= math.cos, math.floor, math.pi, math.random, math.sin,
string.format
-- LUALOCALS > ---------------------------------------------------------
local function shortdesc(stack, noqty)
stack = ItemStack(stack)
if noqty and stack:get_count() > 1 then stack:set_count(1) end
local pre = stack:to_string()
stack:get_meta():from_table({})
local desc = stack:to_string()
if pre == desc then return desc end
return string_format("%s @%d", desc, #pre - #desc)
end
nodecore.stack_shortdesc = shortdesc
local function family(stack)
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.stackfamily or stack:to_string()
if def and def.stackfamily then
stack:set_name(def.stackfamily)
end
if stack:get_count() > 1 then
stack:set_count(1)
end
return stack:to_string()
end
nodecore.stack_family = family
function nodecore.stack_merge(dest, src)
if dest:is_empty() then return dest:add_item(src) end
if family(src) ~= family(dest) then
@ -32,17 +57,19 @@ function nodecore.stack_get(pos)
end
local function update(pos, ...)
for _, v in ipairs(nodecore.visinv_update_ents(pos)) do
v:get_luaentity():itemcheck()
end
nodecore.visinv_update_ents(pos)
return ...
end
function nodecore.stack_set(pos, stack)
function nodecore.stack_set(pos, stack, player)
if player then
nodecore.log("action", string_format("%s sets stack %q at %s",
player:get_player_name(), shortdesc(stack), minetest.pos_to_string(pos)))
end
return update(pos, nodecore.node_inv(pos):set_stack("solo", 1, ItemStack(stack)))
end
function nodecore.stack_add(pos, stack)
function nodecore.stack_add(pos, stack, player)
local node = minetest.get_node(pos)
local def = minetest.registered_items[node.name] or {}
if def.stack_allow then
@ -51,7 +78,9 @@ function nodecore.stack_add(pos, stack)
if ret and ret ~= true then return ret end
end
stack = ItemStack(stack)
local donate = stack:get_count()
local item = nodecore.stack_get(pos)
local exist = item:get_count()
local left
if item:is_empty() then
left = nodecore.node_inv(pos):add_item("solo", stack)
@ -59,7 +88,15 @@ function nodecore.stack_add(pos, stack)
left = nodecore.stack_merge(item, stack)
nodecore.stack_set(pos, item)
end
if left:get_count() ~= stack:get_count() then
local remain = left:get_count()
if donate ~= remain then
if player then
nodecore.log("action", string_format(
"%s adds stack %q %d + %d = %d + %d at %s",
player:get_player_name(), shortdesc(stack, true),
exist, donate, exist + donate - remain, remain,
minetest.pos_to_string(pos)))
end
nodecore.stack_sounds(pos, "place")
end
return update(pos, left)
@ -70,10 +107,144 @@ function nodecore.stack_giveto(pos, player)
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
local left = player:get_inventory():add_item("main", stack)
local remain = left:get_count()
if remain == qty then return stack:is_empty() end
nodecore.log("action", string_format(
"%s takes stack %q %d - %d = %d at %s",
player:get_player_name(), shortdesc(stack, true),
qty, qty - remain, remain, minetest.pos_to_string(pos)))
nodecore.stack_sounds(pos, "dug")
nodecore.stack_set(pos, stack)
nodecore.stack_set(pos, left)
return stack:is_empty()
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, y = vel.y, z = vel.z}
if speed > 0 then
local inc = math_random() * math_pi / 3
local y = math_sin(inc)
local xz = math_cos(inc)
local theta = math_random() * math_pi * 2
local x = math_sin(theta) * xz
local z = math_cos(theta) * xz
v = {
x = v.x + x * speed,
y = v.y + y * speed,
z = v.z + z * speed
}
end
local p = {x = pos.x, y = pos.y + 0.25, z = pos.z}
local obj = minetest.add_item(p, stack)
if obj then obj:set_velocity(v) end
end
end
do
local stddirs = {}
for _, v in pairs(nodecore.dirs()) do
if v.y <= 0 then stddirs[#stddirs + 1] = v end
end
function nodecore.item_disperse(pos, name, qty, outdirs)
if qty < 1 then return end
local dirs = {}
for _, d in pairs(outdirs or stddirs) do
local p = vector.add(pos, d)
if nodecore.buildable_to(p) then
dirs[#dirs + 1] = {pos = p, qty = 0}
end
end
if #dirs < 1 then
return nodecore.item_eject(pos, name .. " " .. qty)
end
for _ = 1, qty 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, name .. " " .. v.qty)
end
end
end
end
local function item_lose(player, listname, slot, speed)
local inv = player:get_inventory()
local stack = inv:get_stack(listname, slot)
if stack:is_empty() or nodecore.item_is_virtual(stack) then return end
local pos = player:get_pos()
pos.y = pos.y + player:get_properties().eye_height
local def = stack:get_definition() or {}
if def.on_drop
and def.on_drop ~= minetest.item_drop
and def.on_drop ~= minetest.nodedef_default.on_drop
and def.on_drop ~= minetest.craftitemdef_default.on_drop
and def.on_drop ~= minetest.tooldef_default.on_drop
and def.on_drop ~= minetest.noneitemdef_default.on_drop then
nodecore.log("action", string_format("%s loses item %q at %s by on_drop",
player:get_player_name(), shortdesc(stack),
minetest.pos_to_string(pos, 0)))
stack = def.on_drop(stack, player, pos)
return inv:set_stack(listname, slot, stack)
end
nodecore.log("action", string_format("%s loses item %q at %s by eject(%d)",
player:get_player_name(), shortdesc(stack),
minetest.pos_to_string(pos, 0), math_floor(speed + 0.5)))
nodecore.item_eject(pos, stack, speed)
return inv:set_stack(listname, slot, "")
end
nodecore.item_lose = item_lose
function nodecore.inventory_dump(player)
for listname, list in pairs(player:get_inventory():get_lists()) do
if listname ~= "hand" then
for slot in pairs(list) do
item_lose(player, listname, slot, 0.001)
end
end
end
end
local keeppriv = "keepinv"
minetest.register_privilege(keeppriv, {
description = "Allow player to keep inventory on teleport",
give_to_singleplayer = false,
give_to_admin = false
})
local telefunc = minetest.registered_chatcommands.teleport
telefunc = telefunc and telefunc.func
if telefunc then
minetest.registered_chatcommands.teleport.func = function(...)
local anyplayer = minetest.get_connected_players()[1]
local meta = anyplayer and getmetatable(anyplayer)
local oldsetpos = meta and meta.set_pos
if not oldsetpos then return telefunc(...) end
meta.set_pos = function(player, ...)
if not minetest.check_player_privs(player, keeppriv) then
nodecore.inventory_dump(player)
end
return oldsetpos(player, ...)
end
local function helper(...)
meta.set_pos = oldsetpos
return ...
end
return helper(telefunc(...))
end
end

View File

@ -0,0 +1,95 @@
-- LUALOCALS < ---------------------------------------------------------
local nodecore, pairs, setmetatable, string, tostring
= nodecore, pairs, setmetatable, string, tostring
local string_find, string_gsub
= string.find, string.gsub
-- LUALOCALS > ---------------------------------------------------------
local tmod = {}
local tmeta = {}
setmetatable(tmod, tmeta)
nodecore.tmod = tmod
function tmod:new(img)
local obj = {img = img}
local ometa = {}
for k, v in pairs(tmeta) do ometa[k] = v end
ometa.__index = self
setmetatable(obj, ometa)
return obj
end
tmeta.__call = tmod.new
function tmeta:__tostring()
return self.img
end
function tmod:add(img)
if not self.img then return tmod:new(img) end
img = tostring(img)
if string_find(img, "%^") then
return tmod:new(self.img .. "^(" .. img .. ")")
else
return tmod:new(self.img .. "^" .. img)
end
end
local function esc(s)
return string_gsub(string_gsub(tostring(s),
"%^", "\\^"), ":", "\\:")
end
local function addmod(self, name)
if self.img then
return self.img .. "^[" .. name
end
return "[" .. name
end
local function simplemod(name, ...)
local delims = {...}
local lastdelim = delims[#delims]
return function(self, ...)
local s = addmod(self, name)
local args = {...}
for i = 1, #args do
s = s .. (delims[i] or lastdelim) .. esc(args[i])
end
return tmod:new(s)
end
end
for k in pairs({
crack = true,
cracko = true,
opacity = true,
invert = true,
brighten = true,
noalpha = true,
lowpart = true,
verticalframe = true,
mask = true,
colorize = true,
multiply = true
}) do
tmod[k] = simplemod(k, ":")
end
tmod.resize = simplemod("resize", ":", "x")
tmod.makealpha = simplemod("makealpha", ":", ",")
tmod.transform = simplemod("transform", "")
tmod.sheet = simplemod("sheet", ":", "x", ":", ",")
function tmod:inventorycube(...)
local s = addmod(self, "inventorycube")
for _, arg in pairs({...}) do
s = s .. "{" .. string_gsub(tostring(arg), "%^", "&")
end
return tmod:new(s)
end
tmod.combine = simplemod("combine", ":", "x")
function tmod:layer(x, y, img)
return tmod:new((self.img or "") .. ":" .. esc(x) .. ","
.. esc(y) .. "=" .. esc(img))
end

View File

@ -11,6 +11,7 @@ local basetimes = {
choppy = 2,
crumbly = 0.5,
snappy = 0.4,
scratchy = 2
}
nodecore.tool_basetimes = basetimes
@ -36,5 +37,5 @@ function nodecore.toolcaps(opts)
}
end
end
return {groupcaps = gcaps, opts = opts}
return {groupcaps = gcaps, opts = opts, punch_attack_uses = 0}
end

View File

@ -30,19 +30,21 @@ function nodecore.translate(str, ...)
return minetest.translate(modname, str, ...)
end
minetest.register_globalstep(function()
if not strings_dirty then return end
strings_dirty = nil
if nodecore.infodump() then
nodecore.register_globalstep("translate templates", 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 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 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)
local p = minetest.get_worldpath() .. "/" .. modname .. ".template.tr"
return minetest.safe_file_write(p, data)
end)
end

View File

@ -0,0 +1,85 @@
-- LUALOCALS < ---------------------------------------------------------
local minetest, nodecore, pairs, rawset, table
= minetest, nodecore, pairs, rawset, table
local table_concat
= table.concat
-- LUALOCALS > ---------------------------------------------------------
local muxdefs = {}
local abmsdefined = {}
local grp = "group:"
local function matches(name, def, nodenames)
for _, n in pairs(nodenames) do
if name == n then return true
elseif n:sub(1, #grp) == grp then
local g = def.groups and def.groups[n:sub(#grp + 1)]
if g and g > 0 then return true end
end
end
end
nodecore.register_on_register_item(function(name, def)
if def.type == "node" then
for _, mux in pairs(muxdefs) do
if (not (def.groups and def.groups[mux.muxkey]))
and matches(name, def, mux.nodenames) then
rawset(def.groups, "abmmux_" .. mux.muxkey, 1)
end
end
end
end)
local muxidx = nodecore.item_matching_index(muxdefs,
function(i) return i.nodenames end,
"register_abm",
true,
function(n, i) return i.muxkey .. n end
)
local oldreg = minetest.register_abm
function minetest.register_abm(def)
local rawkey = table_concat({
def.interval,
def.chance,
def.catchup and 1 or 0,
table_concat(def.neighbors or {}, ";")
}, "|")
def.rawkey = rawkey
local muxkey = minetest.sha1(rawkey):sub(1, 8)
def.muxkey = muxkey
muxdefs[#muxdefs + 1] = def
for k, v in pairs(minetest.registered_nodes) do
if (not v.groups[muxkey]) and matches(k, v, def.nodenames) then
rawset(v.groups, "abmmux_" .. muxkey, 1)
minetest.override_item(k, {groups = v.groups})
end
end
if abmsdefined[muxkey] then return end
abmsdefined[muxkey] = true
local warnunused
warnunused = function(nn)
warnunused = function() end
return nodecore.log("warning", "no abm found for mux " .. rawkey
.. " node " .. nn)
end
return oldreg({
label = "mux abm for " .. rawkey,
interval = def.interval,
chance = def.chance,
catchup = def.catchup,
neighbors = def.neighbors,
nodenames = {"group:abmmux_" .. muxkey},
action = function(pos, node, ...)
local oldname = node.name
local found = muxidx[muxkey .. oldname]
if not found then return warnunused(oldname) end
found[1].action(pos, node, ...)
if #found <= 1 then return end
for i = 2, #found do
if minetest.get_node(pos).name ~= oldname then return end
found[i].action(pos, node, ...)
end
end
})
end

106
mods/nc_api_active/aism.lua Normal file
View File

@ -0,0 +1,106 @@
-- LUALOCALS < ---------------------------------------------------------
local ItemStack, math, minetest, nodecore, pairs
= ItemStack, math, minetest, nodecore, pairs
local math_random
= math.random
-- LUALOCALS > ---------------------------------------------------------
-- Active ItemStack Modifiers
-- Definition:
--- itemnames: {"mod:itemname", "group:name"}
--- interval: integer,
--- chance: integer,
--- action: function(stack, data) end
-- Data:
--- {pos, node}
--- {player, inv, list, slot}
nodecore.register_aism,
nodecore.registered_aisms
= nodecore.mkreg()
local aismidx = nodecore.item_matching_index(
nodecore.registered_aisms,
function(i) return i.itemnames end,
"register_aism"
)
local function checkrun(def, stack, data)
if nodecore.stasis and not def.ignore_stasis then return end
if def.chance and def.chance > 1 and math_random(1, def.chance) ~= 1 then return end
if def.interval and def.interval > 1 and (minetest.get_gametime() % def.interval) ~= 0 then return end
stack = def.action(stack, data)
if stack and data.set then data.set(ItemStack(stack)) end
end
local function checkstack(stack, data)
local defs = aismidx[stack:get_name()]
if not defs then return end
for def in pairs(defs) do
checkrun(def, stack, data)
end
end
nodecore.aism_check_stack = checkstack
nodecore.register_limited_abm({
label = "aism schedule",
nodenames = {"group:visinv"},
interval = 1,
chance = 1,
ignore_stasis = true,
action = function(pos, node)
return checkstack(nodecore.stack_get(pos), {
pos = pos,
node = node,
set = function(s)
return nodecore.stack_set(pos, s)
end
})
end
})
nodecore.interval(1, function()
for _, player in pairs(minetest.get_connected_players()) do
local pos = player:get_pos()
pos.y = pos.y + player:get_properties().eye_height
local inv = player:get_inventory()
for lname, list in pairs(inv:get_lists()) do
for slot, stack in pairs(list) do
checkstack(stack, {
pos = pos,
player = player,
inv = inv,
list = lname,
slot = slot,
set = function(s)
return inv:set_stack(lname, slot, s)
end
})
end
end
end
end)
nodecore.register_item_entity_step(function(self, dtime)
local t = (self.aismtimer or 0) + dtime
while t >= 1 do
t = t - 1
local pos = self.object:get_pos()
if not pos then return end
local setstack
checkstack(ItemStack(self.itemstring), {
pos = pos,
obj = self.object,
ent = self,
set = function(s) setstack = s end
})
if setstack then
if setstack:is_empty() then
return self.object:remove()
end
self.itemstring = setstack:to_string()
end
end
self.aismtimer = t
end)

View File

@ -5,7 +5,7 @@ local math_random
= math.random
-- LUALOCALS > ---------------------------------------------------------
function nodecore.register_ambiance(def)
local function ambiance_core(def, getpos)
local max = def.queue_max or 100
local rate = 1 / (def.queue_rate or 20)
@ -15,7 +15,7 @@ function nodecore.register_ambiance(def)
local batch
local time = 0
minetest.register_globalstep(function(dtime)
nodecore.register_globalstep("ambiance_core " .. (def.label or "unlabeled"), function(dtime)
time = time + dtime
while time > rate do
if not batch then
@ -32,13 +32,14 @@ function nodecore.register_ambiance(def)
opts.name = opts.name or def.sound_name
opts.gain = opts.gain or def.sound_gain
minetest.sound_play(opts.name, opts)
nodecore.sound_play(opts.name, opts)
time = time - rate
end
end)
def.action = function(pos)
def.action = function(...)
local pos = getpos(...)
local hash = minetest.hash_node_position(pos)
if seen[hash] then return end
seen[hash] = true
@ -60,6 +61,16 @@ function nodecore.register_ambiance(def)
end
total = total + 1
end
end
local function abm_pos(pos) return pos end
function nodecore.register_ambiance(def)
ambiance_core(def, abm_pos)
return nodecore.register_limited_abm(def)
end
local function aism_pos(_, data) return data.pos end
function nodecore.register_item_ambiance(def)
ambiance_core(def, aism_pos)
return nodecore.register_aism(def)
end

144
mods/nc_api_active/dnts.lua Normal file
View File

@ -0,0 +1,144 @@
-- LUALOCALS < ---------------------------------------------------------
local error, math, minetest, nodecore, pairs, string
= error, math, minetest, nodecore, pairs, string
local math_random, string_format
= math.random, string.format
-- LUALOCALS > ---------------------------------------------------------
-- Active Block Modifiers, meet Delayed Node Triggers.
-- Definition:
--- mname: "modname:technicalname"
--- nodenames: {"mod:itemname", "group:name"}
--- time: float (optional),
--- loop: boolean,
--- action: function(pos, node) end
nodecore.registered_dnts = {}
local grouppref = "group:"
local function buildidx(list)
if not list then return end
local n = {}
local g
for _, v in pairs(list) do
if v:sub(1, #grouppref) == grouppref then
g = g or {}
g[v:sub(#grouppref + 1)] = true
else
n[v] = true
end
end
if g then
minetest.after(0, function()
for k in pairs(minetest.registered_nodes) do
for x in pairs(g) do
if minetest.get_item_group(k, x) > 0 then
n[k] = true
end
end
end
end)
end
return n
end
function nodecore.register_dnt(def)
if not def.name then return error("dnt name required") end
if not def.action then return error("dnt action required") end
if nodecore.registered_dnts[def.name] then
return error(string_format("dnt %q already registered", def.name))
end
def.nodeidx = buildidx(def.nodenames)
nodecore.registered_dnts[def.name] = def
end
local dntkey = "dnt"
local function dntsave(pos, meta, data)
local now = nodecore.gametime
local prev = data[false]
local el = prev and (now - prev) or 0
local min
local run = {}
local reg = nodecore.registered_dnts
for k, v in pairs(data) do
if k then
v = v - el
if v < 0 then
local def = reg[k]
if def then
if def.ignore_stasis or not nodecore.stasis then
run[def] = true
v = def.loop and def.time or nil
else
v = def.time and (def.time < 1) and def.time or 1
end
data[k] = v
if (not min) or (min < v) then min = v end
end
else
data[k] = v
if (not min) or (min < v) then min = v end
end
end
end
data[false] = now
meta:set_string(dntkey, minetest.serialize(data))
if min then minetest.get_node_timer(pos):start(min) end
local node = minetest.get_node(pos)
local nn = node.name
for k in pairs(run) do
local idx = k.nodeidx
if (not idx) or idx[nn] then k.action(pos, node) end
end
end
local function dntload(pos)
local meta = minetest.get_meta(pos)
local s = meta:get_string(dntkey)
s = s and s ~= "" and minetest.deserialize(s) or {}
return s, function() return dntsave(pos, meta, s) end
end
local squelched = {}
local function maybecheck(pos, save)
local hash = minetest.hash_node_position(pos)
local s = squelched[hash]
if s and s > nodecore.gametime then return end
squelched[hash] = nodecore.gametime + 5 + math_random() * 10
return save()
end
function nodecore.dnt_set(pos, name, time)
local data, save = dntload(pos)
local prev = data[name]
time = time or nodecore.registered_dnts[name].time or 1
if prev and prev < time then return maybecheck(pos, save) end
data[name] = time
return save()
end
function nodecore.dnt_reset(pos, name, time)
local data, save = dntload(pos)
local prev = data[name]
time = time or nodecore.registered_dnts[name].time or 1
if prev and prev == time then return maybecheck(pos, save) end
data[name] = time
return save()
end
minetest.nodedef_default.on_timer = function(pos)
local _, save = dntload(pos)
return save()
end
nodecore.register_on_register_item(function(def)
if def.on_timer then
return error("on_timer hook is disallowed in "
.. nodecore.product .. "; use DNT instead")
end
end)

View File

@ -0,0 +1,186 @@
-- LUALOCALS < ---------------------------------------------------------
local ItemStack, minetest, nodecore, pairs, setmetatable, vector
= ItemStack, minetest, nodecore, pairs, setmetatable, vector
-- LUALOCALS > ---------------------------------------------------------
local modname = minetest.get_current_modname()
-- Register nodes that can be replaced by dynamic lights
local canreplace = {air = 0}
local true_airlike = {
drawtype = "airlike",
pointable = false,
walkable = false,
climbable = false,
buildable_to = true,
floodable = true,
air_equivalent = true,
paramtype = "light",
light_source = 0,
sunlight_propagates = true,
}
minetest.after(0, function()
for k, v in pairs(minetest.registered_nodes) do
local ok = not canreplace[k]
for dk, dv in pairs(true_airlike) do
ok = ok and v[dk] == dv
end
if ok then canreplace[k] = 0 end
end
end)
-- API for checking if dynamic lights are valid
local ttl = 0.25
local active_lights = {}
local function setup_light(pos, check)
active_lights[minetest.hash_node_position(pos)] = {
exp = nodecore.gametime + ttl,
check = check
}
minetest.get_node_timer(pos):start(ttl)
end
local function check_light(pos)
local data = active_lights[minetest.hash_node_position(pos)]
if not data then return minetest.remove_node(pos) end
if nodecore.gametime < data.exp then return end
if data.check and data.check() then
data.exp = nodecore.gametime + ttl
minetest.get_node_timer(pos):start(ttl)
return
end
minetest.remove_node(pos)
return true
end
-- Register dynamic light nodes
local nodes = {}
local function dynamic_light_node(level) return modname .. ":light" .. level end
nodecore.dynamic_light_node = dynamic_light_node
for level = 1, nodecore.light_sun - 1 do
if nodes[level] then return nodes[level] end
local name = dynamic_light_node(level)
local def = {
light_source = level,
on_timer = check_light,
air_equivalent = true,
groups = {dynamic_light = level}
}
for k, v in pairs(true_airlike) do def[k] = def[k] or v end
minetest.register_node(":" .. name, def)
nodes[level] = name
canreplace[name] = level
end
minetest.register_alias("nc_torch:wield_light", dynamic_light_node(8))
-- API for adding dynamic lights to world
nodecore.register_limited_abm({
label = "dynamic light cleanup",
interval = 1,
chance = 1,
nodenames = {"group:dynamic_light"},
action = check_light
})
local function dynamic_light_add(pos, level, check, exact)
if not pos then return end
local name = minetest.get_node(pos).name
local curlight = canreplace[name]
if not curlight then
if exact then return end
return dynamic_light_add({x = pos.x, y = pos.y - 1, z = pos.z}, level, check, true)
or dynamic_light_add({x = pos.x, y = pos.y + 1, z = pos.z}, level, check, true)
or dynamic_light_add({x = pos.x + 1, y = pos.y, z = pos.z}, level, check, true)
or dynamic_light_add({x = pos.x - 1, y = pos.y, z = pos.z}, level, check, true)
or dynamic_light_add({x = pos.x, y = pos.y, z = pos.z + 1}, level, check, true)
or dynamic_light_add({x = pos.x, y = pos.y, z = pos.z - 1}, level, check, true)
end
if level < 1 then return end
if level > nodecore.light_sun - 1 then level = nodecore.light_sun - 1 end
local setname = dynamic_light_node(level)
pos = vector.round(pos)
if curlight <= level then
local ll = nodecore.get_node_light(pos)
if ll and ll > level then return end
end
if curlight > level and not check_light(pos) then return end
if name ~= setname then minetest.set_node(pos, {name = setname}) end
setup_light(pos, check)
return true
end
nodecore.dynamic_light_add = dynamic_light_add
-- Automatic player wield lights
local function lightsrc(stack)
local def = minetest.registered_items[stack:get_name()] or {}
return def.light_source or 0
end
local function player_wield_light(player)
local glow = 0
for _, stack in pairs(player:get_inventory():get_list("main")) do
local src = lightsrc(stack)
if src > glow then glow = src end
end
if glow < 1 then return end
local pos = player:get_pos()
pos.y = pos.y + player:get_properties().eye_height
pos = vector.round(pos)
local pname = player:get_player_name()
return dynamic_light_add(pos, glow, function()
local pl = minetest.get_player_by_name(pname)
if not pl then return end
local pp = pl:get_pos()
pp.y = pp.y + pl:get_properties().eye_height
return vector.equals(pos, vector.round(pp))
end)
end
nodecore.register_playerstep({
label = "player wield light",
action = function(player)
if nodecore.player_visible(player) then
return player_wield_light(player)
end
end
})
-- Automatic entity light sources
local function entlight(self, ...)
local stack = ItemStack(self.node and self.node.name or self.itemstring or "")
local src = lightsrc(stack)
if src > 0 then
local pos = self.object:get_pos()
if not pos then return ... end
pos = vector.round(pos)
nodecore.dynamic_light_add(pos, src, function()
for _, v in pairs(nodecore.get_objects_at_pos(pos)) do
if v == self.object then return true end
end
end)
end
return ...
end
for _, name in pairs({"item", "falling_node"}) do
local def = minetest.registered_entities["__builtin:" .. name]
local ndef = {
on_step = function(self, ...)
return entlight(self, def.on_step(self, ...))
end
}
setmetatable(ndef, def)
minetest.register_entity(":__builtin:" .. name, ndef)
end

View File

@ -0,0 +1,17 @@
-- LUALOCALS < ---------------------------------------------------------
local include, minetest, nodecore
= include, minetest, nodecore
-- LUALOCALS > ---------------------------------------------------------
nodecore.amcoremod()
nodecore.register_limited_abm = function(...) return minetest.register_abm(...) end
include("abmmux")
include("stasis")
include("dnts")
include("aism")
include("soaking")
include("ambiance")
include("playerstep")
include("dynalight")

View File

@ -0,0 +1 @@
depends = nc_api, nc_api_ents

Some files were not shown because too many files have changed in this diff Show More