Merge tag '0.88.0' into mtsr_devel
This commit is contained in:
commit
aac9a30a0d
@ -10,7 +10,7 @@ whether you're a programmer or not.
|
||||
|
||||
## VoxeLibre's development target is to...
|
||||
- Create a stable, peformant, moddable, free/libre game inspired by Minecraft
|
||||
using the Minetest engine, usable in both singleplayer and multiplayer.
|
||||
using the Luanti engine, usable in both singleplayer and multiplayer.
|
||||
- Currently, a lot of features are already implemented.
|
||||
Polishing existing features is always welcome.
|
||||
|
||||
@ -20,8 +20,8 @@ Polishing existing features is always welcome.
|
||||
* [YouTube](https://www.youtube.com/channel/UClI_YcsXMF3KNeJtoBfnk9A)
|
||||
* [Matrix](https://app.element.io/#/room/#voxelibre:matrix.org)
|
||||
* [Reddit](https://www.reddit.com/r/VoxeLibre/)
|
||||
* [Minetest forums](https://forum.minetest.net/viewtopic.php?f=50&t=16407)
|
||||
* [ContentDB](https://content.minetest.net/packages/wuzzy/mineclone2/)
|
||||
* [Luanti forums](https://forum.luanti.org/viewtopic.php?f=50&t=16407)
|
||||
* [ContentDB](https://content.luanti.org/packages/wuzzy/mineclone2/)
|
||||
* [OpenCollective](https://opencollective.com/mineclone2)
|
||||
|
||||
## Using git
|
||||
@ -39,7 +39,7 @@ https://git.minetest.land/VoxeLibre/VoxeLibre/wiki/
|
||||
|
||||
## How you can help as a non-programmer
|
||||
As someone who does not know how to write programs in Lua or does not
|
||||
know how to use the Minetest API, you can still help us out a lot. For
|
||||
know how to use the Luanti API, you can still help us out a lot. For
|
||||
example, by opening an issue in the
|
||||
[Issue tracker](https://git.minetest.land/VoxeLibre/VoxeLibre/issues),
|
||||
you can report a bug or request a feature.
|
||||
@ -53,10 +53,10 @@ discussion.
|
||||
Try not to report bugs that have already been reported or request features
|
||||
that already have been requested. This can often be ambiguous though.
|
||||
If in doubt open an issue!
|
||||
* If you know about Minetest's inner workings, please think about
|
||||
* If you know about Luanti's inner workings, please think about
|
||||
whether the bug / the feature that you are reporting / requesting is
|
||||
actually an issue with Minetest itself, and if it is, head to the
|
||||
[Minetest issue tracker](https://github.com/minetest/minetest/issues)
|
||||
actually an issue with Luanti itself, and if it is, head to the
|
||||
[Luanti issue tracker](https://github.com/minetest/minetest/issues)
|
||||
instead.
|
||||
* If you need any help regarding creating a Mesehub account or opening
|
||||
an issue, feel free to ask on the Discord or Matrix space.
|
||||
@ -69,11 +69,11 @@ The link to the mesehub registration page is: https://git.minetest.land/user/sig
|
||||
However, it is not a bug if you believe something is missing in the
|
||||
game. In this case, please read "Requesting features"
|
||||
* If you report a crash, always include the error message. If you play
|
||||
in singleplayer, post a screenshot of the message that Minetest showed
|
||||
in singleplayer, post a screenshot of the message that Luanti showed
|
||||
when the crash happened (or copy the message into your issue). If you
|
||||
are a server admin, you can find error messages in the log file of the
|
||||
server.
|
||||
* Tell us which VoxeLibre and Minetest versions you are using (from Minetest 5.7 type /ver, for previous versions, check the game.conf or README.md file).
|
||||
* Tell us which VoxeLibre and Luanti versions you are using (from Luanti 5.7 type /ver, for previous versions, check the game.conf or README.md file).
|
||||
* Tell us how to reproduce the problem: What you were doing to trigger
|
||||
the bug, e.g. before the crash happened or what causes the faulty
|
||||
behavior.
|
||||
@ -182,13 +182,13 @@ is by giving us profiler results. Profiler results give us detailed
|
||||
information about the game's performance and let us know places to
|
||||
investigate optimization issues. This way we can make the game faster.
|
||||
|
||||
#### Using Minetest's profiler
|
||||
#### Using Luanti's profiler
|
||||
We frequently will use profiling to optimise our code. We recommend use of
|
||||
the JIT profiler (RIP Jude) to fully understand performance impact:
|
||||
|
||||
https://content.minetest.net/packages/jwmhjwmh/jitprofiler/
|
||||
https://content.luanti.org/packages/jwmhjwmh/jitprofiler/
|
||||
|
||||
Minetest also has a built in profiler. Simply set `profiler.load = true` in
|
||||
Luanti also has a built in profiler. Simply set `profiler.load = true` in
|
||||
your configuration file and restart the server. After running the server
|
||||
for some time, just run `/profiler save` in chat - then you will find a
|
||||
file in the world directory containing the results. Open a new issue and
|
||||
@ -243,7 +243,7 @@ you'd like to take care of it, to avoid duplicate work.
|
||||
### Don't hesitate to ask for help
|
||||
We appreciate any contributing effort to VoxeLibre. If you are a
|
||||
relatively new programmer, you can reach us on Discord or Matrix
|
||||
for questions about git, Lua, Minetest API, VoxeLibre codebase or
|
||||
for questions about git, Lua, Luanti API, VoxeLibre codebase or
|
||||
anything related to VoxeLibre. We can help you avoid writing code that
|
||||
would be deemed inadequate, or help you become familiar with VoxeLibre
|
||||
better, or assist you use development tools.
|
||||
@ -294,7 +294,7 @@ split up but in general multiple small PRs are better than a big one
|
||||
* Each mod must provide `mod.conf`.
|
||||
* Mod names are snake case, and newly added mods (or substantially changed mods
|
||||
that are included from the outside) start with `vl_`, e.g.
|
||||
`vl_hollow_logs`, . Keep in mind Minetest
|
||||
`vl_hollow_logs`, . Keep in mind Luanti
|
||||
does not support capital letters in mod names.
|
||||
* In the past mods were prefixed with `mcl_`, e.g.
|
||||
`mcl_core`, `mcl_farming`, `mcl_monster_eggs`. New mods should **never** use this prefix.
|
||||
@ -325,7 +325,7 @@ function mcl_example.do_something()
|
||||
end
|
||||
```
|
||||
|
||||
* Use modern Minetest API, e.g. no usage of `minetest.env`
|
||||
* Use modern Luanti API, e.g. no usage of `minetest.env`
|
||||
* Tabs should be used for indent, spaces for alignment, e.g.
|
||||
|
||||
```lua
|
||||
@ -423,7 +423,7 @@ from `CREDITS.md` and commit the result (if anything changed)
|
||||
version number
|
||||
* Push to repository (don't forget `--tags`!)
|
||||
* Update ContentDB
|
||||
(https://content.minetest.net/packages/Wuzzy/mineclone2/)
|
||||
(https://content.luanti.org/packages/Wuzzy/mineclone2/)
|
||||
* Update first post in forum thread
|
||||
(https://forum.minetest.net/viewtopic.php?f=50&t=16407)
|
||||
* Post release announcement and changelog in forums
|
||||
|
23
CREDITS.md
23
CREDITS.md
@ -24,6 +24,7 @@
|
||||
* Faerraven / Michieal
|
||||
* rudzik8
|
||||
* teknomunk
|
||||
* kno10
|
||||
|
||||
## Past Developers
|
||||
* jordan4ibanez
|
||||
@ -141,6 +142,17 @@
|
||||
* Bram
|
||||
* qoheniac
|
||||
* WillConker
|
||||
* 0ldude
|
||||
* tacotexmex
|
||||
* Pixel-Peter
|
||||
* OgelGames
|
||||
* blitzdoughnuts
|
||||
* goodspeed
|
||||
* Bloodaxe
|
||||
* ClementMR
|
||||
* THE-NERD2
|
||||
* ethan
|
||||
* villager8472
|
||||
|
||||
## Music
|
||||
* Jordach for the jukebox music compilation from Big Freaking Dig
|
||||
@ -193,6 +205,7 @@
|
||||
* Faerraven / Michieal
|
||||
* SumianVoice
|
||||
* thunder1035
|
||||
* Herowl
|
||||
|
||||
## Textures
|
||||
* XSSheep
|
||||
@ -237,6 +250,14 @@
|
||||
* ADLON
|
||||
* Sab Pyrope
|
||||
* JoseDouglas26
|
||||
* 0ldude
|
||||
* Bloodaxe
|
||||
* ethan
|
||||
* Herowl
|
||||
* kno10
|
||||
* Pixel-Peter
|
||||
* Laudrin
|
||||
* chmodsayshello
|
||||
|
||||
## Funders
|
||||
* 40W
|
||||
@ -244,6 +265,6 @@
|
||||
* Cora
|
||||
|
||||
## Special thanks
|
||||
* The Minetest team for making and supporting an engine, and distribution infrastructure that makes this all possible
|
||||
* The Luanti team for making and supporting an engine, and distribution infrastructure that makes this all possible
|
||||
* The workaholics who spent way too much time writing for the Minecraft Wiki. It's an invaluable resource for creating this game
|
||||
* Notch and Jeb for being the major forces behind Minecraft
|
||||
|
@ -2,8 +2,8 @@ Survive, farm, build, explore, play with friends, and do much more. Inspired by
|
||||
|
||||
How to play:
|
||||
|
||||
#### Download Minetest
|
||||
- Navigate to https://www.minetest.net/ to download the client.
|
||||
#### Download Luanti
|
||||
- Navigate to https://www.luanti.org/ to download the client.
|
||||
- Once installed, open and select the "Content" tab
|
||||
|
||||
#### Install VoxeLibre from ContentDB
|
||||
|
3
LEGAL.md
3
LEGAL.md
@ -46,6 +46,9 @@ Armor trim models were created by Aeonix_Aeon
|
||||
Source: <https://www.curseforge.com/minecraft/texture-packs/ozocraft-remix>
|
||||
License: [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/)
|
||||
|
||||
Charcoal block texture was created by [blitzdoughnuts](https://gitlab.com/ApplemunchFromDaDead), based on the Pixel Perfection coal block.
|
||||
License: [CC BY-SA 4.0](http://creativecommons.org/licenses/by-sa/4.0/)
|
||||
|
||||
The main menu images are released under: [CC0](https://creativecommons.org/publicdomain/zero/1.0/)
|
||||
|
||||
All other files, unless mentioned otherwise, fall under:
|
||||
|
16
MODELS.md
16
MODELS.md
@ -1,22 +1,22 @@
|
||||
# Models in Minetest/VoxeLibre
|
||||
# Models in Luanti/VoxeLibre
|
||||
|
||||
Models are an important part of all entities & unique nodes in VoxeLibre. They provide a 3 dimensional map of an object for which textures are then applied to. This document is for modders, it quickly highlights some important information for the software needed to open models in VoxeLibre.
|
||||
|
||||
## Minetest Wiki
|
||||
## Luanti Wiki
|
||||
|
||||
For more detailed information on actually using blender to create and modify models for Minetest/VoxeLibre, please visit the Minetest wiki's page on using Blender [Here](https://wiki.minetest.net/Using_Blender)
|
||||
For more detailed information on actually using blender to create and modify models for Luanti/VoxeLibre, please visit the Luanti wiki's page on using Blender [Here](https://wiki.luanti.org/Using_Blender)
|
||||
|
||||
## Recommended software
|
||||
|
||||
### Blender
|
||||
|
||||
Blender is a very popular and free modeling software supported on Windows, MacOS, and most Linux distributions. It is recommended to use Blender to create and modify 3D models within the minetest engine.
|
||||
Blender is a very popular and free modeling software supported on Windows, MacOS, and most Linux distributions. It is recommended to use Blender to create and modify 3D models within the Luanti engine.
|
||||
|
||||
Download blender [Here](https://www.blender.org/download/)
|
||||
|
||||
### .b3d addon for blender
|
||||
|
||||
Blitz 3D (.b3d) Is one of the main animated model formats used for entities in the minetest engine. It cannot be imported to blender without a plugin called "Import-Export:Bitz 3D format (.b3d)".
|
||||
Blitz 3D (.b3d) Is one of the main animated model formats used for entities in the Luanti engine. It cannot be imported to blender without a plugin called "Import-Export:Bitz 3D format (.b3d)".
|
||||
|
||||
The most up to date version of this Blender plugin can be downloaded [Here](https://github.com/GreenXenith/io_scene_b3d/releases/tag/f189786)
|
||||
|
||||
@ -34,7 +34,7 @@ The most up to date version of this Blender plugin can be downloaded [Here](http
|
||||
|
||||
Note: The sometimes accompanying .mtl files are not supported and can safely be deleted.
|
||||
|
||||
Note: Do not use .b3d and .x files for static meshes at the moment, Minetest currently spawns animated mesh scene nodes for these, which may result in reduced performance.
|
||||
Note: Do not use .b3d and .x files for static meshes at the moment, Luanti currently spawns animated mesh scene nodes for these, which may result in reduced performance.
|
||||
|
||||
### Supported texture formats
|
||||
|
||||
@ -42,9 +42,9 @@ Note: Do not use .b3d and .x files for static meshes at the moment, Minetest cur
|
||||
|
||||
* .jpg
|
||||
|
||||
* .bmp (depreciated, please use .png or .jpg)
|
||||
* .bmp (deprecated, please use .png or .jpg)
|
||||
|
||||
* .tga (depreciated, please use .png or .jpg)
|
||||
* .tga (deprecated, please use .png or .jpg)
|
||||
|
||||
Note: Any formats not mentioned above but known to work in the past were removed in 5.5.0 and aren't supported anymore.
|
||||
|
||||
|
28
README.md
28
README.md
@ -1,5 +1,5 @@
|
||||
# VoxeLibre
|
||||
A game inspired by Minecraft for Minetest. Forked from MineClone by davedevils.
|
||||
A game inspired by Minecraft for Luanti. Forked from MineClone by davedevils.
|
||||
Developed by many people, see CREDITS.md for a complete list.
|
||||
|
||||
### Gameplay
|
||||
@ -65,16 +65,16 @@ an explanation.
|
||||
|
||||
## Installation
|
||||
To run the game with the best performance and support, we recommend the latest
|
||||
stable version of [Minetest](http://minetest.net), be we always make an effort
|
||||
stable version of [Luanti](https://www.luanti.org/), but we always make an effort
|
||||
to support one version behind the latest stable version. In some cases, older
|
||||
versions might still be good enough but you would be missing out on important
|
||||
Minetest features that enable important features for our game.
|
||||
Luanti features that enable important features for our game.
|
||||
|
||||
There is no support for running VoxeLibre in development versions of Minetest.
|
||||
There is no support for running VoxeLibre in development versions of Luanti.
|
||||
|
||||
To install VoxeLibre (if you haven't already), move this directory into the
|
||||
“games” directory of your Minetest data directory. Consult the help of
|
||||
Minetest to learn more.
|
||||
“games” directory of your Luanti data directory. Consult the help of
|
||||
Luanti to learn more.
|
||||
|
||||
## Useful links
|
||||
The VoxeLibre repository is hosted at Mesehub. To contribute or report issues, head there.
|
||||
@ -82,18 +82,18 @@ The VoxeLibre repository is hosted at Mesehub. To contribute or report issues, h
|
||||
* Mesehub: <https://git.minetest.land/VoxeLibre/VoxeLibre>
|
||||
* Discord: <https://discord.gg/xE4z8EEpDC>
|
||||
* YouTube: <https://www.youtube.com/channel/UClI_YcsXMF3KNeJtoBfnk9A>
|
||||
* ContentDB: <https://content.minetest.net/packages/wuzzy/mineclone2/>
|
||||
* OpenCollective: <https://opencollective.com/mineclone2>
|
||||
* ContentDB: <https://content.luanti.org/packages/wuzzy/mineclone2/>
|
||||
* OpenCollective: <https://opencollective.com/voxelibre>
|
||||
* Mastodon: <https://fosstodon.org/@VoxeLibre>
|
||||
* Lemmy: <https://lemm.ee/c/voxelibre>
|
||||
* Matrix space: <https://app.element.io/#/room/#voxelibre:matrix.org>
|
||||
* Minetest forums: <https://forum.minetest.net/viewtopic.php?f=50&t=16407>
|
||||
* Luanti forums: <https://forum.luanti.org/viewtopic.php?f=50&t=16407>
|
||||
* Reddit: <https://www.reddit.com/r/VoxeLibre/>
|
||||
* IRC (barely used): <https://web.libera.chat/#mineclone2>
|
||||
|
||||
## Target
|
||||
- Create a stable, peformant, moddable, free/libre game inspired by Minecraft
|
||||
using the Minetest engine, usable in both singleplayer and multiplayer.
|
||||
using the Luanti engine, usable in both singleplayer and multiplayer.
|
||||
- Currently, a lot of features are already implemented.
|
||||
Polishing existing features is always welcome.
|
||||
|
||||
@ -159,8 +159,8 @@ Bonus features (not found in Minecraft):
|
||||
* Built-in crafting guide which shows you crafting and smelting recipes
|
||||
* In-game help system containing extensive help about gameplay basics, blocks, items and more
|
||||
* Temporary crafting recipes. They only exist to make some otherwise unaccessible items available when you're not in creative mode. These recipes will be removed as development goes on an more features become available
|
||||
* Saplings in chests in [mapgen v6](https://wiki.minetest.net/Map_generator#v6)
|
||||
* Fully moddable (thanks to Minetest's powerful Lua API)
|
||||
* Saplings in chests in [mapgen v6](https://wiki.luanti.org/Map_generator#v6)
|
||||
* Fully moddable (thanks to Luanti's powerful Lua API)
|
||||
* New blocks and items:
|
||||
* Lookup tool, shows you the help for whatever it touches
|
||||
* More slabs and stairs
|
||||
@ -181,7 +181,7 @@ Technical differences from Minecraft:
|
||||
* Different music for jukebox
|
||||
* Different textures (Pixel Perfection)
|
||||
* Different sounds (various sources)
|
||||
* Different engine (Minetest)
|
||||
* Different engine (Luanti)
|
||||
* Different easter eggs
|
||||
|
||||
… and finally, VoxeLibre is free software (“free” as in “freedom”)!
|
||||
@ -190,6 +190,6 @@ Technical differences from Minecraft:
|
||||
|
||||
* `LICENSE.txt`: The GPLv3 license text
|
||||
* `CONTRIBUTING.md`: Information for those who want to contribute
|
||||
* `API.md`: For Minetest modders who want to mod this game
|
||||
* `API.md`: For Luanti modders who want to mod this game
|
||||
* `LEGAL.md`: Legal information
|
||||
* `CREDITS.md`: List of everyone who contributed
|
||||
|
@ -1,5 +1,5 @@
|
||||
# VoxeLibre
|
||||
Un jeu inspiré de Minecraft pour Minetest. Forké depuis Mineclone par davedevils.
|
||||
Un jeu inspiré de Minecraft pour Luanti. Forké depuis Mineclone par davedevils.
|
||||
Développé par de nombreuses personnes, voir CREDITS.md pour une liste complète.
|
||||
|
||||
### Gameplay
|
||||
@ -54,10 +54,10 @@ Les objets suivants sont intéressants pour le mode Créatif et pour les constru
|
||||
Utilisez la commande de chat `/giveme` pour les obtenir. Voir l'aide interne au jeu pour une explication.
|
||||
|
||||
## Installation
|
||||
Ce jeu nécessite [Minetest](http://minetest.net) pour fonctionner (version 5.4.1 ou plus). Vous devez donc installer Minetest d'abord. Seules les versions stables de Minetest sont officielement supportées.
|
||||
Il n'y a pas de support de VoxeLibre dans les versions développement de Minetest.
|
||||
Ce jeu nécessite [Luanti](https://www.luanti.org) pour fonctionner (version 5.4.1 ou plus). Vous devez donc installer Luanti d'abord. Seules les versions stables de Luanti sont officielement supportées.
|
||||
Il n'y a pas de support de VoxeLibre dans les versions développement de Luanti.
|
||||
|
||||
Pour installer VoxeLibre (si ce n'est pas déjà fait), déplacez ce dossier dans le dossier “games” de Minetest. Consultez l'aide de Minetest pour en apprendre plus.
|
||||
Pour installer VoxeLibre (si ce n'est pas déjà fait), déplacez ce dossier dans le dossier “games” de Luanti. Consultez l'aide de Luanti pour en apprendre plus.
|
||||
|
||||
## Liens utiles
|
||||
Le dépôt de VoxeLibre est hébergé sur Mesehub. Pour contribuer ou signaler des problèmes, allez là-bas.
|
||||
@ -65,17 +65,17 @@ Le dépôt de VoxeLibre est hébergé sur Mesehub. Pour contribuer ou signaler d
|
||||
* Mesehub : <https://git.minetest.land/VoxeLibre/VoxeLibre>
|
||||
* Discord : <https://discord.gg/xE4z8EEpDC>
|
||||
* YouTube : <https://www.youtube.com/channel/UClI_YcsXMF3KNeJtoBfnk9A>
|
||||
* ContentDB : <https://content.minetest.net/packages/wuzzy/mineclone2/>
|
||||
* ContentDB : <https://content.luanti.org/packages/wuzzy/mineclone2/>
|
||||
* OpenCollective : <https://opencollective.com/mineclone2>
|
||||
* Mastodon : <https://fosstodon.org/@VoxeLibre>
|
||||
* Lemmy : <https://lemm.ee/c/voxelibre>
|
||||
* Espace Matrix : <https://app.element.io/#/room/#voxelibre:matrix.org>
|
||||
* Forums Minetest : <https://forum.minetest.net/viewtopic.php?f=50&t=16407>
|
||||
* Forums Luanti : <https://forum.luanti.org/viewtopic.php?f=50&t=16407>
|
||||
* Reddit : <https://www.reddit.com/r/VoxeLibre/>
|
||||
* IRC (peu utilisé) : <https://web.libera.chat/#mineclone2>
|
||||
|
||||
## Objectif
|
||||
* Créer un jeu stable, performant, moddable et libre inspiré de Minecraft en utilisant le moteur de jeu Minetest, utilisable à la fois en mode solo et multijoueur.
|
||||
* Créer un jeu stable, performant, moddable et libre inspiré de Minecraft en utilisant le moteur de jeu Luanti, utilisable à la fois en mode solo et multijoueur.
|
||||
* Actuellement, un grand nombre de fonctionnalités sont déjà implémentées.
|
||||
L'amélioration des fonctionnalités existantes est toujours la bienvenue.
|
||||
|
||||
@ -140,8 +140,8 @@ Fonctionnalités bonus (absentes de Minecraft) :
|
||||
* Guide d'artisanat intégré au jeu qui montre les recettes d'artisanat et de cuisson
|
||||
* Système d'aide intégré au jeu contenant des informations à propos des techniques de base, blocs, objets et plus
|
||||
* Recettes d'artisanat temporaires. Elles existent uniquement pour rendre des objets accessibles qui ne le seraient pas autrement sauf en mode créatif. Elles seront retirées au cours de l'avancement du développement et de l'ajout de nouvelles fonctionnalités.
|
||||
* Pousses dans les coffres en [mapgen v6](https://wiki.minetest.net/Map_generator#v6)
|
||||
* Entièrement moddable (grâce la puissante API Lua de Minetest)
|
||||
* Pousses dans les coffres en [mapgen v6](https://wiki.luanti.org/Map_generator#v6)
|
||||
* Entièrement moddable (grâce la puissante API Lua de Luanti)
|
||||
* Nouveaux blocs et objets :
|
||||
* Outil de recherche, montre l'aide de ce qu'il touche
|
||||
* Plus de dalles et d'escaliers
|
||||
@ -162,7 +162,7 @@ Différences techniques avec Minecraft :
|
||||
* Des musiques différentes pour le juke-boxe
|
||||
* Des textures différentes (Pixel Perfection)
|
||||
* Des sons différents (sources diverses)
|
||||
* Un moteur de jeu différent (Minetest)
|
||||
* Un moteur de jeu différent (Luanti)
|
||||
* Des bonus cachés différents
|
||||
|
||||
...et enfin VoxeLibre est un logiciel libre !
|
||||
@ -171,6 +171,6 @@ Différences techniques avec Minecraft :
|
||||
|
||||
* `LICENSE.txt` : Le texte de la licence GPLv3
|
||||
* `CONTRIBUTING.md` : Information pour ceux qui veulent contribuer
|
||||
* `API.md` : Pour les modders Minetest qui veulent modder ce jeu
|
||||
* `API.md` : Pour les modders Luanti qui veulent modder ce jeu
|
||||
* `LEGAL.md` : Information légale
|
||||
* `CREDITS.md` : Liste de toutes les personnes qui ont contribué
|
||||
|
203
README_locale/README.it.md
Normal file
203
README_locale/README.it.md
Normal file
@ -0,0 +1,203 @@
|
||||
# VoxeLibre
|
||||
Un gioco Minecraft-like non ufficiale per Luanti. Derivato da MineClone di davedevilis.
|
||||
Sviluppato da molte persone. Non sviluppato o sponsorizzato da Mojang AB.
|
||||
|
||||
### Gameplay
|
||||
Cominci in un mondo generato casualmente, fatto interamente di cubi. Puoi esplorare
|
||||
il mondo e scavare e costruire quasi ogni blocco nel mondo per creare nuove
|
||||
strutture. Puoi scegliere di giocare in "modalità sopravvivenza" nella quale dovrai
|
||||
combattere i mostri e la fame per sopravvivere e progredire lentamente attraverso
|
||||
vari aspetti del gioco, come le miniere, l'agricoltura, costruire dei meccanismi, e così via
|
||||
O puoi giocare in "modalità creativa" nella quale puoi costruire quasi qualunque cosa istantaneamente.
|
||||
|
||||
#### Sintesi del Gameplay
|
||||
|
||||
* Gameplay sandbox, nessun obiettivo
|
||||
* Sopravvivenza: Combatti contro i mostri ostili e la fame
|
||||
* Scava in cerca di materiali e altri tesori
|
||||
* Magia: Guadagna esperienza e incanta i tuoi attrezzi
|
||||
* Usa i blocchi che hai collezionato per creare grandiose costruzioni, l'unico limite sarà la tua immaginazione
|
||||
* Colleziona fiori (e altre risorse per coloranti) e colora il tuo mondo
|
||||
* Trova dei semi e inizia a coltivare
|
||||
* Trova o costruisci uno di centinaia di oggetti
|
||||
* Costruisci complessi macchinari con i circuiti di redstone
|
||||
* In modalità creativa puoi costruire quasi qualunque cosa gratis e senza limiti
|
||||
|
||||
## Come giocare (quick start)
|
||||
### Per cominciare
|
||||
* **Colpisci il tronco di un albero** affinchè si rompa e raccogli il legno
|
||||
* Piazza il **legno nella griglia 2x2** (la tua "griglia da fabbricazione" nel tuo inventario) e costruisci 4 assi di legno
|
||||
* Piazza le 4 assi di legno in una forma 2x2 nella griglia da fabbricazione per **creare un banco da lavoro**
|
||||
* **Fai click destro sul banco da lavoro** per sfruttare una griglia 3x3 per costruire cose più complesse
|
||||
* Usa la **guida da fabbricazione** (icona del libro) per apprendere tuttle le possibili ricette
|
||||
* **Costruisci una piccozza di legno** per poter scavare la pietra
|
||||
* Diversi strumenti rompono diversi tipi di blocco. Provali tutti!
|
||||
* Continua a giocare come preferisci. Divertiti!
|
||||
|
||||
### Agricoltura
|
||||
* Trova dei semi
|
||||
* Costruisci una zappa
|
||||
* Fai click destro sulla terra o un blocco simile con la zappa per renderla coltivabile
|
||||
* Piazza dei semi sulla terra lavorata e guardali crescere
|
||||
* Raccogli le piante quando maturano completamente
|
||||
* Se vicino all'acqua, la terra lavorata si bagna e accelera la maturazione
|
||||
|
||||
### Fornace
|
||||
* Costruisci una fornace
|
||||
* La fornace ti permette di ottenere più oggetti
|
||||
* Lo slot superiore deve contenere un oggetto fondibile (esempio: minerale di ferro)
|
||||
* Lo slot inferiore deve contenere un carburante (esempio: carbone)
|
||||
* Leggi i consigli nella guida di fabbricazione per saperne di più sui carburanti e gli oggetti fondibili
|
||||
|
||||
### Aiuti aggiuntivi
|
||||
More help about the gameplay, blocks items and much more can be found from inside
|
||||
the game. You can access the help from your inventory menu.
|
||||
Ulteriore aiuto sul gameplay, i blocchi, gli oggetti e molto altro possono essere
|
||||
trovati all'interno del gioco. Puoi accedere alla schermata di aiuti dall'inventario.
|
||||
|
||||
### Oggetti speciali
|
||||
The following items are interesting for Creative Mode and for adventure
|
||||
map builders. They can not be obtained in-game or in the creative inventory.
|
||||
I seguenti oggetti sono interessanti per la Modalità Creativa e per i costruttori
|
||||
di mappe da avventura. Non possono essere ottenuti in gioco o dall'inventario
|
||||
della modalità creativa.
|
||||
|
||||
* Barriera: `mcl_core:barrier`
|
||||
|
||||
Usa il comando `/giveme` nella per ottenerli. Vedi gli aiuti in gioco per ottenere
|
||||
una spiegazione
|
||||
|
||||
## Installazione
|
||||
Per eseguire il gioco con le migliori prestazioni e supporto, consigliamo l'ultima
|
||||
versione stabile di [Luanti](https://www.luanti.org/), ma ci impegniamo sempre a
|
||||
supportare una versione dietro l'ultima versione stabile.
|
||||
Quindi come prima cosa installa Luanti. Solo le versioni stable di Luanti
|
||||
sono ufficialmente supportate.
|
||||
Non è supportato l'avvio di VoxeLibre su versioni da sviluppatore di Luanti.
|
||||
|
||||
Per installare VoxeLibre (se non lo hai già fatto), sposta questa cartella dentro
|
||||
la cartella "games" nella tua cartella dei dati di Luanti. Consulta la wiki di
|
||||
Luanti per saperne di più.
|
||||
|
||||
## Link utili
|
||||
La repo di VoxeLibre è su Mesehub. Per contribuire o comunicare dei problemi, procedi là.
|
||||
|
||||
* Mesehub: <https://git.minetest.land/VoxeLibre/VoxeLibre>
|
||||
* Discord: <https://discord.gg/xE4z8EEpDC>
|
||||
* YouTube: <https://www.youtube.com/channel/UClI_YcsXMF3KNeJtoBfnk9A>
|
||||
* ContentDB: <https://content.luanti.org/packages/wuzzy/mineclone2/>
|
||||
* OpenCollective: <https://opencollective.com/voxelibre>
|
||||
* Mastodon: <https://fosstodon.org/@VoxeLibre>
|
||||
* Lemmy: <https://lemm.ee/c/voxelibre>
|
||||
* Matrix space: <https://app.element.io/#/room/#voxelibre:matrix.org>
|
||||
* Luanti forums: <https://forum.luanti.org/viewtopic.php?f=50&t=16407>
|
||||
* Reddit: <https://www.reddit.com/r/VoxeLibre/>
|
||||
* IRC (barely used): <https://web.libera.chat/#mineclone2>
|
||||
|
||||
## Obiettivi
|
||||
- Creare un gioco basato su Minecraft, sul motore di gioco di Luanti
|
||||
che sia libero, stabile e moddabile, con funzioni perfezionate, usabile sia in
|
||||
giocatore singolo che in multigiocatore. Al momento, molte funzionalità della versione
|
||||
Java di Minecraft sono state implementate e il perfezionamento di quelle già esistenti
|
||||
è prioritario rispetto all'aggiungta di nuove funzionalità.
|
||||
- Implementare funzionalità comprese nella versione corrente di Minecraft + OptiFine
|
||||
(OptiFine solo come supportato dal motore di gioco di Luanti).
|
||||
- Creare un'esperienza performante che giri relativamente su computer poco prestanti.
|
||||
|
||||
## Stato dello sviluppo
|
||||
Questo gioco è in fase di **beta** al momento.
|
||||
È giocabile, ma non ancora completo per quanto riguarda le funzionalità.
|
||||
Compatibilità con versioni precedenti di Luanti non è garantita, aggiornare il tuo mondo
|
||||
potrebbe causare dei piccoli bug.
|
||||
Se desideri usare le versioni da sviluppatore di VoxeLibre in produzione, il branch master è solitamente relativamente stabile.
|
||||
|
||||
Le seguenti funzionalità principali sono disponibili:
|
||||
|
||||
* Strumenti e armi
|
||||
* Armature
|
||||
* Sistema di fabbricazione: griglia 2x2, banco da lavoro (griglia 3x3), fornace e guida di fabbricazione
|
||||
* Bauli, bauli grandi, bauli di ender, scatole di shulker
|
||||
* Fornaci, tramoggie
|
||||
* Fame
|
||||
* La maggior parte dei mostri e degli animali
|
||||
* Tutti i minerali di Minecraft
|
||||
* La maggior parte dei blocchi dell'overworld
|
||||
* Acqua e lava
|
||||
* Meteo
|
||||
* 28 biomi + 5 biomi del Nether
|
||||
* Il Nether, un ardente sotterraneo in un'altra dimensione
|
||||
* Circuiti di Redstone (parziale)
|
||||
* Carrelli da miniera (parziale)
|
||||
* Effetti di stato (parziale)
|
||||
* Esperienza
|
||||
* Incantamento
|
||||
* Alchimia, pozioni, frecce imbevute (parziale)
|
||||
* Barche
|
||||
* Fuoco
|
||||
* Blocchi da costruzione: Scale, lastre, porte, botole, staccionate, cancelli (staccionate), muri
|
||||
* Orologio
|
||||
* Bussola
|
||||
* Spugna
|
||||
* Blocco di slime
|
||||
* Piccole piante e alberelli
|
||||
* Coloranti
|
||||
* Stendardi
|
||||
* Blocchi decorativi: Vetro, vetro colorato, pannelli di vetro, terracotta (e colori), teste e tanto altro
|
||||
* Cornici
|
||||
* Jukeboxes
|
||||
* Letti
|
||||
* Menu dell'inventario
|
||||
* Inventario modalità creativa
|
||||
* Agricoltura
|
||||
* Libri scrivibili
|
||||
* Comandi
|
||||
* Villaggi
|
||||
* The End
|
||||
* E tanto altro!
|
||||
|
||||
Le seguenti funzionalità sono incomplete:
|
||||
|
||||
* Alcuni mostri e animali
|
||||
* Cose relative all redstone
|
||||
* Alcuni carrelli da miniera particolari (i carrelli da miniera con tramoggia e con baule funzionano)
|
||||
* Alcuni blocchi e oggetti non banali
|
||||
|
||||
Funzionalità bonus (non incluse in Minecraft):
|
||||
|
||||
* Guida da fabbricazione inclusa che mostra ricette di fabbricazione e di forgiatura
|
||||
* Sistema di aiuti in gioco contenente informazioni estese su basi del gameplay, blocchi, oggetti e altro
|
||||
* Ricette di fabbricazione temporanee. Esistono solamente per rendere disponibili oggetti altrimenti non ottenibili quando non sei in modalità creativa. Queste ricette verranno rimosse man mano che lo sviluppo avanza e più funzionalità vengono implementate.
|
||||
* Alberelli nei bauli con [mapgen v6](https://wiki.luanti.org/Map_generator#v6)
|
||||
* Completamente moddabile (grazie alla potente API Lua di Luanti)
|
||||
* Nuovi blocchi e oggetti:
|
||||
* Strumento informativo, ti mostra l'aiuto per ciò che colpisci
|
||||
* Più lastre e scale
|
||||
* Cancello di Mattoni del Nether
|
||||
* Staccionata di Mattoni Rossi del Nether
|
||||
* Cancello di Mattoni Rossi del Nether
|
||||
* Strutture di rimpiazzo - queste piccole varianti dell strutture di Minecraft servono come rimpiazzo finchè faremo funzionare strutture più grandi:
|
||||
* Cabina dei boschi (Ville)
|
||||
* Avamposto del Nether (Fortezza)
|
||||
|
||||
Technical differences from Minecraft:
|
||||
Differenze tecniche da Minecraft:
|
||||
* Limite di altezza di circa 31000 blocchi (molto più alto che in Minecraft)
|
||||
* Limite orizzontale del mondo di circa 62000x62000 blocchi (molto più piccolo che in Minecraft, ma comunque molto ampio)
|
||||
* Ancora molto incompleto e buggato
|
||||
* Blocchi, oggett, nemici e altre funzionalità mancano
|
||||
* Alcuni oggetti hanno nomi leggermente diversi per renderli più facili da distinguere
|
||||
* Diverse musiche per il jukebox
|
||||
* Diverse texture (Pixel Perfection)
|
||||
* Diversi suoni (varie fonti)
|
||||
* Diverso motore di gioco (Luanti)
|
||||
* Diversi easter eggs
|
||||
|
||||
… e infine, VoxeLibre è software libero!
|
||||
|
||||
## Altri file readme
|
||||
|
||||
* `LICENSE.txt`: Il testo della licenza GPLv3
|
||||
* `CONTRIBUTING.md`: Informazioni per coloro che vogliono contribuire
|
||||
* `API.md`: Per i modder di Luanti che vogliono moddare questo gioco
|
||||
* `LEGAL.md`: Informazioni legali
|
||||
* `CREDITS.md`: List di tutti coloro che hanno contribuito
|
@ -1,5 +1,5 @@
|
||||
# VoxeLibre
|
||||
Неофициальная игра в стиле Minecraft для Minetest. Форк MineClone от davedevils.
|
||||
Неофициальная игра в стиле Minecraft для Luanti. Форк MineClone от davedevils.
|
||||
Разработана многими людьми. Не разработана и не одобрена Mojang AB.
|
||||
|
||||
### Игровой процесс
|
||||
@ -65,12 +65,12 @@
|
||||
Смотрите справку для дальнейшей информации.
|
||||
|
||||
## Установка
|
||||
Эта игра требует [Minetest](http://minetest.net) для запуска (версия 5.4.1 или
|
||||
выше). Вам нужно сперва установить Minetest. Только стабильные версии поддерживаются
|
||||
официально. Не поддерживается запуск VoxeLibre на разрабатываемых версиях Minetest.
|
||||
Эта игра требует [Luanti](http://www.luanti.org) для запуска (версия 5.4.1 или
|
||||
выше). Вам нужно сперва установить Luanti. Только стабильные версии поддерживаются
|
||||
официально. Не поддерживается запуск VoxeLibre на разрабатываемых версиях Luanti.
|
||||
|
||||
Чтобы установить VoxeLibre (если вы этого еще не сделали), переместите эту папку в
|
||||
“games” в папке данных Minetest. Смотрите справку Minetest, чтобы узнать больше.
|
||||
“games” в папке данных Luanti. Смотрите справку Luanti, чтобы узнать больше.
|
||||
|
||||
## Полезные ссылки
|
||||
Репозиторий VoxeLibre хранится на Mesehub. Зайдите туда, чтобы оставить запрос или
|
||||
@ -79,23 +79,23 @@
|
||||
* Mesehub: <https://git.minetest.land/MineClone2/MineClone2>
|
||||
* Discord: <https://discord.gg/xE4z8EEpDC>
|
||||
* YouTube: <https://www.youtube.com/channel/UClI_YcsXMF3KNeJtoBfnk9A>
|
||||
* ContentDB: <https://content.minetest.net/packages/wuzzy/mineclone2/>
|
||||
* ContentDB: <https://content.luanti.org/packages/wuzzy/mineclone2/>
|
||||
* OpenCollective: <https://opencollective.com/mineclone2>
|
||||
* Mastodon: <https://fosstodon.org/@MineClone2>
|
||||
* Lemmy: <https://lemmy.world/c/mineclone2>
|
||||
* Matrix space: <https://app.element.io/#/room/#mcl2:matrix.org>
|
||||
* Форум Minetest: <https://forum.minetest.net/viewtopic.php?f=50&t=16407>
|
||||
* Форум Luanti: <https://forum.luanti.org/viewtopic.php?f=50&t=16407>
|
||||
* Reddit: <https://www.reddit.com/r/MineClone2/>
|
||||
* IRC (едва используется): <https://web.libera.chat/#mineclone2>
|
||||
|
||||
## Цели
|
||||
- Создать стабильную, модифицируемую, бесплатную и свободную игру основанную на
|
||||
Minecraft на движке Minetest с проработанными возможностями для одиночной игры и
|
||||
Minecraft на движке Luanti с проработанными возможностями для одиночной игры и
|
||||
для мультиплеера. На данный момент множество возможностей **Minecraft Java
|
||||
Edition** уже реализовано и доработка имеющегося контента в приоритете над
|
||||
добавлением нового.
|
||||
- Реализовать возможности на уровне **текущей версии Minecraft + OptiFine** (OptiFine
|
||||
настолько, насколько это поддерживается движком Minetest).
|
||||
настолько, насколько это поддерживается движком Luanti).
|
||||
- Добиться производительности для запуска на действительно слабых компьютерах.
|
||||
|
||||
## Готовность
|
||||
@ -159,8 +159,8 @@ VoxeLibre, то ветка master обычно относительно стаб
|
||||
* Встроенный гайд для крафта покажет вам рецепты крафта и переплавки
|
||||
* Внутриигровая справка содержит всестороннюю информацию об основах игры, блоках, предметах и прочее
|
||||
* Временные рецепты крафта. Они существуют, чтобы получить доступ к ранее недоступным предметам вне творческого режима. Они будут удалены как только разработка позволит им стать доступными
|
||||
* Саженцы в сундуках в [mapgen v6](https://wiki.minetest.net/Map_generator#v6)
|
||||
* Полностью модифицируема (благодаря мощному Lua API в Minetest)
|
||||
* Саженцы в сундуках в [mapgen v6](https://wiki.luanti.org/Map_generator#v6)
|
||||
* Полностью модифицируема (благодаря мощному Lua API в Luanti)
|
||||
* Новые блоки и предметы:
|
||||
* Инструмент просмотра покажет справку о том чего коснется
|
||||
* Больше ступеней и плит
|
||||
@ -179,7 +179,7 @@ VoxeLibre, то ветка master обычно относительно стаб
|
||||
* Другая музыка для проигрывателей
|
||||
* Другие текстуры (Pixel Perfection)
|
||||
* Другие звуки (разные источники)
|
||||
* Другой движок (Minetest)
|
||||
* Другой движок (Luanti)
|
||||
* Другие пасхалки
|
||||
|
||||
… и наконец, VoxeLibre это свободное программное обеспечение!
|
||||
@ -188,6 +188,6 @@ VoxeLibre, то ветка master обычно относительно стаб
|
||||
|
||||
* `LICENSE.txt`: текст лицензии GPLv3
|
||||
* `CONTRIBUTING.md`: информация для тех кто хочет поучаствовать в разработке
|
||||
* `API.md`: для моддеров Minetest кто хочет изменить эту игру
|
||||
* `API.md`: для моддеров Luanti кто хочет изменить эту игру
|
||||
* `LEGAL.md`: юридическая информация
|
||||
* `CREDITS.md`: список участников проекта
|
||||
|
168
README_locale/README.zh_CN.md
Normal file
168
README_locale/README.zh_CN.md
Normal file
@ -0,0 +1,168 @@
|
||||
# VoxeLibre
|
||||
一款受 Minecraft 启发的 Luanti 游戏。由 davedevils 从 MineClone 分叉。由许多人开发,请参阅 CREDITS.md 以获取完整列表。
|
||||
|
||||
### 游戏玩法
|
||||
你从一个完全由方块组成的随机生成的世界开始。您可以探索世界,挖掘和建造世界上几乎所有的方块,以创建新的结构。您可以选择 “生存模式”,在这种模式下,您必须与怪物搏斗,为生存而忍饥挨饿,并在游戏的其他各方面慢慢取得进展。如采矿、耕作、建造机器等。或者你也可以选择 “创意模式”,在这种模式下,你几乎可以立即建造任何东西。
|
||||
|
||||
#### 游戏概述
|
||||
|
||||
* 沙盒式游戏,无目标
|
||||
* 生存:与敌对怪物和饥饿作斗争
|
||||
* 开采矿石和其他宝藏
|
||||
* 魔法:获得经验并对工具施魔法
|
||||
* 用收集到的方块来建造伟大的建筑,你的想象力是有限的
|
||||
* 收集鲜花(和其他染料来源),为你的世界着色
|
||||
* 找到一些种子,开始耕种
|
||||
* 找到或制作数百件物品中的一件
|
||||
* 建设铁路系统,享受矿车的乐趣
|
||||
* 用红石电路建造复杂的机器
|
||||
* 在创意模式下,你几乎可以自由、无限制地构建任何东西
|
||||
|
||||
## 如何游玩(快速入门)
|
||||
### 开始
|
||||
* **砍树** 直到它折断,然后收集木头
|
||||
* 将 **木材放入2×2网格** (库存菜单中的“制作网格”)中,制作4块木板
|
||||
* 将4块木板以2×2的形状放置在制作网格中,以 **制作一个工作台**
|
||||
* **右键单击工作台** 获得3×3的制作网格,以制作更复杂的东西
|
||||
* 使用 **制作指南** (书籍图标)学习所有可能的制作方法
|
||||
* **制作一把木镐** 这样你就可以挖石头了
|
||||
* 不同的工具会打破不同种类的方块。试试看!
|
||||
* 按照你的意愿继续玩。玩得高兴!
|
||||
|
||||
### 耕种
|
||||
* 寻找种子
|
||||
* 制作一把锄头
|
||||
* 用锄头右键点击泥土或类似的块,创建农田
|
||||
* 把种子放在农田里,观察它们生长
|
||||
* 植物长成后收集起来
|
||||
* 如果靠近水源,农田会变得潮湿并加速生长
|
||||
|
||||
### 熔炉
|
||||
* 制作一个熔炉
|
||||
* 熔炉可让你获取更多物品
|
||||
* 上方的格子必须放置可熔炼的物品(例如:铁矿石)
|
||||
* 下方的格子必须放置燃料物品(例如:煤炭)
|
||||
* 查看制作指南中的提示信息以了解燃料及可熔炼物品的相关情况。
|
||||
|
||||
### 额外帮助
|
||||
有关游戏玩法、方块、物品等更多帮助内容可在游戏内查看。你可以从你的物品栏菜单中进入帮助界面。
|
||||
|
||||
### 特殊物品
|
||||
以下物品对于创造模式以及冒险地图制作者来说很有意思。它们无法在游戏内或创造模式物品栏中获取。
|
||||
* 屏障:`mcl_core:barrier`
|
||||
使用`/giveme`聊天命令来获取它们。查看游戏内的帮助以获取相关说明。
|
||||
|
||||
## 安装
|
||||
为了能以最佳性能运行游戏并获得支持,我们推荐使用[Luanti](https://www.luanti.org/)的最新稳定版本,不过我们也一直尽力对次新版本提供支持。在某些情况下,旧版本或许也够用,但你会错过Luanti的一些重要功能,而这些功能对我们这款游戏的重要特性起着关键作用。
|
||||
VoxeLibre不支持在Luanti的开发版本中运行。
|
||||
要安装VoxeLibre(如果你还未安装的话),将此目录移至你的Luanti数据目录下的“games”目录中。查阅Luanti的帮助文档以了解更多信息。
|
||||
|
||||
## 有用链接
|
||||
VoxeLibre的代码仓库托管在Mesehub上。如需贡献代码或报告问题,请前往此处。
|
||||
* Mesehub:<https://git.minetest.land/VoxeLibre/VoxeLibre>
|
||||
* Discord:<https://discord.gg/xE4z8EEpDC>
|
||||
* YouTube:<https://www.youtube.com/channel/UClI_YcsXMF3KNeJtoBfnk9A>
|
||||
* ContentDB:<https://content.minetest.net/packages/wuzzy/mineclone2/>
|
||||
* OpenCollective:<https://opencollective.com/mineclone2>
|
||||
* Mastodon:<https://fosstodon.org/@VoxeLibre>
|
||||
* Lemmy:<https://lemm.ee/c/voxelibre>
|
||||
* Matrix空间:<https://app.element.io/#/room/#voxelibre:matrix.org>
|
||||
* Minetest论坛:<https://forum.minetest.net/viewtopic.php?f=50&t=16407>
|
||||
* Reddit:<https://www.reddit.com/r/VoxeLibre/>
|
||||
* IRC(很少使用):<https://web.libera.chat/#mineclone2>
|
||||
|
||||
## 目标
|
||||
- 利用Luanti引擎打造一款稳定、性能良好、可模组化、自由开源且受《我的世界》启发的游戏,该游戏可用于单人及多人模式。
|
||||
- 目前,很多功能已经实现。对现有功能进行完善总是受欢迎的。
|
||||
|
||||
## 完成状态
|
||||
这款游戏目前处于**测试版**阶段。
|
||||
它可以玩,但功能尚未完备。
|
||||
并不完全保证向后兼容性,更新你的世界可能会导致一些小的漏洞出现。
|
||||
如果你想在正式环境中使用VoxeLibre的开发版本,主分支通常相对稳定。
|
||||
|
||||
以下是已有的主要功能:
|
||||
* 工具、武器
|
||||
* 盔甲
|
||||
* 制作系统:2×2制作格、工作台(3×3制作格)、熔炉,包括制作指南
|
||||
* 箱子、大箱子、末影箱、潜影盒
|
||||
* 熔炉、漏斗
|
||||
* 饥饿值系统
|
||||
* 大多数怪物和动物
|
||||
* 《我的世界》中的所有矿石
|
||||
* 主世界中的大多数方块
|
||||
* 水和岩浆
|
||||
* 天气系统
|
||||
* 28种生物群系 + 5种下界生物群系
|
||||
* 下界,另一个维度中的炽热地下世界
|
||||
* 红石电路(部分功能)
|
||||
* 矿车(部分功能)
|
||||
* 状态效果(部分功能)
|
||||
* 经验系统
|
||||
* 附魔系统
|
||||
* 酿造、药水、药箭(部分功能)
|
||||
* 船
|
||||
* 火
|
||||
* 建筑方块:楼梯、台阶、门、活板门、栅栏、栅栏门、围墙
|
||||
* 时钟
|
||||
* 指南针
|
||||
* 海绵
|
||||
* 黏液块
|
||||
* 小型植物和树苗
|
||||
* 染料
|
||||
* 旗帜
|
||||
* 装饰方块:玻璃、染色玻璃、玻璃板、铁栏杆、硬化黏土(及各种颜色)、头颅等等
|
||||
* 物品展示框
|
||||
* 唱片机
|
||||
* 床
|
||||
* 物品栏菜单
|
||||
* 创造模式物品栏
|
||||
* 农耕系统
|
||||
* 可书写的书籍
|
||||
* 指令系统
|
||||
* 村庄
|
||||
* 末地
|
||||
* 以及更多功能!
|
||||
|
||||
以下是尚未完成的功能:
|
||||
* 部分怪物和动物
|
||||
* 与红石相关的内容
|
||||
* 部分特殊矿车(漏斗矿车和箱子矿车可用)
|
||||
* 一些较复杂的方块和物品
|
||||
|
||||
额外特色功能(《我的世界》中没有的):
|
||||
* 内置制作指南,可向你展示制作和熔炼配方
|
||||
* 游戏内帮助系统,包含有关游戏玩法基础、方块、物品等的详尽帮助内容
|
||||
* 临时制作配方。它们的存在只是为了让你在非创造模式下能获取一些原本无法获取的物品。随着开发推进以及更多功能上线,这些配方将会被移除。
|
||||
* 在[地图生成器v6](https://wiki.minetest.net/Map_generator#v6)中箱子里的树苗
|
||||
* 完全可模组化(得益于Minetest强大的Lua应用程序编程接口)
|
||||
* 新的方块和物品:
|
||||
* 查找工具,触碰任何东西都会显示其相关帮助信息
|
||||
* 更多的台阶和楼梯
|
||||
* 下界砖栅栏门
|
||||
* 红色下界砖栅栏
|
||||
* 红色下界砖栅栏门
|
||||
* 结构替换——这些《我的世界》结构的小型变体可作为替代品,直至我们能让大型结构正常运作:
|
||||
* 林地小屋(代替府邸)
|
||||
* 下界前哨站(代替要塞)
|
||||
|
||||
与《我的世界》的技术差异:
|
||||
* 高度限制约为31000格(比《我的世界》中的高很多)
|
||||
* 水平世界大小约为62000×62000格(比《我的世界》中的小很多,但仍然非常大)
|
||||
* 仍然很不完善且存在漏洞
|
||||
* 方块、物品、敌人及其他功能有所缺失
|
||||
* 一些物品的名称稍有不同,以便于区分
|
||||
* 唱片机的音乐不同
|
||||
* 纹理不同(像素完美风格)
|
||||
* 声音不同(来源多样)
|
||||
* 引擎不同(Luanti)
|
||||
* 彩蛋不同
|
||||
|
||||
……最后,VoxeLibre是自由软件(“自由”意为“自由权”)!
|
||||
|
||||
## 其他自述文件
|
||||
* `LICENSE.txt`:GPLv3许可协议文本
|
||||
* `CONTRIBUTING.md`:面向想要做出贡献的人员的相关信息
|
||||
* `API.md`:供想要为此游戏制作模组的Minetest模组制作者使用的文档
|
||||
* `LEGAL.md`:法律相关信息
|
||||
* `CREDITS.md`:所有贡献者名单
|
@ -1,11 +1,9 @@
|
||||
This file is severely out of date. If you can help updating this translation, please reach out to us (contact in README.md - the English version).
|
||||
|
||||
# VoxeLibre
|
||||
一個非官方的Minetest遊戲,遊玩方式和Minecraft類似。由davedevils從MineClone分拆。
|
||||
一個非官方的Luanti遊戲,遊玩方式和Minecraft類似。由davedevils從MineClone分拆。
|
||||
由許多人開發。並非由Mojang Studios開發。<!-- "Mojang AB"'s Name changed at 2020/05, main README should change too -->
|
||||
|
||||
版本:0.71.0
|
||||
|
||||
### 遊玩
|
||||
你開始在一個完全由方塊隨機生成的世界裡。你可以探索這個世界,挖掘和建造世界上幾乎所有的方塊,以創造新的結構。你可以選擇在「生存模式」中進行遊戲,在這個模式中,你必須與怪物戰鬥,飢餓求生,並在遊戲的其他各個環節中慢慢進步,如採礦、養殖、建造機器等等。
|
||||
|
||||
@ -72,26 +70,24 @@ These items do not work yet, but you can get them with `/giveme` for testing:
|
||||
* Minecart with Command Block: `mcl_minecarts:command_block_minecart`
|
||||
|
||||
## Installation
|
||||
This game requires [Minetest](http://minetest.net) to run (version 5.0.0 or
|
||||
later). So you need to install Minetest first. Only stable versions of Minetest
|
||||
This game requires [Luanti](https://www.luanti.org) to run (version 5.0.0 or
|
||||
later). So you need to install Luanti first. Only stable versions of Luanti
|
||||
are officially supported.
|
||||
There is no support for running MineClone 2 in development versions of Minetest.
|
||||
There is no support for running VoxeLibre in development versions of Luanti.
|
||||
|
||||
To install MineClone 2 (if you haven't already), move this directory into the
|
||||
“games” directory of your Minetest data directory. Consult the help of
|
||||
Minetest to learn more.
|
||||
To install VoxeLibre (if you haven't already), move this directory into the
|
||||
“games” directory of your Luanti data directory. Consult the help of
|
||||
Luanti to learn more.
|
||||
|
||||
## Project description
|
||||
The main goal of **MineClone 2** is to be a clone of Minecraft and to be released as free software.
|
||||
|
||||
* **開發目標:我的世界, Java版, 版本 1.12**
|
||||
* VoxeLibre還包括Minetest支持的Optifine功能。
|
||||
* VoxeLibre還包括Luanti支持的Optifine功能。
|
||||
* 後期Minecraft版本的功能可能會偷偷加入,但它們的優先級較低。
|
||||
* 總的來說,Minecraft的目標是在Minetest目前允許的情況下進行克隆。
|
||||
* 總的來說,Minecraft的目標是在Luanti目前允許的情況下進行克隆。
|
||||
* 克隆Minecraft是最優先的。
|
||||
* VoxeLibre將使用不同的圖形和聲音,但風格相似。
|
||||
* 克隆界面沒有優先權。只會被粗略地模仿。
|
||||
* 在Minetest中發現的局限性將在開發過程中被記錄和報告。
|
||||
* 在Luanti中發現的局限性將在開發過程中被記錄和報告。
|
||||
|
||||
## 完成程度
|
||||
該遊戲目前處於**alpha**階段。
|
||||
@ -155,7 +151,7 @@ The main goal of **MineClone 2** is to be a clone of Minecraft and to be release
|
||||
* 遊戲中的幫助系統包含了大量關於遊戲基礎知識、方塊、物品等方面的幫助。
|
||||
* 臨時製作配方。它們的存在只是為了在你不在創造模式下時,提供一些其他無法獲得的物品。這些配方將隨著開發的進行和更多功能的出現而被移除。
|
||||
* v6地圖生成器中箱子裡的樹苗。
|
||||
* 完全可修改(得益於Minetest強大的Lua API)。
|
||||
* 完全可修改(得益於Luanti強大的Lua API)。
|
||||
* 新的方塊和物品:
|
||||
* 查找工具,顯示觸及事物的幫助
|
||||
* 更多的半磚和樓梯
|
||||
@ -173,14 +169,14 @@ The main goal of **MineClone 2** is to be a clone of Minecraft and to be release
|
||||
* 唱片機的音樂不同
|
||||
* 不同的材質(像素完美)
|
||||
* 不同的聲音(各種來源)
|
||||
* 不同的引擎(Minetest)
|
||||
* 不同的引擎(Luanti)
|
||||
|
||||
...最後,VoxeLibre是自由軟件!
|
||||
|
||||
## 錯誤報告
|
||||
請在此處報告所有錯誤和缺少的功能:
|
||||
|
||||
<https://git.minetest.land/MineClone2/MineClone2/issues>
|
||||
<https://git.minetest.land/VoxeLibre/VoxeLibre/issues>
|
||||
|
||||
## Chating with the community
|
||||
我們有Discord交流羣:
|
||||
@ -192,15 +188,15 @@ The main goal of **MineClone 2** is to be a clone of Minecraft and to be release
|
||||
|
||||
* `LICENSE.txt`:GPLv3許可文本
|
||||
* `CONTRIBUTING.md`: 為那些想參與貢獻的人提供資訊
|
||||
* `MISSING_ENGINE_FEATURES.md`: VoxeLibre需要改进,Minetest中缺失的功能列表。
|
||||
* `MISSING_ENGINE_FEATURES.md`: VoxeLibre需要改进,Luanti中缺失的功能列表。
|
||||
* `API.md`: 關於MineClone2的API
|
||||
|
||||
## 參與者
|
||||
有這麼多人要列出(抱歉)。詳情請查看各mod目錄。本節只是粗略地介紹了本遊戲的核心作者。
|
||||
|
||||
### 程式碼
|
||||
* [Wuzzy](https://forum.minetest.net/memberlist.php?mode=viewprofile&u=3082):大多數mod的主要程序員(已退休)
|
||||
* davedevils:MineClone 2的原型——「MineClone」的創造者
|
||||
* [Wuzzy](https://forum.luanti.org/memberlist.php?mode=viewprofile&u=3082):大多數mod的主要程序員(已退休)
|
||||
* davedevils:VoxeLibre的原型——「MineClone」的創造者
|
||||
* [ex-bart](https://github.com/ex-bart):紅石比較器
|
||||
* [Rootyjr](https://github.com/Rootyjr):釣竿和錯誤修復
|
||||
* [aligator](https://github.com/aligator):改進門
|
||||
@ -221,8 +217,8 @@ The main goal of **MineClone 2** is to be a clone of Minecraft and to be release
|
||||
* `drippingwater`: kddekadenz
|
||||
* `mobs_mc`: maikerumine, 22i and others
|
||||
* `awards`: rubenwardy
|
||||
* `screwdriver`: RealBadAngel, Maciej Kastakin, Minetest contributors
|
||||
* `xpanes`: Minetest contributors
|
||||
* `screwdriver`: RealBadAngel, Maciej Kastakin, Luanti contributors
|
||||
* `xpanes`: Luanti contributors
|
||||
* `mesecons` mods: Jeija and contributors
|
||||
* `wieldview`: Stuart Jones
|
||||
* `mcl_meshhand`: Based on `newhand` by jordan4ibanez
|
||||
@ -233,7 +229,7 @@ The main goal of **MineClone 2** is to be a clone of Minecraft and to be release
|
||||
|
||||
### 圖形
|
||||
* [XSSheep](http://www.minecraftforum.net/members/XSSheep):主要作者;Minecraft 1.11的Pixel Perfection资源包的制作者
|
||||
* [Wuzzy](https://forum.minetest.net/memberlist.php?mode=viewprofile&u=3082):主菜單圖像和各種編輯和添加的材質包
|
||||
* [Wuzzy](https://forum.luanti.org/memberlist.php?mode=viewprofile&u=3082):主菜單圖像和各種編輯和添加的材質包
|
||||
* [kingoscargames](https://github.com/kingoscargames):現有材質的各種編輯和添加
|
||||
* [leorockway](https://github.com/leorockway):怪物紋理的一些編輯
|
||||
* [xMrVizzy](https://minecraft.curseforge.com/members/xMrVizzy):釉陶(材質以後會被替換)
|
||||
@ -257,8 +253,8 @@ The main goal of **MineClone 2** is to be a clone of Minecraft and to be release
|
||||
### 特殊感謝
|
||||
|
||||
* Wuzzy,感謝他啟動和維護VoxeLibre多年。
|
||||
* celeron55,創建Minetest。
|
||||
* Minetest的社區提供了大量的mods選擇,其中一些最終被納入MineClone 2。
|
||||
* celeron55,創建Luanti。
|
||||
* Luanti的社區提供了大量的mods選擇,其中一些最終被納入VoxeLibre。
|
||||
* Jordach,為《Big Freaking Dig》的唱片機音樂合輯而來
|
||||
* 花了太多時間為Minecraft Wiki寫作的工作狂。它是創建這個遊戲的寶貴資源。
|
||||
* Notch和Jeb是Minecraft背后的主要力量
|
||||
@ -277,10 +273,10 @@ The main goal of **MineClone 2** is to be a clone of Minecraft and to be release
|
||||
|
||||
### License of source code
|
||||
```
|
||||
MineClone 2 (by kay27, EliasFleckenstein, Wuzzy, davedevils and countless others)
|
||||
VoxeLibre (by kay27, EliasFleckenstein, Wuzzy, davedevils and countless others)
|
||||
is an imitation of Minecraft.
|
||||
|
||||
MineClone 2 is free software: you can redistribute it and/or modify
|
||||
VoxeLibre is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
@ -294,15 +290,15 @@ details.
|
||||
In the mods you might find in the read-me or license
|
||||
text files a different license. This counts as dual-licensing.
|
||||
You can choose which license applies to you: Either the
|
||||
license of MineClone 2 (GNU GPLv3) or the mod's license.
|
||||
license of VoxeLibre (GNU GPLv3) or the mod's license.
|
||||
|
||||
MineClone 2 is a direct continuation of the discontinued MineClone
|
||||
VoxeLibre is a direct continuation of the discontinued MineClone
|
||||
project by davedevils.
|
||||
|
||||
Mod credits:
|
||||
See `README.txt` or `README.md` in each mod directory for information about other authors.
|
||||
For mods that do not have such a file, the license is the source code license
|
||||
of MineClone 2 and the author is Wuzzy.
|
||||
of VoxeLibre and the author is Wuzzy.
|
||||
```
|
||||
|
||||
### License of media (textures and sounds)
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
Textures are a crucial asset for all items, nodes, and models in VoxeLibre. This document is for artist who would like to make and modify textures for VoxeLibre. While no means comprehensive, this document contains the basic important information for beginners to get started with texture curation and optimization.
|
||||
|
||||
## Minetest Wiki
|
||||
For more detailed information on creating and modifing texture packs for Minetest/VoxeLibre, please visit the Minetest wiki's page on creating a texture pack. Click [here](https://wiki.minetest.net/Creating_texture_packs) to view the wiki page on creating texture packs.
|
||||
## Luanti Wiki
|
||||
For more detailed information on creating and modifing texture packs for Luanti/VoxeLibre, please visit the Luanti wiki's page on creating a texture pack. Click [here](https://wiki.luanti.org/Creating_texture_packs) to view the wiki page on creating texture packs.
|
||||
|
||||
## GIMP Tutorials Pixel Art Guide
|
||||
GIMP Tutorials has an excellent guide to making pixel art in GIMP. If you would like further clarification as well as screenshots for what we are about to cover, it is an excellent resource to turn to. Click [here](https://thegimptutorials.com/how-to-make-pixel-art/) to view the guide
|
||||
@ -12,7 +12,7 @@ GIMP Tutorials has an excellent guide to making pixel art in GIMP. If you would
|
||||
|
||||
### GIMP
|
||||
|
||||
GIMP (GNU Image Manipulation Program) is a very popular and free image editing software supported on Windows, MacOS, and most Linux distributions. It is recommended to use GIMP to create and modify textures within the minetest engine.
|
||||
GIMP (GNU Image Manipulation Program) is a very popular and free image editing software supported on Windows, MacOS, and most Linux distributions. It is recommended to use GIMP to create and modify textures within the minetest engine.
|
||||
|
||||
Download GIMP [here](http://gimp.org/)
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
title = VoxeLibre
|
||||
description = A survival sandbox game. Survive, gather, hunt, build, explore, and do much more.
|
||||
disallowed_mapgens = v6
|
||||
version=0.87.2
|
||||
version=0.88.0
|
||||
|
@ -11,5 +11,5 @@ tools.
|
||||
|
||||
See init.lua for more infos.
|
||||
|
||||
The leading underscore in the name “_mcl_autogroup” was added to force Minetest to load this mod as late as possible.
|
||||
As of 0.4.16, Minetest loads mods in reverse alphabetical order.
|
||||
The leading underscore in the name “_mcl_autogroup” was added to force Luanti to load this mod as late as possible.
|
||||
As of 0.4.16, Luanti loads mods in reverse alphabetical order.
|
||||
|
@ -1,6 +1,6 @@
|
||||
--[[
|
||||
This mod implements a HACK to make 100% sure the digging times of all tools
|
||||
match Minecraft's perfectly. The digging times system of Minetest is very
|
||||
match Minecraft's perfectly. The digging times system of Luanti is very
|
||||
different, so this weird group trickery has to be used. In Minecraft, each
|
||||
block has a hardness and the actual Minecraft digging time is determined by
|
||||
this:
|
||||
@ -62,8 +62,8 @@ Information about the mod
|
||||
The mod is split up into two parts, mcl_autogroup and _mcl_autogroup.
|
||||
mcl_autogroup contains the API functions used to register custom digging groups.
|
||||
_mcl_autogroup contains most of the code. The leading underscore in the name
|
||||
"_mcl_autogroup" is used to force Minetest to load that part of the mod as late
|
||||
as possible. Minetest loads mods in reverse alphabetical order.
|
||||
"_mcl_autogroup" is used to force Luanti to load that part of the mod as late
|
||||
as possible. Luanti loads mods in reverse alphabetical order.
|
||||
|
||||
This also means that it is very important that no mod adds _mcl_autogroup as a
|
||||
dependency.
|
||||
@ -117,10 +117,6 @@ end
|
||||
-- Array of unique hardness values for each group which affects dig time.
|
||||
local hardness_values = get_hardness_values_for_groups()
|
||||
|
||||
-- Map indexed by hardness values which return the index of that value in
|
||||
-- hardness_value. Used for quick lookup.
|
||||
local hardness_lookup = get_hardness_lookup_for_groups(hardness_values)
|
||||
|
||||
--[[local function compute_creativetimes(group)
|
||||
local creativetimes = {}
|
||||
|
||||
@ -186,6 +182,7 @@ local function add_groupcaps(toolname, groupcaps, groupcaps_def, efficiency)
|
||||
local mult = capsdef.speed or 1
|
||||
local uses = capsdef.uses
|
||||
local def = mcl_autogroup.registered_diggroups[g]
|
||||
assert(def, toolname .. " has unknown diggroup '" .. dump(g) .. "'")
|
||||
local max_level = def.levels and #def.levels or 1
|
||||
|
||||
assert(capsdef.level, toolname .. ' is missing level for ' .. g)
|
||||
@ -313,6 +310,13 @@ function mcl_autogroup.get_wear(toolname, diggroup)
|
||||
end
|
||||
|
||||
local function overwrite()
|
||||
-- Refresh, now that all groups are known.
|
||||
hardness_values = get_hardness_values_for_groups()
|
||||
|
||||
-- Map indexed by hardness values which return the index of that value in
|
||||
-- hardness_value. Used for quick lookup.
|
||||
local hardness_lookup = get_hardness_lookup_for_groups(hardness_values)
|
||||
|
||||
for nname, ndef in pairs(minetest.registered_nodes) do
|
||||
local newgroups = table.copy(ndef.groups)
|
||||
if (nname ~= "ignore" and ndef.diggable) then
|
||||
@ -374,4 +378,5 @@ local function overwrite()
|
||||
end
|
||||
end
|
||||
|
||||
overwrite()
|
||||
-- Make sure all tools and groups are registered
|
||||
minetest.register_on_mods_loaded(overwrite)
|
||||
|
@ -1,3 +1,4 @@
|
||||
name = _mcl_autogroup
|
||||
depends = mcl_autogroup
|
||||
author = ryvnf
|
||||
description = VoxeLibre core mod which automatically adds groups to all items. Very important for digging times.
|
||||
|
@ -19,7 +19,7 @@ local seed = tonumber(minetest.get_mapgen_setting("seed")) or 0
|
||||
|
||||
local mgv6_perlin_biome, mgv6_perlin_humidity, mgv6_np_biome
|
||||
|
||||
-- v6 default noiseparams are hardcoded here because Minetest doesn't give us those
|
||||
-- v6 default noiseparams are hardcoded here because Luanti doesn't give us those
|
||||
local mgv6_np_biome_default = {
|
||||
offset = 0,
|
||||
scale = 1,
|
||||
|
@ -2,33 +2,33 @@
|
||||
Simple flow functions.
|
||||
|
||||
## flowlib.is_touching(realpos, nodepos, radius)
|
||||
Return true if a sphere of <radius> at <realpos> collide with node at <nodepos>.
|
||||
Return true if a sphere of `radius` at `realpos` collide with node at `nodepos`.
|
||||
* realpos: position
|
||||
* nodepos: position
|
||||
* radius: number
|
||||
|
||||
## flowlib.is_water(pos)
|
||||
Return true if node at <pos> is water, false overwise.
|
||||
Return true if node at `pos` is water, false otherwise.
|
||||
* pos: position
|
||||
|
||||
## flowlib.node_is_water(node)
|
||||
Return true if <node> is water, false overwise.
|
||||
Return true if `node` is water, false otherwise.
|
||||
* node: node
|
||||
|
||||
## flowlib.is_lava(pos)
|
||||
Return true if node at <pos> is lava, false overwise.
|
||||
Return true if node at `pos` is lava, false otherwise.
|
||||
* pos: position
|
||||
|
||||
## flowlib.node_is_lava(node)
|
||||
Return true if <node> is lava, false overwise.
|
||||
Return true if `node` is lava, false otherwise.
|
||||
* node: node
|
||||
|
||||
## flowlib.is_liquid(pos)
|
||||
Return true if node at <pos> is liquid, false overwise.
|
||||
Return true if node at `pos` is liquid, false otherwise.
|
||||
* pos: position
|
||||
|
||||
## flowlib.node_is_liquid(node)
|
||||
Return true if <node> is liquid, false overwise.
|
||||
Return true if `node` is liquid, false otherwise.
|
||||
* node: node
|
||||
|
||||
## flowlib.quick_flow(pos, node)
|
||||
@ -37,9 +37,9 @@ Return direction where the water is flowing (to be use to push mobs, items...).
|
||||
* node: node
|
||||
|
||||
## flowlib.move_centre(pos, realpos, node, radius)
|
||||
Return the pos of the nearest not water block near from <pos> in a sphere of <radius> at <realpos>.
|
||||
WARNING: This function is never used in mcl2, use at your own risk. The informations described here may be wrong.
|
||||
Return the pos of the nearest not water block near from `pos` in a sphere of `radius` at `realpos`.
|
||||
WARNING: This function is never used in VL, use at your own risk. The informations described here may be wrong.
|
||||
* pos: position
|
||||
* realpos: position, position of the entity
|
||||
* node: node
|
||||
* radius: number
|
||||
* radius: number
|
||||
|
@ -1,6 +1,6 @@
|
||||
Flowlib
|
||||
================
|
||||
Simple flow functions for use in Minetest mods by Qwertymine3
|
||||
Simple flow functions for use in Luanti mods by Qwertymine3
|
||||
|
||||
License of source code:
|
||||
-----------------------
|
||||
|
@ -1,4 +1,4 @@
|
||||
name = flowlib
|
||||
author = Qwertymine3
|
||||
description = Simple flow functions for use in Minetest mods by Qwertymine3
|
||||
description = Simple flow functions for use in Luanti mods by Qwertymine3
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
# mcl_autogroup
|
||||
This mod emulate digging times from mc.
|
||||
This mod emulates digging times from MC.
|
||||
|
||||
## mcl_autogroup.can_harvest(nodename, toolname, player)
|
||||
Return true if <nodename> can be dig with <toolname> by <player>.
|
||||
Return true if `nodename` can be dig with `toolname` by <player>.
|
||||
* nodename: string, valid nodename
|
||||
* toolname: (optional) string, valid toolname
|
||||
* player: (optinal) ObjectRef, valid player
|
||||
@ -14,7 +14,7 @@ WARNING: This function can only be called after mod initialization.
|
||||
* efficiency: (optional) integer, the efficiency level the tool is enchanted with (default 0)
|
||||
|
||||
## mcl_autogroup.get_wear(toolname, diggroup)
|
||||
Return the max wear of <toolname> with <diggroup>
|
||||
Return the max wear of `toolname` with `diggroup`
|
||||
WARNING: This function can only be called after mod initialization.
|
||||
* toolname: string, name of the tool used
|
||||
* diggroup: string, the name of the diggroup the tool is used on
|
||||
@ -25,4 +25,4 @@ WARNING: This function can only be called after mod initialization.
|
||||
* level: (optional) string, if specified it is an array containing the names of the different digging levels the digging group supports
|
||||
|
||||
## mcl_autogroup.registered_diggroups
|
||||
List of registered diggroups, indexed by name.
|
||||
List of registered diggroups, indexed by name.
|
||||
|
@ -6,8 +6,8 @@ implemented and documented in the _mcl_autogroup.
|
||||
The mod is split up into two parts, mcl_autogroup and _mcl_autogroup.
|
||||
mcl_autogroup contains the API functions used to register custom digging groups.
|
||||
_mcl_autogroup contains most of the code. The leading underscore in the name
|
||||
"_mcl_autogroup" is used to force Minetest to load that part of the mod as late
|
||||
as possible. Minetest loads mods in reverse alphabetical order.
|
||||
"_mcl_autogroup" is used to force Luanti to load that part of the mod as late
|
||||
as possible. Luanti loads mods in reverse alphabetical order.
|
||||
--]]
|
||||
mcl_autogroup = {}
|
||||
mcl_autogroup.registered_diggroups = {}
|
||||
|
@ -1,5 +1,5 @@
|
||||
# mcl_colors
|
||||
Mod providing global table containing legacity minecraft colors to be used in mods.
|
||||
Mod providing global table containing legacy Minecraft colors to be used in mods.
|
||||
|
||||
## mcl_colors.*
|
||||
Colors by upper name, in hex value.
|
||||
|
@ -6,10 +6,10 @@ WARNING: Not using it inside your mods may cause strange bugs (using the native
|
||||
|
||||
## Callbacks
|
||||
|
||||
To modify the amount of damage made by something:
|
||||
To modify the amount of damage dealt by something:
|
||||
|
||||
```lua
|
||||
--obj: an ObjectRef
|
||||
mcl_damage.register_modifier(function(obj, damage, reason)
|
||||
end, 0)
|
||||
```
|
||||
```
|
||||
|
@ -1,9 +1,13 @@
|
||||
## mcl_events
|
||||
### Registering Events
|
||||
`mlc_events.register_event("name",def)`
|
||||
# mcl_events
|
||||
|
||||
#### Event Definition
|
||||
{
|
||||
## Registering Events
|
||||
|
||||
`mcl_events.register_event("name", def)`
|
||||
|
||||
### Event Definition
|
||||
|
||||
```
|
||||
{
|
||||
stage = 0,
|
||||
max_stage = 1,
|
||||
percent = 100,
|
||||
@ -22,6 +26,8 @@
|
||||
cond_complete = function(event) end,
|
||||
--return true if event finished successfully
|
||||
}
|
||||
```
|
||||
|
||||
### Debugging
|
||||
* /event_start <event> -- starts the given event at the current player coordinates
|
||||
## Debugging
|
||||
|
||||
* /event_start `event` -- starts the given event at the current player coordinates
|
||||
|
@ -3,13 +3,13 @@ This mod provide helper functions to create explosions.
|
||||
|
||||
## mcl_explosions.explode(pos, strength, info, puncher)
|
||||
* pos: position, initial position of the explosion
|
||||
* strenght: number, radius of the explosion
|
||||
* strength: number, radius of the explosion
|
||||
* info: table, explosion informations:
|
||||
* drop_chance: number, if specified becomes the drop chance of all nodes in the explosion (default: 1.0 / strength)
|
||||
* max_blast_resistance: int, if specified the explosion will treat all non-indestructible nodes as having a blast resistance of no more than this value
|
||||
* sound: bool, if true, the explosion will play a sound (default: true)
|
||||
* particles: bool, if true, the explosion will create particles (default: true)
|
||||
* fire: bool, if true, 1/3 nodes become fire (default: false)
|
||||
* fire: bool, if true, 1/3 of nodes become fire (default: false)
|
||||
* griefing: bool, if true, the explosion will destroy nodes (default: true)
|
||||
* grief_protected: bool, if true, the explosion will also destroy nodes which have been protected (default: false)
|
||||
* puncher: (optional) entity, will be used as source for damage done by the explosion
|
||||
* puncher: (optional) entity, will be used as source for damage done by the explosion
|
||||
|
@ -1,7 +1,7 @@
|
||||
--[[
|
||||
Explosion API mod for Minetest (adapted to VoxeLibre)
|
||||
Explosion API mod for Luanti (adapted to VoxeLibre)
|
||||
|
||||
This mod is based on the Minetest explosion API mod, but has been changed
|
||||
This mod is based on the Luanti explosion API mod, but has been changed
|
||||
to have the same explosion mechanics as Minecraft and work with VoxeLibre
|
||||
The computation-intensive parts of the mod has been optimized to allow for
|
||||
larger explosions and faster world updating.
|
||||
|
2
mods/CORE/mcl_explosions/locale/mcl_explosions.de.tr
Normal file
2
mods/CORE/mcl_explosions/locale/mcl_explosions.de.tr
Normal file
@ -0,0 +1,2 @@
|
||||
# textdomain:mcl_explosions
|
||||
@1 was caught in an explosion.=@1 wurde Opfer einer Explosion.
|
2
mods/CORE/mcl_explosions/locale/mcl_explosions.it.tr
Normal file
2
mods/CORE/mcl_explosions/locale/mcl_explosions.it.tr
Normal file
@ -0,0 +1,2 @@
|
||||
# textdomain:mcl_explosions
|
||||
@1 was caught in an explosion.=@1 è esploso(a)
|
2
mods/CORE/mcl_explosions/locale/mcl_explosions.nb.tr
Normal file
2
mods/CORE/mcl_explosions/locale/mcl_explosions.nb.tr
Normal file
@ -0,0 +1,2 @@
|
||||
# textdomain:mcl_explosions
|
||||
@1 was caught in an explosion.=@1 ble tatt i en eksplosjon.
|
2
mods/CORE/mcl_explosions/locale/mcl_explosions.zh_CN.tr
Normal file
2
mods/CORE/mcl_explosions/locale/mcl_explosions.zh_CN.tr
Normal file
@ -0,0 +1,2 @@
|
||||
# textdomain:mcl_explosions
|
||||
@1 was caught in an explosion.=@1 被卷入爆炸。
|
@ -3,6 +3,27 @@ mcl_vars = {}
|
||||
|
||||
minetest.log("action", "World seed = " .. minetest.get_mapgen_setting("seed"))
|
||||
|
||||
-- Get a version number for map generation.
|
||||
local map_version = tonumber(core.get_mapgen_setting("vl_world_version") or "")
|
||||
if not map_version then
|
||||
-- Try to read gametime *before* initialization
|
||||
-- Primarily to detect when an old world is loaded.
|
||||
local start_time = tonumber(Settings(core.get_worldpath() .. "/env_meta.txt"):get("game_time")) or 0
|
||||
if start_time > 0 then -- old world, assume "0.87 or earlier"
|
||||
map_version = 0.87 -- starting in 0.88, the version should be stored.
|
||||
else
|
||||
local game_version = Settings(core.get_game_info().path .. "/game.conf"):get("version")
|
||||
map_version = game_version and tostring(game_version:match("(%d+%.%d+)"))
|
||||
if not map_version then
|
||||
core.log("warning", "Could not obtain a game version. Fallback to 0.87. "..dump(game_version))
|
||||
map_version = 0.87
|
||||
end
|
||||
end
|
||||
core.set_mapgen_setting("vl_world_version", map_version, true)
|
||||
end
|
||||
mcl_vars.map_version = map_version -- make available
|
||||
core.log("action", "Voxelibre mapgen version = "..map_version)
|
||||
|
||||
mcl_vars.redstone_tick = 0.1
|
||||
|
||||
-- GUI / inventory menu settings
|
||||
|
@ -1,6 +1,9 @@
|
||||
mcl_util = {}
|
||||
|
||||
dofile(minetest.get_modpath(minetest.get_current_modname()).."/roman_numerals.lua")
|
||||
local modname = core.get_current_modname()
|
||||
local modpath = core.get_modpath(modname)
|
||||
dofile(modpath.."/roman_numerals.lua")
|
||||
dofile(modpath.."/nodes.lua")
|
||||
|
||||
-- Updates all values in t using values from to*.
|
||||
function table.update(t, ...)
|
||||
@ -48,6 +51,20 @@ function table.pairs_by_keys(t, f)
|
||||
return iter
|
||||
end
|
||||
|
||||
-- Removes one element randomly selected from the array section of the table and
|
||||
-- returns it, or nil if there are no elements in the array section of the table
|
||||
function table.remove_random_element(table)
|
||||
local count = #table
|
||||
if count == 0 then return nil end
|
||||
|
||||
local idx = math.random(count)
|
||||
local res = table[idx]
|
||||
table[idx] = table[count]
|
||||
table[count] = nil
|
||||
count = count - 1
|
||||
return res
|
||||
end
|
||||
|
||||
local LOGGING_ON = minetest.settings:get_bool("mcl_logging_default", false)
|
||||
local LOG_MODULE = "[MCL2]"
|
||||
function mcl_util.mcl_log(message, module, bypass_default_logger)
|
||||
@ -59,6 +76,15 @@ function mcl_util.mcl_log(message, module, bypass_default_logger)
|
||||
minetest.log(selected_module .. " " .. message)
|
||||
end
|
||||
end
|
||||
function mcl_util.make_mcl_logger(label, option)
|
||||
-- Return dummy function if debug option isn't set
|
||||
if not minetest.settings:get_bool(option,false) then return function() end, false end
|
||||
|
||||
local label_text = "["..tostring(label).."]"
|
||||
return function(message)
|
||||
mcl_util.mcl_log(message, label_text, true)
|
||||
end, true
|
||||
end
|
||||
|
||||
local player_timers = {}
|
||||
|
||||
@ -112,24 +138,6 @@ function mcl_util.validate_vector (vect)
|
||||
return false
|
||||
end
|
||||
|
||||
-- Minetest 5.3.0 or less can only measure the light level. This came in at 5.4
|
||||
-- This function has been known to fail in multiple places so the error handling is added increase safety and improve
|
||||
-- debugging. See:
|
||||
-- https://git.minetest.land/VoxeLibre/VoxeLibre/issues/1392
|
||||
function mcl_util.get_natural_light (pos, time)
|
||||
local status, retVal = pcall(minetest.get_natural_light, pos, time)
|
||||
if status then
|
||||
return retVal
|
||||
else
|
||||
minetest.log("warning", "Failed to get natural light at pos: " .. dump(pos) .. ", time: " .. dump(time))
|
||||
if (pos) then
|
||||
local node = minetest.get_node(pos)
|
||||
minetest.log("warning", "Node at pos: " .. dump(node.name))
|
||||
end
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
function mcl_util.file_exists(name)
|
||||
if type(name) ~= "string" then return end
|
||||
local f = io.open(name)
|
||||
@ -140,119 +148,6 @@ function mcl_util.file_exists(name)
|
||||
return true
|
||||
end
|
||||
|
||||
-- Based on minetest.rotate_and_place
|
||||
|
||||
--[[
|
||||
Attempt to predict the desired orientation of the pillar-like node
|
||||
defined by `itemstack`, and place it accordingly in one of 3 possible
|
||||
orientations (X, Y or Z).
|
||||
|
||||
Stacks are handled normally if the `infinitestacks`
|
||||
field is false or omitted (else, the itemstack is not changed).
|
||||
* `invert_wall`: if `true`, place wall-orientation on the ground and ground-
|
||||
orientation on wall
|
||||
|
||||
This function is a simplified version of minetest.rotate_and_place.
|
||||
The Minetest function is seen as inappropriate because this includes mirror
|
||||
images of possible orientations, causing problems with pillar shadings.
|
||||
]]
|
||||
function mcl_util.rotate_axis_and_place(itemstack, placer, pointed_thing, infinitestacks, invert_wall)
|
||||
local unode = minetest.get_node_or_nil(pointed_thing.under)
|
||||
if not unode then
|
||||
return
|
||||
end
|
||||
local undef = minetest.registered_nodes[unode.name]
|
||||
if undef and undef.on_rightclick and not invert_wall then
|
||||
undef.on_rightclick(pointed_thing.under, unode, placer,
|
||||
itemstack, pointed_thing)
|
||||
return
|
||||
end
|
||||
local fdir = minetest.dir_to_facedir(placer:get_look_dir())
|
||||
local wield_name = itemstack:get_name()
|
||||
|
||||
local above = pointed_thing.above
|
||||
local under = pointed_thing.under
|
||||
local is_x = (above.x ~= under.x)
|
||||
local is_y = (above.y ~= under.y)
|
||||
local is_z = (above.z ~= under.z)
|
||||
|
||||
local anode = minetest.get_node_or_nil(above)
|
||||
if not anode then
|
||||
return
|
||||
end
|
||||
local pos = pointed_thing.above
|
||||
local node = anode
|
||||
|
||||
if undef and undef.buildable_to then
|
||||
pos = pointed_thing.under
|
||||
node = unode
|
||||
end
|
||||
|
||||
if minetest.is_protected(pos, placer:get_player_name()) then
|
||||
minetest.record_protection_violation(pos, placer:get_player_name())
|
||||
return
|
||||
end
|
||||
|
||||
local ndef = minetest.registered_nodes[node.name]
|
||||
if not ndef or not ndef.buildable_to then
|
||||
return
|
||||
end
|
||||
|
||||
local p2
|
||||
if is_y then
|
||||
p2 = 0
|
||||
elseif is_x then
|
||||
p2 = 12
|
||||
elseif is_z then
|
||||
p2 = 6
|
||||
end
|
||||
minetest.set_node(pos, {name = wield_name, param2 = p2})
|
||||
|
||||
if not infinitestacks then
|
||||
itemstack:take_item()
|
||||
return itemstack
|
||||
end
|
||||
end
|
||||
|
||||
-- Wrapper of above function for use as `on_place` callback (Recommended).
|
||||
-- Similar to minetest.rotate_node.
|
||||
function mcl_util.rotate_axis(itemstack, placer, pointed_thing)
|
||||
mcl_util.rotate_axis_and_place(itemstack, placer, pointed_thing,
|
||||
minetest.is_creative_enabled(placer:get_player_name()),
|
||||
placer:get_player_control().sneak)
|
||||
return itemstack
|
||||
end
|
||||
|
||||
-- Returns position of the neighbor of a double chest node
|
||||
-- or nil if node is invalid.
|
||||
-- This function assumes that the large chest is actually intact
|
||||
-- * pos: Position of the node to investigate
|
||||
-- * param2: param2 of that node
|
||||
-- * side: Which "half" the investigated node is. "left" or "right"
|
||||
function mcl_util.get_double_container_neighbor_pos(pos, param2, side)
|
||||
if side == "right" then
|
||||
if param2 == 0 then
|
||||
return {x = pos.x - 1, y = pos.y, z = pos.z}
|
||||
elseif param2 == 1 then
|
||||
return {x = pos.x, y = pos.y, z = pos.z + 1}
|
||||
elseif param2 == 2 then
|
||||
return {x = pos.x + 1, y = pos.y, z = pos.z}
|
||||
elseif param2 == 3 then
|
||||
return {x = pos.x, y = pos.y, z = pos.z - 1}
|
||||
end
|
||||
else
|
||||
if param2 == 0 then
|
||||
return {x = pos.x + 1, y = pos.y, z = pos.z}
|
||||
elseif param2 == 1 then
|
||||
return {x = pos.x, y = pos.y, z = pos.z - 1}
|
||||
elseif param2 == 2 then
|
||||
return {x = pos.x - 1, y = pos.y, z = pos.z}
|
||||
elseif param2 == 3 then
|
||||
return {x = pos.x, y = pos.y, z = pos.z + 1}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Selects item stack to transfer from
|
||||
---@param src_inventory InvRef Source innentory to pull from
|
||||
---@param src_list string Name of source inventory list to pull from
|
||||
@ -345,13 +240,7 @@ function mcl_util.hopper_push(pos, dst_pos)
|
||||
return ok
|
||||
end
|
||||
|
||||
-- Try pulling from source inventory to hopper inventory
|
||||
---@param pos Vector
|
||||
---@param src_pos Vector
|
||||
function mcl_util.hopper_pull(pos, src_pos)
|
||||
local hop_inv = minetest.get_meta(pos):get_inventory()
|
||||
local hop_list = 'main'
|
||||
|
||||
function mcl_util.hopper_pull_to_inventory(hop_inv, hop_list, src_pos, pos)
|
||||
-- Get node pos' for item transfer
|
||||
local src = minetest.get_node(src_pos)
|
||||
if not minetest.registered_nodes[src.name] then return end
|
||||
@ -367,7 +256,7 @@ function mcl_util.hopper_pull(pos, src_pos)
|
||||
else
|
||||
local src_meta = minetest.get_meta(src_pos)
|
||||
src_inv = src_meta:get_inventory()
|
||||
stack_id = mcl_util.select_stack(src_inv, src_list, hop_inv, hop_list, nil, 1)
|
||||
stack_id = mcl_util.select_stack(src_inv, src_list, hop_inv, hop_list)
|
||||
end
|
||||
|
||||
if stack_id ~= nil then
|
||||
@ -377,6 +266,12 @@ function mcl_util.hopper_pull(pos, src_pos)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Try pulling from source inventory to hopper inventory
|
||||
---@param pos Vector
|
||||
---@param src_pos Vector
|
||||
function mcl_util.hopper_pull(pos, src_pos)
|
||||
return mcl_util.hopper_pull_to_inventory(minetest.get_meta(pos):get_inventory(), "main", src_pos, pos)
|
||||
end
|
||||
|
||||
local function drop_item_stack(pos, stack)
|
||||
if not stack or stack:is_empty() then return end
|
||||
@ -410,61 +305,6 @@ function mcl_util.is_fuel(item)
|
||||
return minetest.get_craft_result({method = "fuel", width = 1, items = {item}}).time ~= 0
|
||||
end
|
||||
|
||||
-- Returns a on_place function for plants
|
||||
-- * condition: function(pos, node, itemstack)
|
||||
-- * A function which is called by the on_place function to check if the node can be placed
|
||||
-- * Must return true, if placement is allowed, false otherwise.
|
||||
-- * If it returns a string, placement is allowed, but will place this itemstring as a node instead
|
||||
-- * pos, node: Position and node table of plant node
|
||||
-- * itemstack: Itemstack to place
|
||||
function mcl_util.generate_on_place_plant_function(condition)
|
||||
return function(itemstack, placer, pointed_thing)
|
||||
if pointed_thing.type ~= "node" then
|
||||
-- no interaction possible with entities
|
||||
return itemstack
|
||||
end
|
||||
|
||||
-- Call on_rightclick if the pointed node defines it
|
||||
local node = minetest.get_node(pointed_thing.under)
|
||||
if placer and not placer:get_player_control().sneak then
|
||||
if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then
|
||||
return minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, placer, itemstack) or itemstack
|
||||
end
|
||||
end
|
||||
|
||||
local place_pos
|
||||
local def_under = minetest.registered_nodes[minetest.get_node(pointed_thing.under).name]
|
||||
local def_above = minetest.registered_nodes[minetest.get_node(pointed_thing.above).name]
|
||||
if not def_under or not def_above then
|
||||
return itemstack
|
||||
end
|
||||
if def_under.buildable_to and def_under.name ~= itemstack:get_name() then
|
||||
place_pos = pointed_thing.under
|
||||
elseif def_above.buildable_to and def_above.name ~= itemstack:get_name() then
|
||||
place_pos = pointed_thing.above
|
||||
pointed_thing.under = pointed_thing.above
|
||||
else
|
||||
return itemstack
|
||||
end
|
||||
|
||||
-- Check placement rules
|
||||
local result, param2 = condition(place_pos, node, itemstack)
|
||||
if result == true then
|
||||
local idef = itemstack:get_definition()
|
||||
local new_itemstack, success = minetest.item_place_node(itemstack, placer, pointed_thing, param2)
|
||||
|
||||
if success then
|
||||
if idef.sounds and idef.sounds.place then
|
||||
minetest.sound_play(idef.sounds.place, {pos = pointed_thing.above, gain = 1}, true)
|
||||
end
|
||||
end
|
||||
itemstack = new_itemstack
|
||||
end
|
||||
|
||||
return itemstack
|
||||
end
|
||||
end
|
||||
|
||||
-- adjust the y level of an object to the center of its collisionbox
|
||||
-- used to get the origin position of entity explosions
|
||||
function mcl_util.get_object_center(obj)
|
||||
@ -727,249 +567,25 @@ function mcl_util.set_properties(obj, props)
|
||||
end
|
||||
end
|
||||
|
||||
-- Update bones, but only when changed
|
||||
function mcl_util.set_bone_position(obj, bone, pos, rot)
|
||||
local current_pos, current_rot = obj:get_bone_position(bone)
|
||||
local pos_equal = not pos or vector.equals(vector.round(current_pos), vector.round(pos))
|
||||
local rot_equal = not rot or vector.equals(vector.round(current_rot), vector.round(rot))
|
||||
if not pos_equal or not rot_equal then
|
||||
obj:set_bone_position(bone, pos or current_pos, rot or current_rot)
|
||||
end
|
||||
end
|
||||
|
||||
---Return a function to use in `on_place`.
|
||||
---
|
||||
---Allow to bypass the `buildable_to` node field in a `on_place` callback.
|
||||
---
|
||||
---You have to make sure that the nodes you return true for have `buildable_to = true`.
|
||||
---@param func fun(node_name: string): boolean Return `true` if node must not replace the buildable_to node which have `node_name`
|
||||
---@return fun(itemstack: ItemStack, placer: ObjectRef, pointed_thing: pointed_thing, param2: integer): ItemStack?
|
||||
function mcl_util.bypass_buildable_to(func)
|
||||
--------------------------
|
||||
-- MINETEST CODE: UTILS --
|
||||
--------------------------
|
||||
|
||||
local function copy_pointed_thing(pointed_thing)
|
||||
return {
|
||||
type = pointed_thing.type,
|
||||
above = pointed_thing.above and vector.copy(pointed_thing.above),
|
||||
under = pointed_thing.under and vector.copy(pointed_thing.under),
|
||||
ref = pointed_thing.ref,
|
||||
}
|
||||
end
|
||||
|
||||
local function user_name(user)
|
||||
return user and user:get_player_name() or ""
|
||||
end
|
||||
|
||||
-- Returns a logging function. For empty names, does not log.
|
||||
local function make_log(name)
|
||||
return name ~= "" and minetest.log or function() end
|
||||
end
|
||||
|
||||
local function check_attached_node(p, n, group_rating)
|
||||
local def = core.registered_nodes[n.name]
|
||||
local d = vector.zero()
|
||||
if group_rating == 3 then
|
||||
-- always attach to floor
|
||||
d.y = -1
|
||||
elseif group_rating == 4 then
|
||||
-- always attach to ceiling
|
||||
d.y = 1
|
||||
elseif group_rating == 2 then
|
||||
-- attach to facedir or 4dir direction
|
||||
if (def.paramtype2 == "facedir" or
|
||||
def.paramtype2 == "colorfacedir") then
|
||||
-- Attach to whatever facedir is "mounted to".
|
||||
-- For facedir, this is where tile no. 5 point at.
|
||||
|
||||
-- The fallback vector here is in case 'facedir to dir' is nil due
|
||||
-- to voxelmanip placing a wallmounted node without resetting a
|
||||
-- pre-existing param2 value that is out-of-range for facedir.
|
||||
-- The fallback vector corresponds to param2 = 0.
|
||||
d = core.facedir_to_dir(n.param2) or vector.new(0, 0, 1)
|
||||
elseif (def.paramtype2 == "4dir" or
|
||||
def.paramtype2 == "color4dir") then
|
||||
-- Similar to facedir handling
|
||||
d = core.fourdir_to_dir(n.param2) or vector.new(0, 0, 1)
|
||||
end
|
||||
elseif def.paramtype2 == "wallmounted" or
|
||||
def.paramtype2 == "colorwallmounted" then
|
||||
-- Attach to whatever this node is "mounted to".
|
||||
-- This where tile no. 2 points at.
|
||||
|
||||
-- The fallback vector here is used for the same reason as
|
||||
-- for facedir nodes.
|
||||
d = core.wallmounted_to_dir(n.param2) or vector.new(0, 1, 0)
|
||||
else
|
||||
d.y = -1
|
||||
if core.get_bone_override then -- minetest >= 5.9
|
||||
local over = obj:get_bone_override(bone)
|
||||
local pos_equal = not pos or not over.position.absolute or vector.equals(vector.round(over.position.vec), vector.round(pos))
|
||||
local rot_equal = not rot or not over.rotation.absolute or vector.equals(vector.round(over.rotation.vec), vector.round(rot))
|
||||
if not pos_equal or not rot_equal then
|
||||
if pos then over.position = { vec = pos, absolute = true, interpolation = 0.1 } end
|
||||
if rot then over.rotation = { vec = rot, absolute = true, interpolation = 0.1 } end
|
||||
obj:set_bone_override(bone, over)
|
||||
end
|
||||
local p2 = vector.add(p, d)
|
||||
local nn = core.get_node(p2).name
|
||||
local def2 = core.registered_nodes[nn]
|
||||
if def2 and not def2.walkable then
|
||||
return false
|
||||
else -- minetest up to 5.8
|
||||
rot = rot and rot:apply(math.deg)
|
||||
local current_pos, current_rot = obj:get_bone_position(bone)
|
||||
local pos_equal = not pos or vector.equals(vector.round(current_pos), vector.round(pos))
|
||||
local rot_equal = not rot or vector.equals(vector.round(current_rot), vector.round(rot))
|
||||
if not pos_equal or not rot_equal then
|
||||
obj:set_bone_position(bone, pos or current_pos, rot or current_rot)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
return function(itemstack, placer, pointed_thing, param2)
|
||||
-------------------
|
||||
-- MINETEST CODE --
|
||||
-------------------
|
||||
local def = itemstack:get_definition()
|
||||
if def.type ~= "node" or pointed_thing.type ~= "node" then
|
||||
return itemstack
|
||||
end
|
||||
|
||||
local under = pointed_thing.under
|
||||
local oldnode_under = minetest.get_node_or_nil(under)
|
||||
local above = pointed_thing.above
|
||||
local oldnode_above = minetest.get_node_or_nil(above)
|
||||
local playername = user_name(placer)
|
||||
local log = make_log(playername)
|
||||
|
||||
if not oldnode_under or not oldnode_above then
|
||||
log("info", playername .. " tried to place"
|
||||
.. " node in unloaded position " .. minetest.pos_to_string(above))
|
||||
return itemstack
|
||||
end
|
||||
|
||||
local olddef_under = minetest.registered_nodes[oldnode_under.name]
|
||||
olddef_under = olddef_under or minetest.nodedef_default
|
||||
local olddef_above = minetest.registered_nodes[oldnode_above.name]
|
||||
olddef_above = olddef_above or minetest.nodedef_default
|
||||
|
||||
if not olddef_above.buildable_to and not olddef_under.buildable_to then
|
||||
log("info", playername .. " tried to place"
|
||||
.. " node in invalid position " .. minetest.pos_to_string(above)
|
||||
.. ", replacing " .. oldnode_above.name)
|
||||
return itemstack
|
||||
end
|
||||
|
||||
---------------------
|
||||
-- CUSTOMIZED CODE --
|
||||
---------------------
|
||||
|
||||
-- Place above pointed node
|
||||
local place_to = vector.copy(above)
|
||||
|
||||
-- If node under is buildable_to, check for callback result and place into it instead
|
||||
if olddef_under.buildable_to and not func(oldnode_under.name) then
|
||||
log("info", "node under is buildable to")
|
||||
place_to = vector.copy(under)
|
||||
end
|
||||
|
||||
-------------------
|
||||
-- MINETEST CODE --
|
||||
-------------------
|
||||
|
||||
if minetest.is_protected(place_to, playername) then
|
||||
log("action", playername
|
||||
.. " tried to place " .. def.name
|
||||
.. " at protected position "
|
||||
.. minetest.pos_to_string(place_to))
|
||||
minetest.record_protection_violation(place_to, playername)
|
||||
return itemstack
|
||||
end
|
||||
|
||||
local oldnode = minetest.get_node(place_to)
|
||||
local newnode = {name = def.name, param1 = 0, param2 = param2 or 0}
|
||||
|
||||
-- Calculate direction for wall mounted stuff like torches and signs
|
||||
if def.place_param2 ~= nil then
|
||||
newnode.param2 = def.place_param2
|
||||
elseif (def.paramtype2 == "wallmounted" or
|
||||
def.paramtype2 == "colorwallmounted") and not param2 then
|
||||
local dir = vector.subtract(under, above)
|
||||
newnode.param2 = minetest.dir_to_wallmounted(dir)
|
||||
-- Calculate the direction for furnaces and chests and stuff
|
||||
elseif (def.paramtype2 == "facedir" or
|
||||
def.paramtype2 == "colorfacedir" or
|
||||
def.paramtype2 == "4dir" or
|
||||
def.paramtype2 == "color4dir") and not param2 then
|
||||
local placer_pos = placer and placer:get_pos()
|
||||
if placer_pos then
|
||||
local dir = vector.subtract(above, placer_pos)
|
||||
newnode.param2 = minetest.dir_to_facedir(dir)
|
||||
log("info", "facedir: " .. newnode.param2)
|
||||
end
|
||||
end
|
||||
|
||||
local metatable = itemstack:get_meta():to_table().fields
|
||||
|
||||
-- Transfer color information
|
||||
if metatable.palette_index and not def.place_param2 then
|
||||
local color_divisor = nil
|
||||
if def.paramtype2 == "color" then
|
||||
color_divisor = 1
|
||||
elseif def.paramtype2 == "colorwallmounted" then
|
||||
color_divisor = 8
|
||||
elseif def.paramtype2 == "colorfacedir" then
|
||||
color_divisor = 32
|
||||
elseif def.paramtype2 == "color4dir" then
|
||||
color_divisor = 4
|
||||
elseif def.paramtype2 == "colordegrotate" then
|
||||
color_divisor = 32
|
||||
end
|
||||
if color_divisor then
|
||||
local color = math.floor(metatable.palette_index / color_divisor)
|
||||
local other = newnode.param2 % color_divisor
|
||||
newnode.param2 = color * color_divisor + other
|
||||
end
|
||||
end
|
||||
|
||||
-- Check if the node is attached and if it can be placed there
|
||||
local an = minetest.get_item_group(def.name, "attached_node")
|
||||
if an ~= 0 and
|
||||
not check_attached_node(place_to, newnode, an) then
|
||||
log("action", "attached node " .. def.name ..
|
||||
" cannot be placed at " .. minetest.pos_to_string(place_to))
|
||||
return itemstack
|
||||
end
|
||||
|
||||
log("action", playername .. " places node "
|
||||
.. def.name .. " at " .. minetest.pos_to_string(place_to))
|
||||
|
||||
-- Add node and update
|
||||
minetest.add_node(place_to, newnode)
|
||||
|
||||
-- Play sound if it was done by a player
|
||||
if playername ~= "" and def.sounds and def.sounds.place then
|
||||
minetest.sound_play(def.sounds.place, {
|
||||
pos = place_to,
|
||||
exclude_player = playername,
|
||||
}, true)
|
||||
end
|
||||
|
||||
local take_item = true
|
||||
|
||||
-- Run callback
|
||||
if def.after_place_node then
|
||||
-- Deepcopy place_to and pointed_thing because callback can modify it
|
||||
local place_to_copy = vector.copy(place_to)
|
||||
local pointed_thing_copy = copy_pointed_thing(pointed_thing)
|
||||
if def.after_place_node(place_to_copy, placer, itemstack,
|
||||
pointed_thing_copy) then
|
||||
take_item = false
|
||||
end
|
||||
end
|
||||
|
||||
-- Run script hook
|
||||
for _, callback in ipairs(minetest.registered_on_placenodes) do
|
||||
-- Deepcopy pos, node and pointed_thing because callback can modify them
|
||||
local place_to_copy = vector.copy(place_to)
|
||||
local newnode_copy = {name = newnode.name, param1 = newnode.param1, param2 = newnode.param2}
|
||||
local oldnode_copy = {name = oldnode.name, param1 = oldnode.param1, param2 = oldnode.param2}
|
||||
local pointed_thing_copy = copy_pointed_thing(pointed_thing)
|
||||
if callback(place_to_copy, newnode_copy, placer, oldnode_copy, itemstack, pointed_thing_copy) then
|
||||
take_item = false
|
||||
end
|
||||
end
|
||||
|
||||
if take_item then
|
||||
itemstack:take_item()
|
||||
end
|
||||
return itemstack
|
||||
end
|
||||
end
|
||||
|
||||
@ -1018,33 +634,6 @@ function mcl_util.check_position_protection(position, player)
|
||||
return false
|
||||
end
|
||||
|
||||
local palette_indexes = {grass_palette_index = 0, foliage_palette_index = 0, water_palette_index = 0}
|
||||
function mcl_util.get_palette_indexes_from_pos(pos)
|
||||
local biome_data = minetest.get_biome_data(pos)
|
||||
local biome = biome_data.biome
|
||||
local biome_name = minetest.get_biome_name(biome)
|
||||
local reg_biome = minetest.registered_biomes[biome_name]
|
||||
if reg_biome and reg_biome._mcl_grass_palette_index and reg_biome._mcl_foliage_palette_index and reg_biome._mcl_water_palette_index then
|
||||
local gpi = reg_biome._mcl_grass_palette_index
|
||||
local fpi = reg_biome._mcl_foliage_palette_index
|
||||
local wpi = reg_biome._mcl_water_palette_index
|
||||
local palette_indexes = {grass_palette_index = gpi, foliage_palette_index = fpi, water_palette_index = wpi}
|
||||
return palette_indexes
|
||||
else
|
||||
return palette_indexes
|
||||
end
|
||||
end
|
||||
|
||||
function mcl_util.get_colorwallmounted_rotation(pos)
|
||||
local colorwallmounted_node = minetest.get_node(pos)
|
||||
for i = 0, 32, 1 do
|
||||
local colorwallmounted_rotation = colorwallmounted_node.param2 - (i * 8)
|
||||
if colorwallmounted_rotation < 6 then
|
||||
return colorwallmounted_rotation
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---Move items from one inventory list to another, drop items that do not fit in provided pos and direction.
|
||||
---@param src_inv mt.InvRef
|
||||
---@param src_listname string
|
||||
@ -1103,3 +692,148 @@ function mcl_util.is_it_christmas()
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function mcl_util.to_bool(val)
|
||||
if not val then return false end
|
||||
return true
|
||||
end
|
||||
|
||||
if not vector.in_area then
|
||||
-- backport from minetest 5.8, can be removed when the minimum version is 5.8
|
||||
vector.in_area = function(pos, min, max)
|
||||
return (pos.x >= min.x) and (pos.x <= max.x) and
|
||||
(pos.y >= min.y) and (pos.y <= max.y) and
|
||||
(pos.z >= min.z) and (pos.z <= max.z)
|
||||
end
|
||||
end
|
||||
|
||||
-- Traces along a line of nodes vertically to find the next possition that isn't an allowed node
|
||||
---@param pos The position to start tracing from
|
||||
---@param dir The direction to trace in. 1 is up, -1 is down, all other values are not allowed.
|
||||
---@param allowed_nodes A set of node names to trace along.
|
||||
---@param limit The maximum number of steps to make. Defaults to 16 if nil or missing
|
||||
---@return Three return values:
|
||||
--- the position of the next node that isn't allowed or nil if no such node was found,
|
||||
--- the distance from the start where that node was found,
|
||||
--- the node table if a node was found
|
||||
function mcl_util.trace_nodes(pos, dir, allowed_nodes, limit)
|
||||
if (dir ~= -1) and (dir ~= 1) then return nil, 0, nil end
|
||||
limit = limit or 16
|
||||
|
||||
for i = 1,limit do
|
||||
pos = vector.offset(pos, 0, dir, 0)
|
||||
local node = minetest.get_node(pos)
|
||||
if not allowed_nodes[node.name] then return pos, i, node end
|
||||
end
|
||||
|
||||
return nil, limit, nil
|
||||
end
|
||||
function mcl_util.gen_uuid()
|
||||
-- Generate a random 128-bit ID that can be assumed to be unique
|
||||
-- To have a 1% chance of a collision, there would have to be 1.6x10^76 IDs generated
|
||||
-- https://en.wikipedia.org/wiki/Birthday_problem#Probability_table
|
||||
local u = {}
|
||||
for i = 1,16 do
|
||||
u[#u + 1] = string.format("%02X",math.random(1,255))
|
||||
end
|
||||
return table.concat(u)
|
||||
end
|
||||
function mcl_util.get_entity_id(entity)
|
||||
if entity.object then entity = entity.object end
|
||||
|
||||
if entity:is_player() then
|
||||
return entity:get_player_name()
|
||||
else
|
||||
local le = entity:get_luaentity()
|
||||
local id = le._uuid
|
||||
if not id then
|
||||
id = mcl_util.gen_uuid()
|
||||
le._uuid = id
|
||||
end
|
||||
return id
|
||||
end
|
||||
end
|
||||
function mcl_util.remove_entity(luaentity)
|
||||
if luaentity._removed then return end
|
||||
luaentity._removed = true
|
||||
|
||||
local hook = luaentity._on_remove
|
||||
if hook then hook(luaentity) end
|
||||
|
||||
luaentity.object:remove()
|
||||
end
|
||||
local function table_merge(base, overlay)
|
||||
for k,v in pairs(overlay) do
|
||||
if type(base[k]) == "table" and type(v) == "table" then
|
||||
table_merge(base[k], v)
|
||||
else
|
||||
base[k] = v
|
||||
end
|
||||
end
|
||||
return base
|
||||
end
|
||||
mcl_util.table_merge = table_merge
|
||||
|
||||
function mcl_util.table_keys(t)
|
||||
local keys = {}
|
||||
for k,_ in pairs(t) do
|
||||
keys[#keys + 1] = k
|
||||
end
|
||||
return keys
|
||||
end
|
||||
|
||||
local uuid_to_aoid_cache = {}
|
||||
local function scan_active_objects()
|
||||
-- Update active object ids for all active objects
|
||||
for active_object_id,o in pairs(minetest.luaentities) do
|
||||
o._active_object_id = active_object_id
|
||||
if o._uuid then
|
||||
uuid_to_aoid_cache[o._uuid] = active_object_id
|
||||
end
|
||||
end
|
||||
end
|
||||
function mcl_util.get_active_object_id(obj)
|
||||
local le = obj:get_luaentity()
|
||||
|
||||
-- If the active object id in the lua entity is correct, return that
|
||||
if le._active_object_id and minetest.luaentities[le._active_object_id] == le then
|
||||
return le._active_object_id
|
||||
end
|
||||
|
||||
scan_active_objects()
|
||||
|
||||
return le._active_object_id
|
||||
end
|
||||
function mcl_util.get_active_object_id_from_uuid(uuid)
|
||||
return uuid_to_aoid_cache[uuid] or scan_active_objects() or uuid_to_aoid_cache[uuid]
|
||||
end
|
||||
function mcl_util.get_luaentity_from_uuid(uuid)
|
||||
return minetest.luaentities[ mcl_util.get_active_object_id_from_uuid(uuid) ]
|
||||
end
|
||||
function mcl_util.assign_uuid(obj)
|
||||
assert(obj)
|
||||
|
||||
local le = obj:get_luaentity()
|
||||
if not le._uuid then
|
||||
le._uuid = mcl_util.gen_uuid()
|
||||
end
|
||||
|
||||
-- Update the cache with this new id
|
||||
local aoid = mcl_util.get_active_object_id(obj)
|
||||
uuid_to_aoid_cache[le._uuid] = aoid
|
||||
|
||||
return le._uuid
|
||||
end
|
||||
function mcl_util.metadata_last_act(meta, name, delay)
|
||||
local last_act = meta:get_float(name)
|
||||
local now = minetest.get_us_time() * 1e-6
|
||||
if last_act > now + 0.5 then
|
||||
-- Last action was in the future, clock went backwards, so reset
|
||||
elseif last_act >= now - delay then
|
||||
return false
|
||||
end
|
||||
|
||||
meta:set_float(name, now)
|
||||
return true
|
||||
end
|
||||
|
||||
|
444
mods/CORE/mcl_util/nodes.lua
Normal file
444
mods/CORE/mcl_util/nodes.lua
Normal file
@ -0,0 +1,444 @@
|
||||
-- Functions related to nodes and node definitions
|
||||
|
||||
-- Luanti 5.3.0 or less can only measure the light level. This came in at 5.4
|
||||
-- This function has been known to fail in multiple places so the error handling is added increase safety and improve
|
||||
-- debugging. See:
|
||||
-- https://git.minetest.land/VoxeLibre/VoxeLibre/issues/1392
|
||||
function mcl_util.get_natural_light (pos, time)
|
||||
local status, retVal = pcall(core.get_natural_light, pos, time)
|
||||
if status then
|
||||
return retVal
|
||||
else
|
||||
core.log("warning", "Failed to get natural light at pos: " .. dump(pos) .. ", time: " .. dump(time))
|
||||
if (pos) then
|
||||
local node = core.get_node(pos)
|
||||
core.log("warning", "Node at pos: " .. dump(node.name))
|
||||
end
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
-- Based on core.rotate_and_place
|
||||
|
||||
--[[
|
||||
Attempt to predict the desired orientation of the pillar-like node
|
||||
defined by `itemstack`, and place it accordingly in one of 3 possible
|
||||
orientations (X, Y or Z).
|
||||
|
||||
Stacks are handled normally if the `infinitestacks`
|
||||
field is false or omitted (else, the itemstack is not changed).
|
||||
* `invert_wall`: if `true`, place wall-orientation on the ground and ground-
|
||||
orientation on wall
|
||||
|
||||
This function is a simplified version of core.rotate_and_place.
|
||||
The Luanti function is seen as inappropriate because this includes mirror
|
||||
images of possible orientations, causing problems with pillar shadings.
|
||||
]]
|
||||
function mcl_util.rotate_axis_and_place(itemstack, placer, pointed_thing, infinitestacks, invert_wall)
|
||||
local unode = core.get_node_or_nil(pointed_thing.under)
|
||||
if not unode then
|
||||
return
|
||||
end
|
||||
local undef = core.registered_nodes[unode.name]
|
||||
if undef and undef.on_rightclick and not invert_wall then
|
||||
undef.on_rightclick(pointed_thing.under, unode, placer,
|
||||
itemstack, pointed_thing)
|
||||
return
|
||||
end
|
||||
local wield_name = itemstack:get_name()
|
||||
|
||||
local above = pointed_thing.above
|
||||
local under = pointed_thing.under
|
||||
|
||||
local anode = core.get_node_or_nil(above)
|
||||
if not anode then
|
||||
return
|
||||
end
|
||||
local pos = pointed_thing.above
|
||||
local node = anode
|
||||
|
||||
if undef and undef.buildable_to then
|
||||
pos = pointed_thing.under
|
||||
node = unode
|
||||
end
|
||||
|
||||
if core.is_protected(pos, placer:get_player_name()) then
|
||||
core.record_protection_violation(pos, placer:get_player_name())
|
||||
return
|
||||
end
|
||||
|
||||
local ndef = core.registered_nodes[node.name]
|
||||
if not ndef or not ndef.buildable_to then
|
||||
return
|
||||
end
|
||||
|
||||
local p2
|
||||
if above.y ~= under.y then
|
||||
p2 = 0
|
||||
elseif above.x ~= under.x then
|
||||
p2 = 12
|
||||
elseif above.z ~= under.z then
|
||||
p2 = 6
|
||||
end
|
||||
core.set_node(pos, {name = wield_name, param2 = p2})
|
||||
|
||||
if not infinitestacks then
|
||||
itemstack:take_item()
|
||||
return itemstack
|
||||
end
|
||||
end
|
||||
|
||||
-- Wrapper of above function for use as `on_place` callback (Recommended).
|
||||
-- Similar to core.rotate_node.
|
||||
function mcl_util.rotate_axis(itemstack, placer, pointed_thing)
|
||||
mcl_util.rotate_axis_and_place(itemstack, placer, pointed_thing,
|
||||
core.is_creative_enabled(placer:get_player_name()),
|
||||
placer:get_player_control().sneak)
|
||||
return itemstack
|
||||
end
|
||||
|
||||
-- Returns position of the neighbor of a double chest node
|
||||
-- or nil if node is invalid.
|
||||
-- This function assumes that the large chest is actually intact
|
||||
-- * pos: Position of the node to investigate
|
||||
-- * param2: param2 of that node
|
||||
-- * side: Which "half" the investigated node is. "left" or "right"
|
||||
function mcl_util.get_double_container_neighbor_pos(pos, param2, side)
|
||||
local sign = (side == "right" and 1 or -1)
|
||||
|
||||
if param2 == 0 then
|
||||
return vector.offset(pos, -sign, 0, 0)
|
||||
elseif param2 == 1 then
|
||||
return vector.offset(pos, 0, 0, sign)
|
||||
elseif param2 == 2 then
|
||||
return vector.offset(pos, sign, 0, 0)
|
||||
elseif param2 == 3 then
|
||||
return vector.offset(pos, 0, 0, -sign)
|
||||
end
|
||||
end
|
||||
|
||||
-- Returns a on_place function for plants
|
||||
-- * condition: function(pos, node, itemstack)
|
||||
-- * A function which is called by the on_place function to check if the node can be placed
|
||||
-- * Must return true, if placement is allowed, false otherwise.
|
||||
-- * If it returns a string, placement is allowed, but will place this itemstring as a node instead
|
||||
-- * pos, node: Position and node table of plant node
|
||||
-- * itemstack: Itemstack to place
|
||||
function mcl_util.generate_on_place_plant_function(condition)
|
||||
return function(itemstack, placer, pointed_thing)
|
||||
if pointed_thing.type ~= "node" then
|
||||
-- no interaction possible with entities
|
||||
return itemstack
|
||||
end
|
||||
|
||||
-- Call on_rightclick if the pointed node defines it
|
||||
local node = core.get_node(pointed_thing.under)
|
||||
local node_def = core.registered_nodes[node.name]
|
||||
|
||||
if placer and not placer:get_player_control().sneak then
|
||||
if node_def and node_def.on_rightclick then
|
||||
return node_def.on_rightclick(pointed_thing.under, node, placer, itemstack) or itemstack
|
||||
end
|
||||
end
|
||||
|
||||
local place_pos
|
||||
local def_under = core.registered_nodes[core.get_node(pointed_thing.under).name]
|
||||
local def_above = core.registered_nodes[core.get_node(pointed_thing.above).name]
|
||||
if not def_under or not def_above then
|
||||
return itemstack
|
||||
end
|
||||
if def_under.buildable_to and def_under.name ~= itemstack:get_name() then
|
||||
place_pos = pointed_thing.under
|
||||
elseif def_above.buildable_to and def_above.name ~= itemstack:get_name() then
|
||||
place_pos = pointed_thing.above
|
||||
pointed_thing.under = pointed_thing.above
|
||||
else
|
||||
return itemstack
|
||||
end
|
||||
|
||||
-- Check placement rules
|
||||
local result, param2 = condition(place_pos, node, itemstack)
|
||||
if result == true then
|
||||
local idef = itemstack:get_definition()
|
||||
local new_itemstack, success = core.item_place_node(itemstack, placer, pointed_thing, param2)
|
||||
|
||||
if success then
|
||||
if idef.sounds and idef.sounds.place then
|
||||
core.sound_play(idef.sounds.place, {pos = pointed_thing.above, gain = 1}, true)
|
||||
end
|
||||
end
|
||||
itemstack = new_itemstack
|
||||
end
|
||||
|
||||
return itemstack
|
||||
end
|
||||
end
|
||||
|
||||
---Return a function to use in `on_place`.
|
||||
---
|
||||
---Allow to bypass the `buildable_to` node field in a `on_place` callback.
|
||||
---
|
||||
---You have to make sure that the nodes you return true for have `buildable_to = true`.
|
||||
---@param func fun(node_name: string): boolean Return `true` if node must not replace the buildable_to node
|
||||
--- which have `node_name`
|
||||
---@return fun(itemstack: ItemStack, placer: ObjectRef, pointed_thing: pointed_thing, param2: integer): ItemStack?
|
||||
function mcl_util.bypass_buildable_to(func)
|
||||
-- Copied from minetest builtin
|
||||
-- https://github.com/minetest/minetest/blob/526a2f7b8c45504088e194a83d54a19045227bbd/builtin/game/item.lua#L5-L12
|
||||
local function copy_pointed_thing(pointed_thing)
|
||||
return {
|
||||
type = pointed_thing.type,
|
||||
above = pointed_thing.above and vector.copy(pointed_thing.above),
|
||||
under = pointed_thing.under and vector.copy(pointed_thing.under),
|
||||
ref = pointed_thing.ref,
|
||||
}
|
||||
end
|
||||
|
||||
-- Copied from minetest builtin
|
||||
-- https://github.com/minetest/minetest/blob/526a2f7b8c45504088e194a83d54a19045227bbd/builtin/game/item.lua#L137-L139
|
||||
local function user_name(user)
|
||||
return user and user:get_player_name() or ""
|
||||
end
|
||||
|
||||
-- Returns a logging function. For empty names, does not log. Copied from minetest builtin
|
||||
-- https://github.com/minetest/minetest/blob/526a2f7b8c45504088e194a83d54a19045227bbd/builtin/game/item.lua#L142-L144
|
||||
local function make_log(name)
|
||||
return name ~= "" and core.log or function() end
|
||||
end
|
||||
|
||||
-- Copied from minetest builtin
|
||||
-- https://github.com/minetest/minetest/blob/526a2f7b8c45504088e194a83d54a19045227bbd/builtin/game/falling.lua#L503-L547
|
||||
local function check_attached_node(p, n, group_rating)
|
||||
local def = core.registered_nodes[n.name]
|
||||
local d = vector.zero()
|
||||
if group_rating == 3 then
|
||||
-- always attach to floor
|
||||
d.y = -1
|
||||
elseif group_rating == 4 then
|
||||
-- always attach to ceiling
|
||||
d.y = 1
|
||||
elseif group_rating == 2 then
|
||||
-- attach to facedir or 4dir direction
|
||||
if (def.paramtype2 == "facedir" or
|
||||
def.paramtype2 == "colorfacedir") then
|
||||
-- Attach to whatever facedir is "mounted to".
|
||||
-- For facedir, this is where tile no. 5 point at.
|
||||
|
||||
-- The fallback vector here is in case 'facedir to dir' is nil due
|
||||
-- to voxelmanip placing a wallmounted node without resetting a
|
||||
-- pre-existing param2 value that is out-of-range for facedir.
|
||||
-- The fallback vector corresponds to param2 = 0.
|
||||
d = core.facedir_to_dir(n.param2) or vector.new(0, 0, 1)
|
||||
elseif (def.paramtype2 == "4dir" or
|
||||
def.paramtype2 == "color4dir") then
|
||||
-- Similar to facedir handling
|
||||
d = core.fourdir_to_dir(n.param2) or vector.new(0, 0, 1)
|
||||
end
|
||||
elseif def.paramtype2 == "wallmounted" or
|
||||
def.paramtype2 == "colorwallmounted" then
|
||||
-- Attach to whatever this node is "mounted to".
|
||||
-- This where tile no. 2 points at.
|
||||
|
||||
-- The fallback vector here is used for the same reason as
|
||||
-- for facedir nodes.
|
||||
d = core.wallmounted_to_dir(n.param2) or vector.new(0, 1, 0)
|
||||
else
|
||||
d.y = -1
|
||||
end
|
||||
local p2 = vector.add(p, d)
|
||||
local nn = core.get_node(p2).name
|
||||
local def2 = core.registered_nodes[nn]
|
||||
|
||||
return not def2 or def2.walkable
|
||||
end
|
||||
|
||||
-- Copied from minetest builtin
|
||||
-- https://github.com/minetest/minetest/blob/e7dd9737bd5deb573c9fef7b3ff2ead29b2cfe31/builtin/game/item.lua#L146-L294
|
||||
return function(itemstack, placer, pointed_thing, param2)
|
||||
local def = itemstack:get_definition()
|
||||
if def.type ~= "node" or pointed_thing.type ~= "node" then
|
||||
return itemstack
|
||||
end
|
||||
|
||||
local under = pointed_thing.under
|
||||
local oldnode_under = core.get_node_or_nil(under)
|
||||
local above = pointed_thing.above
|
||||
local oldnode_above = core.get_node_or_nil(above)
|
||||
local playername = user_name(placer)
|
||||
local log = make_log(playername)
|
||||
|
||||
if not oldnode_under or not oldnode_above then
|
||||
log("info", playername .. " tried to place"
|
||||
.. " node in unloaded position " .. core.pos_to_string(above))
|
||||
return itemstack
|
||||
end
|
||||
|
||||
local olddef_under = core.registered_nodes[oldnode_under.name] or core.nodedef_default
|
||||
local olddef_above = core.registered_nodes[oldnode_above.name] or core.nodedef_default
|
||||
|
||||
if not olddef_above.buildable_to and not olddef_under.buildable_to then
|
||||
log("info", playername .. " tried to place"
|
||||
.. " node in invalid position " .. core.pos_to_string(above)
|
||||
.. ", replacing " .. oldnode_above.name)
|
||||
return itemstack
|
||||
end
|
||||
|
||||
-- Place above pointed node
|
||||
local place_to = above
|
||||
|
||||
-- If node under is buildable_to, check for callback result and place into it instead
|
||||
-- This line was modified from minetest code to allow overriding builtable_to
|
||||
if olddef_under.buildable_to and not func(oldnode_under.name) then
|
||||
log("info", "node under is buildable to")
|
||||
place_to = under
|
||||
end
|
||||
|
||||
if core.is_protected(place_to, playername) then
|
||||
log("action", playername
|
||||
.. " tried to place " .. def.name
|
||||
.. " at protected position "
|
||||
.. core.pos_to_string(place_to))
|
||||
core.record_protection_violation(place_to, playername)
|
||||
return itemstack
|
||||
end
|
||||
|
||||
local oldnode = core.get_node(place_to)
|
||||
local newnode = {name = def.name, param1 = 0, param2 = param2 or 0}
|
||||
|
||||
-- Calculate direction for wall mounted stuff like torches and signs
|
||||
if def.place_param2 ~= nil then
|
||||
newnode.param2 = def.place_param2
|
||||
elseif (def.paramtype2 == "wallmounted" or
|
||||
def.paramtype2 == "colorwallmounted") and not param2 then
|
||||
newnode.param2 = core.dir_to_wallmounted(vector.subtract(under, above))
|
||||
-- Calculate the direction for furnaces and chests and stuff
|
||||
elseif (def.paramtype2 == "facedir" or
|
||||
def.paramtype2 == "colorfacedir" or
|
||||
def.paramtype2 == "4dir" or
|
||||
def.paramtype2 == "color4dir") and not param2 then
|
||||
local placer_pos = placer and placer:get_pos()
|
||||
if placer_pos then
|
||||
newnode.param2 = core.dir_to_facedir(vector.subtract(above, placer_pos))
|
||||
log("info", "facedir: " .. newnode.param2)
|
||||
end
|
||||
end
|
||||
|
||||
local metatable = itemstack:get_meta():to_table().fields
|
||||
|
||||
-- Transfer color information
|
||||
if metatable.palette_index and not def.place_param2 then
|
||||
local color_divisor = nil
|
||||
if def.paramtype2 == "color" then
|
||||
color_divisor = 1
|
||||
elseif def.paramtype2 == "colorwallmounted" then
|
||||
color_divisor = 8
|
||||
elseif def.paramtype2 == "colorfacedir" then
|
||||
color_divisor = 32
|
||||
elseif def.paramtype2 == "color4dir" then
|
||||
color_divisor = 4
|
||||
elseif def.paramtype2 == "colordegrotate" then
|
||||
color_divisor = 32
|
||||
end
|
||||
if color_divisor then
|
||||
local color = math.floor(metatable.palette_index / color_divisor)
|
||||
local other = newnode.param2 % color_divisor
|
||||
newnode.param2 = color * color_divisor + other
|
||||
end
|
||||
end
|
||||
|
||||
-- Check if the node is attached and if it can be placed there
|
||||
local an = core.get_item_group(def.name, "attached_node")
|
||||
if an ~= 0 and
|
||||
not check_attached_node(place_to, newnode, an) then
|
||||
log("action", "attached node " .. def.name ..
|
||||
" cannot be placed at " .. core.pos_to_string(place_to))
|
||||
return itemstack
|
||||
end
|
||||
|
||||
log("action", playername .. " places node "
|
||||
.. def.name .. " at " .. core.pos_to_string(place_to))
|
||||
|
||||
-- Add node and update
|
||||
core.add_node(place_to, newnode)
|
||||
|
||||
-- Play sound if it was done by a player
|
||||
if playername ~= "" and def.sounds and def.sounds.place then
|
||||
core.sound_play(def.sounds.place, {
|
||||
pos = place_to,
|
||||
exclude_player = playername,
|
||||
}, true)
|
||||
end
|
||||
|
||||
local take_item = true
|
||||
|
||||
-- Run callback
|
||||
if def.after_place_node then
|
||||
-- Deepcopy place_to and pointed_thing because callback can modify it
|
||||
local place_to_copy = vector.copy(place_to)
|
||||
local pointed_thing_copy = copy_pointed_thing(pointed_thing)
|
||||
if def.after_place_node(place_to_copy, placer, itemstack,
|
||||
pointed_thing_copy) then
|
||||
take_item = false
|
||||
end
|
||||
end
|
||||
|
||||
-- Run script hook
|
||||
for _, callback in ipairs(core.registered_on_placenodes) do
|
||||
-- Deepcopy pos, node and pointed_thing because callback can modify them
|
||||
local place_to_copy = vector.copy(place_to)
|
||||
local newnode_copy = {name = newnode.name, param1 = newnode.param1, param2 = newnode.param2}
|
||||
local oldnode_copy = {name = oldnode.name, param1 = oldnode.param1, param2 = oldnode.param2}
|
||||
local pointed_thing_copy = copy_pointed_thing(pointed_thing)
|
||||
if callback(place_to_copy, newnode_copy, placer, oldnode_copy, itemstack, pointed_thing_copy) then
|
||||
take_item = false
|
||||
end
|
||||
end
|
||||
|
||||
if take_item then
|
||||
itemstack:take_item()
|
||||
end
|
||||
return itemstack
|
||||
end
|
||||
end
|
||||
|
||||
local DEFAULT_PALETTE_INDEXES = {grass_palette_index = 0, foliage_palette_index = 0, water_palette_index = 0}
|
||||
function mcl_util.get_palette_indexes_from_pos(pos)
|
||||
local biome_data = core.get_biome_data(pos)
|
||||
local biome = biome_data.biome
|
||||
local biome_name = core.get_biome_name(biome)
|
||||
local reg_biome = core.registered_biomes[biome_name]
|
||||
if reg_biome and reg_biome._mcl_grass_palette_index and reg_biome._mcl_foliage_palette_index
|
||||
and reg_biome._mcl_water_palette_index then
|
||||
return {
|
||||
grass_palette_index = reg_biome._mcl_grass_palette_index,
|
||||
foliage_palette_index = reg_biome._mcl_foliage_palette_index,
|
||||
water_palette_index = reg_biome._mcl_water_palette_index,
|
||||
}
|
||||
else
|
||||
return DEFAULT_PALETTE_INDEXES
|
||||
end
|
||||
end
|
||||
|
||||
function mcl_util.get_colorwallmounted_rotation(pos)
|
||||
local colorwallmounted_node = core.get_node(pos)
|
||||
for i = 0, 32, 1 do
|
||||
local colorwallmounted_rotation = colorwallmounted_node.param2 - (i * 8)
|
||||
if colorwallmounted_rotation < 6 then
|
||||
return colorwallmounted_rotation
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function mcl_util.match_node_to_filter(node_name, filters)
|
||||
for i = 1,#filters do
|
||||
local filter = filters[i]
|
||||
if node_name == filter then return true end
|
||||
|
||||
if string.sub(filter,1,6) == "group:" and core.get_item_group(node_name, string.sub(filter,7)) ~= 0 then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
@ -5,20 +5,21 @@ This mod provides utility functions about positions and dimensions.
|
||||
This function returns:
|
||||
|
||||
* true, true: if pos is in deep void (deadly)
|
||||
* true, false: if the pos is in void (non deadly)
|
||||
* false, false: owerwise
|
||||
* true, false: if the pos is in void (non-deadly)
|
||||
* false, false: otherwise
|
||||
|
||||
Params:
|
||||
|
||||
* pos: position
|
||||
|
||||
## mcl_worlds.y_to_layer(y)
|
||||
This function is used to calculate the minetest y layer and dimension of the given <y> minecraft layer.
|
||||
This function is used to calculate the Luanti y layer and dimension of the given y Minecraft layer.
|
||||
Mainly used for ore generation.
|
||||
Takes an Y coordinate as input and returns:
|
||||
Takes a Y coordinate as input and returns:
|
||||
|
||||
* The corresponding Minecraft layer (can be `nil` if void)
|
||||
* The corresponding Minecraft dimension ("overworld", "nether" or "end") or "void" if y is in the void
|
||||
|
||||
* The corresponding Minecraft layer (can be nil if void)
|
||||
* The corresponding Minecraft dimension ("overworld", "nether" or "end") or "void" if <y> is in the void
|
||||
If the Y coordinate is not located in any dimension, it will return: nil, "void"
|
||||
|
||||
Params:
|
||||
@ -26,7 +27,7 @@ Params:
|
||||
* y: int
|
||||
|
||||
## mcl_worlds.pos_to_dimension(pos)
|
||||
This function return the Minecraft dimension of <pos> ("overworld", "nether" or "end") or "void" if <y> is in the void.
|
||||
This function return the Minecraft dimension of pos ("overworld", "nether" or "end") or "void" if y is in the void.
|
||||
|
||||
* pos: position
|
||||
|
||||
@ -38,31 +39,32 @@ mc_dimension can be "overworld", "nether", "end" (default: "overworld").
|
||||
* mc_dimension: string
|
||||
|
||||
## mcl_worlds.has_weather(pos)
|
||||
Returns true if <pos> can have weather, false owerwise.
|
||||
Returns true if pos can have weather, false otherwise.
|
||||
Weather can be only in the overworld.
|
||||
|
||||
* pos: position
|
||||
|
||||
## mcl_worlds.has_dust(pos)
|
||||
Returns true if <pos> can have nether dust, false owerwise.
|
||||
Returns true if pos can have nether dust, false otherwise.
|
||||
Nether dust can be only in the nether.
|
||||
|
||||
* pos: position
|
||||
|
||||
## mcl_worlds.compass_works(pos)
|
||||
Returns true if compasses are working at <pos>, false owerwise.
|
||||
In mc, you cant use compass in the nether and the end.
|
||||
Returns true if compasses are working at pos, false otherwise.
|
||||
In MC, you cant use compass in the nether and the end.
|
||||
|
||||
* pos: position
|
||||
|
||||
## mcl_worlds.compass_works(pos)
|
||||
Returns true if clock are working at <pos>, false owerwise.
|
||||
In mc, you cant use clock in the nether and the end.
|
||||
Returns true if clock are working at pos, false otherwise.
|
||||
In MC, you cant use clock in the nether and the end.
|
||||
|
||||
* pos: position
|
||||
|
||||
## mcl_worlds.register_on_dimension_change(function(player, dimension, last_dimension))
|
||||
Register a callback function func(player, dimension).
|
||||
|
||||
It will be called whenever a player changes between dimensions.
|
||||
The void counts as dimension.
|
||||
|
||||
@ -75,7 +77,7 @@ The void counts as dimension.
|
||||
Table containing all function registered with mcl_worlds.register_on_dimension_change()
|
||||
|
||||
## mcl_worlds.dimension_change(player, dimension)
|
||||
Notify this mod of a dimension change of <player> to <dimension>
|
||||
Notify this mod of a dimension change of player to dimension
|
||||
|
||||
* player: player, player who changed the dimension
|
||||
* dimension: string, new dimension ("overworld", "nether", "end", "void")
|
||||
|
@ -3,7 +3,7 @@ A TGA Encoder written in Lua without the use of external Libraries.
|
||||
|
||||
Created by fleckenstein for VoxeLibre, then improved by erlehmann.
|
||||
|
||||
May be used as a Minetest mod.
|
||||
May be used as a Luanti mod.
|
||||
|
||||
See `examples.lua` for example code and usage hints.
|
||||
|
||||
@ -19,13 +19,13 @@ No checksums need to be updated on any kind of in-place texture editing.
|
||||
|
||||
**Tip**: When storing an editable image in item meta, use zlib compression.
|
||||
|
||||
### Legacy Minetest Texture Encoding
|
||||
### Legacy Luanti Texture Encoding
|
||||
|
||||
Minetest 5.4 did not include `minetest.encode_png()` (or any equvivalent).
|
||||
Luanti 5.4 did not include `minetest.encode_png()` (or any equvivalent).
|
||||
|
||||
Since `tga_encoder` is written in pure Lua, it does not need engine support.
|
||||
|
||||
**Tip:** Look at `examples.lua` and the Minetest mod `mcl_maps` for guidance.
|
||||
**Tip:** Look at `examples.lua` and the Luanti mod `mcl_maps` for guidance.
|
||||
|
||||
### Advanced Texture Format Control
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
dofile("init.lua")
|
||||
|
||||
-- This generates images necessary to colorize 16 Minetest nodes in 4096 colors.
|
||||
-- This generates images necessary to colorize 16 Luanti nodes in 4096 colors.
|
||||
-- It serves as a demonstration of what you can achieve using colormapped nodes.
|
||||
-- It is be useful for grass or beam or glass nodes that need to blend smoothly.
|
||||
|
||||
|
35
mods/CORE/vl_legacy/API.md
Normal file
35
mods/CORE/vl_legacy/API.md
Normal file
@ -0,0 +1,35 @@
|
||||
# Legacy Code Support Functions
|
||||
|
||||
## `vl_legacy.deprecated(description, replacement)`
|
||||
|
||||
Creates a wrapper that logs calls to deprecated function.
|
||||
|
||||
Arguments:
|
||||
* `description`: The text logged when the deprecated function is called.
|
||||
* `replacement`: The function that should be called instead. This is invoked passing
|
||||
along the parameters exactly as provided.
|
||||
|
||||
## `vl_legacy.register_item_conversion`
|
||||
|
||||
Allows automatic conversion of items.
|
||||
|
||||
Arguments:
|
||||
* `old`: Itemstring to be converted
|
||||
* `new`: New item string
|
||||
|
||||
## `vl_legacy.convert_node(pos, node)`
|
||||
|
||||
Converts legacy nodes to newer versions.
|
||||
|
||||
Arguments:
|
||||
* `pos`: Position of the node to attempt conversion
|
||||
* `node`: Node definition to convert. The node will be loaded from map data if `nil`.
|
||||
|
||||
The node definition for the old node must contain the field `_vl_legacy_convert` with
|
||||
a value that is either a `function(pos, node)` or `string` for this call to have any
|
||||
affect. If a function is provided, the function is called with `pos` and `node` as
|
||||
arguments. If a string is provided, a node name conversion will occur.
|
||||
|
||||
This mod provides an LBM and ABM that will automatically call this function for nodes
|
||||
with `group:legacy` set.
|
||||
|
75
mods/CORE/vl_legacy/init.lua
Normal file
75
mods/CORE/vl_legacy/init.lua
Normal file
@ -0,0 +1,75 @@
|
||||
local mod = {}
|
||||
vl_legacy = mod
|
||||
|
||||
function mod.deprecated(description, func)
|
||||
return function(...)
|
||||
minetest.log("warning",description .. debug.traceback())
|
||||
return func(...)
|
||||
end
|
||||
end
|
||||
|
||||
local item_conversions = {}
|
||||
mod.registered_item_conversions = item_conversions
|
||||
|
||||
function mod.register_item_conversion(old, new, func)
|
||||
item_conversions[old] = {new, func}
|
||||
end
|
||||
function mod.convert_inventory_lists(lists)
|
||||
for _,list in pairs(lists) do
|
||||
for i = 1,#list do
|
||||
local itemstack = list[i]
|
||||
local conversion = itemstack and item_conversions[itemstack:get_name()]
|
||||
if conversion then
|
||||
local new_name,func = conversion[1],conversion[2]
|
||||
if func then
|
||||
func(itemstack)
|
||||
else
|
||||
itemstack:set_name(new_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
function mod.convert_inventory(inv)
|
||||
local lists = inv:get_lists()
|
||||
mod.convert_inventory_lists(lists)
|
||||
inv:set_lists(lists)
|
||||
end
|
||||
function mod.convert_node(pos, node)
|
||||
local node = node or minetest.get_node(pos)
|
||||
local node_def = minetest.registered_nodes[node.name]
|
||||
local convert = node_def._vl_legacy_convert_node
|
||||
if type(convert) == "function" then
|
||||
convert(pos, node)
|
||||
elseif type(convert) == "string" then
|
||||
node.name = convert
|
||||
minetest.swap_node(pos, node)
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
mod.convert_inventory(player:get_inventory())
|
||||
end)
|
||||
|
||||
minetest.register_lbm({
|
||||
name = "vl_legacy:convert_container_inventories",
|
||||
nodenames = "group:container",
|
||||
run_at_every_load = true,
|
||||
action = function(pos, node)
|
||||
local meta = minetest.get_meta(pos)
|
||||
mod.convert_inventory(meta:get_inventory())
|
||||
end
|
||||
})
|
||||
minetest.register_lbm({
|
||||
name = "vl_legacy:convert_nodes",
|
||||
nodenames = "group:legacy",
|
||||
run_at_every_load = true,
|
||||
action = mod.convert_node,
|
||||
})
|
||||
minetest.register_abm({
|
||||
label = "Convert Legacy Nodes",
|
||||
nodenames = "group:legacy",
|
||||
interval = 5,
|
||||
chance = 1,
|
||||
action = mod.convert_node,
|
||||
})
|
3
mods/CORE/vl_legacy/mod.conf
Normal file
3
mods/CORE/vl_legacy/mod.conf
Normal file
@ -0,0 +1,3 @@
|
||||
name = vl_legacy
|
||||
author = teknomunk
|
||||
description = API to ease conversion of items, deprecated function logging and similar functions
|
@ -17,7 +17,7 @@ Code based on Minetest Game, licensed under the MIT License (MIT).
|
||||
|
||||
Authors include:
|
||||
* PilzAdam (2012-2016)
|
||||
* Various Minetest / Minetest Game developers and contributors (2012-2016)
|
||||
* Various Luanti / Minetest Game developers and contributors (2012-2016)
|
||||
* maikerumine (2017)
|
||||
* Wuzzy (2017)
|
||||
* Fleckenstein (2020-2021)
|
||||
|
@ -1,12 +1,23 @@
|
||||
# textdomain: mcl_boats
|
||||
Acacia Boat=Akazienboot
|
||||
Birch Boat=Birkenboot
|
||||
Boat=Boot
|
||||
Boats are used to travel on the surface of water.=Boote werden benutzt, um sich auf der Wasseroberfläche zu bewegen.
|
||||
Dark Oak Boat=Schwarzeichenboot
|
||||
Jungle Boat=Dschungelboot
|
||||
Sneak to dismount=Schleichen zum Aussteigen
|
||||
Oak Boat=Eichenboot
|
||||
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Use [Sneak] to leave the boat, punch the boat to make it drop as an item.=Rechtsklicken Sie auf eine Wasserquelle, um das Boot zu platzieren. Rechtsklicken Sie auf das Boot, um es zu betreten. Mit [Links] und [Rechts] lenken, mit [Vorwärts] und [Rückwärts] Geschwindigkeit regeln oder rückwärts fahren. Nutzen sie [Schleichen], um das Boot zu verlassen, schlagen Sie das Boot, um es als Gegenstand fallen zu lassen.
|
||||
Spruce Boat=Fichtenboot
|
||||
Birch Boat=Birkenboot
|
||||
Jungle Boat=Dschungelboot
|
||||
Acacia Boat=Akazienboot
|
||||
Dark Oak Boat=Schwarzeichenboot
|
||||
Obsidian Boat=Obsidianboot
|
||||
Mangrove Boat=Mangrovenboot
|
||||
Cherry Boat=Kirschholzboot
|
||||
Oak Chest Boat=Eichentruhenboot
|
||||
Spruce Chest Boat=Fichtentruhenboot
|
||||
Birch Chest Boat=Birkentruhenboot
|
||||
Jungle Chest Boat=Dschungeltruhenboot
|
||||
Acacia Chest Boat=Akazientruhenboot
|
||||
Dark Oak Chest Boat=Schwarzeichentruhenboot
|
||||
Mangrove Chest Boat=Mangroventruhenboot
|
||||
Cherry Chest Boat=Kirschtruhenboot
|
||||
Boats are used to travel on the surface of water.=Boote werden benutzt, um sich auf der Wasseroberfläche zu bewegen.
|
||||
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Use [Sneak] to leave the boat, punch the boat to make it drop as an item.=Rechtsklicken Sie auf eine Wasserquelle, um das Boot zu platzieren. Rechtsklicken Sie auf das Boot, um es zu betreten. Mit [Links] und [Rechts] lenken, mit [Vorwärts] und [Rückwärts] Geschwindigkeit regeln oder rückwärts fahren. Nutzen sie [Schleichen], um das Boot zu verlassen, schlagen Sie das Boot, um es als Gegenstand fallen zu lassen.
|
||||
Boat=Boot
|
||||
Water vehicle=Wasserfahrzeug
|
||||
Sneak to dismount=Zum Aussteigen schleichen
|
||||
|
@ -1,13 +1,23 @@
|
||||
# textdomain: mcl_boats
|
||||
Acacia Boat=Akaciebåd
|
||||
Birch Boat=Birkebåd
|
||||
Boat=Båd
|
||||
Boats are used to travel on the surface of water.=Både blier brugt til at rejse på vandoverflader.
|
||||
Dark Oak Boat=Mørk egetræsbåd
|
||||
Jungle Boat=Junglebåd
|
||||
Oak Boat=Egetræsbåd
|
||||
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Use [Sneak] to leave the boat, punch the boat to make it drop as an item.=Højre-klik på en vand for at placere båden. Højre-klik på båden for at gå ombord. Brug [Left] og [Right] til at styre. [Forwards] for at øge hastigheden, og [Backwards] for at sænke farten eller sejle bagud. Brug [Sneak] for at forlade båden, slå båden for at lave den om til en genstand.
|
||||
Spruce Boat=Granbåd
|
||||
Water vehicle=Vandfartøj
|
||||
Sneak to dismount=Snig for at stige ud
|
||||
Obsidian Boat=Obsidianbåd
|
||||
Oak Boat=Egetræsbåd
|
||||
Spruce Boat=Granbåd
|
||||
Birch Boat=Birkebåd
|
||||
Jungle Boat=Junglebåd
|
||||
Acacia Boat=Akaciebåd
|
||||
Dark Oak Boat=Mørk egetræsbåd
|
||||
Obsidian Boat=Obsidianbåd
|
||||
Mangrove Boat=
|
||||
Cherry Boat=
|
||||
Oak Chest Boat=
|
||||
Spruce Chest Boat=
|
||||
Birch Chest Boat=
|
||||
Jungle Chest Boat=
|
||||
Acacia Chest Boat=
|
||||
Dark Oak Chest Boat=
|
||||
Mangrove Chest Boat=
|
||||
Cherry Chest Boat=
|
||||
Boats are used to travel on the surface of water.=Både blier brugt til at rejse på vandoverflader.
|
||||
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Use [Sneak] to leave the boat, punch the boat to make it drop as an item.=Højre-klik på en vand for at placere båden. Højre-klik på båden for at gå ombord. Brug [Left] og [Right] til at styre. [Forwards] for at øge hastigheden, og [Backwards] for at sænke farten eller sejle bagud. Brug [Sneak] for at forlade båden, slå båden for at lave den om til en genstand.
|
||||
Boat=Båd
|
||||
Water vehicle=Vandfartøj
|
||||
|
@ -1,13 +1,28 @@
|
||||
# textdomain: mcl_boats
|
||||
Acacia Boat=Barca de acacia
|
||||
Birch Boat=Barca de abedul
|
||||
Boat=Barca
|
||||
Boats are used to travel on the surface of water.=Las barcas se utilizan para viajar en la superficie del agua.
|
||||
Dark Oak Boat=Barca de roble oscuro
|
||||
Jungle Boat=Barca de la selva
|
||||
Oak Boat=Barca de roble
|
||||
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Rightclick the boat again to leave it, punch the boat to make it drop as an item.=Haga clic derecho en una fuente de agua para colocar el barco. Haga clic derecho en el barco para entrar. Utilice [Izquierda] y [Derecha] para dirigir, [Adelante] para acelerar y [Atrás] para reducir la velocidad o retroceder. Haga clic derecho en el barco nuevamente para dejarlo, golpee el barco para que se caiga como un artículo.
|
||||
Spruce Boat=Barca de abeto
|
||||
Water vehicle=Vehículo acuático
|
||||
Sneak to dismount=Agáchate para bajar
|
||||
Oak Boat=Barca de roble
|
||||
Spruce Boat=Barca de abeto
|
||||
Birch Boat=Barca de abedul
|
||||
Jungle Boat=Barca de la selva
|
||||
Acacia Boat=Barca de acacia
|
||||
Dark Oak Boat=Barca de roble oscuro
|
||||
Obsidian Boat=Barca de obsidiana
|
||||
Mangrove Boat=
|
||||
Cherry Boat=
|
||||
Oak Chest Boat=
|
||||
Spruce Chest Boat=
|
||||
Birch Chest Boat=
|
||||
Jungle Chest Boat=
|
||||
Acacia Chest Boat=
|
||||
Dark Oak Chest Boat=
|
||||
Mangrove Chest Boat=
|
||||
Cherry Chest Boat=
|
||||
Boats are used to travel on the surface of water.=Las barcas se utilizan para viajar en la superficie del agua.
|
||||
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Use [Sneak] to leave the boat, punch the boat to make it drop as an item.=
|
||||
Boat=Barca
|
||||
Water vehicle=Vehículo acuático
|
||||
|
||||
|
||||
##### not used anymore #####
|
||||
|
||||
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Rightclick the boat again to leave it, punch the boat to make it drop as an item.=Haga clic derecho en una fuente de agua para colocar el barco. Haga clic derecho en el barco para entrar. Utilice [Izquierda] y [Derecha] para dirigir, [Adelante] para acelerar y [Atrás] para reducir la velocidad o retroceder. Haga clic derecho en el barco nuevamente para dejarlo, golpee el barco para que se caiga como un artículo.
|
||||
|
@ -1,15 +1,11 @@
|
||||
# textdomain: mcl_boats
|
||||
Acacia Boat=Bateau en acacia
|
||||
Birch Boat=Bateau en bouleau
|
||||
Boat=Bateau
|
||||
Boats are used to travel on the surface of water.=Les bateaux sont utilisés pour voyager à la surface de l'eau.
|
||||
Dark Oak Boat=Bateau en chêne noir
|
||||
Jungle Boat=Bateau en acajou
|
||||
Oak Boat=Bateau en chêne
|
||||
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Use [Sneak] to leave the boat, punch the boat to make it drop as an item.=Faites un clic droit sur une source d'eau pour placer le bateau. Faites un clic droit sur le bateau pour y entrer. Utilisez [Gauche] et [Droite] pour diriger, [Avant] pour accélérer et [Arrière] pour ralentir ou reculer. Utilisez [Sneak] pour le quitter, frappez le bateau pour le faire tomber en tant qu'objet.
|
||||
Spruce Boat=Bateau en sapin
|
||||
Water vehicle=Véhicule aquatique
|
||||
Sneak to dismount=Se baisser pour descendre
|
||||
Oak Boat=Bateau en chêne
|
||||
Spruce Boat=Bateau en sapin
|
||||
Birch Boat=Bateau en bouleau
|
||||
Jungle Boat=Bateau en acajou
|
||||
Acacia Boat=Bateau en acacia
|
||||
Dark Oak Boat=Bateau en chêne noir
|
||||
Obsidian Boat=Bateau en obsidienne
|
||||
Mangrove Boat=Bateau en palétuvier
|
||||
Cherry Boat=Bateau en cerisier
|
||||
@ -21,3 +17,7 @@ Acacia Chest Boat=Bateau en acacia avec coffre
|
||||
Dark Oak Chest Boat=Bateau en chêne noir avec coffre
|
||||
Mangrove Chest Boat=Bateau en palétuvier avec coffre
|
||||
Cherry Chest Boat=Bateau en cerisier avec coffre
|
||||
Boats are used to travel on the surface of water.=Les bateaux sont utilisés pour voyager à la surface de l'eau.
|
||||
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Use [Sneak] to leave the boat, punch the boat to make it drop as an item.=Faites un clic droit sur une source d'eau pour placer le bateau. Faites un clic droit sur le bateau pour y entrer. Utilisez [Gauche] et [Droite] pour diriger, [Avant] pour accélérer et [Arrière] pour ralentir ou reculer. Utilisez [Sneak] pour le quitter, frappez le bateau pour le faire tomber en tant qu'objet.
|
||||
Boat=Bateau
|
||||
Water vehicle=Véhicule aquatique
|
||||
|
23
mods/ENTITIES/mcl_boats/locale/mcl_boats.it.tr
Normal file
23
mods/ENTITIES/mcl_boats/locale/mcl_boats.it.tr
Normal file
@ -0,0 +1,23 @@
|
||||
# textdomain: mcl_boats
|
||||
Sneak to dismount=Accovacciati per scendere
|
||||
Oak Boat=Barca di Quercia
|
||||
Spruce Boat=Barca d'Abete
|
||||
Birch Boat=Barca di Betulla
|
||||
Jungle Boat=Barca di Giungla
|
||||
Acacia Boat=Barca d'Acacia
|
||||
Dark Oak Boat=Barca di Quercia Scura
|
||||
Obsidian Boat=Barca d'Ossidiana
|
||||
Mangrove Boat=Barca di Mangrovia
|
||||
Cherry Boat=Barca di Ciliegio
|
||||
Oak Chest Boat=Barca di Quercia con Baule
|
||||
Spruce Chest Boat=Barca d'Abete con Baule
|
||||
Birch Chest Boat=Barca di Betulla con Baule
|
||||
Jungle Chest Boat=Barca di Giungla con Baule
|
||||
Acacia Chest Boat=Barca d'Acacia con Baule
|
||||
Dark Oak Chest Boat=Barca di Quercia Scura con Baule
|
||||
Mangrove Chest Boat=Barca di Mangrovia con Baule
|
||||
Cherry Chest Boat=Barca di Ciliegio con Baule
|
||||
Boats are used to travel on the surface of water.=Le barche vengono usate per viaggiare sulla superficie dell'acqua.
|
||||
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Use [Sneak] to leave the boat, punch the boat to make it drop as an item.=Click Destro su una fonte d'acqua per piazzare la barca. Click Destro sulla barca per salire a bordo. Usa [Sinistra] e [Destra] per girare, [Avanti] per accelerare e [Indietro] per rallentare o muoverti indietro. Usa [Accovacciati] per scendere dalla barca, colpisci la barca per rilasciarla come oggetto.
|
||||
Boat=Barca
|
||||
Water vehicle=Veicolo acquatico
|
@ -1,13 +1,23 @@
|
||||
# textdomain: mcl_boats
|
||||
Acacia Boat=アカシアのボート
|
||||
Birch Boat=シラカバのボート
|
||||
Boat=ボート
|
||||
Boats are used to travel on the surface of water.=ボートは、水面を移動するために使われます。
|
||||
Dark Oak Boat=ダークオークのボート
|
||||
Jungle Boat=ジャングルのボート
|
||||
Oak Boat=オークのボート
|
||||
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Use [Sneak] to leave the boat, punch the boat to make it drop as an item.=水源を右クリックすると、ボートが配置されます。ボートを右クリックすると、乗り込みます。[左][右]で舵取り、[前]で加速、[後]で減速または後退します。[スニーク]でボートから離れ、ボートをパンチするとアイテムとしてドロップします。
|
||||
Spruce Boat=トウヒのボート
|
||||
Water vehicle=水上用の乗物
|
||||
Sneak to dismount=スニークで降りる
|
||||
Obsidian Boat=黒曜石のボート
|
||||
Oak Boat=オークのボート
|
||||
Spruce Boat=トウヒのボート
|
||||
Birch Boat=シラカバのボート
|
||||
Jungle Boat=ジャングルのボート
|
||||
Acacia Boat=アカシアのボート
|
||||
Dark Oak Boat=ダークオークのボート
|
||||
Obsidian Boat=黒曜石のボート
|
||||
Mangrove Boat=
|
||||
Cherry Boat=
|
||||
Oak Chest Boat=
|
||||
Spruce Chest Boat=
|
||||
Birch Chest Boat=
|
||||
Jungle Chest Boat=
|
||||
Acacia Chest Boat=
|
||||
Dark Oak Chest Boat=
|
||||
Mangrove Chest Boat=
|
||||
Cherry Chest Boat=
|
||||
Boats are used to travel on the surface of water.=ボートは、水面を移動するために使われます。
|
||||
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Use [Sneak] to leave the boat, punch the boat to make it drop as an item.=水源を右クリックすると、ボートが配置されます。ボートを右クリックすると、乗り込みます。[左][右]で舵取り、[前]で加速、[後]で減速または後退します。[スニーク]でボートから離れ、ボートをパンチするとアイテムとしてドロップします。
|
||||
Boat=ボート
|
||||
Water vehicle=水上用の乗物
|
||||
|
23
mods/ENTITIES/mcl_boats/locale/mcl_boats.nb.tr
Normal file
23
mods/ENTITIES/mcl_boats/locale/mcl_boats.nb.tr
Normal file
@ -0,0 +1,23 @@
|
||||
# textdomain: mcl_boats
|
||||
Sneak to dismount=Snik for å gå av
|
||||
Oak Boat=Eikebåt
|
||||
Spruce Boat=Granbåt
|
||||
Birch Boat=Bjørkebåt
|
||||
Jungle Boat=Jungelbåt
|
||||
Acacia Boat=Akasiebåt
|
||||
Dark Oak Boat=Mørkeikbåt
|
||||
Obsidian Boat=Obsidianbåt
|
||||
Mangrove Boat=Mangrovebåt
|
||||
Cherry Boat=Kirsebærtrebåt
|
||||
Oak Chest Boat=Eikebåt med kiste
|
||||
Spruce Chest Boat=Granbåt med kiste
|
||||
Birch Chest Boat=Bjørkebåt med kiste
|
||||
Jungle Chest Boat=Jungelbåt med kiste
|
||||
Acacia Chest Boat=Akasiebåt med kiste
|
||||
Dark Oak Chest Boat=Mørkeikbåt med kiste
|
||||
Mangrove Chest Boat=Mangrovebåt med kiste
|
||||
Cherry Chest Boat=Kirsebærtrebåt med kiste
|
||||
Boats are used to travel on the surface of water.=Båter brukes for å reise på overflaten av vann.
|
||||
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Use [Sneak] to leave the boat, punch the boat to make it drop as an item.=Høyreklikk på en vannkilde for å plassere båten. Høyreklikk på båten for å sitte oppi. Bruk [Venstre] og [Høyre] for å styre, [Fremover] for å øke hastigheten og [Backwards] for å slakke ned eller bevege deg baklengs.
|
||||
Boat=Båt
|
||||
Water vehicle=Vannkjøretøy
|
@ -1,17 +1,14 @@
|
||||
# textdomain: mcl_boats
|
||||
Acacia Boat=Barca de Cacèir
|
||||
Birch Boat=Barca de Beç
|
||||
Boat=Barca
|
||||
Boats are used to travel on the surface of water.=Las barcas son utilizadas per voiatja per aigas.
|
||||
Dark Oak Boat=Barca de Ròure Nèir
|
||||
Jungle Boat=Barca d'Acajó
|
||||
Oak Boat=Barca de Ròure
|
||||
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Use [Sneak] to leave the boat, punch the boat to make it drop as an item.=Fasetz un clic dreit sobre una sorça d'aiga per plaça la barca. Fasetz un clic dreit sobre la barca per rintrar. Utilizatz [Gaucha] e [Dreita] per menar, [Davant] per accelerar e [Darrèir] per ralentir o racuolar. Utilizatz [Sneak] per z-o quitar, tustatz la barca per z-o faire tombar coma objècte.
|
||||
Spruce Boat=Barca de Sap
|
||||
Water vehicle=Veïcule per aiga
|
||||
Sneak to dismount=Se baissar per descendre
|
||||
Oak Boat=Barca de Ròure
|
||||
Spruce Boat=Barca de Sap
|
||||
Birch Boat=Barca de Beç
|
||||
Jungle Boat=Barca d'Acajó
|
||||
Acacia Boat=Barca de Cacèir
|
||||
Dark Oak Boat=Barca de Ròure Nèir
|
||||
Obsidian Boat=Barca d'Obsidiana
|
||||
Mangrove Boat=Barca de Paletuvèir
|
||||
Cherry Boat=
|
||||
Oak Chest Boat=Barca de Ròure embei una Mala
|
||||
Spruce Chest Boat=Barca de Sap embei una Mala
|
||||
Birch Chest Boat=Barca de Beç embei una Mala
|
||||
@ -19,3 +16,8 @@ Jungle Chest Boat=Barca d'Acajó embei una Mala
|
||||
Acacia Chest Boat=Barca de Cacèir embei una Mala
|
||||
Dark Oak Chest Boat=Barca de Ròure Nèir embei una Mala
|
||||
Mangrove Chest Boat=Barca de Paletuvèir embei una Mala
|
||||
Cherry Chest Boat=
|
||||
Boats are used to travel on the surface of water.=Las barcas son utilizadas per voiatja per aigas.
|
||||
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Use [Sneak] to leave the boat, punch the boat to make it drop as an item.=Fasetz un clic dreit sobre una sorça d'aiga per plaça la barca. Fasetz un clic dreit sobre la barca per rintrar. Utilizatz [Gaucha] e [Dreita] per menar, [Davant] per accelerar e [Darrèir] per ralentir o racuolar. Utilizatz [Sneak] per z-o quitar, tustatz la barca per z-o faire tombar coma objècte.
|
||||
Boat=Barca
|
||||
Water vehicle=Veïcule per aiga
|
||||
|
@ -1,12 +1,23 @@
|
||||
# textdomain: mcl_boats
|
||||
Acacia Boat=Akacjowa łódź
|
||||
Birch Boat=Brzozowa łódź
|
||||
Boat=Łódź
|
||||
Boats are used to travel on the surface of water.=Łodzie są wykorzystywane do podróżowania po powierzchni wody.
|
||||
Dark Oak Boat=Ciemno-dębowa łódź
|
||||
Jungle Boat=Tropikalna łódź
|
||||
Oak Boat=Dębowa łódź
|
||||
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Use [Sneak] to leave the boat, punch the boat to make it drop as an item.=Kliknij prawym przyciskiem myszy na źródło wody by postawić łódź. Kliknij prawym przyciskiem myszy by w nią wsiąść. Użyj przycisków [Lewy] oraz [Prawy] by sterować, [Naprzód] by przyspieszyć i [W tył] by zwolnić lub się cofać. Kliknij [Skradanie] by z niej wyjść, uderz ją by wziąć ją jako przedmiot.
|
||||
Spruce Boat=Świerkowa łódź
|
||||
Water vehicle=Pojazd wodny
|
||||
Sneak to dismount=Skradaj się by opuścić łódź
|
||||
Oak Boat=Dębowa łódź
|
||||
Spruce Boat=Świerkowa łódź
|
||||
Birch Boat=Brzozowa łódź
|
||||
Jungle Boat=Tropikalna łódź
|
||||
Acacia Boat=Akacjowa łódź
|
||||
Dark Oak Boat=Ciemno-dębowa łódź
|
||||
Obsidian Boat=
|
||||
Mangrove Boat=
|
||||
Cherry Boat=
|
||||
Oak Chest Boat=
|
||||
Spruce Chest Boat=
|
||||
Birch Chest Boat=
|
||||
Jungle Chest Boat=
|
||||
Acacia Chest Boat=
|
||||
Dark Oak Chest Boat=
|
||||
Mangrove Chest Boat=
|
||||
Cherry Chest Boat=
|
||||
Boats are used to travel on the surface of water.=Łodzie są wykorzystywane do podróżowania po powierzchni wody.
|
||||
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Use [Sneak] to leave the boat, punch the boat to make it drop as an item.=Kliknij prawym przyciskiem myszy na źródło wody by postawić łódź. Kliknij prawym przyciskiem myszy by w nią wsiąść. Użyj przycisków [Lewy] oraz [Prawy] by sterować, [Naprzód] by przyspieszyć i [W tył] by zwolnić lub się cofać. Kliknij [Skradanie] by z niej wyjść, uderz ją by wziąć ją jako przedmiot.
|
||||
Boat=Łódź
|
||||
Water vehicle=Pojazd wodny
|
||||
|
@ -1,15 +1,11 @@
|
||||
# textdomain: mcl_boats
|
||||
Acacia Boat=Barco de Acácia
|
||||
Birch Boat=Barco de Bétula
|
||||
Boat=Barco
|
||||
Boats are used to travel on the surface of water.=Barcos são usados para viajar na superfície da água
|
||||
Dark Oak Boat=Barco de Carvalho Escuro
|
||||
Jungle Boat=Barco de Selva
|
||||
Oak Boat=Barco de Carvalho
|
||||
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Use [Sneak] to leave the boat, punch the boat to make it drop as an item.=Clique com o botão direito em uma fonte de água para posicionar o barco. Clique com o botão direito no barco para entrar nele. Use [Esquerda] e [Direita] para fazer curva, [Frente] para acelerar e [Trás] para frear e ir para trás. Use [Agachar] para deixar o barco, soque-o para fazê-lo dropar como um item.
|
||||
Spruce Boat=Barco de Pinheiro
|
||||
Water vehicle=Veículo aquático
|
||||
Sneak to dismount=Agache para desmontar
|
||||
Oak Boat=Barco de Carvalho
|
||||
Spruce Boat=Barco de Pinheiro
|
||||
Birch Boat=Barco de Bétula
|
||||
Jungle Boat=Barco de Selva
|
||||
Acacia Boat=Barco de Acácia
|
||||
Dark Oak Boat=Barco de Carvalho Escuro
|
||||
Obsidian Boat=Barco de Obsidiana
|
||||
Mangrove Boat=Barco de Mangue
|
||||
Cherry Boat=Barco de Cerejeira
|
||||
@ -21,3 +17,7 @@ Acacia Chest Boat=Barco de Acácia com Baú
|
||||
Dark Oak Chest Boat=Barco de Carvalho Escuro com Baú
|
||||
Mangrove Chest Boat=Barco de Mangue com Baú
|
||||
Cherry Chest Boat=Barco de Cerejeira com Baú
|
||||
Boats are used to travel on the surface of water.=Barcos são usados para viajar na superfície da água
|
||||
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Use [Sneak] to leave the boat, punch the boat to make it drop as an item.=Clique com o botão direito em uma fonte de água para posicionar o barco. Clique com o botão direito no barco para entrar nele. Use [Esquerda] e [Direita] para fazer curva, [Frente] para acelerar e [Trás] para frear e ir para trás. Use [Agachar] para deixar o barco, soque-o para fazê-lo dropar como um item.
|
||||
Boat=Barco
|
||||
Water vehicle=Veículo aquático
|
||||
|
@ -1,15 +1,11 @@
|
||||
# textdomain: mcl_boats
|
||||
Acacia Boat=Акациевая лодка
|
||||
Birch Boat=Берёзовая лодка
|
||||
Boat=Лодка
|
||||
Boats are used to travel on the surface of water.=На лодке можно плыть по водной поверхности.
|
||||
Dark Oak Boat=Лодка из тёмного дуба
|
||||
Jungle Boat=Лодка из тропического дерева
|
||||
Oak Boat=Дубовая лодка
|
||||
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Use [Sneak] to leave the boat, punch the boat to make it drop as an item.=Правый клик на воде, чтобы установить лодку. Правый клик по лодке, чтобы сесть в нее. [Влево] и [Вправо] - рулить, [Вперед] - разгоняться, [Назад] - тормозить или плыть назад. Нажмите [Красться] для высадки, бейте по лодке, чтобы забрать её.
|
||||
Spruce Boat=Еловая лодка
|
||||
Water vehicle=Водный транспорт
|
||||
Sneak to dismount=Нажмите [Красться] для высадки
|
||||
Oak Boat=Дубовая лодка
|
||||
Spruce Boat=Еловая лодка
|
||||
Birch Boat=Берёзовая лодка
|
||||
Jungle Boat=Лодка из тропического дерева
|
||||
Acacia Boat=Акациевая лодка
|
||||
Dark Oak Boat=Лодка из тёмного дуба
|
||||
Obsidian Boat=Обсидиановая лодка
|
||||
Mangrove Boat=Мангровая лодка
|
||||
Cherry Boat=Вишнёвая лодка
|
||||
@ -20,4 +16,8 @@ Jungle Chest Boat=Лодка из тропического дерева с су
|
||||
Acacia Chest Boat=Акациевая лодка с сундуком
|
||||
Dark Oak Chest Boat=Лодка из тёмного дуба с сундуком
|
||||
Mangrove Chest Boat=Мангровая лодка с сундуком
|
||||
Cherry Chest Boat=Вишнёвая лодка с сундуком
|
||||
Cherry Chest Boat=Вишнёвая лодка с сундуком
|
||||
Boats are used to travel on the surface of water.=На лодке можно плыть по водной поверхности.
|
||||
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Use [Sneak] to leave the boat, punch the boat to make it drop as an item.=Правый клик на воде, чтобы установить лодку. Правый клик по лодке, чтобы сесть в нее. [Влево] и [Вправо] - рулить, [Вперед] - разгоняться, [Назад] - тормозить или плыть назад. Нажмите [Красться] для высадки, бейте по лодке, чтобы забрать её.
|
||||
Boat=Лодка
|
||||
Water vehicle=Водный транспорт
|
||||
|
23
mods/ENTITIES/mcl_boats/locale/mcl_boats.zh_CN.tr
Normal file
23
mods/ENTITIES/mcl_boats/locale/mcl_boats.zh_CN.tr
Normal file
@ -0,0 +1,23 @@
|
||||
# textdomain: mcl_boats
|
||||
Sneak to dismount=潜行以离开
|
||||
Oak Boat=橡木船
|
||||
Spruce Boat=云杉木船
|
||||
Birch Boat=白桦木船
|
||||
Jungle Boat=丛林木船
|
||||
Acacia Boat=金合欢木船
|
||||
Dark Oak Boat=深色橡木船
|
||||
Obsidian Boat=黑曜石船
|
||||
Mangrove Boat=红树木船
|
||||
Cherry Boat=樱桃木船
|
||||
Oak Chest Boat=橡木箱船
|
||||
Spruce Chest Boat=云杉木箱船
|
||||
Birch Chest Boat=白桦木箱船
|
||||
Jungle Chest Boat=丛林木箱船
|
||||
Acacia Chest Boat=金合欢木箱船
|
||||
Dark Oak Chest Boat=深色橡木箱船
|
||||
Mangrove Chest Boat=红树木箱船
|
||||
Cherry Chest Boat=樱桃木箱船
|
||||
Boats are used to travel on the surface of water.=船用于在水面上航行。
|
||||
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Use [Sneak] to leave the boat, punch the boat to make it drop as an item.=右键点击水源来放置船,右键点击船进入船内。使用【左】和【右】键操控方向,使用【前】键加速,使用【后】键减速或向后移动。使用【潜行】键离开船,击打船使其变为物品掉落。
|
||||
Boat=船
|
||||
Water vehicle=水上交通工具
|
@ -1,11 +1,28 @@
|
||||
# textdomain: mcl_boats
|
||||
Acacia Boat=相思木船
|
||||
Birch Boat=白樺木船
|
||||
Boat=船
|
||||
Boats are used to travel on the surface of water.=船是用來在水上行走的交通工具。
|
||||
Dark Oak Boat=黑橡木船
|
||||
Jungle Boat=叢林木船
|
||||
Sneak to dismount=
|
||||
Oak Boat=橡木船
|
||||
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Rightclick the boat again to leave it, punch the boat to make it drop as an item.=右鍵單擊水源以放置船。右鍵單擊船以搭乘它。使用[左]和[右]進行轉向,[向前]加快速度,[向後]減速或向後移動。再次右鍵單擊船以離開它,打擊船以使其掉落為物品。
|
||||
Spruce Boat=杉木船
|
||||
Birch Boat=白樺木船
|
||||
Jungle Boat=叢林木船
|
||||
Acacia Boat=相思木船
|
||||
Dark Oak Boat=黑橡木船
|
||||
Obsidian Boat=
|
||||
Mangrove Boat=
|
||||
Cherry Boat=
|
||||
Oak Chest Boat=
|
||||
Spruce Chest Boat=
|
||||
Birch Chest Boat=
|
||||
Jungle Chest Boat=
|
||||
Acacia Chest Boat=
|
||||
Dark Oak Chest Boat=
|
||||
Mangrove Chest Boat=
|
||||
Cherry Chest Boat=
|
||||
Boats are used to travel on the surface of water.=船是用來在水上行走的交通工具。
|
||||
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Use [Sneak] to leave the boat, punch the boat to make it drop as an item.=
|
||||
Boat=船
|
||||
Water vehicle=水上交通工具
|
||||
|
||||
|
||||
##### not used anymore #####
|
||||
|
||||
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Rightclick the boat again to leave it, punch the boat to make it drop as an item.=右鍵單擊水源以放置船。右鍵單擊船以搭乘它。使用[左]和[右]進行轉向,[向前]加快速度,[向後]減速或向後移動。再次右鍵單擊船以離開它,打擊船以使其掉落為物品。
|
||||
|
@ -1,15 +1,11 @@
|
||||
# textdomain: mcl_boats
|
||||
Acacia Boat=
|
||||
Birch Boat=
|
||||
Boat=
|
||||
Boats are used to travel on the surface of water.=
|
||||
Dark Oak Boat=
|
||||
Jungle Boat=
|
||||
Oak Boat=
|
||||
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Use [Sneak] to leave the boat, punch the boat to make it drop as an item.=
|
||||
Spruce Boat=
|
||||
Water vehicle=
|
||||
Sneak to dismount=
|
||||
Oak Boat=
|
||||
Spruce Boat=
|
||||
Birch Boat=
|
||||
Jungle Boat=
|
||||
Acacia Boat=
|
||||
Dark Oak Boat=
|
||||
Obsidian Boat=
|
||||
Mangrove Boat=
|
||||
Cherry Boat=
|
||||
@ -20,4 +16,8 @@ Jungle Chest Boat=
|
||||
Acacia Chest Boat=
|
||||
Dark Oak Chest Boat=
|
||||
Mangrove Chest Boat=
|
||||
Cherry Chest Boat=
|
||||
Cherry Chest Boat=
|
||||
Boats are used to travel on the surface of water.=
|
||||
Rightclick on a water source to place the boat. Rightclick the boat to enter it. Use [Left] and [Right] to steer, [Forwards] to speed up and [Backwards] to slow down or move backwards. Use [Sneak] to leave the boat, punch the boat to make it drop as an item.=
|
||||
Boat=
|
||||
Water vehicle=
|
||||
|
@ -14,7 +14,21 @@ function mcl_burning.is_burning(obj)
|
||||
end
|
||||
|
||||
function mcl_burning.is_affected_by_rain(obj)
|
||||
return mcl_weather.get_weather() == "rain" and mcl_weather.is_outdoor(obj:get_pos())
|
||||
local pos = obj:get_pos()
|
||||
if not pos then return false end
|
||||
return mcl_weather.rain.raining and mcl_weather.is_outdoor(pos) and mcl_weather.has_rain(pos)
|
||||
end
|
||||
|
||||
function mcl_burning.is_affected_by_sunlight(obj, threshold)
|
||||
threshold = threshold or core.LIGHT_MAX
|
||||
|
||||
local pos = obj:get_pos()
|
||||
if not pos then return false end
|
||||
local _,dim = mcl_worlds.y_to_layer(pos.y)
|
||||
if dim ~= "overworld" then return false end
|
||||
|
||||
local sunlight = mcl_util.get_natural_light(pos, core.get_timeofday()) or 0
|
||||
if sunlight > threshold then return true end
|
||||
end
|
||||
|
||||
function mcl_burning.get_collisionbox(obj, smaller, storage)
|
||||
|
@ -1,4 +1,4 @@
|
||||
name = mcl_burning
|
||||
description = Burning Objects for VoxeLibre
|
||||
author = Fleckenstein
|
||||
depends = mcl_weather
|
||||
depends = mcl_weather, mcl_worlds
|
||||
|
@ -29,7 +29,7 @@ local function make_drop(pos, liquid, sound, interval, texture)
|
||||
pt.expirationtime = t
|
||||
|
||||
pt.texture = "[combine:2x2:" ..
|
||||
-math.random(1, 16) .. "," .. -math.random(1, 16) .. "=" .. texture
|
||||
math.random(-14, 0) .. "," .. math.random(-14, 0) .. "=" .. texture
|
||||
|
||||
minetest.add_particle(pt)
|
||||
|
||||
|
@ -27,28 +27,33 @@ local inv_callbacks = {
|
||||
}
|
||||
|
||||
function mcl_entity_invs.load_inv(ent,size)
|
||||
mcl_log("load_inv")
|
||||
if not ent._inv_id then return end
|
||||
mcl_log("load_inv 2")
|
||||
local inv = minetest.get_inventory({type="detached", name=ent._inv_id})
|
||||
if not inv then
|
||||
mcl_log("load_inv 3")
|
||||
inv = minetest.create_detached_inventory(ent._inv_id, inv_callbacks)
|
||||
inv:set_size("main", size)
|
||||
if ent._items then
|
||||
if ent._mcl_entity_invs_load_items then
|
||||
local lists = ent:_mcl_entity_invs_load_items()
|
||||
vl_legacy.convert_inventory_lists(lists)
|
||||
inv:set_list("main", lists)
|
||||
elseif ent._items then
|
||||
vl_legacy.convert_inventory_lists(ent._items)
|
||||
inv:set_list("main",ent._items)
|
||||
end
|
||||
else
|
||||
mcl_log("load_inv 4")
|
||||
end
|
||||
return inv
|
||||
end
|
||||
|
||||
function mcl_entity_invs.save_inv(ent)
|
||||
if ent._inv then
|
||||
ent._items = {}
|
||||
local items = {}
|
||||
for i,it in ipairs(ent._inv:get_list("main")) do
|
||||
ent._items[i] = it:to_string()
|
||||
items[i] = it:to_string()
|
||||
end
|
||||
if ent._mcl_entity_invs_save_items then
|
||||
ent:_mcl_entity_invs_save_items(items)
|
||||
else
|
||||
ent._items = items
|
||||
end
|
||||
minetest.remove_detached_inventory(ent._inv_id)
|
||||
ent._inv = nil
|
||||
@ -108,7 +113,11 @@ function mcl_entity_invs.show_inv_form(ent,player,text)
|
||||
|
||||
local playername = player:get_player_name()
|
||||
|
||||
minetest.show_formspec(playername, ent._inv_id, load_default_formspec (ent, text))
|
||||
-- Workaround: wait at least 50ms to ensure that the detached inventory exists before
|
||||
-- the formspec attempts to use it. (See https://git.minetest.land/VoxeLibre/VoxeLibre/issues/4670#issuecomment-84875)
|
||||
minetest.after(0.05, function()
|
||||
minetest.show_formspec(playername, ent._inv_id, load_default_formspec (ent, text))
|
||||
end)
|
||||
end
|
||||
|
||||
local function drop_inv(ent)
|
||||
|
@ -1,3 +1,3 @@
|
||||
name = mcl_entity_invs
|
||||
author = cora
|
||||
depends = mcl_formspec
|
||||
depends = mcl_formspec, vl_legacy
|
||||
|
@ -91,7 +91,7 @@ minetest.register_entity(":__builtin:falling_node", {
|
||||
get_staticdata = function(self)
|
||||
local meta = self.meta
|
||||
-- Workaround: Save inventory seperately from metadata.
|
||||
-- Because Minetest crashes when a node with inventory gets deactivated
|
||||
-- Because Luanti crashes when a node with inventory gets deactivated
|
||||
-- (GitHub issue #7020).
|
||||
-- FIXME: Remove the _inv workaround when it is no longer needed
|
||||
local inv
|
||||
|
@ -0,0 +1,3 @@
|
||||
# textdomain: mcl_falling_nodes
|
||||
@1 was smashed by a falling anvil.=@1 wurde von einem herabfallenden Amboss erschlagen
|
||||
@1 was smashed by a falling block.=@1 wurde von einem herabfallenden Block erschlagen.
|
@ -0,0 +1,3 @@
|
||||
# textdomain: mcl_falling_nodes
|
||||
@1 was smashed by a falling anvil.=Un'incudine caduta ha schiacciato @1.
|
||||
@1 was smashed by a falling block.=Un blocco caduto ha schiacciato @1.
|
@ -0,0 +1,3 @@
|
||||
# textdomain: mcl_falling_nodes
|
||||
@1 was smashed by a falling anvil.=@1 ble knust av en fallende ambolt
|
||||
@1 was smashed by a falling block.=@1 ble knust av en fallende blokk
|
@ -0,0 +1,3 @@
|
||||
# textdomain: mcl_falling_nodes
|
||||
@1 was smashed by a falling anvil.=@1 被落下的铁砧砸得粉碎。
|
||||
@1 was smashed by a falling block.=@1 被落下的石块砸碎了。
|
@ -1,8 +1,8 @@
|
||||
===ITEM_DROP MOD for MINETEST-C55===
|
||||
===ITEM_DROP MOD for Luanti===
|
||||
by PilzAdam
|
||||
|
||||
Introduction:
|
||||
This mod adds Minecraft like drop/pick up of items to Minetest.
|
||||
This mod adds Minecraft like drop/pick up of items to Luanti.
|
||||
|
||||
This mod has been forked from item_drop in the VoxBox game.
|
||||
|
||||
@ -11,7 +11,7 @@ Sourcecode: WTFPL (see below)
|
||||
Sound: WTFPL (see below)
|
||||
|
||||
See also:
|
||||
http://minetest.net/
|
||||
https://www.luanti.org/
|
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
Version 2, December 2004
|
||||
@ -31,4 +31,4 @@ http://minetest.net/
|
||||
|
||||
Alterations and contributions are released under GNU GPLv3 after 11/11/2022 and for contributors:
|
||||
|
||||
AncientMariner/ancientmarinerdev
|
||||
AncientMariner/ancientmarinerdev
|
||||
|
@ -136,6 +136,7 @@ local function try_object_pickup(player, inv, object, checkpos)
|
||||
-- Destroy entity
|
||||
-- This just prevents this section to be run again because object:remove() doesn't remove the item immediately.
|
||||
le.target = checkpos
|
||||
le.itemstring = ""
|
||||
le._removed = true
|
||||
|
||||
-- Stop the object
|
||||
@ -317,9 +318,15 @@ function minetest.handle_node_drops(pos, drops, digger)
|
||||
end
|
||||
end
|
||||
|
||||
if tool and nodedef._mcl_fortune_drop and enchantments.fortune then
|
||||
-- Special node drops (crushing) when digging with a hammer
|
||||
local hammer = tooldef and tooldef.groups.hammer
|
||||
if hammer and hammer > 0 and nodedef._vl_crushing_drop then
|
||||
drops = nodedef._vl_crushing_drop
|
||||
-- Fortune drops
|
||||
elseif tool and nodedef._mcl_fortune_drop and enchantments.fortune then
|
||||
local fortune_level = enchantments.fortune
|
||||
local fortune_drop = nodedef._mcl_fortune_drop
|
||||
local simple_drop = nodedef._mcl_fortune_drop.drop_without_fortune
|
||||
if fortune_drop.discrete_uniform_distribution then
|
||||
local min_count = fortune_drop.min_count
|
||||
local max_count = fortune_drop.max_count + fortune_level * (fortune_drop.factor or 1)
|
||||
@ -335,6 +342,12 @@ function minetest.handle_node_drops(pos, drops, digger)
|
||||
local drop = get_fortune_drops(fortune_drop, fortune_level)
|
||||
drops = get_drops(drop, tool:get_name(), dug_node.param2, nodedef.paramtype2)
|
||||
end
|
||||
|
||||
if simple_drop then
|
||||
for _, item in pairs(simple_drop) do
|
||||
table.insert(drops, item)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if digger and mcl_experience.throw_xp and not silk_touch_drop then
|
||||
@ -376,7 +389,7 @@ function minetest.handle_node_drops(pos, drops, digger)
|
||||
end
|
||||
end
|
||||
|
||||
-- the following code is pulled from Minetest builtin without changes except for the call order being changed,
|
||||
-- the following code is pulled from Luanti builtin without changes except for the call order being changed,
|
||||
-- until a comment saying explicitly it's the end of such code
|
||||
-- TODO if this gets a fix in the engine, remove the block of code
|
||||
local function user_name(user)
|
||||
@ -490,7 +503,7 @@ function minetest.node_dig(pos, node, digger)
|
||||
|
||||
return true
|
||||
end
|
||||
-- end of code pulled from Minetest
|
||||
-- end of code pulled from Luanti
|
||||
|
||||
-- Drop single items by default
|
||||
function minetest.item_drop(itemstack, dropper, pos)
|
||||
@ -832,6 +845,7 @@ minetest.register_entity(":__builtin:item", {
|
||||
_insta_collect = self._insta_collect,
|
||||
_flowing = self._flowing,
|
||||
_removed = self._removed,
|
||||
_immortal = self._immortal,
|
||||
})
|
||||
-- sfan5 guessed that the biggest serializable item
|
||||
-- entity would have a size of 65530 bytes. This has
|
||||
@ -884,6 +898,7 @@ minetest.register_entity(":__builtin:item", {
|
||||
self._insta_collect = data._insta_collect
|
||||
self._flowing = data._flowing
|
||||
self._removed = data._removed
|
||||
self._immortal = data._immortal
|
||||
end
|
||||
else
|
||||
self.itemstring = staticdata
|
||||
@ -957,6 +972,7 @@ minetest.register_entity(":__builtin:item", {
|
||||
self.random_velocity = 0
|
||||
self:set_item(own_stack:to_string())
|
||||
|
||||
entity.itemstring = ""
|
||||
entity._removed = true
|
||||
object:remove()
|
||||
return true
|
||||
@ -976,7 +992,7 @@ minetest.register_entity(":__builtin:item", {
|
||||
if self._collector_timer then
|
||||
self._collector_timer = self._collector_timer + dtime
|
||||
end
|
||||
if time_to_live > 0 and self.age > time_to_live then
|
||||
if time_to_live > 0 and ( self.age > time_to_live and not self._immortal ) then
|
||||
self._removed = true
|
||||
self.object:remove()
|
||||
return
|
||||
|
284
mods/ENTITIES/mcl_minecarts/API.md
Normal file
284
mods/ENTITIES/mcl_minecarts/API.md
Normal file
@ -0,0 +1,284 @@
|
||||
# Table of Contents
|
||||
1. [Useful Constants](#useful-constants)
|
||||
2. [Rail](#rail)
|
||||
1. [Constants](#constants)
|
||||
2. [Functions](#functions)
|
||||
3. [Node Definition Options](#node-definition-options)
|
||||
3. [Cart Functions](#cart-functions)
|
||||
4. [Cart Data Functions](#cart-data-functions)
|
||||
5. [Cart-Node Interactions](#cart-node-interactions)
|
||||
6. [Train Functions](#train-functions)
|
||||
|
||||
## Useful Constants
|
||||
|
||||
- `mcl_minecarts.north`
|
||||
- `mcl_minecarts.south`
|
||||
- `mcl_minecarts.east`
|
||||
- `mcl_minecarts.west`
|
||||
|
||||
Human-readable names for the cardinal directions.
|
||||
|
||||
- `mcl_minecarts.SPEED_MAX`
|
||||
|
||||
Maximum speed that minecarts will be accelerated to with powered rails, in blocks per
|
||||
second. Defined as 10 blocks/second.
|
||||
|
||||
- `mcl_minecarts.CART_BLOCKS_SIZE`
|
||||
|
||||
The size of blocks to use when searching for carts to respawn. Defined as is 64 blocks.
|
||||
|
||||
- `mcl_minecarts.FRICTION`
|
||||
|
||||
Rail friction. Defined as is 0.4 blocks/second^2.
|
||||
|
||||
- `mcl_minecarts.MAX_TRAIN_LENGTH`
|
||||
|
||||
The maximum number of carts that can be in a single train. Defined as 4 carts.
|
||||
|
||||
- `mcl_minecarts.PASSENGER_ATTACH_POSITION`
|
||||
|
||||
Where to attach passengers to the minecarts.
|
||||
|
||||
## Rail
|
||||
|
||||
### Constants
|
||||
|
||||
`mcl_minecarts.HORIZONTAL_CURVES_RULES`
|
||||
`mcl_minecarts.HORIZONTAL_STANDARD_RULES`
|
||||
|
||||
Rail connection rules. Each rule is a table with the following indexes:
|
||||
|
||||
1. `node_name_suffix` - The suffix added to a node's `_mcl_minecarts.base_name` to
|
||||
get the name of the node to use for this connection.
|
||||
2. `param2_value` - The value of the node's param2. Used to specify rotation.
|
||||
|
||||
and the following named options:
|
||||
|
||||
- `mask` - Directional connections mask
|
||||
- `score` - priority of the rule. If more than one rule matches, the one with the
|
||||
highest store is selected.
|
||||
- `can_slope` - true if the result of this rule can be converted into a slope.
|
||||
|
||||
`mcl_minecarts.RAIL_GROUPS.STANDARD`
|
||||
`mcl_minecarts.RAIL_GROUPS.CURVES`
|
||||
|
||||
These constants are used to specify a rail node's `group.rail` value.
|
||||
|
||||
### Functions
|
||||
|
||||
`mcl_minecarts.get_rail_connections(node_position, options)`
|
||||
|
||||
Calculate the rail adjacency information for rail placement. Arguments are:
|
||||
|
||||
- `node_position` - the location of the node to calculate adjacency for.
|
||||
- `options` - A table containing any of these options:
|
||||
- `legacy`- if true, don't check that a connection proceeds out in a direction
|
||||
a cart can travel. Used for converting legacy rail to newer equivalents.
|
||||
- `ignore_neightbor_connections` - if true, don't check that a cart could leave
|
||||
the neighboring node from this direction.
|
||||
|
||||
`mcl_minecarts.is_rail(position, railtype)`
|
||||
|
||||
Determines if the node at `position` is a rail. If `railtype` is provided,
|
||||
determine if the node at `position` is that type of rail.
|
||||
|
||||
`mcl_minecarts.register_rail(itemstring, node_definition)`
|
||||
|
||||
Registers a rail with a few sensible defaults and if a craft recipe was specified,
|
||||
register that as well.
|
||||
|
||||
`mcl_minecarts.register_straight_rail(base_name, tiles, node_definition)`
|
||||
|
||||
Registers a rail with only straight and sloped variants.
|
||||
|
||||
`mcl_minecarts.register_curves_rail(base_name, tiles, node_definition)`
|
||||
|
||||
Registers a rail with straight, sloped, curved, tee and cross variants.
|
||||
|
||||
`mcl_minecarts.update_rail_connections(node_position, options)`
|
||||
|
||||
Converts the rail at `node_position`, if possible, another variant (curve, etc.)
|
||||
and rotates the node as needed so that rails connect together. `options` is
|
||||
passed thru to `mcl_minecarts.get_rail_connections()`
|
||||
|
||||
`mcl_minecarts.get_rail_direction(rail_position, cart_direction)`
|
||||
|
||||
Returns the next direction a cart traveling in the direction specified in `cart_direction`
|
||||
will travel from the rail located at `rail_position`.
|
||||
|
||||
### Node Definition Options
|
||||
|
||||
`_mcl_minecarts.railtype`
|
||||
|
||||
This declares the variant type of the rail. This will be one of the following:
|
||||
|
||||
- "straight" - two connections opposite each other and no vertical change.
|
||||
- "sloped" - two connections opposite each other with one of these connections
|
||||
one block higher.
|
||||
- "corner" - two connections at 90 degrees from each other.
|
||||
- "tee" - three connections
|
||||
- "cross" - four connections allowing only straight-thru movement
|
||||
|
||||
#### Hooks
|
||||
`_mcl_minecarts.get_next_dir = function(node_position, current_direction, node)`
|
||||
|
||||
Called to get the next direction a cart will travel after passing thru this node.
|
||||
|
||||
## Cart Functions
|
||||
|
||||
`mcl_minecarts.attach_driver(cart, player)`
|
||||
|
||||
This attaches (ObjectRef) `player` to the (LuaEntity) `cart`.
|
||||
|
||||
`mcl_minecarts.detach_minecart(cart_data)`
|
||||
|
||||
This detaches a minecart from any rail it is attached to and makes it start moving
|
||||
as an entity affected by gravity. It will keep moving in the same direction and
|
||||
at the same speed it was moving at before it detaches.
|
||||
|
||||
`mcl_minecarts.get_cart_position(cart_data)`
|
||||
|
||||
Compute the location of a minecart from its cart data. This works even when the entity
|
||||
is unloaded.
|
||||
|
||||
`mcl_minecarts.kill_cart(cart_data)`
|
||||
|
||||
Kills a cart and drops it as an item, even if the cart entity is unloaded.
|
||||
|
||||
`mcl_minecarts.place_minecart(itemstack, pointed_thing, placer)`
|
||||
|
||||
Places a minecart at the location specified by `pointed_thing`
|
||||
|
||||
`mcl_minecarts.register_minecart(minecart_definition)`
|
||||
|
||||
Registers a minecart. `minecart_definition` defines the entity. All the options supported by
|
||||
normal minetest entities are supported, with a few additions:
|
||||
|
||||
- `craft` - Crafting recipe for this cart.
|
||||
- `drop` - List of items to drop when the cart is killed. (required)
|
||||
- `entity_id` - The entity id of the cart. (required)
|
||||
- `itemstring` - This is the itemstring to use for this entity. (required)
|
||||
|
||||
`mcl_minecarts.reverse_cart_direction(cart_data)`
|
||||
|
||||
Force a minecart to start moving in the opposite direction of its current direction.
|
||||
|
||||
`mcl_minecarts.snap_direction(direction_vector)`
|
||||
|
||||
Returns a valid cart movement direction that has the smallest angle between it and `direction_vector`.
|
||||
|
||||
`mcl_minecarts.update_cart_orientation(cart)`
|
||||
|
||||
Updates the rotation of a cart entity to match the cart's data.
|
||||
|
||||
## Cart Data Functions
|
||||
|
||||
`mcl_minecarts.destroy_cart_data(uuid)`
|
||||
|
||||
Destroys the data for the cart with the identitfier in `uuid`.
|
||||
|
||||
`mcl_minecarts.find_carts_by_block_map(block_map)`
|
||||
|
||||
Returns a list of cart data for carts located in the blocks specified in `block_map`. Used
|
||||
to respawn carts entering areas around players.
|
||||
|
||||
`mcl_minecarts.add_blocks_to_map(block_map, min_pos, max_pos)`
|
||||
|
||||
Add blocks that fully contain `min_pos` and `max_pos` to `block_map` for use by
|
||||
`mcl_minecarts.find_cart_by_block_map`.
|
||||
|
||||
`mcl_minecarts.get_cart_data(uuid)`
|
||||
|
||||
Loads the data for the cart with the identitfier in `uuid`.
|
||||
|
||||
`mcl_minecarts.save_cart_data(uuid)`
|
||||
|
||||
Saves the data for the cart with the identifier in `uuid`.
|
||||
|
||||
`mcl_minecart.update_cart_data(data)`
|
||||
|
||||
Replaces the cart data for the cart with the identifier in `data.uuid`, then saves
|
||||
the data.
|
||||
|
||||
## Cart-Node Interactions
|
||||
|
||||
As the cart moves thru the environment, it can interact with the surrounding blocks
|
||||
thru a number of handlers in the block definitions. All these handlers are defined
|
||||
as:
|
||||
|
||||
`function(node_position, cart_luaentity, cart_direction, cart_position)`
|
||||
|
||||
Arguments:
|
||||
- `node_position` - position of the node the cart is interacting with
|
||||
- `cart_luaentity` - The luaentity of the cart that is entering this block. Will
|
||||
be nil for minecarts moving thru unloaded blocks
|
||||
- `cart_direction` - The direction the cart is moving
|
||||
- `cart_position` - The location of the cart
|
||||
- `cart_data` - Information about the cart. This will always be defined.
|
||||
|
||||
There are several variants of this handler:
|
||||
- `_mcl_minecarts_on_enter` - The cart enters this block
|
||||
- `_mcl_minecarts_on_enter_below` - The cart enters above this block
|
||||
- `_mcl_minecarts_on_enter_above` - The cart enters below this block
|
||||
- `_mcl_minecarts_on_enter_side` - The cart enters beside this block
|
||||
|
||||
Mods can also define global handlers that are called for every node. These
|
||||
handlers are defined as:
|
||||
|
||||
`function(node_position, cart_luaentity, cart_direction, node_definition, cart_data)`
|
||||
|
||||
Arguments:
|
||||
- `node_position` - position of the node the cart is interacting with
|
||||
- `cart_luaentity` - The luaentity of the cart that is entering this block. Will
|
||||
be nil for minecarts moving thru unloaded blocks
|
||||
- `cart_direction` - The direction the cart is moving
|
||||
- `cart_position` - The location of the cart
|
||||
- `cart_data` - Information about the cart. This will always be defined.
|
||||
- `node_definition` - The definition of the node at `node_position`
|
||||
|
||||
The available hooks are:
|
||||
- `_mcl_minecarts.on_enter` - The cart enters this block
|
||||
- `_mcl_minecarts.on_enter_below` - The cart enters above this block
|
||||
- `_mcl_minecarts.on_enter_above` - The cart enters below this block
|
||||
- `_mcl_minecarts.on_enter_side` - The cart enters beside this block
|
||||
|
||||
Only a single function can be installed in each of these handlers. Before installing,
|
||||
preserve the existing handler and call it from inside your handler if not `nil`.
|
||||
|
||||
## Train Functions
|
||||
|
||||
`mcl_minecarts.break_train_at(cart_data)`
|
||||
|
||||
Splits a train apart at the specified cart.
|
||||
|
||||
`mcl_minecarts.distance_between_cars(cart1_data, cart2_data)`
|
||||
|
||||
Returns the distance between two carts even if both entities are unloaded, or nil if either
|
||||
cart is not on a rail.
|
||||
|
||||
`mcl_minecarts.is_in_same_train(cart1_data, cart2_data)`
|
||||
|
||||
Returns true if cart1 and cart2 are a part of the same train and false otherwise.
|
||||
|
||||
`mcl_minecarts.link_cart_ahead(cart_data, cart_ahead_data)`
|
||||
|
||||
Given two carts, link them together into a train, with the second cart ahead of the first.
|
||||
|
||||
`mcl_minecarts.train_cars(cart_data)`
|
||||
|
||||
Use to iterate over all carts in a train. Expected usage:
|
||||
|
||||
`for cart in mcl_minecarts.train_cars(cart) do --[[ code ]] end`
|
||||
|
||||
`mcl_minecarts.reverse_train(cart)`
|
||||
|
||||
Make all carts in a train reverse and start moving in the opposite direction.
|
||||
|
||||
`mcl_minecarts.train_length(cart_data)`
|
||||
|
||||
Compute the current length of the train containing the cart whose data is `cart_data`.
|
||||
|
||||
`mcl_minecarts.update_train(cart_data)`
|
||||
|
||||
When provided with the rear-most cart of a tain, update speeds of all carts in the train
|
||||
so that it holds together and moves as a unit.
|
120
mods/ENTITIES/mcl_minecarts/DOC.md
Normal file
120
mods/ENTITIES/mcl_minecarts/DOC.md
Normal file
@ -0,0 +1,120 @@
|
||||
|
||||
## Organization
|
||||
- [ init.lua](./init.lua) - module entrypoint. The other files are included from here
|
||||
and several constants are defined here
|
||||
|
||||
- [carts.lua](./carts/lua) - This file contains code related to cart entities, cart
|
||||
type registration, creation, estruction and updating. The global step function
|
||||
responsible for updating attached carts is in this file. The various carts are
|
||||
referenced from this file but actually reside in the subdirectory [carts/](./carts/).
|
||||
|
||||
- [functions.lua](./functions.lua) - This file contains various minecart and rail
|
||||
utility functions used by the rest of the code.
|
||||
|
||||
- [movement.lua](./movement.lua) - This file contains the code related to cart
|
||||
movement physics.
|
||||
|
||||
- [rails.lua](./rails.lua) - This file contains code related to rail registation,
|
||||
placement, connection rules and cart direction selection. This contains the rail
|
||||
behaviors and the LBM code for updating legacy rail nodes to the new versions
|
||||
that don't use the raillike draw type.
|
||||
|
||||
- [storage.lua](./storage.lua) - This file contains the code than manages minecart
|
||||
state data to allow processing minecarts while entities are unloaded.
|
||||
|
||||
- [train.lua](./train.lua) - This file contains code related to multi-car trains.
|
||||
|
||||
## Rail Nodes
|
||||
|
||||
Previous versions of mcl\_minecarts used one node type for each rail type (standard,
|
||||
powered, detector and activator) using the raillike draw type that minetest provides.
|
||||
This version does not use the raillike draw type and instead uses a 1/16th of a block
|
||||
high nodebox and uses an additional node definition for each variant. The variants
|
||||
present are:
|
||||
|
||||
- straight
|
||||
- sloped
|
||||
- corner
|
||||
- tee
|
||||
- cross
|
||||
|
||||
Of the rail types provided by this module, standard has all of these variants. The
|
||||
remaining types only have straight and sloped variants.
|
||||
|
||||
Unlike the old rail type, this version will only update connections when placed, and
|
||||
will only place a variant that already has connections into the space the rail is
|
||||
being placed. Here is how to create the various varients:
|
||||
|
||||
- Straight rail is placed when with zero or one adjacent rail nodes. If no rails
|
||||
are adjacent, the rail is placed in line with the direction the player is facing.
|
||||
If there is exactly one adjacent rail present, the straight rail will always rotate
|
||||
to connect to it.
|
||||
|
||||
- Sloped rail is placed when there are two rails in a straight line, with one being
|
||||
one block higher. When rail is placed adjacent to a straight rail one block lower
|
||||
and the rail is facing the block the rail is being placed on, the lower rail will
|
||||
convert into a slope.
|
||||
|
||||
- A corner rail is placed when there are exactly two adjacent rails that are not in
|
||||
a line and lead into the space the rail is being placed. The corner will be rotated
|
||||
to connect these two rails.
|
||||
|
||||
- A tee rail is placed where there are exactly three rails adjact and those existing
|
||||
rails lead into the the space the new rail is being placed.
|
||||
|
||||
- A rail cross is placed when there is rail in all four adjacent blocks and they all
|
||||
have a path into the space the new rail is being placed.
|
||||
|
||||
The tee variant will interact with redstone and mesecons to switch the curved section.
|
||||
|
||||
## On-rail Minecart Movement
|
||||
|
||||
Minecart movement is handled in two distinct regimes: on a rail and off. The
|
||||
off-rail movement is handled with minetest's builtin entity movement handling.
|
||||
The on-rail movement is handled with a custom algorithm. This section details
|
||||
the latter.
|
||||
|
||||
The data for on-rail minecart movement is stored entirely inside mod storage
|
||||
and indexed by a hex-encoded 128-bit universally-unique identifier (uuid). Minecart
|
||||
entities store this uuid and a sequence identifier. The code for handling this
|
||||
storage is in [storage.lua](./storage.lua). This was done so that minecarts can
|
||||
still move while no players are connected or when out of range of players. Inspiration
|
||||
for this was the [Advanced Trains mod](http://advtrains.de/). This is a behavior difference
|
||||
when compared to minecraft, as carts there will stop movement when out of range of
|
||||
players.
|
||||
|
||||
Processing for minecart movement is as follows:
|
||||
1. In a globalstep handler in [carts.lua](./carts.lua), determine which carts are
|
||||
moving.
|
||||
2. Call `do_movement` in [movement.lua](./movement.lua) to update
|
||||
each cart's location and handle interactions with the environment.
|
||||
1. Each movement is broken up into one or more steps that are completely
|
||||
contained inside a block. This prevents carts from ever jumping from
|
||||
one rail to another over a gap or thru solid blocks because of server
|
||||
lag. Each step is processed with `do_movement_step`
|
||||
2. Each step uses physically accurate, timestep-independent physics
|
||||
to move the cart. Calculating the acceleration to apply to a cart
|
||||
is broken out into its own function (`calculate_acceperation`).
|
||||
3. As the cart enters and leaves blocks, handlers in nearby blocks are called
|
||||
to allow the cart to efficiently interact with the environment. Handled by
|
||||
the functions `handle_cart_enter` and `handle_cart_leave`
|
||||
4. The cart checks for nearby carts and collides elastically with these. The
|
||||
calculations for these collisions are in the function `handle_cart_collision`
|
||||
5. If the cart enters a new block, determine the new direction the cart will
|
||||
move with `mcl_minecarts:get_rail_direction` in [functions.lua](./functions.lua).
|
||||
The rail nodes provide a hook `_mcl_minecarts.get_next_direction` that
|
||||
provides this information based on the previous movement direction.
|
||||
3. If an entity exists for a given cart, the entity will update its position
|
||||
while loaded in.
|
||||
|
||||
Cart movement when on a rail occurs regarless of whether an entity for that
|
||||
cart exists or is loaded into memory. As a consequence of this movement, it
|
||||
is possible for carts with unloaded entities to enter range of a player.
|
||||
To handle this, periodic checks are performed around players and carts that
|
||||
are within range but don't have a cart have a new entity spawned.
|
||||
|
||||
Every time a cart has a new entity spawned, it increases a sequence number in
|
||||
the cart data to allow removing old entities from the minetest engine. Any cart
|
||||
entity that does not have the current sequence number for a minecart gets removed
|
||||
once processing for that entity resumes.
|
||||
|
@ -10,6 +10,7 @@ MIT License
|
||||
Copyright (C) 2012-2016 PilzAdam
|
||||
Copyright (C) 2014-2016 SmallJoker
|
||||
Copyright (C) 2012-2016 Various Minetest developers and contributors
|
||||
Copyright (C) 2024 teknomunk
|
||||
|
||||
Authors/licenses of media files:
|
||||
-----------------------
|
||||
|
695
mods/ENTITIES/mcl_minecarts/carts.lua
Normal file
695
mods/ENTITIES/mcl_minecarts/carts.lua
Normal file
@ -0,0 +1,695 @@
|
||||
local modname = minetest.get_current_modname()
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
local mod = mcl_minecarts
|
||||
local S = minetest.get_translator(modname)
|
||||
|
||||
local mcl_log,DEBUG = mcl_util.make_mcl_logger("mcl_logging_minecarts", "Minecarts")
|
||||
|
||||
-- Imports
|
||||
local CART_BLOCK_SIZE = mod.CART_BLOCK_SIZE
|
||||
local table_merge = mcl_util.table_merge
|
||||
local get_cart_data = mod.get_cart_data
|
||||
local save_cart_data = mod.save_cart_data
|
||||
local update_cart_data = mod.update_cart_data
|
||||
local destroy_cart_data = mod.destroy_cart_data
|
||||
local find_carts_by_block_map = mod.find_carts_by_block_map
|
||||
local movement = dofile(modpath.."/movement.lua")
|
||||
assert(movement.do_movement)
|
||||
assert(movement.do_detached_movement)
|
||||
assert(movement.handle_cart_enter)
|
||||
|
||||
-- Constants
|
||||
local max_step_distance = 0.5
|
||||
local MINECART_MAX_HP = 4
|
||||
local TWO_OVER_PI = 2 / math.pi
|
||||
|
||||
local function detach_driver(self)
|
||||
local staticdata = self._staticdata
|
||||
|
||||
if not self._driver then
|
||||
return
|
||||
end
|
||||
|
||||
-- Update player infomation
|
||||
local driver_name = self._driver
|
||||
local playerinfo = mcl_playerinfo[driver_name]
|
||||
if playerinfo then
|
||||
playerinfo.attached_to = nil
|
||||
end
|
||||
mcl_player.player_attached[driver_name] = nil
|
||||
|
||||
minetest.log("action", driver_name.." left a minecart")
|
||||
|
||||
-- Update cart informatino
|
||||
self._driver = nil
|
||||
self._start_pos = nil
|
||||
local player_meta = mcl_playerinfo.get_mod_meta(driver_name, modname)
|
||||
player_meta.attached_to = nil
|
||||
|
||||
-- Detatch the player object from the minecart
|
||||
local player = minetest.get_player_by_name(driver_name)
|
||||
if player then
|
||||
local dir = staticdata.dir or vector.new(1,0,0)
|
||||
local cart_pos = mod.get_cart_position(staticdata) or self.object:get_pos()
|
||||
local new_pos = vector.offset(cart_pos, -dir.z, 0, dir.x)
|
||||
player:set_detach()
|
||||
--print("placing player at "..tostring(new_pos).." from cart at "..tostring(cart_pos)..", old_pos="..tostring(player:get_pos()).."dir="..tostring(dir))
|
||||
|
||||
-- There needs to be a delay here or the player's position won't update
|
||||
minetest.after(0.1,function(driver_name,new_pos)
|
||||
local player = minetest.get_player_by_name(driver_name)
|
||||
player:moveto(new_pos, false)
|
||||
end, driver_name, new_pos)
|
||||
|
||||
player:set_eye_offset(vector.zero(),vector.zero())
|
||||
mcl_player.player_set_animation(player, "stand" , 30)
|
||||
--else
|
||||
--print("No player object found for "..driver_name)
|
||||
end
|
||||
end
|
||||
mod.detach_driver = detach_driver
|
||||
|
||||
function mod.kill_cart(staticdata, killer)
|
||||
local pos
|
||||
mcl_log("cart #"..staticdata.uuid.." was killed")
|
||||
|
||||
-- Leave nodes
|
||||
if staticdata.attached_at then
|
||||
handle_cart_leave(self, staticdata.attached_at, staticdata.dir )
|
||||
else
|
||||
--mcl_log("TODO: handle detatched minecart death")
|
||||
end
|
||||
|
||||
-- Handle entity-related items
|
||||
local le = mcl_util.get_luaentity_from_uuid(staticdata.uuid)
|
||||
if le then
|
||||
pos = le.object:get_pos()
|
||||
|
||||
detach_driver(le)
|
||||
|
||||
-- Detach passenger
|
||||
if le._passenger then
|
||||
local mob = le._passenger.object
|
||||
mob:set_detach()
|
||||
end
|
||||
|
||||
-- Remove the entity
|
||||
le.object:remove()
|
||||
else
|
||||
pos = mod.get_cart_position(staticdata)
|
||||
end
|
||||
|
||||
-- Drop items
|
||||
if not staticdata.dropped then
|
||||
-- Try to drop the cart
|
||||
local entity_def = minetest.registered_entities[staticdata.cart_type]
|
||||
if entity_def then
|
||||
local drop_cart = true
|
||||
if killer and minetest.is_creative_enabled(killer:get_player_name()) then
|
||||
drop_cart = false
|
||||
end
|
||||
|
||||
if drop_cart then
|
||||
local drop = entity_def.drop
|
||||
for d=1, #drop do
|
||||
minetest.add_item(pos, drop[d])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Drop any items in the inventory
|
||||
local inventory = staticdata.inventory
|
||||
if inventory then
|
||||
for i=1,#inventory do
|
||||
minetest.add_item(pos, inventory[i])
|
||||
end
|
||||
end
|
||||
|
||||
-- Prevent item duplication
|
||||
staticdata.dropped = true
|
||||
end
|
||||
|
||||
-- Remove data
|
||||
destroy_cart_data(staticdata.uuid)
|
||||
end
|
||||
local kill_cart = mod.kill_cart
|
||||
|
||||
|
||||
-- Table for item-to-entity mapping. Keys: itemstring, Values: Corresponding entity ID
|
||||
local entity_mapping = {}
|
||||
|
||||
local function make_staticdata( _, connected_at, dir )
|
||||
return {
|
||||
connected_at = connected_at,
|
||||
distance = 0,
|
||||
velocity = 0,
|
||||
dir = vector.new(dir),
|
||||
mass = 1,
|
||||
seq = 1,
|
||||
}
|
||||
end
|
||||
|
||||
local DEFAULT_CART_DEF = {
|
||||
initial_properties = {
|
||||
physical = true,
|
||||
collisionbox = {-10/16., -0.5, -10/16, 10/16, 0.25, 10/16},
|
||||
visual = "mesh",
|
||||
visual_size = {x=1, y=1},
|
||||
},
|
||||
|
||||
hp_max = MINECART_MAX_HP,
|
||||
|
||||
groups = {
|
||||
minecart = 1,
|
||||
},
|
||||
|
||||
_driver = nil, -- player who sits in and controls the minecart (only for minecart!)
|
||||
_passenger = nil, -- for mobs
|
||||
_start_pos = nil, -- Used to calculate distance for “On A Rail” achievement
|
||||
_last_float_check = nil, -- timestamp of last time the cart was checked to be still on a rail
|
||||
_boomtimer = nil, -- how many seconds are left before exploding
|
||||
_blinktimer = nil, -- how many seconds are left before TNT blinking
|
||||
_blink = false, -- is TNT blink texture active?
|
||||
_old_pos = nil,
|
||||
_staticdata = nil,
|
||||
}
|
||||
function DEFAULT_CART_DEF:on_activate(staticdata, dtime_s)
|
||||
-- Transfer older data
|
||||
local data = minetest.deserialize(staticdata) or {}
|
||||
if not data.uuid then
|
||||
data.uuid = mcl_util.assign_uuid(self.object)
|
||||
|
||||
if data._items then
|
||||
data.inventory = data._items
|
||||
data._items = nil
|
||||
data._inv_id = nil
|
||||
data._inv_size = nil
|
||||
end
|
||||
end
|
||||
self._seq = data.seq or 1
|
||||
|
||||
local cd = get_cart_data(data.uuid)
|
||||
if not cd then
|
||||
update_cart_data(data)
|
||||
else
|
||||
if not cd.seq then cd.seq = 1 end
|
||||
data = cd
|
||||
end
|
||||
|
||||
-- Fix up types
|
||||
data.dir = vector.new(data.dir)
|
||||
|
||||
-- Fix mass
|
||||
data.mass = data.mass or 1
|
||||
|
||||
-- Make sure all carts have an ID to isolate them
|
||||
self._uuid = data.uuid
|
||||
self._staticdata = data
|
||||
|
||||
-- Activate cart if on powered activator rail
|
||||
if self.on_activate_by_rail then
|
||||
local pos = self.object:get_pos()
|
||||
local node = minetest.get_node(vector.floor(pos))
|
||||
if node.name == "mcl_minecarts:activator_rail_on" then
|
||||
self:on_activate_by_rail()
|
||||
end
|
||||
end
|
||||
end
|
||||
function DEFAULT_CART_DEF:get_staticdata()
|
||||
save_cart_data(self._staticdata.uuid)
|
||||
return minetest.serialize({uuid = self._staticdata.uuid, seq=self._seq})
|
||||
end
|
||||
|
||||
function DEFAULT_CART_DEF:_mcl_entity_invs_load_items()
|
||||
local staticdata = self._staticdata
|
||||
return staticdata.inventory or {}
|
||||
end
|
||||
function DEFAULT_CART_DEF:_mcl_entity_invs_save_items(items)
|
||||
local staticdata = self._staticdata
|
||||
staticdata.inventory = table.copy(items)
|
||||
end
|
||||
|
||||
function DEFAULT_CART_DEF:add_node_watch(pos)
|
||||
local staticdata = self._staticdata
|
||||
local watches = staticdata.node_watches or {}
|
||||
|
||||
for i=1,#watches do
|
||||
if watches[i] == pos then return end
|
||||
end
|
||||
|
||||
watches[#watches+1] = pos
|
||||
staticdata.node_watches = watches
|
||||
end
|
||||
function DEFAULT_CART_DEF:remove_node_watch(pos)
|
||||
local staticdata = self._staticdata
|
||||
local watches = staticdata.node_watches or {}
|
||||
|
||||
local new_watches = {}
|
||||
for i=1,#watches do
|
||||
local node_pos = watches[i]
|
||||
if node_pos ~= pos then
|
||||
new_watches[#new_watches + 1] = node_pos
|
||||
end
|
||||
end
|
||||
staticdata.node_watches = new_watches
|
||||
end
|
||||
function DEFAULT_CART_DEF:get_cart_position()
|
||||
local staticdata = self._staticdata
|
||||
|
||||
if staticdata.connected_at then
|
||||
return staticdata.connected_at + staticdata.dir * staticdata.distance
|
||||
else
|
||||
return self.object:get_pos()
|
||||
end
|
||||
end
|
||||
function DEFAULT_CART_DEF:on_punch(puncher, time_from_last_punch, tool_capabilities, dir, damage)
|
||||
if puncher == self._driver then return end
|
||||
|
||||
local staticdata = self._staticdata
|
||||
|
||||
if puncher:get_player_control().sneak then
|
||||
mod.kill_cart(staticdata, puncher)
|
||||
return
|
||||
end
|
||||
|
||||
local controls = staticdata.controls or {}
|
||||
dir.y = 0
|
||||
dir = vector.normalize(dir)
|
||||
local impulse = vector.dot(staticdata.dir, vector.multiply(dir, damage * 4))
|
||||
if impulse < 0 and staticdata.velocity == 0 then
|
||||
mod.reverse_direction(staticdata)
|
||||
impulse = -impulse
|
||||
end
|
||||
|
||||
controls.impulse = impulse
|
||||
staticdata.controls = controls
|
||||
end
|
||||
function DEFAULT_CART_DEF:on_step(dtime)
|
||||
local staticdata = self._staticdata
|
||||
if not staticdata then
|
||||
staticdata = make_staticdata()
|
||||
self._staticdata = staticdata
|
||||
end
|
||||
if self._items then
|
||||
self._items = nil
|
||||
end
|
||||
|
||||
-- Update entity position
|
||||
local pos = mod.get_cart_position(staticdata)
|
||||
if pos then self.object:move_to(pos) end
|
||||
|
||||
-- Repair cart_type
|
||||
if not staticdata.cart_type then
|
||||
staticdata.cart_type = self.name
|
||||
end
|
||||
|
||||
-- Remove superceded entities
|
||||
if staticdata.seq and (self._seq or -1) < staticdata.seq then
|
||||
if not self._seq then
|
||||
core.log("warning", "Removing minecart entity missing sequence number")
|
||||
end
|
||||
--print("removing cart #"..staticdata.uuid.." with sequence number mismatch")
|
||||
self.object:remove()
|
||||
self._removed = true
|
||||
return
|
||||
end
|
||||
|
||||
-- Regen
|
||||
local hp = self.object:get_hp()
|
||||
local time_now = minetest.get_gametime()
|
||||
if hp < MINECART_MAX_HP and (staticdata.last_regen or 0) <= time_now - 1 then
|
||||
staticdata.last_regen = time_now
|
||||
hp = hp + 1
|
||||
self.object:set_hp(hp)
|
||||
end
|
||||
|
||||
-- Cart specific behaviors
|
||||
local hook = self._mcl_minecarts_on_step
|
||||
if hook then hook(self,dtime) end
|
||||
|
||||
if (staticdata.hopper_delay or 0) > 0 then
|
||||
staticdata.hopper_delay = staticdata.hopper_delay - dtime
|
||||
end
|
||||
|
||||
-- Controls
|
||||
local ctrl, player = nil, nil
|
||||
if self._driver then
|
||||
player = minetest.get_player_by_name(self._driver)
|
||||
if player then
|
||||
ctrl = player:get_player_control()
|
||||
-- player detach
|
||||
if ctrl.sneak then
|
||||
detach_driver(self)
|
||||
return
|
||||
end
|
||||
|
||||
-- Experimental controls
|
||||
local now_time = minetest.get_gametime()
|
||||
local controls = {}
|
||||
if ctrl.up then controls.forward = now_time end
|
||||
if ctrl.down then controls.brake = now_time end
|
||||
controls.look = math.round(player:get_look_horizontal() * TWO_OVER_PI) % 4
|
||||
staticdata.controls = controls
|
||||
end
|
||||
|
||||
-- Give achievement when player reached a distance of 1000 nodes from the start position
|
||||
if pos and vector.distance(self._start_pos, pos) >= 1000 then
|
||||
awards.unlock(self._driver, "mcl:onARail")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if not staticdata.connected_at then
|
||||
movement.do_detached_movement(self, dtime)
|
||||
else
|
||||
mod.update_cart_orientation(self)
|
||||
end
|
||||
end
|
||||
function DEFAULT_CART_DEF:on_death(killer)
|
||||
kill_cart(self._staticdata, killer)
|
||||
end
|
||||
|
||||
-- Create a minecart
|
||||
function mod.create_minecart(entity_id, pos, dir)
|
||||
-- Setup cart data
|
||||
local uuid = mcl_util.gen_uuid()
|
||||
local data = make_staticdata( nil, pos, dir )
|
||||
data.uuid = uuid
|
||||
data.cart_type = entity_id
|
||||
update_cart_data(data)
|
||||
save_cart_data(uuid)
|
||||
|
||||
return uuid
|
||||
end
|
||||
local create_minecart = mod.create_minecart
|
||||
|
||||
-- Place a minecart at pointed_thing
|
||||
function mod.place_minecart(itemstack, pointed_thing, placer)
|
||||
if not pointed_thing.type == "node" then
|
||||
return
|
||||
end
|
||||
|
||||
local look_4dir = math.round(placer:get_look_horizontal() * TWO_OVER_PI) % 4
|
||||
local look_dir = core.fourdir_to_dir(look_4dir)
|
||||
look_dir.x = -look_dir.x
|
||||
|
||||
local spawn_pos = pointed_thing.above
|
||||
local cart_dir = look_dir
|
||||
|
||||
local railpos, node
|
||||
if mcl_minecarts.is_rail(pointed_thing.under) then
|
||||
railpos = pointed_thing.under
|
||||
elseif mcl_minecarts.is_rail(pointed_thing.above) then
|
||||
railpos = pointed_thing.above
|
||||
end
|
||||
if railpos then
|
||||
spawn_pos = railpos
|
||||
node = minetest.get_node(railpos)
|
||||
|
||||
-- Try two orientations, and select the second if the first is at an angle
|
||||
cart_dir1 = mcl_minecarts.get_rail_direction(railpos, look_dir)
|
||||
cart_dir2 = mcl_minecarts.get_rail_direction(railpos, -look_dir)
|
||||
if vector.length(cart_dir1) <= 1 then
|
||||
cart_dir = cart_dir1
|
||||
else
|
||||
cart_dir = cart_dir2
|
||||
end
|
||||
end
|
||||
|
||||
-- Make sure to always go down slopes
|
||||
if cart_dir.y > 0 then cart_dir = -cart_dir end
|
||||
|
||||
local entity_id = entity_mapping[itemstack:get_name()]
|
||||
|
||||
local uuid = create_minecart(entity_id, railpos, cart_dir)
|
||||
|
||||
-- Create the entity with the staticdata already setup
|
||||
local sd = minetest.serialize({ uuid=uuid, seq=1 })
|
||||
local cart = minetest.add_entity(spawn_pos, entity_id, sd)
|
||||
local staticdata = get_cart_data(uuid)
|
||||
|
||||
cart:set_yaw(minetest.dir_to_yaw(cart_dir))
|
||||
|
||||
-- Call placer
|
||||
local le = cart:get_luaentity()
|
||||
if le._mcl_minecarts_on_place then
|
||||
le._mcl_minecarts_on_place(le, placer)
|
||||
end
|
||||
|
||||
if railpos then
|
||||
movement.handle_cart_enter(staticdata, railpos)
|
||||
end
|
||||
|
||||
local pname = placer and placer:get_player_name() or ""
|
||||
if not minetest.is_creative_enabled(pname) then
|
||||
itemstack:take_item()
|
||||
end
|
||||
return itemstack
|
||||
end
|
||||
|
||||
local function dropper_place_minecart(dropitem, pos)
|
||||
-- Don't try to place the minecart if pos isn't a rail
|
||||
local node = minetest.get_node(pos)
|
||||
if minetest.get_item_group(node.name, "rail") == 0 then return false end
|
||||
|
||||
mod.place_minecart(dropitem, {
|
||||
above = pos,
|
||||
under = vector.offset(pos,0,-1,0)
|
||||
})
|
||||
return true
|
||||
end
|
||||
|
||||
local function register_minecart_craftitem(itemstring, def)
|
||||
local groups = { minecart = 1, transport = 1 }
|
||||
if def.creative == false then
|
||||
groups.not_in_creative_inventory = 1
|
||||
end
|
||||
local item_def = {
|
||||
stack_max = 1,
|
||||
_mcl_dropper_on_drop = dropper_place_minecart,
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
if not pointed_thing.type == "node" then
|
||||
return
|
||||
end
|
||||
|
||||
-- Call on_rightclick if the pointed node defines it
|
||||
local node = minetest.get_node(pointed_thing.under)
|
||||
if placer and not placer:get_player_control().sneak then
|
||||
if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then
|
||||
return minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, placer, itemstack) or itemstack
|
||||
end
|
||||
end
|
||||
|
||||
return mod.place_minecart(itemstack, pointed_thing, placer)
|
||||
end,
|
||||
_on_dispense = function(stack, pos, droppos, dropnode, dropdir)
|
||||
-- Place minecart as entity on rail. If there's no rail, just drop it.
|
||||
local placed
|
||||
if minetest.get_item_group(dropnode.name, "rail") ~= 0 then
|
||||
-- FIXME: This places minecarts even if the spot is already occupied
|
||||
local pointed_thing = { under = droppos, above = vector.new( droppos.x, droppos.y+1, droppos.z ) }
|
||||
placed = mod.place_minecart(stack, pointed_thing)
|
||||
end
|
||||
if placed == nil then
|
||||
-- Drop item
|
||||
minetest.add_item(droppos, stack)
|
||||
end
|
||||
end,
|
||||
groups = groups,
|
||||
}
|
||||
item_def.description = def.description
|
||||
item_def._tt_help = def.tt_help
|
||||
item_def._doc_items_longdesc = def.longdesc
|
||||
item_def._doc_items_usagehelp = def.usagehelp
|
||||
item_def.inventory_image = def.icon
|
||||
item_def.wield_image = def.icon
|
||||
minetest.register_craftitem(itemstring, item_def)
|
||||
end
|
||||
|
||||
--[[
|
||||
Register a minecart
|
||||
* itemstring: Itemstring of minecart item
|
||||
* entity_id: ID of minecart entity
|
||||
* description: Item name / description
|
||||
* longdesc: Long help text
|
||||
* usagehelp: Usage help text
|
||||
* mesh: Minecart mesh
|
||||
* textures: Minecart textures table
|
||||
* icon: Item icon
|
||||
* drop: Dropped items after destroying minecart
|
||||
* on_rightclick: Called after rightclick
|
||||
* on_activate_by_rail: Called when above activator rail
|
||||
* creative: If false, don't show in Creative Inventory
|
||||
]]
|
||||
function mod.register_minecart(def)
|
||||
-- Make sure all required parameters are present
|
||||
for _,name in pairs({"drop","itemstring","entity_id"}) do
|
||||
assert( def[name], "def."..name..", a required parameter, is missing")
|
||||
end
|
||||
|
||||
local entity_id = def.entity_id; def.entity_id = nil
|
||||
local craft = def.craft; def.craft = nil
|
||||
local itemstring = def.itemstring; def.itemstring = nil
|
||||
|
||||
-- Build cart definition
|
||||
local cart = table.copy(DEFAULT_CART_DEF)
|
||||
table_merge(cart, def)
|
||||
minetest.register_entity(entity_id, cart)
|
||||
|
||||
-- Register item to entity mapping
|
||||
entity_mapping[itemstring] = entity_id
|
||||
|
||||
register_minecart_craftitem(itemstring, def)
|
||||
if minetest.get_modpath("doc_identifier") then
|
||||
doc.sub.identifier.register_object(entity_id, "craftitems", itemstring)
|
||||
end
|
||||
|
||||
if craft then
|
||||
minetest.register_craft(craft)
|
||||
end
|
||||
end
|
||||
local register_minecart = mod.register_minecart
|
||||
|
||||
dofile(modpath.."/carts/minecart.lua")
|
||||
dofile(modpath.."/carts/with_chest.lua")
|
||||
dofile(modpath.."/carts/with_commandblock.lua")
|
||||
dofile(modpath.."/carts/with_hopper.lua")
|
||||
dofile(modpath.."/carts/with_furnace.lua")
|
||||
dofile(modpath.."/carts/with_tnt.lua")
|
||||
|
||||
if minetest.get_modpath("mcl_wip") then
|
||||
mcl_wip.register_wip_item("mcl_minecarts:chest_minecart")
|
||||
mcl_wip.register_wip_item("mcl_minecarts:furnace_minecart")
|
||||
mcl_wip.register_wip_item("mcl_minecarts:command_block_minecart")
|
||||
end
|
||||
|
||||
local function respawn_cart(cart)
|
||||
local cart_type = cart.cart_type or "mcl_minecarts:minecart"
|
||||
local pos = mod.get_cart_position(cart)
|
||||
|
||||
local players = minetest.get_connected_players()
|
||||
local distance = nil
|
||||
for _,player in pairs(players) do
|
||||
local d = vector.distance(player:get_pos(), pos)
|
||||
if not distance or d < distance then distance = d end
|
||||
end
|
||||
if not distance or distance > 90 then return end
|
||||
|
||||
mcl_log("Respawning cart #"..cart.uuid.." at "..tostring(pos)..",distance="..distance..",node="..minetest.get_node(pos).name)
|
||||
|
||||
-- Update sequence so that old cart entities get removed
|
||||
cart.seq = (cart.seq or 1) + 1
|
||||
save_cart_data(cart.uuid)
|
||||
|
||||
-- Create the new entity and refresh caches
|
||||
local sd = minetest.serialize({ uuid=cart.uuid, seq=cart.seq })
|
||||
local entity = minetest.add_entity(pos, cart_type, sd)
|
||||
local le = entity:get_luaentity()
|
||||
le._staticdata = cart
|
||||
mcl_util.assign_uuid(entity)
|
||||
|
||||
-- We intentionally don't call the normal hooks because this minecart was already there
|
||||
end
|
||||
|
||||
-- Try to respawn cart entities for carts that have moved into range of a player
|
||||
local function try_respawn_carts()
|
||||
-- Build a map of blocks near players
|
||||
local block_map = {}
|
||||
local players = minetest.get_connected_players()
|
||||
for _,player in pairs(players) do
|
||||
local pos = player:get_pos()
|
||||
mod.add_blocks_to_map(
|
||||
block_map,
|
||||
vector.offset(pos,-CART_BLOCK_SIZE,-CART_BLOCK_SIZE,-CART_BLOCK_SIZE),
|
||||
vector.offset(pos, CART_BLOCK_SIZE, CART_BLOCK_SIZE, CART_BLOCK_SIZE)
|
||||
)
|
||||
end
|
||||
|
||||
-- Find all cart data that are in these blocks
|
||||
local carts = find_carts_by_block_map(block_map)
|
||||
|
||||
-- Check to see if any of these don't have an entity
|
||||
for _,cart in pairs(carts) do
|
||||
local le = mcl_util.get_luaentity_from_uuid(cart.uuid)
|
||||
if not le then
|
||||
respawn_cart(cart)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local timer = 0
|
||||
minetest.register_globalstep(function(dtime)
|
||||
|
||||
-- Periodically respawn carts that come into range of a player
|
||||
timer = timer - dtime
|
||||
if timer <= 0 then
|
||||
local start_time = minetest.get_us_time()
|
||||
try_respawn_carts()
|
||||
local stop_time = minetest.get_us_time()
|
||||
local duration = (stop_time - start_time) / 1e6
|
||||
timer = duration / 250e-6 -- Schedule 50us per second
|
||||
if timer > 5 then timer = 5 end
|
||||
end
|
||||
|
||||
-- Handle periodically updating out-of-range carts
|
||||
-- TODO: change how often cart positions are updated based on velocity
|
||||
local start_time
|
||||
if DEBUG then start_time = minetest.get_us_time() end
|
||||
|
||||
for uuid,staticdata in mod.carts() do
|
||||
local pos = mod.get_cart_position(staticdata)
|
||||
--[[
|
||||
local le = mcl_util.get_luaentity_from_uuid(staticdata.uuid)
|
||||
print("cart# "..uuid..
|
||||
",velocity="..tostring(staticdata.velocity)..
|
||||
",pos="..tostring(pos)..
|
||||
",le="..tostring(le)..
|
||||
",connected_at="..tostring(staticdata.connected_at)
|
||||
)]]
|
||||
|
||||
--- Non-entity code
|
||||
if staticdata.connected_at then
|
||||
movement.do_movement(staticdata, dtime)
|
||||
end
|
||||
end
|
||||
|
||||
if DEBUG then
|
||||
local stop_time = minetest.get_us_time()
|
||||
print("Update took "..((stop_time-start_time)*1e-6).." seconds")
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
-- Try cart reattachment
|
||||
local player_name = player:get_player_name()
|
||||
local player_meta = mcl_playerinfo.get_mod_meta(player_name, modname)
|
||||
local cart_uuid = player_meta.attached_to
|
||||
if cart_uuid then
|
||||
local cartdata = get_cart_data(cart_uuid)
|
||||
|
||||
-- Can't get into a cart that was destroyed
|
||||
if not cartdata then
|
||||
return
|
||||
end
|
||||
|
||||
-- Don't reattach players if someone else got in the cart
|
||||
if cartdata.last_player ~= player_name then
|
||||
return
|
||||
end
|
||||
|
||||
minetest.after(0.2,function(player_name, cart_uuid)
|
||||
local player = minetest.get_player_by_name(player_name)
|
||||
if not player then
|
||||
return
|
||||
end
|
||||
|
||||
local cart = mcl_util.get_luaentity_from_uuid(cart_uuid)
|
||||
if not cart then
|
||||
return
|
||||
end
|
||||
|
||||
mod.attach_driver(cart, player)
|
||||
end, player_name, cart_uuid)
|
||||
end
|
||||
end)
|
||||
|
106
mods/ENTITIES/mcl_minecarts/carts/minecart.lua
Normal file
106
mods/ENTITIES/mcl_minecarts/carts/minecart.lua
Normal file
@ -0,0 +1,106 @@
|
||||
local modname = minetest.get_current_modname()
|
||||
local S = minetest.get_translator(modname)
|
||||
local mcl_log = mcl_util.make_mcl_logger("mcl_logging_minecarts", "Minecarts")
|
||||
local mod = mcl_minecarts
|
||||
|
||||
-- Imports
|
||||
local PASSENGER_ATTACH_POSITION = mod.PASSENGER_ATTACH_POSITION
|
||||
|
||||
local function activate_normal_minecart(self)
|
||||
mod.detach_driver(self)
|
||||
|
||||
-- Detach passenger
|
||||
if self._passenger then
|
||||
local mob = self._passenger.object
|
||||
mob:set_detach()
|
||||
self._passenger = nil
|
||||
end
|
||||
end
|
||||
|
||||
function mod.attach_driver(cart, player)
|
||||
local staticdata = cart._staticdata
|
||||
|
||||
-- Make sure we have a player
|
||||
if not player or not player:is_player() then return end
|
||||
|
||||
-- Prevent more than one player getting in the cart
|
||||
local player_name = player:get_player_name()
|
||||
if cart._driver or player:get_player_control().sneak then return end
|
||||
|
||||
-- Prevent getting into a cart that already has a passenger
|
||||
if cart._passenger then return end
|
||||
|
||||
-- Update cart information
|
||||
cart._driver = player_name
|
||||
cart._start_pos = cart.object:get_pos()
|
||||
|
||||
-- Keep track of player attachment
|
||||
local player_meta = mcl_playerinfo.get_mod_meta(player_name, modname)
|
||||
player_meta.attached_to = cart._uuid
|
||||
staticdata.last_player = player_name
|
||||
|
||||
-- Update player information
|
||||
local uuid = staticdata.uuid
|
||||
mcl_player.player_attached[player_name] = true
|
||||
--minetest.log("action", player_name.." entered minecart #"..tostring(uuid).." at "..tostring(cart._start_pos))
|
||||
|
||||
-- Attach the player object to the minecart
|
||||
player:set_attach(cart.object, "", vector.new(1,-1.75,-2), vector.new(0,0,0))
|
||||
minetest.after(0.2, function(name)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if player then
|
||||
mcl_player.player_set_animation(player, "sit" , 30)
|
||||
player:set_eye_offset(vector.new(0,-5.5,0), vector.new(0,-4,0))
|
||||
mcl_title.set(player, "actionbar", {text=S("Sneak to dismount"), color="white", stay=60})
|
||||
end
|
||||
end, player_name)
|
||||
end
|
||||
|
||||
mod.register_minecart({
|
||||
itemstring = "mcl_minecarts:minecart",
|
||||
craft = {
|
||||
output = "mcl_minecarts:minecart",
|
||||
recipe = {
|
||||
{"mcl_core:iron_ingot", "", "mcl_core:iron_ingot"},
|
||||
{"mcl_core:iron_ingot", "mcl_core:iron_ingot", "mcl_core:iron_ingot"},
|
||||
},
|
||||
},
|
||||
entity_id = "mcl_minecarts:minecart",
|
||||
description = S("Minecart"),
|
||||
tt_helop = S("Vehicle for fast travel on rails"),
|
||||
long_descp = S("Minecarts can be used for a quick transportion on rails.") .. "\n" ..
|
||||
S("Minecarts only ride on rails and always follow the tracks. At a T-junction with no straight way ahead, they turn left. The speed is affected by the rail type."),
|
||||
S("You can place the minecart on rails. Right-click it to enter it. Punch it to get it moving.") .. "\n" ..
|
||||
S("To obtain the minecart, punch it while holding down the sneak key.") .. "\n" ..
|
||||
S("If it moves over a powered activator rail, you'll get ejected."),
|
||||
initial_properties = {
|
||||
mesh = "mcl_minecarts_minecart.b3d",
|
||||
textures = {"mcl_minecarts_minecart.png"},
|
||||
},
|
||||
icon = "mcl_minecarts_minecart_normal.png",
|
||||
drop = {"mcl_minecarts:minecart"},
|
||||
on_rightclick = mod.attach_driver,
|
||||
on_activate_by_rail = activate_normal_minecart,
|
||||
_mcl_minecarts_on_step = function(self, dtime)
|
||||
-- Grab mob
|
||||
if math.random(1,20) > 15 and not self._passenger then
|
||||
local mobsnear = minetest.get_objects_inside_radius(self.object:get_pos(), 1.3)
|
||||
for n=1, #mobsnear do
|
||||
local mob = mobsnear[n]
|
||||
if mob and not mob:get_attach() then
|
||||
local entity = mob:get_luaentity()
|
||||
if entity and entity.is_mob then
|
||||
self._passenger = entity
|
||||
mob:set_attach(self.object, "", PASSENGER_ATTACH_POSITION, vector.zero())
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif self._passenger then
|
||||
local passenger_pos = self._passenger.object:get_pos()
|
||||
if not passenger_pos then
|
||||
self._passenger = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
})
|
35
mods/ENTITIES/mcl_minecarts/carts/with_chest.lua
Normal file
35
mods/ENTITIES/mcl_minecarts/carts/with_chest.lua
Normal file
@ -0,0 +1,35 @@
|
||||
local modname = minetest.get_current_modname()
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
local mod = mcl_minecarts
|
||||
local S = minetest.get_translator(modname)
|
||||
|
||||
-- Minecart with Chest
|
||||
mcl_minecarts.register_minecart({
|
||||
itemstring = "mcl_minecarts:chest_minecart",
|
||||
craft = {
|
||||
output = "mcl_minecarts:chest_minecart",
|
||||
recipe = {
|
||||
{"mcl_chests:chest"},
|
||||
{"mcl_minecarts:minecart"},
|
||||
},
|
||||
},
|
||||
entity_id = "mcl_minecarts:chest_minecart",
|
||||
description = S("Minecart with Chest"),
|
||||
tt_help = nil,
|
||||
longdesc = nil,
|
||||
usagehelp = nil,
|
||||
initial_properties = {
|
||||
mesh = "mcl_minecarts_minecart_chest.b3d",
|
||||
textures = {
|
||||
"mcl_chests_normal.png",
|
||||
"mcl_minecarts_minecart.png"
|
||||
},
|
||||
},
|
||||
icon = "mcl_minecarts_minecart_chest.png",
|
||||
drop = {"mcl_minecarts:minecart", "mcl_chests:chest"},
|
||||
groups = { container = 1 },
|
||||
on_rightclick = nil,
|
||||
on_activate_by_rail = nil,
|
||||
creative = true
|
||||
})
|
||||
mcl_entity_invs.register_inv("mcl_minecarts:chest_minecart","Minecart",27,false,true)
|
64
mods/ENTITIES/mcl_minecarts/carts/with_commandblock.lua
Normal file
64
mods/ENTITIES/mcl_minecarts/carts/with_commandblock.lua
Normal file
@ -0,0 +1,64 @@
|
||||
local modname = minetest.get_current_modname()
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
local mod = mcl_minecarts
|
||||
local S = minetest.get_translator(modname)
|
||||
|
||||
function table_metadata(table)
|
||||
return {
|
||||
table = table,
|
||||
set_string = function(self, key, value)
|
||||
--print("set_string("..tostring(key)..", "..tostring(value)..")")
|
||||
self.table[key] = tostring(value)
|
||||
end,
|
||||
get_string = function(self, key)
|
||||
if self.table[key] then
|
||||
return tostring(self.table[key])
|
||||
end
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
-- Minecart with Command Block
|
||||
mod.register_minecart({
|
||||
itemstring = "mcl_minecarts:command_block_minecart",
|
||||
entity_id = "mcl_minecarts:command_block_minecart",
|
||||
description = S("Minecart with Command Block"),
|
||||
tt_help = nil,
|
||||
loncdesc = nil,
|
||||
usagehelp = nil,
|
||||
initial_properties = {
|
||||
mesh = "mcl_minecarts_minecart_block.b3d",
|
||||
textures = {
|
||||
"jeija_commandblock_off.png^[verticalframe:2:0",
|
||||
"jeija_commandblock_off.png^[verticalframe:2:0",
|
||||
"jeija_commandblock_off.png^[verticalframe:2:0",
|
||||
"jeija_commandblock_off.png^[verticalframe:2:0",
|
||||
"jeija_commandblock_off.png^[verticalframe:2:0",
|
||||
"jeija_commandblock_off.png^[verticalframe:2:0",
|
||||
"mcl_minecarts_minecart.png",
|
||||
},
|
||||
},
|
||||
icon = "mcl_minecarts_minecart_command_block.png",
|
||||
drop = {"mcl_minecarts:minecart"},
|
||||
on_rightclick = function(self, clicker)
|
||||
self._staticdata.meta = self._staticdata.meta or {}
|
||||
local meta = table_metadata(self._staticdata.meta)
|
||||
|
||||
mesecon.commandblock.handle_rightclick(meta, clicker)
|
||||
end,
|
||||
_mcl_minecarts_on_place = function(self, placer)
|
||||
-- Create a fake metadata object that stores into the cart's staticdata
|
||||
self._staticdata.meta = self._staticdata.meta or {}
|
||||
local meta = table_metadata(self._staticdata.meta)
|
||||
|
||||
mesecon.commandblock.initialize(meta)
|
||||
mesecon.commandblock.place(meta, placer)
|
||||
end,
|
||||
on_activate_by_rail = function(self, timer)
|
||||
self._staticdata.meta = self._staticdata.meta or {}
|
||||
local meta = table_metadata(self._staticdata.meta)
|
||||
|
||||
mesecon.commandblock.action_on(meta, self.object:get_pos())
|
||||
end,
|
||||
creative = true
|
||||
})
|
100
mods/ENTITIES/mcl_minecarts/carts/with_furnace.lua
Normal file
100
mods/ENTITIES/mcl_minecarts/carts/with_furnace.lua
Normal file
@ -0,0 +1,100 @@
|
||||
local modname = minetest.get_current_modname()
|
||||
local S = minetest.get_translator(modname)
|
||||
|
||||
local FURNACE_CART_SPEED = tonumber(minetest.settings:get("mcl_minecarts_furnace_speed")) or 4
|
||||
|
||||
-- Minecart with Furnace
|
||||
mcl_minecarts.register_minecart({
|
||||
itemstring = "mcl_minecarts:furnace_minecart",
|
||||
craft = {
|
||||
output = "mcl_minecarts:furnace_minecart",
|
||||
recipe = {
|
||||
{"mcl_furnaces:furnace"},
|
||||
{"mcl_minecarts:minecart"},
|
||||
},
|
||||
},
|
||||
entity_id = "mcl_minecarts:furnace_minecart",
|
||||
description = S("Minecart with Furnace"),
|
||||
tt_help = nil,
|
||||
longdesc = S("A minecart with furnace is a vehicle that travels on rails. It can propel itself with fuel."),
|
||||
usagehelp = S("Place it on rails. If you give it some coal, the furnace will start burning for a long time and the minecart will be able to move itself. Punch it to get it moving.") .. "\n" ..
|
||||
S("To obtain the minecart and furnace, punch them while holding down the sneak key."),
|
||||
|
||||
initial_properties = {
|
||||
mesh = "mcl_minecarts_minecart_block.b3d",
|
||||
textures = {
|
||||
"default_furnace_top.png",
|
||||
"default_furnace_top.png",
|
||||
"default_furnace_front.png",
|
||||
"default_furnace_side.png",
|
||||
"default_furnace_side.png",
|
||||
"default_furnace_side.png",
|
||||
"mcl_minecarts_minecart.png",
|
||||
},
|
||||
},
|
||||
icon = "mcl_minecarts_minecart_furnace.png",
|
||||
drop = {"mcl_minecarts:minecart", "mcl_furnaces:furnace"},
|
||||
on_rightclick = function(self, clicker)
|
||||
local staticdata = self._staticdata
|
||||
|
||||
-- Feed furnace with coal
|
||||
if not clicker or not clicker:is_player() then
|
||||
return
|
||||
end
|
||||
local held = clicker:get_wielded_item()
|
||||
if minetest.get_item_group(held:get_name(), "coal") == 1 then
|
||||
staticdata.fueltime = (staticdata.fueltime or 0) + 180
|
||||
|
||||
-- Trucate to 27 minutes (9 uses)
|
||||
if staticdata.fueltime > 27*60 then
|
||||
staticdata.fuel_time = 27*60
|
||||
end
|
||||
|
||||
if not minetest.is_creative_enabled(clicker:get_player_name()) then
|
||||
held:take_item()
|
||||
local index = clicker:get_wield_index()
|
||||
local inv = clicker:get_inventory()
|
||||
inv:set_stack("main", index, held)
|
||||
end
|
||||
self.object:set_properties({textures =
|
||||
{
|
||||
"default_furnace_top.png",
|
||||
"default_furnace_top.png",
|
||||
"default_furnace_front_active.png",
|
||||
"default_furnace_side.png",
|
||||
"default_furnace_side.png",
|
||||
"default_furnace_side.png",
|
||||
"mcl_minecarts_minecart.png",
|
||||
}})
|
||||
end
|
||||
end,
|
||||
on_activate_by_rail = nil,
|
||||
creative = true,
|
||||
_mcl_minecarts_on_step = function(self, dtime)
|
||||
local staticdata = self._staticdata
|
||||
|
||||
-- Update furnace stuff
|
||||
if (staticdata.fueltime or 0) > 0 then
|
||||
for car in mcl_minecarts.train_cars(staticdata) do
|
||||
if car.velocity < FURNACE_CART_SPEED - 0.1 then -- Slightly less to allow train cars to maintain spacing
|
||||
car.velocity = FURNACE_CART_SPEED
|
||||
end
|
||||
end
|
||||
|
||||
staticdata.fueltime = (staticdata.fueltime or dtime) - dtime
|
||||
if staticdata.fueltime <= 0 then
|
||||
self.object:set_properties({textures =
|
||||
{
|
||||
"default_furnace_top.png",
|
||||
"default_furnace_top.png",
|
||||
"default_furnace_front.png",
|
||||
"default_furnace_side.png",
|
||||
"default_furnace_side.png",
|
||||
"default_furnace_side.png",
|
||||
"mcl_minecarts_minecart.png",
|
||||
}})
|
||||
staticdata.fueltime = 0
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
178
mods/ENTITIES/mcl_minecarts/carts/with_hopper.lua
Normal file
178
mods/ENTITIES/mcl_minecarts/carts/with_hopper.lua
Normal file
@ -0,0 +1,178 @@
|
||||
local modname = minetest.get_current_modname()
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
local mod = mcl_minecarts
|
||||
local S = minetest.get_translator(modname)
|
||||
|
||||
local LOGGING_ON = {minetest.settings:get_bool("mcl_logging_minecarts", false)}
|
||||
local function mcl_log(message)
|
||||
if LOGGING_ON[1] then
|
||||
mcl_util.mcl_log(message, "[Minecarts]", true)
|
||||
end
|
||||
end
|
||||
|
||||
local function hopper_take_item(self, dtime)
|
||||
local pos = self.object:get_pos()
|
||||
if not pos then return end
|
||||
|
||||
if not self or self.name ~= "mcl_minecarts:hopper_minecart" then return end
|
||||
|
||||
if mcl_util.check_dtime_timer(self, dtime, "hoppermc_take", 0.15) then
|
||||
--minetest.log("The check timer was triggered: " .. dump(pos) .. ", name:" .. self.name)
|
||||
else
|
||||
--minetest.log("The check timer was not triggered")
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
local above_pos = vector.offset(pos, 0, 0.9, 0)
|
||||
local objs = minetest.get_objects_inside_radius(above_pos, 1.25)
|
||||
|
||||
if objs then
|
||||
mcl_log("there is an itemstring. Number of objs: ".. #objs)
|
||||
|
||||
for k, v in pairs(objs) do
|
||||
local ent = v:get_luaentity()
|
||||
|
||||
if ent and not ent._removed and ent.itemstring and ent.itemstring ~= "" then
|
||||
local taken_items = false
|
||||
|
||||
mcl_log("ent.name: " .. tostring(ent.name))
|
||||
mcl_log("ent pos: " .. tostring(ent.object:get_pos()))
|
||||
|
||||
local inv = mcl_entity_invs.load_inv(self, 5)
|
||||
if not inv then return false end
|
||||
|
||||
local current_itemstack = ItemStack(ent.itemstring)
|
||||
|
||||
mcl_log("inv. size: " .. self._inv_size)
|
||||
if inv:room_for_item("main", current_itemstack) then
|
||||
mcl_log("Room")
|
||||
inv:add_item("main", current_itemstack)
|
||||
ent.object:get_luaentity().itemstring = ""
|
||||
ent.object:remove()
|
||||
taken_items = true
|
||||
else
|
||||
mcl_log("no Room")
|
||||
end
|
||||
|
||||
if not taken_items then
|
||||
local items_remaining = current_itemstack:get_count()
|
||||
|
||||
-- This will take part of a floating item stack if no slot can hold the full amount
|
||||
for i = 1, self._inv_size, 1 do
|
||||
local stack = inv:get_stack("main", i)
|
||||
|
||||
mcl_log("i: " .. tostring(i))
|
||||
mcl_log("Items remaining: " .. items_remaining)
|
||||
mcl_log("Name: " .. tostring(stack:get_name()))
|
||||
|
||||
if current_itemstack:get_name() == stack:get_name() then
|
||||
mcl_log("We have a match. Name: " .. tostring(stack:get_name()))
|
||||
|
||||
local room_for = stack:get_stack_max() - stack:get_count()
|
||||
mcl_log("Room for: " .. tostring(room_for))
|
||||
|
||||
if room_for == 0 then
|
||||
-- Do nothing
|
||||
mcl_log("No room")
|
||||
elseif room_for < items_remaining then
|
||||
mcl_log("We have more items remaining than space")
|
||||
|
||||
items_remaining = items_remaining - room_for
|
||||
stack:set_count(stack:get_stack_max())
|
||||
inv:set_stack("main", i, stack)
|
||||
taken_items = true
|
||||
else
|
||||
local new_stack_size = stack:get_count() + items_remaining
|
||||
stack:set_count(new_stack_size)
|
||||
mcl_log("We have more than enough space. Now holds: " .. new_stack_size)
|
||||
|
||||
inv:set_stack("main", i, stack)
|
||||
items_remaining = 0
|
||||
|
||||
ent.object:get_luaentity().itemstring = ""
|
||||
ent.object:remove()
|
||||
|
||||
taken_items = true
|
||||
break
|
||||
end
|
||||
|
||||
mcl_log("Count: " .. tostring(stack:get_count()))
|
||||
mcl_log("stack max: " .. tostring(stack:get_stack_max()))
|
||||
--mcl_log("Is it empty: " .. stack:to_string())
|
||||
end
|
||||
|
||||
if i == self._inv_size and taken_items then
|
||||
mcl_log("We are on last item and still have items left. Set final stack size: " .. items_remaining)
|
||||
current_itemstack:set_count(items_remaining)
|
||||
--mcl_log("Itemstack2: " .. current_itemstack:to_string())
|
||||
ent.itemstring = current_itemstack:to_string()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--Add in, and delete
|
||||
if taken_items then
|
||||
mcl_log("Saving")
|
||||
mcl_entity_invs.save_inv(ent)
|
||||
return taken_items
|
||||
else
|
||||
mcl_log("No need to save")
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
-- Minecart with Hopper
|
||||
mod.register_minecart({
|
||||
itemstring = "mcl_minecarts:hopper_minecart",
|
||||
craft = {
|
||||
output = "mcl_minecarts:hopper_minecart",
|
||||
recipe = {
|
||||
{"mcl_hoppers:hopper"},
|
||||
{"mcl_minecarts:minecart"},
|
||||
},
|
||||
},
|
||||
entity_id = "mcl_minecarts:hopper_minecart",
|
||||
description = S("Minecart with Hopper"),
|
||||
tt_help = nil,
|
||||
longdesc = nil,
|
||||
usagehelp = nil,
|
||||
initial_properties = {
|
||||
mesh = "mcl_minecarts_minecart_hopper.b3d",
|
||||
textures = {
|
||||
"mcl_hoppers_hopper_inside.png",
|
||||
"mcl_minecarts_minecart.png",
|
||||
"mcl_hoppers_hopper_outside.png",
|
||||
"mcl_hoppers_hopper_top.png",
|
||||
},
|
||||
},
|
||||
icon = "mcl_minecarts_minecart_hopper.png",
|
||||
drop = {"mcl_minecarts:minecart", "mcl_hoppers:hopper"},
|
||||
groups = { container = 1 },
|
||||
on_rightclick = nil,
|
||||
on_activate_by_rail = nil,
|
||||
_mcl_minecarts_on_enter = function(self, pos, staticdata)
|
||||
if (staticdata.hopper_delay or 0) > 0 then
|
||||
return
|
||||
end
|
||||
|
||||
-- try to pull from containers into our inventory
|
||||
if not self then return end
|
||||
local inv = mcl_entity_invs.load_inv(self,5)
|
||||
local above_pos = vector.offset(pos,0,1,0)
|
||||
mcl_util.hopper_pull_to_inventory(inv, 'main', above_pos, pos)
|
||||
|
||||
staticdata.hopper_delay = (staticdata.hopper_delay or 0) + (1/20)
|
||||
end,
|
||||
_mcl_minecarts_on_step = function(self, dtime)
|
||||
hopper_take_item(self, dtime)
|
||||
end,
|
||||
creative = true
|
||||
})
|
||||
mcl_entity_invs.register_inv("mcl_minecarts:hopper_minecart", "Hopper Minecart", 5, false, true)
|
||||
|
139
mods/ENTITIES/mcl_minecarts/carts/with_tnt.lua
Normal file
139
mods/ENTITIES/mcl_minecarts/carts/with_tnt.lua
Normal file
@ -0,0 +1,139 @@
|
||||
local modname = minetest.get_current_modname()
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
local mod = mcl_minecarts
|
||||
local S = minetest.get_translator(modname)
|
||||
|
||||
local function detonate_tnt_minecart(self)
|
||||
local pos = self.object:get_pos()
|
||||
self.object:remove()
|
||||
mcl_explosions.explode(pos, 6, { drop_chance = 1.0 })
|
||||
end
|
||||
|
||||
local function activate_tnt_minecart(self, timer)
|
||||
if self._boomtimer then
|
||||
return
|
||||
end
|
||||
if timer then
|
||||
self._boomtimer = timer
|
||||
else
|
||||
self._boomtimer = tnt.BOOMTIMER
|
||||
end
|
||||
self.object:set_properties({
|
||||
textures = {
|
||||
"mcl_tnt_blink.png",
|
||||
"mcl_tnt_blink.png",
|
||||
"mcl_tnt_blink.png",
|
||||
"mcl_tnt_blink.png",
|
||||
"mcl_tnt_blink.png",
|
||||
"mcl_tnt_blink.png",
|
||||
"mcl_minecarts_minecart.png",
|
||||
},
|
||||
glow = 15,
|
||||
})
|
||||
self._blinktimer = tnt.BLINKTIMER
|
||||
minetest.sound_play("tnt_ignite", {pos = self.object:get_pos(), gain = 1.0, max_hear_distance = 15}, true)
|
||||
end
|
||||
mod.register_minecart({
|
||||
itemstring = "mcl_minecarts:tnt_minecart",
|
||||
craft = {
|
||||
output = "mcl_minecarts:tnt_minecart",
|
||||
recipe = {
|
||||
{"mcl_tnt:tnt"},
|
||||
{"mcl_minecarts:minecart"},
|
||||
},
|
||||
},
|
||||
entity_id = "mcl_minecarts:tnt_minecart",
|
||||
description = S("Minecart with TNT"),
|
||||
tt_help = S("Vehicle for fast travel on rails").."\n"..S("Can be ignited by tools or powered activator rail"),
|
||||
longdesc = S("A minecart with TNT is an explosive vehicle that travels on rail."),
|
||||
usagehelp = S("Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.") .. "\n" ..
|
||||
S("To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited."),
|
||||
initial_properties = {
|
||||
mesh = "mcl_minecarts_minecart_block.b3d",
|
||||
textures = {
|
||||
"default_tnt_top.png",
|
||||
"default_tnt_bottom.png",
|
||||
"default_tnt_side.png",
|
||||
"default_tnt_side.png",
|
||||
"default_tnt_side.png",
|
||||
"default_tnt_side.png",
|
||||
"mcl_minecarts_minecart.png",
|
||||
},
|
||||
},
|
||||
icon = "mcl_minecarts_minecart_tnt.png",
|
||||
drop = {"mcl_minecarts:minecart", "mcl_tnt:tnt"},
|
||||
on_rightclick = function(self, clicker)
|
||||
-- Ingite
|
||||
if not clicker or not clicker:is_player() then
|
||||
return
|
||||
end
|
||||
if self._boomtimer then
|
||||
return
|
||||
end
|
||||
local held = clicker:get_wielded_item()
|
||||
if held:get_name() == "mcl_fire:flint_and_steel" then
|
||||
if not minetest.is_creative_enabled(clicker:get_player_name()) then
|
||||
held:add_wear(65535/65) -- 65 uses
|
||||
local index = clicker:get_wield_index()
|
||||
local inv = clicker:get_inventory()
|
||||
inv:set_stack("main", index, held)
|
||||
end
|
||||
activate_tnt_minecart(self)
|
||||
end
|
||||
end,
|
||||
on_activate_by_rail = activate_tnt_minecart,
|
||||
creative = true,
|
||||
_mcl_minecarts_on_step = function(self, dtime)
|
||||
-- Impacts reduce the speed greatly. Use this to trigger explosions
|
||||
local current_speed = vector.length(self.object:get_velocity())
|
||||
if current_speed < (self._old_speed or 0) - 6 then
|
||||
detonate_tnt_minecart(self)
|
||||
end
|
||||
self._old_speed = current_speed
|
||||
|
||||
if self._boomtimer then
|
||||
-- Explode
|
||||
self._boomtimer = self._boomtimer - dtime
|
||||
if self._boomtimer <= 0 then
|
||||
detonate_tnt_minecart(self)
|
||||
return
|
||||
else
|
||||
local pos = mod.get_cart_position(self._staticdata) or self.object:get_pos()
|
||||
if pos then
|
||||
tnt.smoke_step(pos)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if self._blinktimer then
|
||||
self._blinktimer = self._blinktimer - dtime
|
||||
if self._blinktimer <= 0 then
|
||||
self._blink = not self._blink
|
||||
if self._blink then
|
||||
self.object:set_properties({textures =
|
||||
{
|
||||
"default_tnt_top.png",
|
||||
"default_tnt_bottom.png",
|
||||
"default_tnt_side.png",
|
||||
"default_tnt_side.png",
|
||||
"default_tnt_side.png",
|
||||
"default_tnt_side.png",
|
||||
"mcl_minecarts_minecart.png",
|
||||
}})
|
||||
else
|
||||
self.object:set_properties({textures =
|
||||
{
|
||||
"mcl_tnt_blink.png",
|
||||
"mcl_tnt_blink.png",
|
||||
"mcl_tnt_blink.png",
|
||||
"mcl_tnt_blink.png",
|
||||
"mcl_tnt_blink.png",
|
||||
"mcl_tnt_blink.png",
|
||||
"mcl_minecarts_minecart.png",
|
||||
}})
|
||||
end
|
||||
self._blinktimer = tnt.BLINKTIMER
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
@ -1,4 +1,36 @@
|
||||
local vector = vector
|
||||
local mod = mcl_minecarts
|
||||
local table_merge = mcl_util.table_merge
|
||||
|
||||
local function get_path(base, first, ...)
|
||||
if not first then return base end
|
||||
if not base then return end
|
||||
return get_path(base[first], ...)
|
||||
end
|
||||
local function force_get_node(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
if node.name ~= "ignore" then return node end
|
||||
|
||||
--local time_start = minetest.get_us_time()
|
||||
local vm = minetest.get_voxel_manip()
|
||||
local emin, emax = vm:read_from_map(pos, pos)
|
||||
local area = VoxelArea:new{
|
||||
MinEdge = emin,
|
||||
MaxEdge = emax,
|
||||
}
|
||||
local data = vm:get_data()
|
||||
local param_data = vm:get_light_data()
|
||||
local param2_data = vm:get_param2_data()
|
||||
|
||||
local vi = area:indexp(pos)
|
||||
--minetest.log("force_get_node() voxel_manip section took "..((minetest.get_us_time()-time_start)*1e-6).." seconds")
|
||||
return {
|
||||
name = minetest.get_name_from_content_id(data[vi]),
|
||||
param = param_data[vi],
|
||||
param2 = param2_data[vi]
|
||||
}
|
||||
|
||||
end
|
||||
|
||||
function mcl_minecarts:get_sign(z)
|
||||
if z == 0 then
|
||||
@ -10,158 +42,485 @@ end
|
||||
|
||||
function mcl_minecarts:velocity_to_dir(v)
|
||||
if math.abs(v.x) > math.abs(v.z) then
|
||||
return {x=mcl_minecarts:get_sign(v.x), y=mcl_minecarts:get_sign(v.y), z=0}
|
||||
return vector.new(
|
||||
mcl_minecarts:get_sign(v.x),
|
||||
mcl_minecarts:get_sign(v.y),
|
||||
0
|
||||
)
|
||||
else
|
||||
return {x=0, y=mcl_minecarts:get_sign(v.y), z=mcl_minecarts:get_sign(v.z)}
|
||||
return vector.new(
|
||||
0,
|
||||
mcl_minecarts:get_sign(v.y),
|
||||
mcl_minecarts:get_sign(v.z)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
function mcl_minecarts:is_rail(pos, railtype)
|
||||
local node = minetest.get_node(pos).name
|
||||
if node == "ignore" then
|
||||
local vm = minetest.get_voxel_manip()
|
||||
local emin, emax = vm:read_from_map(pos, pos)
|
||||
local area = VoxelArea:new{
|
||||
MinEdge = emin,
|
||||
MaxEdge = emax,
|
||||
}
|
||||
local data = vm:get_data()
|
||||
local vi = area:indexp(pos)
|
||||
node = minetest.get_name_from_content_id(data[vi])
|
||||
function mcl_minecarts.is_rail(self, pos, railtype)
|
||||
-- Compatibility with mcl_minecarts:is_rail() usage
|
||||
if self ~= mcl_minecarts then
|
||||
railtype = pos
|
||||
pos = self
|
||||
end
|
||||
if minetest.get_item_group(node, "rail") == 0 then
|
||||
|
||||
local node_name = force_get_node(pos).name
|
||||
|
||||
if minetest.get_item_group(node_name, "rail") == 0 then
|
||||
return false
|
||||
end
|
||||
if not railtype then
|
||||
return true
|
||||
end
|
||||
return minetest.get_item_group(node, "connect_to_raillike") == railtype
|
||||
return minetest.get_item_group(node_name, "connect_to_raillike") == railtype
|
||||
end
|
||||
|
||||
function mcl_minecarts:check_front_up_down(pos, dir_, check_down, railtype)
|
||||
local dir = vector.new(dir_)
|
||||
-- Front
|
||||
dir.y = 0
|
||||
local cur = vector.add(pos, dir)
|
||||
if mcl_minecarts:is_rail(cur, railtype) then
|
||||
return dir
|
||||
end
|
||||
-- Up
|
||||
if check_down then
|
||||
dir.y = 1
|
||||
cur = vector.add(pos, dir)
|
||||
if mcl_minecarts:is_rail(cur, railtype) then
|
||||
return dir
|
||||
-- Directional constants
|
||||
local north = vector.new( 0, 0, 1); local N = 1 -- 4dir = 0
|
||||
local east = vector.new( 1, 0, 0); local E = 4 -- 4dir = 1
|
||||
local south = vector.new( 0, 0,-1); local S = 2 -- 4dir = 2
|
||||
local west = vector.new(-1, 0, 0); local W = 8 -- 4dir = 3
|
||||
|
||||
-- Share. Consider moving this to some shared location
|
||||
mod.north = north
|
||||
mod.south = south
|
||||
mod.east = east
|
||||
mod.west = west
|
||||
|
||||
--[[
|
||||
mcl_minecarts.snap_direction(dir)
|
||||
|
||||
returns a valid cart direction that has the smallest angle difference to `dir'
|
||||
]]
|
||||
local VALID_DIRECTIONS = {
|
||||
north, vector.offset(north, 0, 1, 0), vector.offset(north, 0, -1, 0),
|
||||
south, vector.offset(south, 0, 1, 0), vector.offset(south, 0, -1, 0),
|
||||
east, vector.offset(east, 0, 1, 0), vector.offset(east, 0, -1, 0),
|
||||
west, vector.offset(west, 0, 1, 0), vector.offset(west, 0, -1, 0),
|
||||
}
|
||||
function mod.snap_direction(dir)
|
||||
dir = vector.normalize(dir)
|
||||
local best = nil
|
||||
local diff = -1
|
||||
for _,d in pairs(VALID_DIRECTIONS) do
|
||||
local dot = vector.dot(dir,d)
|
||||
if dot > diff then
|
||||
best = d
|
||||
diff = dot
|
||||
end
|
||||
end
|
||||
-- Down
|
||||
dir.y = -1
|
||||
cur = vector.add(pos, dir)
|
||||
if mcl_minecarts:is_rail(cur, railtype) then
|
||||
return dir
|
||||
end
|
||||
return nil
|
||||
return best
|
||||
end
|
||||
|
||||
function mcl_minecarts:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
|
||||
local pos = vector.round(pos_)
|
||||
local cur
|
||||
local left_check, right_check = true, true
|
||||
local CONNECTIONS = { north, south, east, west }
|
||||
local HORIZONTAL_STANDARD_RULES = {
|
||||
[N] = { "", 0, mask = N, score = 1, can_slope = true },
|
||||
[S] = { "", 0, mask = S, score = 1, can_slope = true },
|
||||
[N+S] = { "", 0, mask = N+S, score = 2, can_slope = true },
|
||||
|
||||
-- Check left and right
|
||||
local left = {x=0, y=0, z=0}
|
||||
local right = {x=0, y=0, z=0}
|
||||
if dir.z ~= 0 and dir.x == 0 then
|
||||
left.x = -dir.z
|
||||
right.x = dir.z
|
||||
elseif dir.x ~= 0 and dir.z == 0 then
|
||||
left.z = dir.x
|
||||
right.z = -dir.x
|
||||
end
|
||||
[E] = { "", 1, mask = E, score = 1, can_slope = true },
|
||||
[W] = { "", 1, mask = W, score = 1, can_slope = true },
|
||||
[E+W] = { "", 1, mask = E+W, score = 2, can_slope = true },
|
||||
}
|
||||
mod.HORIZONTAL_STANDARD_RULES = HORIZONTAL_STANDARD_RULES
|
||||
|
||||
if ctrl then
|
||||
if old_switch == 1 then
|
||||
left_check = false
|
||||
elseif old_switch == 2 then
|
||||
right_check = false
|
||||
end
|
||||
if ctrl.left and left_check then
|
||||
cur = mcl_minecarts:check_front_up_down(pos, left, false, railtype)
|
||||
if cur then
|
||||
return cur, 1
|
||||
end
|
||||
left_check = false
|
||||
end
|
||||
if ctrl.right and right_check then
|
||||
cur = mcl_minecarts:check_front_up_down(pos, right, false, railtype)
|
||||
if cur then
|
||||
return cur, 2
|
||||
end
|
||||
right_check = true
|
||||
end
|
||||
end
|
||||
local HORIZONTAL_CURVES_RULES = {
|
||||
[N+E] = { "_corner", 3, name = "ne corner", mask = N+E, score = 3 },
|
||||
[N+W] = { "_corner", 2, name = "nw corner", mask = N+W, score = 3 },
|
||||
[S+E] = { "_corner", 0, name = "se corner", mask = S+E, score = 3 },
|
||||
[S+W] = { "_corner", 1, name = "sw corner", mask = S+W, score = 3 },
|
||||
|
||||
-- Normal
|
||||
cur = mcl_minecarts:check_front_up_down(pos, dir, true, railtype)
|
||||
if cur then
|
||||
return cur
|
||||
end
|
||||
[N+E+W] = { "_tee_off", 3, mask = N+E+W, score = 4 },
|
||||
[S+E+W] = { "_tee_off", 1, mask = S+E+W, score = 4 },
|
||||
[N+S+E] = { "_tee_off", 0, mask = N+S+E, score = 4 },
|
||||
[N+S+W] = { "_tee_off", 2, mask = N+S+W, score = 4 },
|
||||
|
||||
-- Left, if not already checked
|
||||
if left_check then
|
||||
cur = mcl_minecarts:check_front_up_down(pos, left, false, railtype)
|
||||
if cur then
|
||||
return cur
|
||||
end
|
||||
end
|
||||
[N+S+E+W] = { "_cross", 0, mask = N+S+E+W, score = 5 },
|
||||
}
|
||||
table_merge(HORIZONTAL_CURVES_RULES, HORIZONTAL_STANDARD_RULES)
|
||||
mod.HORIZONTAL_CURVES_RULES = HORIZONTAL_CURVES_RULES
|
||||
|
||||
-- Right, if not already checked
|
||||
if right_check then
|
||||
cur = mcl_minecarts:check_front_up_down(pos, right, false, railtype)
|
||||
if cur then
|
||||
return cur
|
||||
end
|
||||
end
|
||||
-- Backwards
|
||||
if not old_switch then
|
||||
cur = mcl_minecarts:check_front_up_down(pos, {
|
||||
x = -dir.x,
|
||||
y = dir.y,
|
||||
z = -dir.z
|
||||
}, true, railtype)
|
||||
if cur then
|
||||
return cur
|
||||
end
|
||||
end
|
||||
return {x=0, y=0, z=0}
|
||||
end
|
||||
|
||||
local plane_adjacents = {
|
||||
vector.new(-1,0,0),
|
||||
vector.new(1,0,0),
|
||||
vector.new(0,0,-1),
|
||||
vector.new(0,0,1),
|
||||
local HORIZONTAL_RULES_BY_RAIL_GROUP = {
|
||||
[1] = HORIZONTAL_STANDARD_RULES,
|
||||
[2] = HORIZONTAL_CURVES_RULES,
|
||||
}
|
||||
|
||||
function mcl_minecarts:get_start_direction(pos)
|
||||
local dir
|
||||
local i = 0
|
||||
while (not dir and i < #plane_adjacents) do
|
||||
i = i+1
|
||||
local node = minetest.get_node_or_nil(vector.add(pos, plane_adjacents[i]))
|
||||
if node ~= nil
|
||||
and minetest.get_item_group(node.name, "rail") == 0
|
||||
and minetest.get_item_group(node.name, "solid") == 1
|
||||
and minetest.get_item_group(node.name, "opaque") == 1
|
||||
then
|
||||
dir = mcl_minecarts:check_front_up_down(pos, vector.multiply(plane_adjacents[i], -1), true)
|
||||
end
|
||||
local function check_connection_rule(pos, connections, rule)
|
||||
-- All bits in the mask must be set for the connection to be possible
|
||||
if bit.band(rule.mask,connections) ~= rule.mask then
|
||||
--print("Mask mismatch ("..tostring(rule.mask)..","..tostring(connections)..")")
|
||||
return false
|
||||
end
|
||||
return dir
|
||||
|
||||
-- If there is an allow filter, that mush also return true
|
||||
if rule.allow and rule.allow(rule, connections, pos) then
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function mcl_minecarts:set_velocity(obj, dir, factor)
|
||||
obj._velocity = vector.multiply(dir, factor or 3)
|
||||
obj._old_pos = nil
|
||||
obj._punched = true
|
||||
local function make_sloped_if_straight(pos, dir)
|
||||
local node = minetest.get_node(pos)
|
||||
local nodedef = minetest.registered_nodes[node.name]
|
||||
|
||||
local param2 = 0
|
||||
if dir == east then
|
||||
param2 = 3
|
||||
elseif dir == west then
|
||||
param2 = 1
|
||||
elseif dir == north then
|
||||
param2 = 2
|
||||
elseif dir == south then
|
||||
param2 = 0
|
||||
end
|
||||
|
||||
if get_path( nodedef, "_mcl_minecarts", "railtype" ) == "straight" then
|
||||
minetest.swap_node(pos, {name = nodedef._mcl_minecarts.base_name .. "_sloped", param2 = param2})
|
||||
end
|
||||
end
|
||||
|
||||
local function is_connection(pos, dir)
|
||||
local node = force_get_node(pos)
|
||||
local nodedef = minetest.registered_nodes[node.name]
|
||||
|
||||
local get_next_dir = get_path(nodedef, "_mcl_minecarts", "get_next_dir")
|
||||
if not get_next_dir then return end
|
||||
|
||||
local next_dir = get_next_dir(pos, dir, node)
|
||||
next_dir.y = 0
|
||||
return vector.equals(next_dir, dir)
|
||||
end
|
||||
|
||||
local function get_rail_connections(pos, opt)
|
||||
local legacy = opt and opt.legacy
|
||||
local ignore_neighbor_connections = opt and opt.ignore_neighbor_connections
|
||||
|
||||
local connections = 0
|
||||
for i = 1,#CONNECTIONS do
|
||||
local dir = CONNECTIONS[i]
|
||||
local neighbor = vector.add(pos, dir)
|
||||
local node = force_get_node(neighbor)
|
||||
local nodedef = minetest.registered_nodes[node.name]
|
||||
|
||||
-- Only allow connections to the open ends of rails, as decribed by get_next_dir
|
||||
if mcl_minecarts.is_rail(neighbor) and ( legacy or get_path(nodedef, "_mcl_minecarts", "get_next_dir" ) ) then
|
||||
local rev_dir = vector.direction(dir,vector.zero())
|
||||
if ignore_neighbor_connections or is_connection(neighbor, rev_dir) then
|
||||
connections = bit.bor(connections, bit.lshift(1,i - 1))
|
||||
end
|
||||
end
|
||||
|
||||
-- Check for sloped rail one block down
|
||||
local below_neighbor = vector.offset(neighbor, 0, -1, 0)
|
||||
local node = force_get_node(below_neighbor)
|
||||
local nodedef = minetest.registered_nodes[node.name]
|
||||
if mcl_minecarts.is_rail(below_neighbor) and ( legacy or get_path(nodedef, "_mcl_minecarts", "get_next_dir" ) ) then
|
||||
local rev_dir = vector.direction(dir, vector.zero())
|
||||
if ignore_neighbor_connections or is_connection(below_neighbor, rev_dir) then
|
||||
connections = bit.bor(connections, bit.lshift(1,i - 1))
|
||||
end
|
||||
end
|
||||
end
|
||||
return connections
|
||||
end
|
||||
mod.get_rail_connections = get_rail_connections
|
||||
|
||||
local function apply_connection_rules(node, nodedef, pos, rules, connections)
|
||||
-- Select the best allowed connection
|
||||
local rule = nil
|
||||
local score = 0
|
||||
for k,r in pairs(rules) do
|
||||
if check_connection_rule(pos, connections, r) then
|
||||
if r.score > score then
|
||||
--print("Best rule so far is "..dump(r))
|
||||
score = r.score
|
||||
rule = r
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if rule then
|
||||
-- Apply the mapping
|
||||
local new_name = nodedef._mcl_minecarts.base_name..rule[1]
|
||||
if new_name ~= node.name or node.param2 ~= rule[2] then
|
||||
--print("swapping "..node.name.." for "..new_name..","..tostring(rule[2]).." at "..tostring(pos))
|
||||
node.name = new_name
|
||||
node.param2 = rule[2]
|
||||
minetest.swap_node(pos, node)
|
||||
end
|
||||
|
||||
if rule.after then
|
||||
rule.after(rule, pos, connections)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function is_rail_end_connected(pos, dir)
|
||||
-- Handle new track types that have track-specific direction handler
|
||||
local node = force_get_node(pos)
|
||||
local get_next_dir = get_path(minetest.registered_nodes,node.name,"_mcl_minecarts","get_next_dir")
|
||||
if not get_next_dir then return false end
|
||||
|
||||
return get_next_dir(pos, dir, node) == dir
|
||||
end
|
||||
|
||||
local function bend_straight_rail(pos, towards)
|
||||
local node = force_get_node(pos)
|
||||
local nodedef = minetest.registered_nodes[node.name]
|
||||
|
||||
-- Only bend rails
|
||||
local rail_type = minetest.get_item_group(node.name, "rail")
|
||||
if rail_type == 0 then return end
|
||||
|
||||
-- Only bend unbent rails
|
||||
if not nodedef._mcl_minecarts then return end
|
||||
if node.name ~= nodedef._mcl_minecarts.base_name then return end
|
||||
|
||||
-- only bend rails that have at least one free end
|
||||
local dir1 = minetest.fourdir_to_dir(node.param2)
|
||||
local dir2 = minetest.fourdir_to_dir((node.param2+2)%4)
|
||||
local dir1_connected = is_rail_end_connected(pos + dir1, dir2)
|
||||
local dir2_connected = is_rail_end_connected(pos + dir2, dir1)
|
||||
if dir1_connected and dir2_connected then return end
|
||||
|
||||
local connections = {
|
||||
vector.direction(pos, towards),
|
||||
}
|
||||
if dir1_connected then
|
||||
connections[#connections+1] = dir1
|
||||
end
|
||||
if dir2_connected then
|
||||
connections[#connections+1] = dir2
|
||||
end
|
||||
local connections_mask = 0
|
||||
for i = 1,#CONNECTIONS do
|
||||
for j = 1,#connections do
|
||||
if CONNECTIONS[i] == connections[j] then
|
||||
connections_mask = bit.bor(connections_mask, bit.lshift(1, i -1))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local rules = HORIZONTAL_RULES_BY_RAIL_GROUP[nodedef.groups.rail]
|
||||
apply_connection_rules(node, nodedef, pos, rules, connections_mask)
|
||||
end
|
||||
|
||||
local function update_rail_connections(pos, opt)
|
||||
local node = minetest.get_node(pos)
|
||||
local nodedef = minetest.registered_nodes[node.name]
|
||||
if not nodedef or not nodedef._mcl_minecarts then return end
|
||||
|
||||
-- Get the mappings to use
|
||||
local rules = HORIZONTAL_RULES_BY_RAIL_GROUP[nodedef.groups.rail]
|
||||
if nodedef._mcl_minecarts and nodedef._mcl_minecarts.connection_rules then -- Custom connection rules
|
||||
rules = nodedef._mcl_minecarts.connection_rules
|
||||
end
|
||||
if not rules then return end
|
||||
|
||||
if not (opt and opt.no_bend_straights) then
|
||||
for i = 1,#CONNECTIONS do
|
||||
bend_straight_rail(vector.add(pos, CONNECTIONS[i]), pos)
|
||||
end
|
||||
end
|
||||
|
||||
-- Horizontal rules, Check for rails on each neighbor
|
||||
local connections = get_rail_connections(pos, opt)
|
||||
|
||||
-- Check for rasing rails to slopes
|
||||
for i = 1,#CONNECTIONS do
|
||||
local dir = CONNECTIONS[i]
|
||||
local neighbor = vector.add(pos, dir)
|
||||
make_sloped_if_straight(vector.offset(neighbor, 0, -1, 0), dir)
|
||||
end
|
||||
|
||||
apply_connection_rules(node, nodedef, pos, rules, connections)
|
||||
|
||||
local node_def = minetest.registered_nodes[node.name]
|
||||
if get_path(node_def, "_mcl_minecarts", "can_slope") then
|
||||
for i=1,#CONNECTIONS do
|
||||
local dir = CONNECTIONS[i]
|
||||
local higher_rail_pos = vector.offset(pos,dir.x,1,dir.z)
|
||||
local rev_dir = vector.direction(dir,vector.zero())
|
||||
if mcl_minecarts.is_rail(higher_rail_pos) and is_connection(higher_rail_pos, rev_dir) then
|
||||
make_sloped_if_straight(pos, rev_dir)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Recursion guard
|
||||
if opt and opt.convert_neighbors == false then return end
|
||||
|
||||
-- Check if the open end of this rail runs into a corner or a tee and convert that node into a tee or a cross
|
||||
local neighbors = {}
|
||||
for i=1,#CONNECTIONS do
|
||||
local dir = CONNECTIONS[i]
|
||||
if is_connection(pos, dir) then
|
||||
local other_pos = pos - dir
|
||||
local other_node = core.get_node(other_pos)
|
||||
local other_node_def = core.registered_nodes[other_node.name]
|
||||
local railtype = get_path(other_node_def, "_mcl_minecarts","railtype")
|
||||
if railtype == "corner" or railtype == "tee" then
|
||||
update_rail_connections(other_pos, {convert_neighbors = false})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
mod.update_rail_connections = update_rail_connections
|
||||
|
||||
local north = vector.new(0,0,1)
|
||||
local south = vector.new(0,0,-1)
|
||||
local east = vector.new(1,0,0)
|
||||
local west = vector.new(-1,0,0)
|
||||
|
||||
local function is_ahead_slope(pos, dir)
|
||||
local ahead = vector.add(pos,dir)
|
||||
if mcl_minecarts.is_rail(ahead) then return false end
|
||||
|
||||
local below = vector.offset(ahead,0,-1,0)
|
||||
if not mcl_minecarts.is_rail(below) then return false end
|
||||
|
||||
local node_name = force_get_node(below).name
|
||||
return minetest.get_item_group(node_name, "rail_slope") ~= 0
|
||||
end
|
||||
|
||||
local function get_rail_direction_inner(pos, dir)
|
||||
-- Handle new track types that have track-specific direction handler
|
||||
local node = minetest.get_node(pos)
|
||||
local get_next_dir = get_path(minetest.registered_nodes,node.name,"_mcl_minecarts","get_next_dir")
|
||||
if not get_next_dir then return dir end
|
||||
|
||||
dir = get_next_dir(pos, dir, node)
|
||||
|
||||
-- Handle reversing if there is a solid block in the next position
|
||||
local next_pos = vector.add(pos, dir)
|
||||
local next_node = minetest.get_node(next_pos)
|
||||
local node_def = minetest.registered_nodes[next_node.name]
|
||||
if node_def and node_def.groups and ( node_def.groups.solid or node_def.groups.stair ) then
|
||||
-- Reverse the direction without giving -0 members
|
||||
dir = vector.direction(next_pos, pos)
|
||||
end
|
||||
|
||||
-- Handle going downhill
|
||||
if is_ahead_slope(pos,dir) then
|
||||
dir = vector.offset(dir,0,-1,0)
|
||||
end
|
||||
|
||||
return dir
|
||||
end
|
||||
function mcl_minecarts.get_rail_direction(self, pos_, dir)
|
||||
-- Compatibility with mcl_minecarts:get_rail_direction() usage
|
||||
if self ~= mcl_minecarts then
|
||||
dir = pos_
|
||||
pos_ = self
|
||||
end
|
||||
|
||||
local pos = vector.round(pos_)
|
||||
|
||||
-- diagonal direction handling
|
||||
if dir.x ~= 0 and dir.z ~= 0 then
|
||||
-- Check both possible diagonal movements
|
||||
local dir_a = vector.new(dir.x,0,0)
|
||||
local dir_b = vector.new(0,0,dir.z)
|
||||
local new_dir_a = mcl_minecarts.get_rail_direction(pos, dir_a)
|
||||
local new_dir_b = mcl_minecarts.get_rail_direction(pos, dir_b)
|
||||
|
||||
-- If either is the same diagonal direction, continue as you were
|
||||
if vector.equals(dir,new_dir_a) or vector.equals(dir,new_dir_b) then
|
||||
return dir
|
||||
|
||||
-- Otherwise, if either would try to move in the same direction as
|
||||
-- what tried, move that direction
|
||||
elseif vector.equals(dir_a, new_dir_a) then
|
||||
return new_dir_a
|
||||
elseif vector.equals(dir_b, new_dir_b) then
|
||||
return new_dir_b
|
||||
end
|
||||
|
||||
-- And if none of these were true, fall thru into standard behavior
|
||||
end
|
||||
|
||||
local new_dir = get_rail_direction_inner(pos, dir)
|
||||
|
||||
if new_dir.y ~= 0 then return new_dir end
|
||||
|
||||
-- Check four 45 degree movement
|
||||
local next_rails_dir = get_rail_direction_inner(vector.add(pos, new_dir), new_dir)
|
||||
if next_rails_dir.y == 0 and vector.equals(next_rails_dir, dir) and not vector.equals(new_dir, next_rails_dir) then
|
||||
return vector.add(new_dir, next_rails_dir)
|
||||
end
|
||||
|
||||
return new_dir
|
||||
end
|
||||
|
||||
local _2_pi = math.pi * 2
|
||||
local _half_pi = math.pi * 0.5
|
||||
local _quart_pi = math.pi * 0.25
|
||||
local pi = math.pi
|
||||
local rot_debug = {}
|
||||
function mod.update_cart_orientation(self)
|
||||
local staticdata = self._staticdata
|
||||
local dir = staticdata.dir
|
||||
|
||||
-- Calculate an angle from the x,z direction components
|
||||
local rot_y = math.atan2( dir.z, dir.x ) + ( staticdata.rot_adjust or 0 )
|
||||
if rot_y < 0 then
|
||||
rot_y = rot_y + _2_pi
|
||||
end
|
||||
|
||||
-- Check if the rotation is a 180 flip and don't change if so
|
||||
local rot = self.object:get_rotation()
|
||||
local old_rot = vector.new(rot)
|
||||
rot.y = (rot.y - _half_pi + _2_pi) % _2_pi
|
||||
if not rot then return end
|
||||
|
||||
local diff = math.abs((rot_y - ( rot.y + pi ) % _2_pi) )
|
||||
if diff < 0.001 or diff > _2_pi - 0.001 then
|
||||
-- Update rotation adjust
|
||||
staticdata.rot_adjust = ( ( staticdata.rot_adjust or 0 ) + pi ) % _2_pi
|
||||
else
|
||||
rot.y = rot_y
|
||||
end
|
||||
|
||||
-- Forward/backwards tilt (pitch)
|
||||
if dir.y > 0 then
|
||||
rot.x = _quart_pi
|
||||
elseif dir.y < 0 then
|
||||
rot.x = -_quart_pi
|
||||
else
|
||||
rot.x = 0
|
||||
end
|
||||
|
||||
if ( staticdata.rot_adjust or 0 ) < 0.01 then
|
||||
rot.x = -rot.x
|
||||
end
|
||||
|
||||
rot.y = (rot.y + _half_pi) % _2_pi
|
||||
self.object:set_rotation(rot)
|
||||
end
|
||||
|
||||
function mod.get_cart_position(cart_staticdata)
|
||||
local data = cart_staticdata
|
||||
if not data then return nil end
|
||||
if not data.connected_at then return nil end
|
||||
|
||||
return vector.add(data.connected_at, vector.multiply(data.dir or vector.zero(), data.distance or 0))
|
||||
end
|
||||
|
||||
function mod.reverse_cart_direction(staticdata)
|
||||
if staticdata.distance == 0 then
|
||||
staticdata.dir = -staticdata.dir
|
||||
return
|
||||
end
|
||||
|
||||
-- Complete moving thru this block into the next, reverse direction, and put us back at the same position we were at
|
||||
local next_dir = -staticdata.dir
|
||||
if not staticdata.connected_at then return end
|
||||
|
||||
staticdata.connected_at = staticdata.connected_at + staticdata.dir
|
||||
staticdata.distance = 1 - (staticdata.distance or 0)
|
||||
|
||||
-- recalculate direction
|
||||
local next_dir,_ = mod:get_rail_direction(staticdata.connected_at, next_dir)
|
||||
staticdata.dir = next_dir
|
||||
end
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,36 +1,50 @@
|
||||
# textdomain: mcl_minecarts
|
||||
##[ carts/minecart.lua ]##
|
||||
Sneak to dismount=Schleichen zum Aussteigen
|
||||
Minecart=Lore
|
||||
Vehicle for fast travel on rails=Fahrzeug zum schnellen Transport auf Schienen
|
||||
Minecarts can be used for a quick transportion on rails.=Loren können für eine schnelle Fahrt auf Schienen benutzt werden.
|
||||
Minecarts only ride on rails and always follow the tracks. At a T-junction with no straight way ahead, they turn left. The speed is affected by the rail type.=Loren fahren nur auf Schienen und bleiben immer auf der Strecke. An einer Einmündung ohne einem Weg nach vorne fahren sie nach links. Die Geschwindigkeit hängt vom Schienentyp ab.
|
||||
You can place the minecart on rails. Right-click it to enter it. Punch it to get it moving.=Sie können die Lore auf Schienen platzieren. Rechtsklicken, um einzusteigen.
|
||||
You can place the minecart on rails. Right-click it to enter it. Punch it to get it moving.=Sie können die Lore auf Schienen platzieren. Rechtsklicken, um einzusteigen. Schlagen, um es in Bewegung zu setzen.
|
||||
To obtain the minecart, punch it while holding down the sneak key.=Um die Lore aufzusammeln, schlagen Sie sie, während Sie die Schleichen-Taste gedrückt halten.
|
||||
A minecart with TNT is an explosive vehicle that travels on rail.=Eine Lore mit TNT ist ein explosives Fahrzeug, das auf Schienen fährt.
|
||||
Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.=Auf Schienen platzieren. Zuschlagen zum Bewegen. Das TNT wird mit einem Feuerzeug angezündet, oder, wenn die Lore sich auf einer bestromten Aktivierungsschiene befindet.
|
||||
To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited.=Um die Lore und das TNT zu erhalten, schlagen Sie sie, während Sie die Schleichtaste drücken. Das ist nicht möglich, wenn das TNT bereits gezündet wurde.
|
||||
If it moves over a powered activator rail, you'll get ejected.=Wenn sie über eine bestromte Aktivator-Schiene fährt, werden Sie herausgeworfen.
|
||||
##[ carts/with_chest.lua ]##
|
||||
Minecart with Chest=Lore mit Truhe
|
||||
##[ carts/with_commandblock.lua ]##
|
||||
Minecart with Command Block=Lore mit Befehlsblock
|
||||
##[ carts/with_furnace.lua ]##
|
||||
Minecart with Furnace=Lore mit Ofen
|
||||
A minecart with furnace is a vehicle that travels on rails. It can propel itself with fuel.=Eine Lore mit Ofen ist ein Fahrzeug, das auf Rädern fährt. Sie kann mit Brennstoff angetrieben werden.
|
||||
Place it on rails. If you give it some coal, the furnace will start burning for a long time and the minecart will be able to move itself. Punch it to get it moving.=Auf Schienen platzieren. Wird Kohle eingefügt, wird der Ofen für eine lange Zeit brennen und die Lore wird fähig sein, sich selbst anzutreiben. Zuschlagen, um die Bewegung einzuläuten.
|
||||
To obtain the minecart and furnace, punch them while holding down the sneak key.=Um die Lore und den Ofen zu erhalten, schlagen Sie zu, während Sie die Schleichtaste drücken.
|
||||
Minecart with Chest=Lore mit Truhe
|
||||
Minecart with Furnace=Lore mit Ofen
|
||||
Minecart with Command Block=Lore mit Befehlsblock
|
||||
##[ carts/with_hopper.lua ]##
|
||||
Minecart with Hopper=Lore mit Trichter
|
||||
##[ carts/with_tnt.lua ]##
|
||||
Minecart with TNT=Lore mit TNT
|
||||
Can be ignited by tools or powered activator rail=Kann mit Werkzeugen oder bestromten Aktivierungsschienen angezündet werden
|
||||
A minecart with TNT is an explosive vehicle that travels on rail.=Eine Lore mit TNT ist ein explosives Fahrzeug, das auf Schienen fährt.
|
||||
Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.=Auf Schienen platzieren. Zuschlagen zum Bewegen. Das TNT wird mit einem Feuerzeug angezündet, oder, wenn die Lore sich auf einer bestromten Aktivierungsschiene befindet.
|
||||
To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited.=Um die Lore und das TNT zu erhalten, schlagen Sie sie, während Sie die Schleichtaste drücken. Das ist nicht möglich, wenn das TNT bereits gezündet wurde.
|
||||
##[ rails.lua ]##
|
||||
Place them on the ground to build your railway, the rails will automatically connect to each other and will turn into curves, T-junctions, crossings and slopes as needed.=Bauen Sie sie auf den Boden, um Ihr Schienennetzwerk zu errichten, die Schienen werden sich automatisch verbinden und sich nach Bedarf in Kurven, Einmündungen, Kreuzungen und Steigungen verwandeln.
|
||||
Rail=Schiene
|
||||
New Rail=Neue Schiene
|
||||
Track for minecarts=Strecke für Loren
|
||||
Rails can be used to build transport tracks for minecarts. Normal rails slightly slow down minecarts due to friction.=Schienen können benutzt werden, um Strecken für Loren zu bauen. Normale Schienen werden Loren aufgrund von Reibung leicht verlangsamen.
|
||||
Powered Rail=Antriebsschiene
|
||||
Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts.=Schienen können benutzt werden, um Strecken für Loren zu bauen. Antriebsschienen können Loren beschleunigen und abbremsen.
|
||||
Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power.=Ohne Redstone-Energie wird die Schiene Loren abbremsen. Mit Redstone-Energie wird sie sie beschleunigen.
|
||||
Sloped Rail=Schiene mit Steigung
|
||||
##[ rails/activator.lua ]##
|
||||
Activator Rail=Aktivierungsschiene
|
||||
Activates minecarts when powered=Aktiviert Loren, wenn bestromt
|
||||
Rails can be used to build transport tracks for minecarts. Activator rails are used to activate special minecarts.=Schienen können benutzt werden, um Strecken für Loren zu bauen. Aktivierungsschienen werden benutzt, um besondere Loren zu aktivieren.
|
||||
To make this rail activate minecarts, power it with redstone power and send a minecart over this piece of rail.=Wenn diese Schiene mit Redstone-Energie versorgt wird, werden alle Loren, die sie passieren, aktiviert.
|
||||
##[ rails/detector.lua ]##
|
||||
Detector Rail=Sensorschiene
|
||||
Emits redstone power when a minecart is detected=Gibt ein Redstonesignal aus, wenn eine Lore erfasst wird
|
||||
Rails can be used to build transport tracks for minecarts. A detector rail is able to detect a minecart above it and powers redstone mechanisms.=Schienen können benutzt werden, um Strecken für Loren zu bauen. Eine Sensorschiene kann eine Lore erkennen und versorgt Redstone-Mechanismen.
|
||||
To detect a minecart and provide redstone power, connect it to redstone trails or redstone mechanisms and send any minecart over the rail.=Um eine Lore zu erkennen und die Redstone-Energie zu aktivieren, verbinden Sie die Schiene mit Redstonestaub oder Redstone-Mechanismen und schicken Sie eine beliebige Lore über die Schiene.
|
||||
Track for minecarts=Strecke für Loren
|
||||
##[ rails/normal.lua ]##
|
||||
Rail=Schiene
|
||||
##[ rails/powered.lua ]##
|
||||
Powered Rail=Antriebsschiene
|
||||
Speed up when powered, slow down when not powered=Beschleunigt, wenn bestromt, sonst verlangsamt es
|
||||
Activates minecarts when powered=Aktiviert Loren, wenn bestromt
|
||||
Emits redstone power when a minecart is detected=Gibt ein Redstonesignal aus, wenn eine Lore erfasst wird
|
||||
Vehicle for fast travel on rails=Fahrzeug zum schnellen Transport auf Schienen
|
||||
Can be ignited by tools or powered activator rail=Kann mit Werkzeugen oder bestromten Aktivierungsschienen angezündet werden
|
||||
Sneak to dismount=Zum Aussteigen schleichen
|
||||
Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts.=Schienen können benutzt werden, um Strecken für Loren zu bauen. Antriebsschienen können Loren beschleunigen und abbremsen.
|
||||
Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power.=Ohne Redstone-Energie wird die Schiene Loren abbremsen. Mit Redstone-Energie wird sie sie beschleunigen.
|
||||
|
@ -1,36 +1,50 @@
|
||||
# textdomain: mcl_minecarts
|
||||
##[ carts/minecart.lua ]##
|
||||
Sneak to dismount=Snig for at stige af.
|
||||
Minecart=Minevogn
|
||||
Vehicle for fast travel on rails=Fartøj til hurtig kørsel på spor.
|
||||
Minecarts can be used for a quick transportion on rails.=Minevogne kan bruges til hurtig transport på spor.
|
||||
Minecarts only ride on rails and always follow the tracks. At a T-junction with no straight way ahead, they turn left. The speed is affected by the rail type.=Minevogne kan kun køre på spor, og følger dem altid. Ved et T-kryds uden en vej ligeud drejer de altid til venstre. Farten påvirkes af sportypen.
|
||||
You can place the minecart on rails. Right-click it to enter it. Punch it to get it moving.=Du kan placere minevogne på spor. Højre-klik for at stige ombord.
|
||||
To obtain the minecart, punch it while holding down the sneak key.=For at at få minevognen i din oppakning.
|
||||
A minecart with TNT is an explosive vehicle that travels on rail.=En minevogn med TNT as et eksplosivt fartøj som kører på spor.
|
||||
Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.=Placér den på spor. Slå den for at flytte den. TNTet bliver antændt med flint og stål eller når minevognen er på et aktiveringsspor.
|
||||
To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited.=For at få minevognen med TNT i din oppakning skal du slå den mens du holder snigeknappen nede. Du kan ikke gøre dette hvis TNTen er antændt.
|
||||
If it moves over a powered activator rail, you'll get ejected.=
|
||||
##[ carts/with_chest.lua ]##
|
||||
Minecart with Chest=Minevogn med kiste
|
||||
##[ carts/with_commandblock.lua ]##
|
||||
Minecart with Command Block=Minevogn med kommandoblok
|
||||
##[ carts/with_furnace.lua ]##
|
||||
Minecart with Furnace=Minevogn med ovn
|
||||
A minecart with furnace is a vehicle that travels on rails. It can propel itself with fuel.=En minevogn med ovn er et fartøj som kører på spor. Den kan køre af sig selv med brændstof.
|
||||
Place it on rails. If you give it some coal, the furnace will start burning for a long time and the minecart will be able to move itself. Punch it to get it moving.=Placér den på spor. Hvis du putter kul i den vil ovnen brænde i lang tid, og minevognen vil køre af sig selv. Slå den for at sætte den i bevægelse.
|
||||
To obtain the minecart and furnace, punch them while holding down the sneak key.=For at få minevognen med ovn i din oppakning skal du slå den mens du holder snigeknappen nede.
|
||||
Minecart with Chest=Minevogn med kiste
|
||||
Minecart with Furnace=Minevogn med ovn
|
||||
Minecart with Command Block=Minevogn med kommandoblok
|
||||
##[ carts/with_hopper.lua ]##
|
||||
Minecart with Hopper=Minevogn med tragt
|
||||
##[ carts/with_tnt.lua ]##
|
||||
Minecart with TNT=Minevogn med TNT
|
||||
Can be ignited by tools or powered activator rail=Kan antændes med værktøj eller et aktivatorspor med strøm.
|
||||
A minecart with TNT is an explosive vehicle that travels on rail.=En minevogn med TNT as et eksplosivt fartøj som kører på spor.
|
||||
Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.=Placér den på spor. Slå den for at flytte den. TNTet bliver antændt med flint og stål eller når minevognen er på et aktiveringsspor.
|
||||
To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited.=For at få minevognen med TNT i din oppakning skal du slå den mens du holder snigeknappen nede. Du kan ikke gøre dette hvis TNTen er antændt.
|
||||
##[ rails.lua ]##
|
||||
Place them on the ground to build your railway, the rails will automatically connect to each other and will turn into curves, T-junctions, crossings and slopes as needed.=Placér dem på jorden for at bygge din jerbane. Sporene kobler sig automatisk sammen med hinanden og laver sving, T-kryds, kryds og skråninger efter behov.
|
||||
Rail=Spor
|
||||
New Rail=
|
||||
Track for minecarts=Spor til minevogne.
|
||||
Rails can be used to build transport tracks for minecarts. Normal rails slightly slow down minecarts due to friction.=Spor kan bruges til at bygge jernbaner til minevogne. Normale spor sænker minevognene en smule på grund af friktionsmodstand.
|
||||
Powered Rail=Strømspor
|
||||
Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts.=Spor kan bruges til at bygge jernbaner til minevogne. Strømspor kan accelerere eller bremse minevogne.
|
||||
Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power.=Uden redstonekraft vil sporet bremse minevognen. For at accelerere minevognen skal den bruge redstoneskraft.
|
||||
Sloped Rail=
|
||||
##[ rails/activator.lua ]##
|
||||
Activator Rail=Aktiveringsspor
|
||||
Activates minecarts when powered=Aktieverer minevogne når der er strøm.
|
||||
Rails can be used to build transport tracks for minecarts. Activator rails are used to activate special minecarts.=Spor kan bruges til at bygge jernbaner til minevogne. Aktiveringsspor bruges til at aktivere specielle minevogne.
|
||||
To make this rail activate minecarts, power it with redstone power and send a minecart over this piece of rail.=For at få dette spor til at aktiere minevogne skal du give det redstonekraft og sende en minevogn over dette sporstykke.
|
||||
##[ rails/detector.lua ]##
|
||||
Detector Rail=Detektorspor
|
||||
Emits redstone power when a minecart is detected=Udsender redstonekraft når en minevogn bliver opdaget.
|
||||
Rails can be used to build transport tracks for minecarts. A detector rail is able to detect a minecart above it and powers redstone mechanisms.=Spor kan bruges til at bygge jernbaner til minevogne. Et detektorspor kan opdage en minevogn som kører over det og give kraft til redstonemekanismer.
|
||||
To detect a minecart and provide redstone power, connect it to redstone trails or redstone mechanisms and send any minecart over the rail.=For at opdage en minevogn og give redstonekraft skal den forbindes til redstonestøv eller redstonemekanismer og send en hvilkensomhelst minevogn hen over sporet.
|
||||
Track for minecarts=Spor til minevogne.
|
||||
##[ rails/normal.lua ]##
|
||||
Rail=Spor
|
||||
##[ rails/powered.lua ]##
|
||||
Powered Rail=Strømspor
|
||||
Speed up when powered, slow down when not powered=Accelerérer når der er strøm, sænk hastigheden når der ikke er strøm.
|
||||
Activates minecarts when powered=Aktieverer minevogne når der er strøm.
|
||||
Emits redstone power when a minecart is detected=Udsender redstonekraft når en minevogn bliver opdaget.
|
||||
Vehicle for fast travel on rails=Fartøj til hurtig kørsel på spor.
|
||||
Can be ignited by tools or powered activator rail=Kan antændes med værktøj eller et aktivatorspor med strøm.
|
||||
Sneak to dismount=Snig for at stige af.
|
||||
Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts.=Spor kan bruges til at bygge jernbaner til minevogne. Strømspor kan accelerere eller bremse minevogne.
|
||||
Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power.=Uden redstonekraft vil sporet bremse minevognen. For at accelerere minevognen skal den bruge redstoneskraft.
|
||||
|
@ -1,23 +1,50 @@
|
||||
# textdomain: mcl_minecarts
|
||||
##[ carts/minecart.lua ]##
|
||||
Sneak to dismount=
|
||||
Minecart=Vagoneta
|
||||
Vehicle for fast travel on rails=
|
||||
Minecarts can be used for a quick transportion on rails.=Las vagonetas se pueden usar para transportarse rápido en los rieles.
|
||||
Minecarts only ride on rails and always follow the tracks. At a T-junction with no straight way ahead, they turn left. The speed is affected by the rail type.=Las vagonetas solo viajan en rieles y siempre siguen las pistas. En un cruce en T sin camino recto, giran a la izquierda. La velocidad se ve afectada por el tipo de riel.
|
||||
You can place the minecart on rails. Right-click it to enter it. Punch it to get it moving.=Puedes colocar el vagoneta en los rieles. Haga clic derecho para insertarlo. Golpea para que se mueva.
|
||||
To obtain the minecart, punch it while holding down the sneak key.=Para obtener el vagoneta, golpéalo mientras mantienes presionada la tecla.
|
||||
If it moves over a powered activator rail, you'll get ejected.=
|
||||
##[ carts/with_chest.lua ]##
|
||||
Minecart with Chest=Vagoneta con cofre
|
||||
Minecart with Furnace=Vagoneta con horno
|
||||
##[ carts/with_commandblock.lua ]##
|
||||
Minecart with Command Block=Vagoneta con bloque de comandos
|
||||
##[ carts/with_furnace.lua ]##
|
||||
Minecart with Furnace=Vagoneta con horno
|
||||
A minecart with furnace is a vehicle that travels on rails. It can propel itself with fuel.=
|
||||
Place it on rails. If you give it some coal, the furnace will start burning for a long time and the minecart will be able to move itself. Punch it to get it moving.=
|
||||
To obtain the minecart and furnace, punch them while holding down the sneak key.=
|
||||
##[ carts/with_hopper.lua ]##
|
||||
Minecart with Hopper=Vagoneta con tolva
|
||||
##[ carts/with_tnt.lua ]##
|
||||
Minecart with TNT=Vagoneta con dinamita
|
||||
Can be ignited by tools or powered activator rail=
|
||||
A minecart with TNT is an explosive vehicle that travels on rail.=
|
||||
Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.=
|
||||
To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited.=
|
||||
##[ rails.lua ]##
|
||||
Place them on the ground to build your railway, the rails will automatically connect to each other and will turn into curves, T-junctions, crossings and slopes as needed.=Colóquelos en el suelo para construir su ferrocarril, los rieles se conectarán automáticamente entre sí y se convertirán en curvas, uniones en T, cruces y pendientes según sea necesario.
|
||||
Rail=Raíl
|
||||
New Rail=
|
||||
Track for minecarts=
|
||||
Rails can be used to build transport tracks for minecarts. Normal rails slightly slow down minecarts due to friction.=Los rieles se pueden usar para construir vías de transporte para vagonetas. Los rieles normales ralentizan ligeramente las vagonetas debido a la fricción.
|
||||
Powered Rail=Raíl propulsor
|
||||
Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts.=Los rieles se pueden usar para construir vías de transporte para vagonetas. Los railes propulsores pueden acelerar y frenar las vagonetas.
|
||||
Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power.=Sin energía de redstone, el riel frenará las vagonetas. Para hacer que este riel acelere las vagonetas, aliméntalo con redstone.
|
||||
Sloped Rail=
|
||||
##[ rails/activator.lua ]##
|
||||
Activator Rail=Raíl activador
|
||||
Activates minecarts when powered=
|
||||
Rails can be used to build transport tracks for minecarts. Activator rails are used to activate special minecarts.=Los rieles se pueden usar para construir vías de transporte para vagonetas. Los railes activador se utilizan para activar una vagoneta especial.
|
||||
To make this rail activate minecarts, power it with redstone power and send a minecart over this piece of rail.=Para hacer que este riel active las vagonetas, enciéndelo con energía de redstone y envía una vagoneta sobre este pedazo de riel.
|
||||
##[ rails/detector.lua ]##
|
||||
Detector Rail=Raíl detector
|
||||
Emits redstone power when a minecart is detected=
|
||||
Rails can be used to build transport tracks for minecarts. A detector rail is able to detect a minecart above it and powers redstone mechanisms.=Los rieles se pueden usar para construir vías de transporte para vagonetas. Un raíl detector puede detectar una vagoneta sobre él y alimenta los mecanismos de redstone.
|
||||
To detect a minecart and provide redstone power, connect it to redstone trails or redstone mechanisms and send any minecart over the rail.=Para detectar una vagoneta y proporcionar energía de redstone, conéctelo a los senderos de redstone o mecanismos de redstone y envíe cualquier vagoneta sobre el riel.
|
||||
##[ rails/normal.lua ]##
|
||||
Rail=Raíl
|
||||
##[ rails/powered.lua ]##
|
||||
Powered Rail=Raíl propulsor
|
||||
Speed up when powered, slow down when not powered=
|
||||
Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts.=Los rieles se pueden usar para construir vías de transporte para vagonetas. Los railes propulsores pueden acelerar y frenar las vagonetas.
|
||||
Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power.=Sin energía de redstone, el riel frenará las vagonetas. Para hacer que este riel acelere las vagonetas, aliméntalo con redstone.
|
||||
|
@ -1,36 +1,50 @@
|
||||
# textdomain: mcl_minecarts
|
||||
##[ carts/minecart.lua ]##
|
||||
Sneak to dismount=Se baisser pour descendre
|
||||
Minecart=Wagonnet
|
||||
Vehicle for fast travel on rails=Véhicule pour voyager rapidement sur rails
|
||||
Minecarts can be used for a quick transportion on rails.=Les wagonnets peuvent être utilisés pour un transport rapide sur rails.
|
||||
Minecarts only ride on rails and always follow the tracks. At a T-junction with no straight way ahead, they turn left. The speed is affected by the rail type.=Les wagonnets roulent uniquement sur des rails et suivent toujours les pistes. À un carrefour en T sans voie directe, ils tournent à gauche. La vitesse dépend du type de rail.
|
||||
You can place the minecart on rails. Right-click it to enter it. Punch it to get it moving.=Vous pouvez placer le wagonnet sur des rails. Faites un clic droit dessus pour entrer dedans. Frappez-le pour le faire bouger.
|
||||
To obtain the minecart, punch it while holding down the sneak key.=Pour obtenir la wagonnet, frappez-le tout en maintenant la touche furtive enfoncée.
|
||||
A minecart with TNT is an explosive vehicle that travels on rail.=Un wagonnet avec de la TNT est un véhicule explosif qui se déplace sur rail.
|
||||
Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.=Placez-le sur des rails. Frappez-le pour le déplacer. Le TNT est allumé avec un briquet ou lorsque le minecart est sur un rail d'activation alimenté.
|
||||
To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited.=Pour obtenir la wagonnet et la TNT, frappez-les tout en maintenant la touche furtive enfoncée. Vous ne pouvez pas faire cela si le TNT a été allumé.
|
||||
If it moves over a powered activator rail, you'll get ejected.=
|
||||
##[ carts/with_chest.lua ]##
|
||||
Minecart with Chest=Wagonnet avec coffre
|
||||
##[ carts/with_commandblock.lua ]##
|
||||
Minecart with Command Block=Wagonnet avec bloc de commande
|
||||
##[ carts/with_furnace.lua ]##
|
||||
Minecart with Furnace=Wagonnet avec four
|
||||
A minecart with furnace is a vehicle that travels on rails. It can propel itself with fuel.=Une wagonnet avec un four est un véhicule qui se déplace sur rails. Il peut se propulser avec du carburant.
|
||||
Place it on rails. If you give it some coal, the furnace will start burning for a long time and the minecart will be able to move itself. Punch it to get it moving.=Placez-le sur des rails. Si vous lui donnez du charbon, le four commencera à brûler pendant longtemps et le wagonnet pourra se déplacer. Frappez-le pour le faire bouger.
|
||||
To obtain the minecart and furnace, punch them while holding down the sneak key.=Pour obtenir le wagonnet et le four, frappez-les tout en maintenant la touche furtive enfoncée.
|
||||
Minecart with Chest=Wagonnet avec coffre
|
||||
Minecart with Furnace=Wagonnet avec four
|
||||
Minecart with Command Block=Wagonnet avec bloc de commande
|
||||
##[ carts/with_hopper.lua ]##
|
||||
Minecart with Hopper=Wagonnet avec entonnoir
|
||||
##[ carts/with_tnt.lua ]##
|
||||
Minecart with TNT=Wagonnet avec TNT
|
||||
Can be ignited by tools or powered activator rail=Peut être allumé par des outils ou un rail d'activation motorisé
|
||||
A minecart with TNT is an explosive vehicle that travels on rail.=Un wagonnet avec de la TNT est un véhicule explosif qui se déplace sur rail.
|
||||
Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.=Placez-le sur des rails. Frappez-le pour le déplacer. Le TNT est allumé avec un briquet ou lorsque le minecart est sur un rail d'activation alimenté.
|
||||
To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited.=Pour obtenir la wagonnet et la TNT, frappez-les tout en maintenant la touche furtive enfoncée. Vous ne pouvez pas faire cela si le TNT a été allumé.
|
||||
##[ rails.lua ]##
|
||||
Place them on the ground to build your railway, the rails will automatically connect to each other and will turn into curves, T-junctions, crossings and slopes as needed.=Placez-les sur le sol pour construire votre chemin de fer, les rails se connecteront automatiquement les uns aux autres et se transformeront en courbes, en jonctions en T, en traversées et en pentes au besoin.
|
||||
Rail=Rail
|
||||
New Rail=
|
||||
Track for minecarts=Piste pour wagonnets
|
||||
Rails can be used to build transport tracks for minecarts. Normal rails slightly slow down minecarts due to friction.=Les rails peuvent être utilisés pour construire des voies de transport pour les wagonnets. Les rails ralentissent légèrement les wagonnets en raison de la friction.
|
||||
Powered Rail=Rail alimenté
|
||||
Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts.=Les rails peuvent être utilisés pour construire des voies de transport pour les wagonnets. Les rails motorisés sont capables d'accélérer et de freiner les wagonnets.
|
||||
Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power.=Sans énergie de redstone, le rail freinera les wagonnets. Pour que ce rail accélère les minecarts, alimentez-le avec une source d'énergie redstone.
|
||||
Sloped Rail=
|
||||
##[ rails/activator.lua ]##
|
||||
Activator Rail=Rail d'activation
|
||||
Activates minecarts when powered=Active les wagonnets lorsqu'il est alimenté
|
||||
Rails can be used to build transport tracks for minecarts. Activator rails are used to activate special minecarts.=Les rails peuvent être utilisés pour construire des voies de transport pour les wagonnets. Des rails activateurs sont utilisés pour activer des wagonnets spéciaux.
|
||||
To make this rail activate minecarts, power it with redstone power and send a minecart over this piece of rail.=Pour activer ce rail, activez les wagonnets, alimentez-le avec de l'énergie redstone et envoyez un wagonnet sur ce morceau de rail.
|
||||
##[ rails/detector.lua ]##
|
||||
Detector Rail=Rail de détection
|
||||
Emits redstone power when a minecart is detected=Émet de l'énergie redstone lorsqu'un wagonnet est détecté
|
||||
Rails can be used to build transport tracks for minecarts. A detector rail is able to detect a minecart above it and powers redstone mechanisms.=Les rails peuvent être utilisés pour construire des voies de transport pour les wagonnets. Un rail de détection est capable de détecter un wagonnet au-dessus et alimente les mécanismes de redstone.
|
||||
To detect a minecart and provide redstone power, connect it to redstone trails or redstone mechanisms and send any minecart over the rail.=Pour détecter un wagonnet et fournir une alimentation redstone, connectez-le aux câble redstone ou aux mécanismes redstone et envoyez n'importe quel wagonnet sur le rail.
|
||||
Track for minecarts=Piste pour wagonnets
|
||||
##[ rails/normal.lua ]##
|
||||
Rail=Rail
|
||||
##[ rails/powered.lua ]##
|
||||
Powered Rail=Rail alimenté
|
||||
Speed up when powered, slow down when not powered=Accélérez lorsqu'il est alimenté, ralentissez lorsqu'il n'est pas alimenté
|
||||
Activates minecarts when powered=Active les wagonnets lorsqu'il est alimenté
|
||||
Emits redstone power when a minecart is detected=Émet de l'énergie redstone lorsqu'un wagonnet est détecté
|
||||
Vehicle for fast travel on rails=Véhicule pour voyager rapidement sur rails
|
||||
Can be ignited by tools or powered activator rail=Peut être allumé par des outils ou un rail d'activation motorisé
|
||||
Sneak to dismount=Se baisser pour descendre
|
||||
Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts.=Les rails peuvent être utilisés pour construire des voies de transport pour les wagonnets. Les rails motorisés sont capables d'accélérer et de freiner les wagonnets.
|
||||
Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power.=Sans énergie de redstone, le rail freinera les wagonnets. Pour que ce rail accélère les minecarts, alimentez-le avec une source d'énergie redstone.
|
||||
|
50
mods/ENTITIES/mcl_minecarts/locale/mcl_minecarts.it.tr
Normal file
50
mods/ENTITIES/mcl_minecarts/locale/mcl_minecarts.it.tr
Normal file
@ -0,0 +1,50 @@
|
||||
# textdomain: mcl_minecarts
|
||||
##[ carts/minecart.lua ]##
|
||||
Sneak to dismount=Accovacciati per scendere
|
||||
Minecart=Carrello da miniera
|
||||
Vehicle for fast travel on rails=Veicolo per viaggio rapido su binari
|
||||
Minecarts can be used for a quick transportion on rails.=I carrelli da miniera possono essere usati per viaggiare rapidamente su binari.
|
||||
Minecarts only ride on rails and always follow the tracks. At a T-junction with no straight way ahead, they turn left. The speed is affected by the rail type.=I carrelli da miniera viaggiano solo su binari e seguono sempre il tracciato. Ad un incrocio a T senza via frontale, girano a sinistra. La velocità è influenzata dal tipo di binari.
|
||||
You can place the minecart on rails. Right-click it to enter it. Punch it to get it moving.=Puoi piazzare il carrello da miniera sui binari. Click destro sul carrello per salire a bordo.
|
||||
To obtain the minecart, punch it while holding down the sneak key.=Per ottenere il carrello da miniera, colpiscilo mentre premi il pulsante per accovacciarti.
|
||||
If it moves over a powered activator rail, you'll get ejected.=
|
||||
##[ carts/with_chest.lua ]##
|
||||
Minecart with Chest=Carrello da miniera con Baule
|
||||
##[ carts/with_commandblock.lua ]##
|
||||
Minecart with Command Block=Carrello da miniera con Blocco Comandi
|
||||
##[ carts/with_furnace.lua ]##
|
||||
Minecart with Furnace=Carrello da miniera con Fornace
|
||||
A minecart with furnace is a vehicle that travels on rails. It can propel itself with fuel.=Un carrello ca miniera con fornace è un veicolo che viaggia su binari. Può essere alimentato con del carburante.
|
||||
Place it on rails. If you give it some coal, the furnace will start burning for a long time and the minecart will be able to move itself. Punch it to get it moving.=Piazzalo su binari. Se gli darai del carbone, la fornace inizierà a bruciare per un lungo periodo e il carrello da miniera sarà in grado di muoversi da solo. Colpiscilo per avviarlo.
|
||||
To obtain the minecart and furnace, punch them while holding down the sneak key.=Per ottenere il carrello e la fornace, colpiscili tenendo premuto il pulsante per accovacciarti.
|
||||
##[ carts/with_hopper.lua ]##
|
||||
Minecart with Hopper=Carrello da miniera con Tramoggia
|
||||
##[ carts/with_tnt.lua ]##
|
||||
Minecart with TNT=Carrello da miniera con TNT
|
||||
Can be ignited by tools or powered activator rail=Può essere acceso da strumenti o binari attivatori
|
||||
A minecart with TNT is an explosive vehicle that travels on rail.=Un carrello da miniera con la TNT è un veicolo esplosivo che viaggia su binari.
|
||||
Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.=Piazzalo sui binari. Colpiscilo per spostarlo. La TNT viene accesa con l'acciarino o quando il carrello passa su un binario attivatore
|
||||
To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited.=Per ottenere il carrello da miniera e la TNT, colpiscili tenendo premuto il tasto per accovacciarti. Non puoi farlo se la TNT è stata accesa.
|
||||
##[ rails.lua ]##
|
||||
Place them on the ground to build your railway, the rails will automatically connect to each other and will turn into curves, T-junctions, crossings and slopes as needed.=Piazzali sul terreno per costruire la tua ferrovia, i binari si collegheranno automaticamente tra di loro, cambiando in curve, incroci a T, incroci e pendenze quando necessario.
|
||||
New Rail=
|
||||
Track for minecarts=Tracciato per carrelli da miniera
|
||||
Rails can be used to build transport tracks for minecarts. Normal rails slightly slow down minecarts due to friction.=I binari possono essere usati per costruire percorsi per i carrelli da miniera. I binari semplici rallentano leggermente i carrelli da miniera per via dell'attrito.
|
||||
Sloped Rail=
|
||||
##[ rails/activator.lua ]##
|
||||
Activator Rail=Binario Attivatore
|
||||
Activates minecarts when powered=Attiva i carrelli da miniera quando alimentato
|
||||
Rails can be used to build transport tracks for minecarts. Activator rails are used to activate special minecarts.=I binari possono essere usati per costruire percorsi per i carrelli da miniera. I binari attivatori sono usati per attivare particolari carrelli da miniera.
|
||||
To make this rail activate minecarts, power it with redstone power and send a minecart over this piece of rail.=Per far sì che questo binario attivi i carrelli da miniera, alimentalo con della redstone e manda un carrello da miniera su questo pezzo di binario.
|
||||
##[ rails/detector.lua ]##
|
||||
Detector Rail=Binario rilevatore
|
||||
Emits redstone power when a minecart is detected=Emette energia di redstone quando una carrello da miniera è rilevato
|
||||
Rails can be used to build transport tracks for minecarts. A detector rail is able to detect a minecart above it and powers redstone mechanisms.=I binari possono essere usati per costruire percorsi per i carrelli da miniera. Un binario rilevatore è in grado di rilevare il passaggio di un carrello da miniera e attivare un circuito di redstone.
|
||||
To detect a minecart and provide redstone power, connect it to redstone trails or redstone mechanisms and send any minecart over the rail.=Per rilevare un carrello da miniera e fornire energia di redstone, collagalo a delle tracce di redstone o dei meccanismi di redstone e manda un carrello da miniera sopra il binario.
|
||||
##[ rails/normal.lua ]##
|
||||
Rail=Binario
|
||||
##[ rails/powered.lua ]##
|
||||
Powered Rail=Binario Alimentato
|
||||
Speed up when powered, slow down when not powered=Accelera quando alimentato, rallenta quando non alimentato
|
||||
Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts.=I binari possono essere usati per costruire percorsi per i carrelli da miniera. I binari alimentati possono accelerare e frenare i carrelli da miniera.
|
||||
Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power.=Senza alimentazione da redstone, il binario romperà il carrello da miniera. Per far sì che questo binario acceleri i carrelli da miniera, alimentalo con della redstone.
|
@ -1,36 +1,50 @@
|
||||
# textdomain: mcl_minecarts
|
||||
##[ carts/minecart.lua ]##
|
||||
Sneak to dismount=スニークで降りる
|
||||
Minecart=トロッコ
|
||||
Vehicle for fast travel on rails=レール上を快速移動するための車両
|
||||
Minecarts can be used for a quick transportion on rails.=トロッコは、レールを使った高速輸送を可能にします。
|
||||
Minecarts only ride on rails and always follow the tracks. At a T-junction with no straight way ahead, they turn left. The speed is affected by the rail type.=トロッコはレール上にしか乗らない為、常に線路に沿って走ります。直進できない丁字路では、取り敢えず左折します。速度はレールの種類によって異なります。
|
||||
You can place the minecart on rails. Right-click it to enter it. Punch it to get it moving.=レールの上にトロッコを置けます。右クリックで乗り込みます。パンチすると動き出します。
|
||||
To obtain the minecart, punch it while holding down the sneak key.=トロッコを入手するには、スニークキーを押しながらパンチします。
|
||||
A minecart with TNT is an explosive vehicle that travels on rail.=TNT付きトロッコは、レール上を行きかう爆薬車両です。
|
||||
Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.=レール上に配置。パンチで移動。TNTが着火するのは、火打石と打金を使った時か、稼動中のアクティベーターレール上にトロッコが乗った時です。
|
||||
To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited.=トロッコとTNTを入手するには、スニークキーを押しながらパンチしてください。TNTに火が着いていた場合は、無理です。
|
||||
If it moves over a powered activator rail, you'll get ejected.=
|
||||
##[ carts/with_chest.lua ]##
|
||||
Minecart with Chest=チェスト付きトロッコ
|
||||
##[ carts/with_commandblock.lua ]##
|
||||
Minecart with Command Block=コマンドブロック付きトロッコ
|
||||
##[ carts/with_furnace.lua ]##
|
||||
Minecart with Furnace=かまど付きトロッコ
|
||||
A minecart with furnace is a vehicle that travels on rails. It can propel itself with fuel.=かまど付きトロッコは、レール上を走行する車両です。燃料で自走できます。
|
||||
Place it on rails. If you give it some coal, the furnace will start burning for a long time and the minecart will be able to move itself. Punch it to get it moving.=レールの上に置きます。石炭を与えると、かまどが長時間燃え続け、トロッコが自走可能になります。パンチすると動き出します。
|
||||
To obtain the minecart and furnace, punch them while holding down the sneak key.=トロッコとかまどを入手するには、スニークキーを押しながらパンチします。
|
||||
Minecart with Chest=チェスト付きトロッコ
|
||||
Minecart with Furnace=かまど付きトロッコ
|
||||
Minecart with Command Block=コマンドブロック付きトロッコ
|
||||
##[ carts/with_hopper.lua ]##
|
||||
Minecart with Hopper=ホッパー付きトロッコ
|
||||
##[ carts/with_tnt.lua ]##
|
||||
Minecart with TNT=TNT付きトロッコ
|
||||
Can be ignited by tools or powered activator rail=道具や稼動中のアクティベーターレールにより着火が可能
|
||||
A minecart with TNT is an explosive vehicle that travels on rail.=TNT付きトロッコは、レール上を行きかう爆薬車両です。
|
||||
Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.=レール上に配置。パンチで移動。TNTが着火するのは、火打石と打金を使った時か、稼動中のアクティベーターレール上にトロッコが乗った時です。
|
||||
To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited.=トロッコとTNTを入手するには、スニークキーを押しながらパンチしてください。TNTに火が着いていた場合は、無理です。
|
||||
##[ rails.lua ]##
|
||||
Place them on the ground to build your railway, the rails will automatically connect to each other and will turn into curves, T-junctions, crossings and slopes as needed.=地面に置いて線路を作ると、レール同士が自動的につながり、必要に応じてカーブや丁字路、踏切、坂道などに変化します。
|
||||
Rail=レール
|
||||
New Rail=
|
||||
Track for minecarts=トロッコ用の線路
|
||||
Rails can be used to build transport tracks for minecarts. Normal rails slightly slow down minecarts due to friction.=レールを利用して、トロッコの輸送路が敷けます。普通のレールは、摩擦の関係でトロッコが少しずつ減速していきます。
|
||||
Powered Rail=パワードレール
|
||||
Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts.=レールを利用して、トロッコの輸送路が敷けます。パワードレールは、トロッコを加速させたり、ブレーキをかけたりできます。
|
||||
Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power.=レッドストーン動力なしだと、このレールはトロッコにブレーキをかけます。このレールでトロッコを加速させるには、レッドストーン動力を供給してください。
|
||||
Sloped Rail=
|
||||
##[ rails/activator.lua ]##
|
||||
Activator Rail=アクティベーターレール
|
||||
Activates minecarts when powered=稼動中はトロッコを作動
|
||||
Rails can be used to build transport tracks for minecarts. Activator rails are used to activate special minecarts.=レールを利用して、トロッコの輸送路が敷けます。アクティベーターレールは、特殊なトロッコを作動させるために使われます。
|
||||
To make this rail activate minecarts, power it with redstone power and send a minecart over this piece of rail.=このレールでトロッコを作動させるには、レッドストーン動力を与えたレール上にトロッコを送り込みます。
|
||||
##[ rails/detector.lua ]##
|
||||
Detector Rail=
|
||||
Emits redstone power when a minecart is detected=トロッコを検知するとレッドストーン動力を放出
|
||||
Rails can be used to build transport tracks for minecarts. A detector rail is able to detect a minecart above it and powers redstone mechanisms.=レールを利用して、トロッコの輸送路が敷けます。ディテクターレールは、その上にあるトロッコを検知でき、その際レッドストーン機構の動力源となります。
|
||||
To detect a minecart and provide redstone power, connect it to redstone trails or redstone mechanisms and send any minecart over the rail.=トロッコを検知してレッドストーン動力を供給するには、レッドストーン導線またはレッドストーン機構に接続し、任意のトロッコをレール上に送り込みます。
|
||||
Track for minecarts=トロッコ用の線路
|
||||
##[ rails/normal.lua ]##
|
||||
Rail=レール
|
||||
##[ rails/powered.lua ]##
|
||||
Powered Rail=パワードレール
|
||||
Speed up when powered, slow down when not powered=稼動中は加速、非稼動中は減速
|
||||
Activates minecarts when powered=稼動中はトロッコを作動
|
||||
Emits redstone power when a minecart is detected=トロッコを検知するとレッドストーン動力を放出
|
||||
Vehicle for fast travel on rails=レール上を快速移動するための車両
|
||||
Can be ignited by tools or powered activator rail=道具や稼動中のアクティベーターレールにより着火が可能
|
||||
Sneak to dismount=スニークで降りる
|
||||
Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts.=レールを利用して、トロッコの輸送路が敷けます。パワードレールは、トロッコを加速させたり、ブレーキをかけたりできます。
|
||||
Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power.=レッドストーン動力なしだと、このレールはトロッコにブレーキをかけます。このレールでトロッコを加速させるには、レッドストーン動力を供給してください。
|
||||
|
@ -1,36 +1,50 @@
|
||||
# textdomain: mcl_minecarts
|
||||
##[ carts/minecart.lua ]##
|
||||
Sneak to dismount=Se baissar per descendre
|
||||
Minecart=Vagonet
|
||||
Vehicle for fast travel on rails=Veicule per voiatjar vistament per ralhs.
|
||||
Minecarts can be used for a quick transportion on rails.=Los vagonet pòdon èsser utilizats per un transpòrt rapide per ralhs.
|
||||
Minecarts only ride on rails and always follow the tracks. At a T-junction with no straight way ahead, they turn left. The speed is affected by the rail type.=Los vagonets ròtlon mas per ralhs e seguisson totjorn la pista. A una joncion T embei ren davant, tòrnon a gaucha.
|
||||
You can place the minecart on rails. Right-click it to enter it. Punch it to get it moving.=Podètz plaçar le vagonet per ralhs. Fasetz un clic dreit dessobre per çai rentrar. Tustatz z-o per z-o faire bojar.
|
||||
To obtain the minecart, punch it while holding down the sneak key.=Per aver le vagonet, tustatz z-o embei la tocha sneak enfonçada.
|
||||
A minecart with TNT is an explosive vehicle that travels on rail.=Un vagonet embei TNT z-es un vagonet explosiu que voiatja per ralhs.
|
||||
Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.=Plaçatz z-o per ralhs. Tustatz z-o per z-o desplaçar. La TNT z-es atubada embei un batifuòc o quand le vagonet z-es per un ralh d'activacion atubat.
|
||||
To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited.=Per obtenèr le vagonet e la TNT, tustatz z-o embei la tocha sneak enfonçada. Podètz pas faire quo si la TNT z-es atubada.
|
||||
If it moves over a powered activator rail, you'll get ejected.=
|
||||
##[ carts/with_chest.lua ]##
|
||||
Minecart with Chest=Vagonet embei una Mala
|
||||
##[ carts/with_commandblock.lua ]##
|
||||
Minecart with Command Block=Vagonet embei un Blòc de Comandas
|
||||
##[ carts/with_furnace.lua ]##
|
||||
Minecart with Furnace=Vagonet embei un Fornil
|
||||
A minecart with furnace is a vehicle that travels on rails. It can propel itself with fuel.=Un vagonet embei un fornil z-es un veïcule que voiatja per ralhs. Pòt se propulsar embei dau carburant.
|
||||
Place it on rails. If you give it some coal, the furnace will start burning for a long time and the minecart will be able to move itself. Punch it to get it moving.=Plaçatz z-o per ralhs. Si li balhatz dau charbon, le fornil vai començar de borlar lòngtemps e porà rotlar. Tustatz z-o per z-o faire bojar.
|
||||
To obtain the minecart and furnace, punch them while holding down the sneak key.=Per obtener le vagonet e le fornil, tustatz z-o embei la tocha sneak enfonçada.
|
||||
Minecart with Chest=Vagonet embei una Mala
|
||||
Minecart with Furnace=Vagonet embei un Fornil
|
||||
Minecart with Command Block=Vagonet embei un Blòc de Comandas
|
||||
##[ carts/with_hopper.lua ]##
|
||||
Minecart with Hopper=Vagonet embei un Embure
|
||||
##[ carts/with_tnt.lua ]##
|
||||
Minecart with TNT=Vagonet embei de la TNT
|
||||
Can be ignited by tools or powered activator rail=Pòt èsser atubat embei daus otilhs o un ralh d'activacion
|
||||
A minecart with TNT is an explosive vehicle that travels on rail.=Un vagonet embei TNT z-es un vagonet explosiu que voiatja per ralhs.
|
||||
Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.=Plaçatz z-o per ralhs. Tustatz z-o per z-o desplaçar. La TNT z-es atubada embei un batifuòc o quand le vagonet z-es per un ralh d'activacion atubat.
|
||||
To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited.=Per obtenèr le vagonet e la TNT, tustatz z-o embei la tocha sneak enfonçada. Podètz pas faire quo si la TNT z-es atubada.
|
||||
##[ rails.lua ]##
|
||||
Place them on the ground to build your railway, the rails will automatically connect to each other and will turn into curves, T-junctions, crossings and slopes as needed.=Plaçatz z-o per sòu per construrre vostre chamin de fèrre, los ralhs se conectaron entre ilhs e faron de las corbas, de las junccions en T, en traversadas et en pentas au besonh.
|
||||
Rail=Ralh
|
||||
New Rail=
|
||||
Track for minecarts=Pista per vagonets
|
||||
Rails can be used to build transport tracks for minecarts. Normal rails slightly slow down minecarts due to friction.=Los ralhs pòdon èsser utilizats per construrre los chamins de transpòrt per los vagonets. Los ralhs normaus ralentissons gentament los vagonet per causa de friccion.
|
||||
Powered Rail=Ralh Atubat
|
||||
Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts.=Los ralhs pòdon èsser utilizats per construrre los chamins de transpòrt per los vagonets. Los ralhs atubats son per faire accelerar o frenar los vagonets.
|
||||
Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power.=Sens energia de pèirotge, le ralh vai frenar los vagonets. Per que le ralh accelera los vagonets, alimentatz z-o embei de l'energia de pèirotge.
|
||||
Sloped Rail=
|
||||
##[ rails/activator.lua ]##
|
||||
Activator Rail=Ralh d'Activacion
|
||||
Activates minecarts when powered=Activa los vagonets quand pas atubat.
|
||||
Rails can be used to build transport tracks for minecarts. Activator rails are used to activate special minecarts.=Los ralhs pòdon èsser utilizats per construrre los chamins de transpòrt per los vagonets. Los ralhs d'activacion son utilizats per activar daus vagonets speciaus.
|
||||
To make this rail activate minecarts, power it with redstone power and send a minecart over this piece of rail.=Per activar le ralh, alimentatz z-o embei de l'energia de pèirotge e fasetz rotlar un vagonet per aqueste ralh.
|
||||
##[ rails/detector.lua ]##
|
||||
Detector Rail=Ralh de Deteccion
|
||||
Emits redstone power when a minecart is detected=Emeta de l'energia de pèirotge quand un vagonet z-es detectat.
|
||||
Rails can be used to build transport tracks for minecarts. A detector rail is able to detect a minecart above it and powers redstone mechanisms.=Los ralhs pòdon èsser utilizats per construirre los chamins de transpòrt per los vagonets. Los ralhs de deteccion pòdon detectar un vagonet per ilhs e atubar un mecanisme de pèirotge.
|
||||
To detect a minecart and provide redstone power, connect it to redstone trails or redstone mechanisms and send any minecart over the rail.=Per detectar un vagonet e produrre de l'energia de pèirotge, conectatz le ralh a de la pèirotge e fasetz rotlar un vagonet per i-aul.
|
||||
Track for minecarts=Pista per vagonets
|
||||
##[ rails/normal.lua ]##
|
||||
Rail=Ralh
|
||||
##[ rails/powered.lua ]##
|
||||
Powered Rail=Ralh Atubat
|
||||
Speed up when powered, slow down when not powered=Acceleratz quand z-es atubat, ralentissetz quand z-es pas atubat.
|
||||
Activates minecarts when powered=Activa los vagonets quand pas atubat.
|
||||
Emits redstone power when a minecart is detected=Emeta de l'energia de pèirotge quand un vagonet z-es detectat.
|
||||
Vehicle for fast travel on rails=Veicule per voiatjar vistament per ralhs.
|
||||
Can be ignited by tools or powered activator rail=Pòt èsser atubat embei daus otilhs o un ralh d'activacion
|
||||
Sneak to dismount=Se baissar per descendre
|
||||
Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts.=Los ralhs pòdon èsser utilizats per construrre los chamins de transpòrt per los vagonets. Los ralhs atubats son per faire accelerar o frenar los vagonets.
|
||||
Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power.=Sens energia de pèirotge, le ralh vai frenar los vagonets. Per que le ralh accelera los vagonets, alimentatz z-o embei de l'energia de pèirotge.
|
||||
|
@ -1,36 +1,50 @@
|
||||
# textdomain: mcl_minecarts
|
||||
##[ carts/minecart.lua ]##
|
||||
Sneak to dismount=Zacznij się skradać by zejść
|
||||
Minecart=Wagonik
|
||||
Vehicle for fast travel on rails=Pojazd do szybkiej podróży na torach
|
||||
Minecarts can be used for a quick transportion on rails.=Wagoniki mogą być użyte do szybkiego transportu po torach.
|
||||
Minecarts only ride on rails and always follow the tracks. At a T-junction with no straight way ahead, they turn left. The speed is affected by the rail type.=Wagoniki mogą jeździć tylko po torach i zawsze podążają za wytyczoną ścieżką. W przypadku skrzyżowań typu T, gdzie nie ma prostej ścieżki, skręcają w lew. Ich szybkość zależy od typu torów.
|
||||
You can place the minecart on rails. Right-click it to enter it. Punch it to get it moving.=Możesz postawić wagonik na torach. Kliknij prawym przyciskiem myszy aby do niego wejść. Uderz go by zaczął się poruszać.
|
||||
To obtain the minecart, punch it while holding down the sneak key.=Aby odzyskać wagonik uderz go podczas skradania.
|
||||
A minecart with TNT is an explosive vehicle that travels on rail.=Wagonik z TNT jest wybuchowym pojazdem podróżującym po torach.
|
||||
Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.=Postaw go na torach. Uderz by zaczął się poruszać. TNT zapala się krzesiwem lub gdy wagonik jest na zasilonych torach aktywacyjnych.
|
||||
To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited.=Aby odzyskać wagonik z TNT uderz go podczas skradania. Nie możesz tego zrobić gdy TNT jest zapalone.
|
||||
If it moves over a powered activator rail, you'll get ejected.=
|
||||
##[ carts/with_chest.lua ]##
|
||||
Minecart with Chest=Wagonik ze skrzynią
|
||||
##[ carts/with_commandblock.lua ]##
|
||||
Minecart with Command Block=Wagonik z blokiem poleceń
|
||||
##[ carts/with_furnace.lua ]##
|
||||
Minecart with Furnace=Wagonik z piecem
|
||||
A minecart with furnace is a vehicle that travels on rails. It can propel itself with fuel.=Wagonik z piecem jest pojazdem podróżującym na torach. Napędza on samego siebie za pomocą paliwa.
|
||||
Place it on rails. If you give it some coal, the furnace will start burning for a long time and the minecart will be able to move itself. Punch it to get it moving.=Postaw go na torach. Jeśli dasz mu nieco węgla piec zacznie palić przez długi czas, a wagonik będzie się sam poruszał. Uderz go by zaczął się poruszać.
|
||||
To obtain the minecart and furnace, punch them while holding down the sneak key.=Aby odzyskać wagonik z piecem uderz go podczas skradania.
|
||||
Minecart with Chest=Wagonik ze skrzynią
|
||||
Minecart with Furnace=Wagonik z piecem
|
||||
Minecart with Command Block=Wagonik z blokiem poleceń
|
||||
##[ carts/with_hopper.lua ]##
|
||||
Minecart with Hopper=Wagonik z lejem
|
||||
##[ carts/with_tnt.lua ]##
|
||||
Minecart with TNT=Wagonik z TNT
|
||||
Can be ignited by tools or powered activator rail=Może być zapalony przez narzędzia, lub zasilane tor aktywacyjne
|
||||
A minecart with TNT is an explosive vehicle that travels on rail.=Wagonik z TNT jest wybuchowym pojazdem podróżującym po torach.
|
||||
Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.=Postaw go na torach. Uderz by zaczął się poruszać. TNT zapala się krzesiwem lub gdy wagonik jest na zasilonych torach aktywacyjnych.
|
||||
To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited.=Aby odzyskać wagonik z TNT uderz go podczas skradania. Nie możesz tego zrobić gdy TNT jest zapalone.
|
||||
##[ rails.lua ]##
|
||||
Place them on the ground to build your railway, the rails will automatically connect to each other and will turn into curves, T-junctions, crossings and slopes as needed.=Postaw je na ziemi by zbudować ścieżkę z torów. Tory automatycznie połączą się ze sobą i zamienią się w zakręty, skrzyżowania typu T, skrzyżowania i równie w zależności od potrzeb.
|
||||
Rail=Tor
|
||||
New Rail=
|
||||
Track for minecarts=Tor dla wagoników
|
||||
Rails can be used to build transport tracks for minecarts. Normal rails slightly slow down minecarts due to friction.=Tory mogą być wykorzystane do zbudowania torów dla wagoników. Zwyczajne tory nieco spowalniają wagoniki ze względu na tarcie.
|
||||
Powered Rail=Zasilane tory
|
||||
Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts.=Tory mogą być wykorzystane do zbudowania torów dla wagoników. Zasilane tory mogą przyspieszać lub spowalniać wagoniki.
|
||||
Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power.=Bez zasilania czerwienitem tory będą spowalniać wagoniki. Aby sprawić by je przyspieszały zasil je czerwienitem.
|
||||
Sloped Rail=
|
||||
##[ rails/activator.lua ]##
|
||||
Activator Rail=Tory aktywacyjne
|
||||
Activates minecarts when powered=Aktywuje wagoniki gdy zasilane
|
||||
Rails can be used to build transport tracks for minecarts. Activator rails are used to activate special minecarts.=Tory mogą być wykorzystane do zbudowania torów dla wagoników. Tory aktywacyjne są wykorzystywane do aktywacji specjalnych wagoników.
|
||||
To make this rail activate minecarts, power it with redstone power and send a minecart over this piece of rail.=Aby ten tor aktywował wagonik, zasil go czerwienitem i spraw by wagonik po nim przejechał.
|
||||
##[ rails/detector.lua ]##
|
||||
Detector Rail=Tory z czujnikiem
|
||||
Emits redstone power when a minecart is detected=Emituje zasilanie czerwienitem gdy wagonik jest wykryty
|
||||
Rails can be used to build transport tracks for minecarts. A detector rail is able to detect a minecart above it and powers redstone mechanisms.=Tory mogą być wykorzystane do zbudowania torów dla wagoników. Tory z czujnikiem są w stanie wykryć kiedy wagonik po nich przejeżdża i wysłać sygnał do czerwienitowych mechanizmów.
|
||||
To detect a minecart and provide redstone power, connect it to redstone trails or redstone mechanisms and send any minecart over the rail.=Aby wykryć wagonik i dostarczyć zasilanie czerwienitem podłącz go czerwienitem to mechanizmu i spraw by wagonik po nim przejechał.
|
||||
Track for minecarts=Tor dla wagoników
|
||||
##[ rails/normal.lua ]##
|
||||
Rail=Tor
|
||||
##[ rails/powered.lua ]##
|
||||
Powered Rail=Zasilane tory
|
||||
Speed up when powered, slow down when not powered=Przyspiesza gdy zasilane, spowalnia gdy nie
|
||||
Activates minecarts when powered=Aktywuje wagoniki gdy zasilane
|
||||
Emits redstone power when a minecart is detected=Emituje zasilanie czerwienitem gdy wagonik jest wykryty
|
||||
Vehicle for fast travel on rails=Pojazd do szybkiej podróży na torach
|
||||
Can be ignited by tools or powered activator rail=Może być zapalony przez narzędzia, lub zasilane tor aktywacyjne
|
||||
Sneak to dismount=Zacznij się skradać by zejść
|
||||
Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts.=Tory mogą być wykorzystane do zbudowania torów dla wagoników. Zasilane tory mogą przyspieszać lub spowalniać wagoniki.
|
||||
Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power.=Bez zasilania czerwienitem tory będą spowalniać wagoniki. Aby sprawić by je przyspieszały zasil je czerwienitem.
|
||||
|
@ -1,36 +1,50 @@
|
||||
# textdomain: mcl_minecarts
|
||||
##[ carts/minecart.lua ]##
|
||||
Sneak to dismount=Agache para desmontar
|
||||
Minecart=Carrinho
|
||||
Vehicle for fast travel on rails=Veículo para viajar rápido em trilhos
|
||||
Minecarts can be used for a quick transportion on rails.=Carrinhos podem ser usados para transporte rápido em trilhos.
|
||||
Minecarts only ride on rails and always follow the tracks. At a T-junction with no straight way ahead, they turn left. The speed is affected by the rail type.=Carrinhos viajam somente em trilhos e sempre seguem os traçados. Em uma junção em T sem linha reta à frente, eles viram à esquerda. A velocidade é afetada pelo tipo do trilho.
|
||||
You can place the minecart on rails. Right-click it to enter it. Punch it to get it moving.=Você pode posicionar o carrinho em trilhos. Clique com o botão direito para entrar nele. Soque-o para fazê-lo mover.
|
||||
To obtain the minecart, punch it while holding down the sneak key.=Para obter o carrinho, soque-o enquanto segura pressionada a tecla de agachar.
|
||||
A minecart with TNT is an explosive vehicle that travels on rail.=Um carrinho com TNT é um veículo explosivo que viaja nos trilhos.
|
||||
Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.=Posicione-o nos trilhos. Soque-o para movê-lo. A TNT é acesa com um isqueiro ou quando o carrinho está sobre um trilho ativador energizado.
|
||||
To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited.=Para obter o carrinho e a TNT, soque-os enquanto segura pressionada a tecla de agachar. Você não consegue fazer isso se a TNT foi acesa.
|
||||
If it moves over a powered activator rail, you'll get ejected.=
|
||||
##[ carts/with_chest.lua ]##
|
||||
Minecart with Chest=Carrinho com Baú
|
||||
##[ carts/with_commandblock.lua ]##
|
||||
Minecart with Command Block=Carrinho com Bloco de Comandos
|
||||
##[ carts/with_furnace.lua ]##
|
||||
Minecart with Furnace=Carrinho com Fornalha
|
||||
A minecart with furnace is a vehicle that travels on rails. It can propel itself with fuel.=Um carrinho com fornalha é um veículo que viaja nos trilhos. Se move por conta própria com combustível.
|
||||
Place it on rails. If you give it some coal, the furnace will start burning for a long time and the minecart will be able to move itself. Punch it to get it moving.=Posicione-o nos trilhos. Se você o der um pouco de carvão, a fornalha vai começar a queimar por um longo tempo e o carrinho será capaz de se mover por conta própria. Soque-o para fazê-lo mover.
|
||||
To obtain the minecart and furnace, punch them while holding down the sneak key.=Para obter o carrinho e a fornalha, soque-os enquanto segura pressionada a tecla de agachar.
|
||||
Minecart with Chest=Carrinho com Baú
|
||||
Minecart with Furnace=Carrinho com Fornalha
|
||||
Minecart with Command Block=Carrinho com Bloco de Comandos
|
||||
##[ carts/with_hopper.lua ]##
|
||||
Minecart with Hopper=Carrinho com Funil
|
||||
##[ carts/with_tnt.lua ]##
|
||||
Minecart with TNT=Carrinho com TNT
|
||||
Can be ignited by tools or powered activator rail=Pode ser aceso por ferramentas ou trilho ativador energizado
|
||||
A minecart with TNT is an explosive vehicle that travels on rail.=Um carrinho com TNT é um veículo explosivo que viaja nos trilhos.
|
||||
Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.=Posicione-o nos trilhos. Soque-o para movê-lo. A TNT é acesa com um isqueiro ou quando o carrinho está sobre um trilho ativador energizado.
|
||||
To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited.=Para obter o carrinho e a TNT, soque-os enquanto segura pressionada a tecla de agachar. Você não consegue fazer isso se a TNT foi acesa.
|
||||
##[ rails.lua ]##
|
||||
Place them on the ground to build your railway, the rails will automatically connect to each other and will turn into curves, T-junctions, crossings and slopes as needed.=Posicione-os no chão para construir suas linhas férreas, os trilhos vão conectar-se automaticamente uns nos outros e vão se transformar em curvas, junções em T, cruzamentos e rampas quando necessário.
|
||||
Rail=Trilho
|
||||
New Rail=
|
||||
Track for minecarts=Traçado para carrinhos
|
||||
Rails can be used to build transport tracks for minecarts. Normal rails slightly slow down minecarts due to friction.=Trilhos podem ser usados para construir traçados de transporte para carrinhos. Trilhos normais freiam carrinhos gradativamente devido ao atrito.
|
||||
Powered Rail=Trilho Energizador
|
||||
Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts.=Trilhos podem ser usados para construir traçados de transporte para carrinhos. Trilhos energizados são capazes de acelerar e frear carrinhos.
|
||||
Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power.=Sem carga de redstone, o trilho vai frear os carrinhos. Para fazer o trilho acelerar os carrinhos, energize-o com uma carga de redstone.
|
||||
Sloped Rail=
|
||||
##[ rails/activator.lua ]##
|
||||
Activator Rail=Trilho Ativador
|
||||
Activates minecarts when powered=Ativa carrinhos quando energizado
|
||||
Rails can be used to build transport tracks for minecarts. Activator rails are used to activate special minecarts.=Trilhos podem ser usados para construir traçados de transporte para carrinhos. Trilhos ativadores são usados para ativar carrinhos especiais.
|
||||
To make this rail activate minecarts, power it with redstone power and send a minecart over this piece of rail.=Para fazer esse trilho ativar os carrinhos, energize-o com uma carga de redstone e envie um carrinho sobre esse pedaço de trilho.
|
||||
##[ rails/detector.lua ]##
|
||||
Detector Rail=Trilho Detector
|
||||
Emits redstone power when a minecart is detected=Emite carga de redstone quando um carrinho é detectado
|
||||
Rails can be used to build transport tracks for minecarts. A detector rail is able to detect a minecart above it and powers redstone mechanisms.=Trilhos podem ser usados para construir traçados de transporte para carrinhos. Um trilho detector é capaz de detectar um carrinho sobre ele e energizar mecanismos de redstone.
|
||||
To detect a minecart and provide redstone power, connect it to redstone trails or redstone mechanisms and send any minecart over the rail.=Para detectar um carrinho e providenciar carga de redstone, conecte-o em trilhas de redstone ou mecanismos de redstone e envie qualquer carrinho sobre esse trilho.
|
||||
Track for minecarts=Traçado para carrinhos
|
||||
##[ rails/normal.lua ]##
|
||||
Rail=Trilho
|
||||
##[ rails/powered.lua ]##
|
||||
Powered Rail=Trilho Energizador
|
||||
Speed up when powered, slow down when not powered=Acelera quando energizado, desacelera quando não energizado
|
||||
Activates minecarts when powered=Ativa carrinhos quando energizado
|
||||
Emits redstone power when a minecart is detected=Emite carga de redstone quando um carrinho é detectado
|
||||
Vehicle for fast travel on rails=Veículo para viajar rápido em trilhos
|
||||
Can be ignited by tools or powered activator rail=Pode ser aceso por ferramentas ou trilho ativador energizado
|
||||
Sneak to dismount=Agache para desmontar
|
||||
Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts.=Trilhos podem ser usados para construir traçados de transporte para carrinhos. Trilhos energizados são capazes de acelerar e frear carrinhos.
|
||||
Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power.=Sem carga de redstone, o trilho vai frear os carrinhos. Para fazer o trilho acelerar os carrinhos, energize-o com uma carga de redstone.
|
||||
|
@ -1,36 +1,50 @@
|
||||
# textdomain: mcl_minecarts
|
||||
##[ carts/minecart.lua ]##
|
||||
Sneak to dismount=Нажмите [Красться] для высадки
|
||||
Minecart=Вагонетка
|
||||
Vehicle for fast travel on rails=Железнодорожный транспорт
|
||||
Minecarts can be used for a quick transportion on rails.=Вагонетка может быть использована для быстрого перемещения по рельсам.
|
||||
Minecarts only ride on rails and always follow the tracks. At a T-junction with no straight way ahead, they turn left. The speed is affected by the rail type.=Вагонетки едут только по проложенным рельсам. На Т-образной развилке они поворачивают налево. Скорость зависит от типа рельсов.
|
||||
You can place the minecart on rails. Right-click it to enter it. Punch it to get it moving.=Вы можете поставить вагонетку на рельсы. Правым кликом сядьте в неё. Ударьте по ней, чтобы она поехала.
|
||||
To obtain the minecart, punch it while holding down the sneak key.=Чтобы забрать вагонетку, ударьте по ней, удерживая клавишу [Красться].
|
||||
A minecart with TNT is an explosive vehicle that travels on rail.=Вагонетка с ТНТ это взрывающийся железнодорожный транспорт.
|
||||
Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.=Поместите вагонетку на рельсы. Ударьте по ней, чтобы она поехала. ТНТ активируется, если его поджечь огнивом или когда вагонетка проедет через подключенные активирующие рельсы.
|
||||
To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited.=Чтобы забрать вагонетку с ТНТ, ударьте по ней, удерживая клавишу [Красться]. Если ТНТ подожжён, сделать это нельзя.
|
||||
If it moves over a powered activator rail, you'll get ejected.=
|
||||
##[ carts/with_chest.lua ]##
|
||||
Minecart with Chest=Вагонетка с сундуком
|
||||
##[ carts/with_commandblock.lua ]##
|
||||
Minecart with Command Block=Вагонетка с командным блоком
|
||||
##[ carts/with_furnace.lua ]##
|
||||
Minecart with Furnace=Вагонетка с печью
|
||||
A minecart with furnace is a vehicle that travels on rails. It can propel itself with fuel.=Вагонетка с печью это железнодорожный транспорт. Она может ехать сама за счёт топлива.
|
||||
Place it on rails. If you give it some coal, the furnace will start burning for a long time and the minecart will be able to move itself. Punch it to get it moving.=Поставьте вагонетку на рельсы. Если добавить в неё угля, то печь будет гореть продолжительное время и вагонетка сможет поехать сама. Ударьте по ней, чтобы она поехала.
|
||||
To obtain the minecart and furnace, punch them while holding down the sneak key.=Чтобы забрать вагонетку с печью, ударьте по ней, удерживая клавишу [Красться].
|
||||
Minecart with Chest=Вагонетка с сундуком
|
||||
Minecart with Furnace=Вагонетка с печью
|
||||
Minecart with Command Block=Вагонетка с командным блоком
|
||||
##[ carts/with_hopper.lua ]##
|
||||
Minecart with Hopper=Вагонетка с воронкой
|
||||
##[ carts/with_tnt.lua ]##
|
||||
Minecart with TNT=Вагонетка с ТНТ
|
||||
Can be ignited by tools or powered activator rail=Можно поджечь инструментом или активирующими рельсами
|
||||
A minecart with TNT is an explosive vehicle that travels on rail.=Вагонетка с ТНТ это взрывающийся железнодорожный транспорт.
|
||||
Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.=Поместите вагонетку на рельсы. Ударьте по ней, чтобы она поехала. ТНТ активируется, если его поджечь огнивом или когда вагонетка проедет через подключенные активирующие рельсы.
|
||||
To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited.=Чтобы забрать вагонетку с ТНТ, ударьте по ней, удерживая клавишу [Красться]. Если ТНТ подожжён, сделать это нельзя.
|
||||
##[ rails.lua ]##
|
||||
Place them on the ground to build your railway, the rails will automatically connect to each other and will turn into curves, T-junctions, crossings and slopes as needed.=Поместите рельсы на землю, чтобы сделать железную дорогу, рельсы автоматически соединятся между собой и будут образовывать повороты, T-образные развилки, перекрёстки и склоны там, где это потребуется.
|
||||
Rail=Рельсы
|
||||
New Rail=
|
||||
Track for minecarts=Железная дорога
|
||||
Rails can be used to build transport tracks for minecarts. Normal rails slightly slow down minecarts due to friction.=Рельсы используются для строительства железной дороги. Обычные рельсы немного замедляют движение вагонеток из-за трения.
|
||||
Powered Rail=Энергорельсы
|
||||
Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts.=Энергорельсы используются для строительства железной дороги. Энергорельсы могут ускорять и тормозить вагонетки.
|
||||
Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power.=Неподключенные энергорельсы замедляют вагонетки. Чтобы энергорельсы ускоряли вагонетки, проведите к ним сигнал редстоуна.
|
||||
Sloped Rail=
|
||||
##[ rails/activator.lua ]##
|
||||
Activator Rail=Активирующие рельсы
|
||||
Activates minecarts when powered=Активирует особые вагонетки, если подключены
|
||||
Rails can be used to build transport tracks for minecarts. Activator rails are used to activate special minecarts.=Активирующие рельсы используются для строительства железной дороги. Активирующие рельсы активируют некоторые особые вагонетки.
|
||||
To make this rail activate minecarts, power it with redstone power and send a minecart over this piece of rail.=Чтобы эти рельсы активировали вагонетки, подключите активирующие рельсы к сигналу редстоуна и направьте вагонетку через них.
|
||||
##[ rails/detector.lua ]##
|
||||
Detector Rail=Нажимные рельсы
|
||||
Emits redstone power when a minecart is detected=Подает сигнал редстоуна при обнаружении вагонетки
|
||||
Rails can be used to build transport tracks for minecarts. A detector rail is able to detect a minecart above it and powers redstone mechanisms.=Нажимные рельсы используются для строительства железной дороги. Нажимные рельсы реагируют на проезжающие по ним вагонетки и выдают сигнал для механизмов из редстоуна.
|
||||
To detect a minecart and provide redstone power, connect it to redstone trails or redstone mechanisms and send any minecart over the rail.=Подсоедините к нажимным рельсам редстоун или редстоуновые механизмы, чтобы активировать их когда по рельсам проезжает вагонетка.
|
||||
Track for minecarts=Железная дорога
|
||||
##[ rails/normal.lua ]##
|
||||
Rail=Рельсы
|
||||
##[ rails/powered.lua ]##
|
||||
Powered Rail=Энергорельсы
|
||||
Speed up when powered, slow down when not powered=Если подключены - ускоряют, если нет - тормозят
|
||||
Activates minecarts when powered=Активирует особые вагонетки, если подключены
|
||||
Emits redstone power when a minecart is detected=Подает сигнал редстоуна при обнаружении вагонетки
|
||||
Vehicle for fast travel on rails=Железнодорожный транспорт
|
||||
Can be ignited by tools or powered activator rail=Можно поджечь инструментом или активирующими рельсами
|
||||
Sneak to dismount=Нажмите [Красться] для высадки
|
||||
Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts.=Энергорельсы используются для строительства железной дороги. Энергорельсы могут ускорять и тормозить вагонетки.
|
||||
Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power.=Неподключенные энергорельсы замедляют вагонетки. Чтобы энергорельсы ускоряли вагонетки, проведите к ним сигнал редстоуна.
|
||||
|
50
mods/ENTITIES/mcl_minecarts/locale/mcl_minecarts.zh_CN.tr
Normal file
50
mods/ENTITIES/mcl_minecarts/locale/mcl_minecarts.zh_CN.tr
Normal file
@ -0,0 +1,50 @@
|
||||
# textdomain: mcl_minecarts
|
||||
##[ carts/minecart.lua ]##
|
||||
Sneak to dismount=潜行下车
|
||||
Minecart=矿车
|
||||
Vehicle for fast travel on rails=在轨道上快速行驶的车辆
|
||||
Minecarts can be used for a quick transportion on rails.=矿车可以在轨道上快速运输。
|
||||
Minecarts only ride on rails and always follow the tracks. At a T-junction with no straight way ahead, they turn left. The speed is affected by the rail type.=矿车只在轨道上行驶,并始终沿着轨道行驶。在前面没有直路的丁字路口,他们向左转。速度受轨道类型的影响。
|
||||
You can place the minecart on rails. Right-click it to enter it. Punch it to get it moving.=你可以把矿车放在轨道上。右键单击以输入它。击打它,让它动起来。
|
||||
To obtain the minecart, punch it while holding down the sneak key.=要获得矿车,按住潜行键击打它。
|
||||
If it moves over a powered activator rail, you'll get ejected.=
|
||||
##[ carts/with_chest.lua ]##
|
||||
Minecart with Chest=带有箱子的矿车
|
||||
##[ carts/with_commandblock.lua ]##
|
||||
Minecart with Command Block=带有命令方块的矿车
|
||||
##[ carts/with_furnace.lua ]##
|
||||
Minecart with Furnace=带有熔炉的矿车
|
||||
A minecart with furnace is a vehicle that travels on rails. It can propel itself with fuel.=带熔炉的矿车是一种在铁轨上行驶的车辆。它可以用燃料推动自己。
|
||||
Place it on rails. If you give it some coal, the furnace will start burning for a long time and the minecart will be able to move itself. Punch it to get it moving.=把它放在轨道上。如果你给它一些煤,炉子就会开始燃烧很长一段时间,矿车就能自己移动。击打它,让它动起来。
|
||||
To obtain the minecart and furnace, punch them while holding down the sneak key.=要获得矿车和熔炉,请在按住潜行键的同时击打它们。
|
||||
##[ carts/with_hopper.lua ]##
|
||||
Minecart with Hopper=漏斗矿车
|
||||
##[ carts/with_tnt.lua ]##
|
||||
Minecart with TNT=矿车和TNT炸药
|
||||
Can be ignited by tools or powered activator rail=可以通过工具和运行中的激活器轨道点火
|
||||
A minecart with TNT is an explosive vehicle that travels on rail.=装有TNT炸药的矿车是一种在铁路上行驶的爆炸物运输工具。
|
||||
Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.=把它放在轨道上。击打它来移动它。TNT炸药是用火石和钢铁点燃的,或者当矿车在动力激活器轨道上时。
|
||||
To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited.=要获得矿车和TNT,按住潜行键击打它们。如果炸药被点燃了,你就不能这么做。
|
||||
##[ rails.lua ]##
|
||||
Place them on the ground to build your railway, the rails will automatically connect to each other and will turn into curves, T-junctions, crossings and slopes as needed.=把它们放在地上来建造你的铁路,铁轨会自动连接起来,并根据需要变成曲线、T形路口、交叉路口和斜坡。
|
||||
New Rail=
|
||||
Track for minecarts=矿车的轨道
|
||||
Rails can be used to build transport tracks for minecarts. Normal rails slightly slow down minecarts due to friction.=铁轨可以用来建造矿车的运输轨道。正常轨道由于摩擦会使矿车稍微减速。
|
||||
Sloped Rail=
|
||||
##[ rails/activator.lua ]##
|
||||
Activator Rail=激活器轨道
|
||||
Activates minecarts when powered=通电时激活矿车
|
||||
Rails can be used to build transport tracks for minecarts. Activator rails are used to activate special minecarts.=铁轨可以用来建造矿车的运输轨道。激活轨道用于激活特殊矿车。
|
||||
To make this rail activate minecarts, power it with redstone power and send a minecart over this piece of rail.=要使这条轨道激活矿车,请用红石动力为其供电,然后把矿车送到这条轨道上。
|
||||
##[ rails/detector.lua ]##
|
||||
Detector Rail=探测器轨道
|
||||
Emits redstone power when a minecart is detected=当探测到矿车时发射红石能量
|
||||
Rails can be used to build transport tracks for minecarts. A detector rail is able to detect a minecart above it and powers redstone mechanisms.=铁轨可以用来建造矿车的运输轨道。探测轨道能够探测到其上方的矿车并为红石机械提供动力。
|
||||
To detect a minecart and provide redstone power, connect it to redstone trails or redstone mechanisms and send any minecart over the rail.=要探测矿车并提供红石动力,请将其连接到红石轨道或红石机制上,并将任何矿车发送到轨道上。
|
||||
##[ rails/normal.lua ]##
|
||||
Rail=轨道
|
||||
##[ rails/powered.lua ]##
|
||||
Powered Rail=动力轨道
|
||||
Speed up when powered, slow down when not powered=通电时加速,不通电时减速
|
||||
Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts.=铁轨可以用来建造矿车的运输轨道。动力轨道能够加速和制动矿车。
|
||||
Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power.=没有红石动力,铁轨会使矿车刹车。要让这条轨道加速矿车,就要用红石动力。
|
50
mods/ENTITIES/mcl_minecarts/locale/mcl_minecrarts.nb.tr
Normal file
50
mods/ENTITIES/mcl_minecarts/locale/mcl_minecrarts.nb.tr
Normal file
@ -0,0 +1,50 @@
|
||||
# textdomain: mcl_minecarts
|
||||
##[ carts/minecart.lua ]##
|
||||
Sneak to dismount=Snik for å gå ut
|
||||
Minecart=Gruvevogn
|
||||
Vehicle for fast travel on rails=Kjøretøy for rask reise langs skinner
|
||||
Minecarts can be used for a quick transportion on rails.=Gruvevogner kan brukes som rask transport via skinner
|
||||
Minecarts only ride on rails and always follow the tracks. At a T-junction with no straight way ahead, they turn left. The speed is affected by the rail type.=Gruvevogner kan bare kjøre på skinner og følger alltid sporet. I et T-kryss uten en rett vei forran seg, tar de til venstre. Farten anfektes av skinnetypen.
|
||||
You can place the minecart on rails. Right-click it to enter it. Punch it to get it moving.=Du kan plassere gruvevogner på skinner. Høyreklikk for å gå oppi. Slå den for å få den til å gå fremover.
|
||||
To obtain the minecart, punch it while holding down the sneak key.=For å plukke opp gruvevogna, slå den imenst du holder snikeknappen.
|
||||
If it moves over a powered activator rail, you'll get ejected.=
|
||||
##[ carts/with_chest.lua ]##
|
||||
Minecart with Chest=Gruvevogn med kiste
|
||||
##[ carts/with_commandblock.lua ]##
|
||||
Minecart with Command Block=Gruvevogn med kommandoblokk
|
||||
##[ carts/with_furnace.lua ]##
|
||||
Minecart with Furnace=Gruvevogn med ovn
|
||||
A minecart with furnace is a vehicle that travels on rails. It can propel itself with fuel.=En gruvevogn med ovn er et kjøretøy som reiser langs skinner. Den kan drive seg selv med drivstoff.
|
||||
Place it on rails. If you give it some coal, the furnace will start burning for a long time and the minecart will be able to move itself. Punch it to get it moving.=Plasser den på skinner. Hvis du gir den litt kull, vil ovnen begynne å brenne i lang tid og gruvevognen vil kunne bevege seg selv. Slå den for å få den i bevegelse.
|
||||
To obtain the minecart and furnace, punch them while holding down the sneak key.=For å plukke opp gruvevogna og ovnen, slå den imenst du holder snikeknappen.
|
||||
##[ carts/with_hopper.lua ]##
|
||||
Minecart with Hopper=Gruvevogn med trakt
|
||||
##[ carts/with_tnt.lua ]##
|
||||
Minecart with TNT=Gruvevogn med TNT
|
||||
Can be ignited by tools or powered activator rail=Kan antennes med verktøy eller en aktiv aktiveringsskinne
|
||||
A minecart with TNT is an explosive vehicle that travels on rail.=En gruvevogn med TNT er et eksplosivt kjøretøy som kjører langs skinner.
|
||||
Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.=Plasser den på skinner. Slå den for å bevege den. TNTen antennes med tennstål eller når gruvevognen kjører over en aktiv aktiveringsskinne.
|
||||
To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited.=For å plukke opp gruvevognen og TNTen, slå dem imenst du holder snikeknappen.
|
||||
##[ rails.lua ]##
|
||||
Place them on the ground to build your railway, the rails will automatically connect to each other and will turn into curves, T-junctions, crossings and slopes as needed.=Plasser dem på bakken for å bygge en jernbane, skinnene kobles automatisk til hverandre og blir til kurver, kryss og bakker etter behov.
|
||||
New Rail=
|
||||
Track for minecarts=Spor for gruvevogner
|
||||
Rails can be used to build transport tracks for minecarts. Normal rails slightly slow down minecarts due to friction.=Skinner kan brukes til å bygge transportspor for gruvevogner. Normale skinner bremser litt ned gruvevogner på grunn av friksjon.
|
||||
Sloped Rail=
|
||||
##[ rails/activator.lua ]##
|
||||
Activator Rail=Aktiveringsskinne
|
||||
Activates minecarts when powered=Aktiverer gruvevogner når tilført strøm
|
||||
Rails can be used to build transport tracks for minecarts. Activator rails are used to activate special minecarts.= Skinner kan brukes til å bygge transportspor for gruvevogner. Aktiveringsskinner brukes til å aktivere spesielle gruvevogner.
|
||||
To make this rail activate minecarts, power it with redstone power and send a minecart over this piece of rail.=For å få denne skinnen til å aktivere gruvevogner, tilfør aktiv rødsteinkraft og send en gruvevogn over denne delen av sporet.
|
||||
##[ rails/detector.lua ]##
|
||||
Detector Rail=Detektorskinne
|
||||
Emits redstone power when a minecart is detected=Gir fra seg rødsteinkraft når den oppdager en gruvevogn
|
||||
Rails can be used to build transport tracks for minecarts. A detector rail is able to detect a minecart above it and powers redstone mechanisms.=Skinner kan brukes til å bygge transportspor for gruvevogner. En detektorskinne er i stand til å oppdage en gruvevogn over seg og aktivere rødsteinsmekanismer
|
||||
To detect a minecart and provide redstone power, connect it to redstone trails or redstone mechanisms and send any minecart over the rail.=For å oppdage en gruvevogn og gi rødsteinkraft, koble den til et rødsteinspor eller rødsteinsmekanismer og send enhver gruvevogn over skinnen.
|
||||
##[ rails/normal.lua ]##
|
||||
Rail=Skinne
|
||||
##[ rails/powered.lua ]##
|
||||
Powered Rail=Strømskinne
|
||||
Speed up when powered, slow down when not powered=Øker hastighet når aktivert, bremser ned når ikke aktivert
|
||||
Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts.=Skinner kan brukes til å bygge transportspor for gruvevogner. Elektriske skinner er i stand til å akselerere og bremse gruvevogner.
|
||||
Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power.=Uten rødsteinkraft vil skinnen bremse gruvevogner. For å få denne skinnen til å akselerere gruvevognen, tilfør aktiv røsteinkraft.
|
@ -1,36 +1,50 @@
|
||||
# textdomain: mcl_minecarts
|
||||
##[ carts/minecart.lua ]##
|
||||
Sneak to dismount=
|
||||
Minecart=
|
||||
Vehicle for fast travel on rails=
|
||||
Minecarts can be used for a quick transportion on rails.=
|
||||
Minecarts only ride on rails and always follow the tracks. At a T-junction with no straight way ahead, they turn left. The speed is affected by the rail type.=
|
||||
You can place the minecart on rails. Right-click it to enter it. Punch it to get it moving.=
|
||||
To obtain the minecart, punch it while holding down the sneak key.=
|
||||
A minecart with TNT is an explosive vehicle that travels on rail.=
|
||||
Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.=
|
||||
To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited.=
|
||||
If it moves over a powered activator rail, you'll get ejected.=
|
||||
##[ carts/with_chest.lua ]##
|
||||
Minecart with Chest=
|
||||
##[ carts/with_commandblock.lua ]##
|
||||
Minecart with Command Block=
|
||||
##[ carts/with_furnace.lua ]##
|
||||
Minecart with Furnace=
|
||||
A minecart with furnace is a vehicle that travels on rails. It can propel itself with fuel.=
|
||||
Place it on rails. If you give it some coal, the furnace will start burning for a long time and the minecart will be able to move itself. Punch it to get it moving.=
|
||||
To obtain the minecart and furnace, punch them while holding down the sneak key.=
|
||||
Minecart with Chest=
|
||||
Minecart with Furnace=
|
||||
Minecart with Command Block=
|
||||
##[ carts/with_hopper.lua ]##
|
||||
Minecart with Hopper=
|
||||
##[ carts/with_tnt.lua ]##
|
||||
Minecart with TNT=
|
||||
Can be ignited by tools or powered activator rail=
|
||||
A minecart with TNT is an explosive vehicle that travels on rail.=
|
||||
Place it on rails. Punch it to move it. The TNT is ignited with a flint and steel or when the minecart is on an powered activator rail.=
|
||||
To obtain the minecart and TNT, punch them while holding down the sneak key. You can't do this if the TNT was ignited.=
|
||||
##[ rails.lua ]##
|
||||
Place them on the ground to build your railway, the rails will automatically connect to each other and will turn into curves, T-junctions, crossings and slopes as needed.=
|
||||
Rail=
|
||||
New Rail=
|
||||
Track for minecarts=
|
||||
Rails can be used to build transport tracks for minecarts. Normal rails slightly slow down minecarts due to friction.=
|
||||
Powered Rail=
|
||||
Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts.=
|
||||
Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power.=
|
||||
Sloped Rail=
|
||||
##[ rails/activator.lua ]##
|
||||
Activator Rail=
|
||||
Activates minecarts when powered=
|
||||
Rails can be used to build transport tracks for minecarts. Activator rails are used to activate special minecarts.=
|
||||
To make this rail activate minecarts, power it with redstone power and send a minecart over this piece of rail.=
|
||||
##[ rails/detector.lua ]##
|
||||
Detector Rail=
|
||||
Emits redstone power when a minecart is detected=
|
||||
Rails can be used to build transport tracks for minecarts. A detector rail is able to detect a minecart above it and powers redstone mechanisms.=
|
||||
To detect a minecart and provide redstone power, connect it to redstone trails or redstone mechanisms and send any minecart over the rail.=
|
||||
Track for minecarts=
|
||||
##[ rails/normal.lua ]##
|
||||
Rail=
|
||||
##[ rails/powered.lua ]##
|
||||
Powered Rail=
|
||||
Speed up when powered, slow down when not powered=
|
||||
Activates minecarts when powered=
|
||||
Emits redstone power when a minecart is detected=
|
||||
Vehicle for fast travel on rails=
|
||||
Can be ignited by tools or powered activator rail=
|
||||
Sneak to dismount=
|
||||
Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts.=
|
||||
Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power.=
|
||||
|
@ -1,5 +1,5 @@
|
||||
name = mcl_minecarts
|
||||
author = Krock
|
||||
description = Minecarts are vehicles to move players quickly on rails.
|
||||
depends = mcl_title, mcl_explosions, mcl_core, mcl_sounds, mcl_player, mcl_achievements, mcl_chests, mcl_furnaces, mesecons_commandblock, mcl_hoppers, mcl_tnt, mesecons, mcl_entity_invs
|
||||
optional_depends = doc_identifier, mcl_wip
|
||||
depends = mcl_title, mcl_explosions, mcl_core, mcl_util, mcl_sounds, mcl_player, mcl_playerinfo, mcl_achievements, mcl_chests, mcl_furnaces, mesecons_commandblock, mcl_hoppers, mcl_tnt, mesecons, mcl_entity_invs, vl_legacy
|
||||
optional_depends = doc_identifier, mcl_wip, mcl_physics, vl_physics
|
||||
|
15
mods/ENTITIES/mcl_minecarts/models/flat_track.obj
Normal file
15
mods/ENTITIES/mcl_minecarts/models/flat_track.obj
Normal file
@ -0,0 +1,15 @@
|
||||
# hand-made Wavefront .OBJ file for sloped rail
|
||||
mtllib mcl_minecarts_rail.mtl
|
||||
o flat_track.001
|
||||
v -0.500000 -0.437500 -0.500000
|
||||
v -0.500000 -0.437500 0.500000
|
||||
v 0.500000 -0.437500 0.500000
|
||||
v 0.500000 -0.437500 -0.500000
|
||||
vt 1.000000 0.000000
|
||||
vt 1.000000 1.000000
|
||||
vt 0.000000 1.000000
|
||||
vt 0.000000 0.000000
|
||||
vn 0.000000 1.000000 0.000000
|
||||
usemtl None
|
||||
s off
|
||||
f 1/1/1 2/2/1 3/3/1 4/4/1
|
15
mods/ENTITIES/mcl_minecarts/models/sloped_track.obj
Normal file
15
mods/ENTITIES/mcl_minecarts/models/sloped_track.obj
Normal file
@ -0,0 +1,15 @@
|
||||
# hand-made Wavefront .OBJ file for sloped rail
|
||||
mtllib mcl_minecarts_rail.mtl
|
||||
o sloped_rail.001
|
||||
v -0.500000 -0.437500 -0.500000
|
||||
v -0.500000 0.562500 0.500000
|
||||
v 0.500000 0.562500 0.500000
|
||||
v 0.500000 -0.437500 -0.500000
|
||||
vt 1.000000 0.000000
|
||||
vt 1.000000 1.000000
|
||||
vt 0.000000 1.000000
|
||||
vt 0.000000 0.000000
|
||||
vn 0.707106 0.707106 0.000000
|
||||
usemtl None
|
||||
s off
|
||||
f 1/1/1 2/2/1 3/3/1 4/4/1
|
632
mods/ENTITIES/mcl_minecarts/movement.lua
Normal file
632
mods/ENTITIES/mcl_minecarts/movement.lua
Normal file
@ -0,0 +1,632 @@
|
||||
local modname = minetest.get_current_modname()
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
local mod = mcl_minecarts
|
||||
local S = minetest.get_translator(modname)
|
||||
local submod = {}
|
||||
local ENABLE_TRAINS = core.settings:get_bool("mcl_minecarts_enable_trains",true)
|
||||
|
||||
-- Constants
|
||||
local mcl_debug,DEBUG = mcl_util.make_mcl_logger("mcl_logging_minecart_debug", "Minecart Debug")
|
||||
--DEBUG = false
|
||||
--mcl_debug,DEBUG = function(msg) print(msg) end,true
|
||||
|
||||
-- Imports
|
||||
local env_physics
|
||||
if minetest.get_modpath("mcl_physics") then
|
||||
env_physics = mcl_physics
|
||||
elseif minetest.get_modpath("vl_physics") then
|
||||
env_physics = vl_physics
|
||||
end
|
||||
local FRICTION = mod.FRICTION
|
||||
local OFF_RAIL_FRICTION = mod.OFF_RAIL_FRICTION
|
||||
local MAX_TRAIN_LENGTH = mod.MAX_TRAIN_LENGTH
|
||||
local SPEED_MAX = mod.SPEED_MAX
|
||||
local train_length = mod.train_length
|
||||
local update_train = mod.update_train
|
||||
local reverse_train = mod.reverse_train
|
||||
local link_cart_ahead = mod.link_cart_ahead
|
||||
local update_cart_orientation = mod.update_cart_orientation
|
||||
local get_cart_data = mod.get_cart_data
|
||||
local get_cart_position = mod.get_cart_position
|
||||
|
||||
|
||||
local function reverse_direction(staticdata)
|
||||
if staticdata.behind or staticdata.ahead then
|
||||
reverse_train(staticdata)
|
||||
return
|
||||
end
|
||||
|
||||
mod.reverse_cart_direction(staticdata)
|
||||
end
|
||||
mod.reverse_direction = reverse_direction
|
||||
|
||||
|
||||
--[[
|
||||
Array of hooks { {u,v,w}, name }
|
||||
Actual position is pos + u * dir + v * right + w * up
|
||||
]]
|
||||
local enter_exit_checks = {
|
||||
{ 0, 0, 0, "" },
|
||||
{ 0, 0, 1, "_above" },
|
||||
{ 0, 0,-1, "_below" },
|
||||
{ 0, 1, 0, "_side" },
|
||||
{ 0,-1, 0, "_side" },
|
||||
}
|
||||
|
||||
local function handle_cart_enter_exit(staticdata, pos, next_dir, event)
|
||||
local luaentity = mcl_util.get_luaentity_from_uuid(staticdata.uuid)
|
||||
local dir = staticdata.dir
|
||||
local right = vector.new( dir.z, dir.y, -dir.x)
|
||||
local up = vector.new(0,1,0)
|
||||
for i=1,#enter_exit_checks do
|
||||
local check = enter_exit_checks[i]
|
||||
|
||||
local check_pos = pos + dir * check[1] + right * check[2] + up * check[3]
|
||||
local node = minetest.get_node(check_pos)
|
||||
local node_def = minetest.registered_nodes[node.name]
|
||||
if node_def then
|
||||
-- node-specific hook
|
||||
local hook_name = "_mcl_minecarts_"..event..check[4]
|
||||
local hook = node_def[hook_name]
|
||||
if hook then hook(check_pos, luaentity, next_dir, pos, staticdata) end
|
||||
|
||||
-- global minecart hook
|
||||
hook = mcl_minecarts[event..check[4]]
|
||||
if hook then hook(check_pos, luaentity, next_dir, pos, staticdata, node_def) end
|
||||
end
|
||||
end
|
||||
|
||||
-- Handle cart-specific behaviors
|
||||
if luaentity then
|
||||
local hook = luaentity["_mcl_minecarts_"..event]
|
||||
if hook then hook(luaentity, pos, staticdata) end
|
||||
else
|
||||
--minetest.log("warning", "TODO: change _mcl_minecarts_"..event.." calling so it is not dependent on the existence of a luaentity")
|
||||
end
|
||||
end
|
||||
local function set_metadata_cart_status(pos, uuid, state)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local carts = minetest.deserialize(meta:get_string("_mcl_minecarts_carts")) or {}
|
||||
carts[uuid] = state
|
||||
meta:set_string("_mcl_minecarts_carts", minetest.serialize(carts))
|
||||
end
|
||||
local function handle_cart_enter(staticdata, pos, next_dir)
|
||||
--print("entering "..tostring(pos))
|
||||
set_metadata_cart_status(pos, staticdata.uuid, 1)
|
||||
handle_cart_enter_exit(staticdata, pos, next_dir, "on_enter" )
|
||||
end
|
||||
submod.handle_cart_enter = handle_cart_enter
|
||||
local function handle_cart_leave(staticdata, pos, next_dir)
|
||||
--print("leaving "..tostring(pos))
|
||||
set_metadata_cart_status(pos, staticdata.uuid, nil)
|
||||
handle_cart_enter_exit(staticdata, pos, next_dir, "on_leave" )
|
||||
end
|
||||
local function handle_cart_node_watches(staticdata, dtime)
|
||||
local watches = staticdata.node_watches or {}
|
||||
local new_watches = {}
|
||||
local luaentity = mcl_util.get_luaentity_from_uuid(staticdata.uuid)
|
||||
for i=1,#watches do
|
||||
local node_pos = watches[i]
|
||||
local node = minetest.get_node(node_pos)
|
||||
local node_def = minetest.registered_nodes[node.name]
|
||||
if node_def then
|
||||
local hook = node_def._mcl_minecarts_node_on_step
|
||||
if hook and hook(node_pos, luaentity, dtime, staticdata) then
|
||||
new_watches[#new_watches+1] = node_pos
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
staticdata.node_watches = new_watches
|
||||
end
|
||||
|
||||
local function detach_minecart(staticdata)
|
||||
handle_cart_leave(staticdata, staticdata.connected_at, staticdata.dir)
|
||||
staticdata.connected_at = nil
|
||||
mod.break_train_at(staticdata)
|
||||
|
||||
local luaentity = mcl_util.get_luaentity_from_uuid(staticdata.uuid)
|
||||
if luaentity then
|
||||
luaentity.object:set_velocity(staticdata.dir * staticdata.velocity)
|
||||
end
|
||||
end
|
||||
mod.detach_minecart = detach_minecart
|
||||
|
||||
local function try_detach_minecart(staticdata)
|
||||
if not staticdata or not staticdata.connected_at then return end
|
||||
if not mod:is_rail(staticdata.connected_at) then
|
||||
mcl_debug("Detaching minecart #"..tostring(staticdata.uuid))
|
||||
detach_minecart(staticdata)
|
||||
end
|
||||
end
|
||||
|
||||
local function handle_cart_collision(cart1_staticdata, prev_pos, next_dir)
|
||||
if not cart1_staticdata then return end
|
||||
|
||||
-- Look ahead one block
|
||||
local pos = vector.add(prev_pos, next_dir)
|
||||
|
||||
local meta = minetest.get_meta(pos)
|
||||
local carts = minetest.deserialize(meta:get_string("_mcl_minecarts_carts")) or {}
|
||||
local cart_uuid = nil
|
||||
local dirty = false
|
||||
for uuid,v in pairs(carts) do
|
||||
-- Clean up dead carts
|
||||
local data = get_cart_data(uuid)
|
||||
if not data or not data.connected_at then
|
||||
carts[uuid] = nil
|
||||
dirty = true
|
||||
uuid = nil
|
||||
end
|
||||
|
||||
if uuid and uuid ~= cart1_staticdata.uuid then cart_uuid = uuid end
|
||||
end
|
||||
if dirty then
|
||||
meta:set_string("_mcl_minecarts_carts",minetest.serialize(carts))
|
||||
end
|
||||
|
||||
local meta = minetest.get_meta(vector.add(pos,next_dir))
|
||||
if not cart_uuid then return end
|
||||
|
||||
-- Don't collide with the train car in front of you
|
||||
if cart1_staticdata.ahead == cart_uuid then return end
|
||||
|
||||
--minetest.log("action","cart #"..cart1_staticdata.uuid.." collided with cart #"..cart_uuid.." at "..tostring(pos))
|
||||
|
||||
-- Standard Collision Handling
|
||||
local cart2_staticdata = get_cart_data(cart_uuid)
|
||||
|
||||
local u1 = cart1_staticdata.velocity
|
||||
local u2 = cart2_staticdata.velocity
|
||||
local m1 = cart1_staticdata.mass
|
||||
local m2 = cart2_staticdata.mass
|
||||
|
||||
if ENABLE_TRAINS and u2 == 0 and u1 < 4 and train_length(cart1_staticdata) < MAX_TRAIN_LENGTH then
|
||||
link_cart_ahead(cart1_staticdata, cart2_staticdata)
|
||||
cart2_staticdata.dir = mcl_minecarts.get_rail_direction(cart2_staticdata.connected_at, cart1_staticdata.dir)
|
||||
cart2_staticdata.velocity = cart1_staticdata.velocity
|
||||
return
|
||||
end
|
||||
|
||||
-- Reverse direction of the second cart if it is pointing in the wrong direction for this collision
|
||||
local rel = vector.direction(cart1_staticdata.connected_at, cart2_staticdata.connected_at)
|
||||
local dir2 = cart2_staticdata.dir
|
||||
local col_dir = vector.dot(rel, dir2)
|
||||
if col_dir < 0 then
|
||||
cart2_staticdata.dir = -dir2
|
||||
u2 = -u2
|
||||
end
|
||||
|
||||
-- Calculate new velocities according to https://en.wikipedia.org/wiki/Elastic_collision#One-dimensional_Newtonian
|
||||
local c1 = m1 + m2
|
||||
local d = m1 - m2
|
||||
local v1 = ( d * u1 + 2 * m2 * u2 ) / c1
|
||||
local v2 = ( 2 * m1 * u1 + d * u2 ) / c1
|
||||
|
||||
cart1_staticdata.velocity = v1
|
||||
cart2_staticdata.velocity = v2
|
||||
end
|
||||
|
||||
local function vector_away_from_players(cart, staticdata)
|
||||
local function player_repel(obj)
|
||||
-- Only repel from players
|
||||
local player_name = obj:get_player_name()
|
||||
if not player_name or player_name == "" then return false end
|
||||
|
||||
-- Don't repel away from players in minecarts
|
||||
local player_meta = mcl_playerinfo.get_mod_meta(player_name, modname)
|
||||
if player_meta.attached_to then return false end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-- Get the cart position
|
||||
local cart_pos = mod.get_cart_position(staticdata)
|
||||
if cart then cart_pos = cart.object:get_pos() end
|
||||
if not cart_pos then return nil end
|
||||
|
||||
for _,obj in pairs(minetest.get_objects_inside_radius(cart_pos, 1.1)) do
|
||||
if player_repel(obj) then
|
||||
return obj:get_pos() - cart_pos
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
local function direction_away_from_players(staticdata)
|
||||
local diff = vector_away_from_players(nil,staticdata)
|
||||
if not diff then return 0 end
|
||||
|
||||
local length = vector.distance(vector.zero(),diff)
|
||||
local vec = diff / length
|
||||
local force = vector.dot( vec, vector.normalize(staticdata.dir) )
|
||||
|
||||
-- Check if this would push past the end of the track and don't move it it would
|
||||
-- This prevents an oscillation that would otherwise occur
|
||||
local dir = staticdata.dir
|
||||
if force > 0 then
|
||||
dir = -dir
|
||||
end
|
||||
if mcl_minecarts.is_rail( staticdata.connected_at + dir ) then
|
||||
if force > 0.5 then
|
||||
return -length * 4
|
||||
elseif force < -0.5 then
|
||||
return length * 4
|
||||
end
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
local look_directions = {
|
||||
[0] = mod.north,
|
||||
mod.west,
|
||||
mod.south,
|
||||
mod.east,
|
||||
}
|
||||
local function calculate_acceleration(staticdata)
|
||||
local acceleration = 0
|
||||
|
||||
-- Fix up movement data
|
||||
staticdata.velocity = staticdata.velocity or 0
|
||||
|
||||
-- Apply friction if moving
|
||||
if staticdata.velocity > 0 then
|
||||
acceleration = -FRICTION
|
||||
end
|
||||
|
||||
local pos = staticdata.connected_at
|
||||
local node_name = minetest.get_node(pos).name
|
||||
local node_def = minetest.registered_nodes[node_name]
|
||||
|
||||
local ctrl = staticdata.controls or {}
|
||||
local time_active = minetest.get_gametime() - 0.25
|
||||
|
||||
if (ctrl.forward or 0) > time_active then
|
||||
if staticdata.velocity <= 0.05 then
|
||||
local look_dir = look_directions[ctrl.look or 0] or mod.north
|
||||
local dot = vector.dot(staticdata.dir, look_dir)
|
||||
if dot < 0 then
|
||||
reverse_direction(staticdata)
|
||||
end
|
||||
end
|
||||
acceleration = 4
|
||||
elseif (ctrl.brake or 0) > time_active then
|
||||
acceleration = -1.5
|
||||
elseif (staticdata.fueltime or 0) > 0 and staticdata.velocity <= 4 then
|
||||
acceleration = 0.6
|
||||
elseif staticdata.velocity >= ( node_def._max_acceleration_velocity or SPEED_MAX ) then
|
||||
-- Standard friction
|
||||
elseif node_def and node_def._rail_acceleration then
|
||||
local rail_accel = node_def._rail_acceleration
|
||||
if type(rail_accel) == "function" then
|
||||
acceleration = (rail_accel(pos, staticdata) or 0) * 4
|
||||
else
|
||||
acceleration = rail_accel * 4
|
||||
end
|
||||
end
|
||||
|
||||
-- Factor in gravity after everything else
|
||||
local gravity_strength = 2.45 --friction * 5
|
||||
if staticdata.dir.y < 0 then
|
||||
acceleration = gravity_strength - FRICTION
|
||||
elseif staticdata.dir.y > 0 then
|
||||
acceleration = -gravity_strength + FRICTION
|
||||
end
|
||||
|
||||
return acceleration
|
||||
end
|
||||
|
||||
local function do_movement_step(staticdata, dtime)
|
||||
if not staticdata.connected_at then return 0 end
|
||||
|
||||
-- Calculate timestep remaiing in this block
|
||||
local x_0 = staticdata.distance or 0
|
||||
local remaining_in_block = 1 - x_0
|
||||
|
||||
-- Apply velocity impulse
|
||||
local v_0 = staticdata.velocity or 0
|
||||
local ctrl = staticdata.controls or {}
|
||||
if ctrl.impulse then
|
||||
local impulse = ctrl.impulse
|
||||
ctrl.impulse = nil
|
||||
|
||||
local old_v_0 = v_0
|
||||
local new_v_0 = v_0 + impulse
|
||||
if new_v_0 > SPEED_MAX then
|
||||
new_v_0 = SPEED_MAX
|
||||
elseif new_v_0 < 0.025 then
|
||||
new_v_0 = 0
|
||||
end
|
||||
v_0 = new_v_0
|
||||
end
|
||||
|
||||
-- Calculate acceleration
|
||||
local a = 0
|
||||
if staticdata.ahead or staticdata.behind then
|
||||
-- Calculate acceleration of the entire train
|
||||
local count = 0
|
||||
for cart in mod.train_cars(staticdata) do
|
||||
count = count + 1
|
||||
if cart.behind then
|
||||
a = a + calculate_acceleration(cart)
|
||||
end
|
||||
end
|
||||
a = a / count
|
||||
else
|
||||
a = calculate_acceleration(staticdata)
|
||||
end
|
||||
|
||||
-- Repel minecarts
|
||||
local away = direction_away_from_players(staticdata)
|
||||
if away > 0 then
|
||||
v_0 = away
|
||||
elseif away < 0 then
|
||||
reverse_direction(staticdata)
|
||||
v_0 = -away
|
||||
end
|
||||
|
||||
if DEBUG and ( v_0 > 0 or a ~= 0 ) then
|
||||
mcl_debug(" cart "..tostring(staticdata.uuid)..
|
||||
": a="..tostring(a)..
|
||||
",v_0="..tostring(v_0)..
|
||||
",x_0="..tostring(x_0)..
|
||||
",dtime="..tostring(dtime)..
|
||||
",dir="..tostring(staticdata.dir)..
|
||||
",connected_at="..tostring(staticdata.connected_at)..
|
||||
",distance="..tostring(staticdata.distance)
|
||||
)
|
||||
end
|
||||
|
||||
-- Not moving
|
||||
if a == 0 and v_0 == 0 then return 0 end
|
||||
|
||||
-- Prevent movement into solid blocks
|
||||
if staticdata.distance == 0 then
|
||||
local next_node = core.get_node(staticdata.connected_at + staticdata.dir)
|
||||
local next_node_def = core.registered_nodes[next_node.name]
|
||||
if not next_node_def or next_node_def.groups and (next_node_def.groups.solid or next_node_def.groups.stair) then
|
||||
reverse_direction(staticdata)
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
-- Movement equation with acceleration: x_1 = x_0 + v_0 * t + 0.5 * a * t*t
|
||||
local timestep
|
||||
local stops_in_block = false
|
||||
local inside = v_0 * v_0 + 2 * a * remaining_in_block
|
||||
if inside < 0 then
|
||||
-- Would stop or reverse direction inside this block, calculate time to v_1 = 0
|
||||
timestep = -v_0 / a
|
||||
stops_in_block = true
|
||||
if timestep <= 0.01 then
|
||||
reverse_direction(staticdata)
|
||||
end
|
||||
elseif a ~= 0 then
|
||||
-- Setting x_1 = x_0 + remaining_in_block, and solving for t gives:
|
||||
timestep = ( math.sqrt( v_0 * v_0 + 2 * a * remaining_in_block) - v_0 ) / a
|
||||
else
|
||||
timestep = remaining_in_block / v_0
|
||||
end
|
||||
|
||||
-- Truncate timestep to remaining time delta
|
||||
if timestep > dtime then
|
||||
timestep = dtime
|
||||
end
|
||||
|
||||
-- Truncate timestep to prevent v_1 from being larger that speed_max
|
||||
if (v_0 < SPEED_MAX) and ( v_0 + a * timestep > SPEED_MAX) then
|
||||
timestep = ( SPEED_MAX - v_0 ) / a
|
||||
end
|
||||
|
||||
-- Prevent infinite loops
|
||||
if timestep <= 0 then return 0 end
|
||||
|
||||
-- Calculate v_1 taking SPEED_MAX into account
|
||||
local v_1 = v_0 + a * timestep
|
||||
if v_1 > SPEED_MAX then
|
||||
v_1 = SPEED_MAX
|
||||
elseif v_1 < 0.025 then
|
||||
v_1 = 0
|
||||
end
|
||||
|
||||
-- Calculate x_1
|
||||
local x_1 = x_0 + (timestep * v_0 + 0.5 * a * timestep * timestep) / vector.length(staticdata.dir)
|
||||
|
||||
-- Update position and velocity of the minecart
|
||||
staticdata.velocity = v_1
|
||||
staticdata.distance = x_1
|
||||
|
||||
if DEBUG and ( v_0 > 0 or a ~= 0 ) then
|
||||
mcl_debug( "- cart #"..tostring(staticdata.uuid)..
|
||||
": a="..tostring(a)..
|
||||
",v_0="..tostring(v_0)..
|
||||
",v_1="..tostring(v_1)..
|
||||
",x_0="..tostring(x_0)..
|
||||
",x_1="..tostring(x_1)..
|
||||
",timestep="..tostring(timestep)..
|
||||
",dir="..tostring(staticdata.dir)..
|
||||
",connected_at="..tostring(staticdata.connected_at)..
|
||||
",distance="..tostring(staticdata.distance)
|
||||
)
|
||||
end
|
||||
|
||||
-- Entity movement
|
||||
local pos = staticdata.connected_at
|
||||
|
||||
-- Handle movement to next block, account for loss of precision in calculations
|
||||
if x_1 >= 0.99 then
|
||||
staticdata.distance = 0
|
||||
|
||||
-- Anchor at the next node
|
||||
local old_pos = pos
|
||||
pos = pos + staticdata.dir
|
||||
staticdata.connected_at = pos
|
||||
|
||||
-- Get the next direction
|
||||
local next_dir,_ = mcl_minecarts.get_rail_direction(pos, staticdata.dir, nil, nil, staticdata.railtype)
|
||||
if DEBUG and next_dir ~= staticdata.dir then
|
||||
mcl_debug( "Changing direction from "..tostring(staticdata.dir).." to "..tostring(next_dir))
|
||||
end
|
||||
|
||||
-- Handle cart collisions
|
||||
handle_cart_collision(staticdata, pos, next_dir)
|
||||
|
||||
-- Leave the old node
|
||||
handle_cart_leave(staticdata, old_pos, next_dir )
|
||||
|
||||
-- Enter the new node
|
||||
handle_cart_enter(staticdata, pos, next_dir)
|
||||
|
||||
-- Handle end of track
|
||||
if next_dir == staticdata.dir * -1 and next_dir.y == 0 then
|
||||
if DEBUG then mcl_debug("Stopping cart at end of track at "..tostring(pos)) end
|
||||
staticdata.velocity = 0
|
||||
end
|
||||
|
||||
-- Update cart direction
|
||||
staticdata.dir = next_dir
|
||||
elseif stops_in_block and v_1 < (FRICTION/5) and a <= 0 and staticdata.dir.y > 0 then
|
||||
-- Handle direction flip due to gravity
|
||||
if DEBUG then mcl_debug("Gravity flipped direction") end
|
||||
|
||||
-- Velocity should be zero at this point
|
||||
staticdata.velocity = 0
|
||||
|
||||
reverse_direction(staticdata)
|
||||
|
||||
-- Intermediate movement
|
||||
pos = staticdata.connected_at + staticdata.dir * staticdata.distance
|
||||
else
|
||||
-- Intermediate movement
|
||||
pos = pos + staticdata.dir * staticdata.distance
|
||||
end
|
||||
|
||||
-- Debug reporting
|
||||
if DEBUG and ( v_0 > 0 or v_1 > 0 ) then
|
||||
mcl_debug( " cart #"..tostring(staticdata.uuid)..
|
||||
": a="..tostring(a)..
|
||||
",v_0="..tostring(v_0)..
|
||||
",v_1="..tostring(v_1)..
|
||||
",x_0="..tostring(x_0)..
|
||||
",x_1="..tostring(x_1)..
|
||||
",timestep="..tostring(timestep)..
|
||||
",dir="..tostring(staticdata.dir)..
|
||||
",pos="..tostring(pos)..
|
||||
",connected_at="..tostring(staticdata.connected_at)..
|
||||
",distance="..tostring(staticdata.distance)
|
||||
)
|
||||
end
|
||||
|
||||
-- Report the amount of time processed
|
||||
return dtime - timestep
|
||||
end
|
||||
|
||||
function submod.do_movement( staticdata, dtime )
|
||||
assert(staticdata)
|
||||
|
||||
-- Break long movements at block boundaries to make it
|
||||
-- it impossible to jump across gaps due to server lag
|
||||
-- causing large timesteps
|
||||
while dtime > 0 do
|
||||
local new_dtime = do_movement_step(staticdata, dtime)
|
||||
try_detach_minecart(staticdata)
|
||||
|
||||
update_train(staticdata)
|
||||
|
||||
-- Handle node watches here in steps to prevent server lag from changing behavior
|
||||
handle_cart_node_watches(staticdata, dtime - new_dtime)
|
||||
|
||||
dtime = new_dtime
|
||||
end
|
||||
end
|
||||
|
||||
local _half_pi = math.pi * 0.5
|
||||
function submod.do_detached_movement(self, dtime)
|
||||
local staticdata = self._staticdata
|
||||
|
||||
-- Make sure the object is still valid before trying to move it
|
||||
local velocity = self.object:get_velocity()
|
||||
if not self.object or not velocity then return end
|
||||
|
||||
-- Apply physics
|
||||
if env_physics then
|
||||
env_physics.apply_entity_environmental_physics(self)
|
||||
else
|
||||
-- Simple physics
|
||||
local friction = velocity or vector.zero()
|
||||
friction.y = 0
|
||||
|
||||
local accel = vector.new(0,-9.81,0) -- gravity
|
||||
|
||||
-- Don't apply friction in the air
|
||||
local pos_rounded = vector.round(self.object:get_pos())
|
||||
if minetest.get_node(vector.offset(pos_rounded,0,-1,0)).name ~= "air" then
|
||||
accel = vector.add(accel, vector.multiply(friction,-OFF_RAIL_FRICTION))
|
||||
end
|
||||
|
||||
self.object:set_acceleration(accel)
|
||||
end
|
||||
|
||||
-- Shake the cart (also resets pitch)
|
||||
local rot = self.object:get_rotation()
|
||||
local shake_amount = 0.05 * vector.length(velocity)
|
||||
rot.x = (math.random() - 0.5) * shake_amount
|
||||
rot.z = (math.random() - 0.5) * shake_amount
|
||||
self.object:set_rotation(rot)
|
||||
|
||||
local away = vector_away_from_players(self, staticdata)
|
||||
if away then
|
||||
local v = self.object:get_velocity()
|
||||
self.object:set_velocity((v - away)*0.65)
|
||||
|
||||
-- Boost the minecart vertically a bit to get over the edge of rails and things like carpets
|
||||
local boost = vector.offset(vector.multiply(vector.normalize(away), 0.1), 0, 0.07, 0) -- 1/16th + 0.0075
|
||||
local pos = self.object:get_pos()
|
||||
if pos.y - math.floor(pos.y) < boost.y then
|
||||
self.object:set_pos(vector.add(pos,boost))
|
||||
end
|
||||
end
|
||||
|
||||
-- Try to reconnect to rail
|
||||
local pos = self.object:get_pos()
|
||||
local yaw = self.object:get_yaw()
|
||||
local yaw_dir = minetest.yaw_to_dir(yaw)
|
||||
local test_positions = {
|
||||
pos,
|
||||
vector.offset(vector.add(pos, vector.multiply(yaw_dir, 0.5)),0,-0.55,0),
|
||||
vector.offset(vector.add(pos, vector.multiply(yaw_dir,-0.5)),0,-0.55,0),
|
||||
}
|
||||
|
||||
for i=1,#test_positions do
|
||||
local test_pos = test_positions[i]
|
||||
local pos_r = vector.round(test_pos)
|
||||
local node = minetest.get_node(pos_r)
|
||||
if minetest.get_item_group(node.name, "rail") ~= 0 then
|
||||
staticdata.connected_at = pos_r
|
||||
staticdata.railtype = node.name
|
||||
|
||||
local freebody_velocity = self.object:get_velocity()
|
||||
staticdata.dir = mod:get_rail_direction(pos_r, mod.snap_direction(freebody_velocity))
|
||||
|
||||
-- Use vector projection to only keep the velocity in the new direction of movement on the rail
|
||||
-- https://en.wikipedia.org/wiki/Vector_projection
|
||||
staticdata.velocity = vector.dot(staticdata.dir,freebody_velocity)
|
||||
--print("Reattached velocity="..tostring(staticdata.velocity)..", freebody_velocity="..tostring(freebody_velocity))
|
||||
|
||||
-- Clear freebody movement
|
||||
self.object:set_velocity(vector.zero())
|
||||
self.object:set_acceleration(vector.zero())
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- Reset pitch if still not attached
|
||||
local rot = self.object:get_rotation()
|
||||
rot.x = 0
|
||||
self.object:set_rotation(rot)
|
||||
end
|
||||
|
||||
--return do_movement, do_detatched_movement
|
||||
return submod
|
||||
|
@ -1,53 +1,406 @@
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
local modname = minetest.get_current_modname()
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
local mod = mcl_minecarts
|
||||
local S = minetest.get_translator(modname)
|
||||
mod.RAIL_GROUPS = {
|
||||
STANDARD = 1,
|
||||
CURVES = 2,
|
||||
}
|
||||
|
||||
-- Template rail function
|
||||
local function register_rail(itemstring, tiles, def_extras, creative)
|
||||
local groups = {handy=1,pickaxey=1, attached_node=1,rail=1,connect_to_raillike=minetest.raillike_group("rail"),dig_by_water=0,destroy_by_lava_flow=0, transport=1}
|
||||
if creative == false then
|
||||
groups.not_in_creative_inventory = 1
|
||||
end
|
||||
local ndef = {
|
||||
drawtype = "raillike",
|
||||
tiles = tiles,
|
||||
is_ground_content = false,
|
||||
inventory_image = tiles[1],
|
||||
wield_image = tiles[1],
|
||||
paramtype = "light",
|
||||
walkable = false,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
|
||||
},
|
||||
stack_max = 64,
|
||||
groups = groups,
|
||||
sounds = mcl_sounds.node_sound_metal_defaults(),
|
||||
_mcl_blast_resistance = 0.7,
|
||||
_mcl_hardness = 0.7,
|
||||
after_destruct = function(pos)
|
||||
-- Scan for minecarts in this pos and force them to execute their "floating" check.
|
||||
-- Normally, this will make them drop.
|
||||
local objs = minetest.get_objects_inside_radius(pos, 1)
|
||||
for o=1, #objs do
|
||||
local le = objs[o]:get_luaentity()
|
||||
if le then
|
||||
-- All entities in this mod are minecarts, so this works
|
||||
if string.sub(le.name, 1, 14) == "mcl_minecarts:" then
|
||||
le._last_float_check = mcl_minecarts.check_float_time
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
if def_extras then
|
||||
for k,v in pairs(def_extras) do
|
||||
ndef[k] = v
|
||||
-- Inport functions and constants from elsewhere
|
||||
local table_merge = mcl_util.table_merge
|
||||
local check_connection_rules = mod.check_connection_rules
|
||||
local update_rail_connections = mod.update_rail_connections
|
||||
local minetest_fourdir_to_dir = minetest.fourdir_to_dir
|
||||
local minetest_dir_to_fourdir = minetest.dir_to_fourdir
|
||||
local vector_offset = vector.offset
|
||||
local vector_equals = vector.equals
|
||||
local north = mod.north
|
||||
local south = mod.south
|
||||
local east = mod.east
|
||||
local west = mod.west
|
||||
|
||||
--- Rail direction Handlers
|
||||
local function rail_dir_straight(pos, dir, node)
|
||||
dir = vector.new(dir)
|
||||
dir.y = 0
|
||||
|
||||
if node.param2 == 0 or node.param2 == 2 then
|
||||
if vector_equals(dir, north) then
|
||||
return north
|
||||
else
|
||||
return south
|
||||
end
|
||||
else
|
||||
if vector_equals(dir,east) then
|
||||
return east
|
||||
else
|
||||
return west
|
||||
end
|
||||
end
|
||||
end
|
||||
local function rail_dir_sloped(pos, dir, node)
|
||||
local uphill = minetest_fourdir_to_dir(node.param2)
|
||||
local downhill = minetest_fourdir_to_dir((node.param2+2)%4)
|
||||
local up_uphill = vector_offset(uphill,0,1,0)
|
||||
|
||||
if vector_equals(dir, uphill) or vector_equals(dir, up_uphill) then
|
||||
return up_uphill
|
||||
else
|
||||
return downhill
|
||||
end
|
||||
end
|
||||
-- Fourdir to cardinal direction
|
||||
-- 0 = north
|
||||
-- 1 = east
|
||||
-- 2 = south
|
||||
-- 3 = west
|
||||
|
||||
-- This takes a table `dirs` that has one element for each cardinal direction
|
||||
-- and which specifies the direction for a cart to continue in when entering
|
||||
-- a rail node in the direction of the cardinal. This function takes node
|
||||
-- rotations into account.
|
||||
local function rail_dir_from_table(pos, dir, node, dirs)
|
||||
dir = vector.new(dir)
|
||||
dir.y = 0
|
||||
local dir_fourdir = (minetest_dir_to_fourdir(dir) - node.param2 + 4) % 4
|
||||
local new_fourdir = (dirs[dir_fourdir] + node.param2) % 4
|
||||
return minetest_fourdir_to_dir(new_fourdir)
|
||||
end
|
||||
|
||||
local CURVE_RAIL_DIRS = { [0] = 1, 1, 2, 2, }
|
||||
local function rail_dir_curve(pos, dir, node)
|
||||
return rail_dir_from_table(pos, dir, node, CURVE_RAIL_DIRS)
|
||||
end
|
||||
local function rail_dir_tee_off(pos, dir, node)
|
||||
return rail_dir_from_table(pos, dir, node, CURVE_RAIL_DIRS)
|
||||
end
|
||||
|
||||
local TEE_RAIL_ON_DIRS = { [0] = 0, 1, 1, 0 }
|
||||
local function rail_dir_tee_on(pos, dir, node)
|
||||
return rail_dir_from_table(pos, dir, node, TEE_RAIL_ON_DIRS)
|
||||
end
|
||||
|
||||
local function rail_dir_cross(pos, dir, node)
|
||||
dir = vector.new(dir)
|
||||
dir.y = 0
|
||||
|
||||
-- Always continue in the same direction. No direction changes allowed
|
||||
return dir
|
||||
end
|
||||
|
||||
-- Setup shared text
|
||||
local railuse = S(
|
||||
"Place them on the ground to build your railway, the rails will automatically connect to each other and will"..
|
||||
" turn into curves, T-junctions, crossings and slopes as needed."
|
||||
)
|
||||
mod.text = mod.text or {}
|
||||
mod.text.railuse = railuse
|
||||
local BASE_DEF = {
|
||||
drawtype = "mesh",
|
||||
mesh = "flat_track.obj",
|
||||
paramtype = "light",
|
||||
paramtype2 = "4dir",
|
||||
stack_max = 64,
|
||||
sounds = mcl_sounds.node_sound_metal_defaults(),
|
||||
is_ground_content = true,
|
||||
paramtype = "light",
|
||||
use_texture_alpha = "clip",
|
||||
collision_box = {
|
||||
type = "fixed",
|
||||
fixed = { -8/16, -8/16, -8/16, 8/16, -7/16, 8/15 }
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
|
||||
},
|
||||
groups = {
|
||||
handy=1, pickaxey=1,
|
||||
attached_node=1,
|
||||
rail=1,
|
||||
connect_to_raillike=minetest.raillike_group("rail"),
|
||||
dig_by_water=0,destroy_by_lava_flow=0,
|
||||
transport=1
|
||||
},
|
||||
_tt_help = S("Track for minecarts"),
|
||||
_doc_items_usagehelp = railuse,
|
||||
_doc_items_longdesc = S("Rails can be used to build transport tracks for minecarts. Normal rails slightly slow down minecarts due to friction."),
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
local node = minetest.get_node(pointed_thing.under)
|
||||
local node_name = node.name
|
||||
|
||||
-- Don't allow placing rail above rail
|
||||
if minetest.get_item_group(node_name,"rail") ~= 0 then
|
||||
return itemstack
|
||||
end
|
||||
|
||||
-- Handle right-clicking nodes with right-click handlers
|
||||
if placer and not placer:get_player_control().sneak then
|
||||
local node_def = minetest.registered_nodes[node_name] or {}
|
||||
local on_rightclick = node_def and node_def.on_rightclick
|
||||
if on_rightclick then
|
||||
return on_rightclick(pointed_thing.under, node, placer, itemstack, pointed_thing) or itemstack
|
||||
end
|
||||
end
|
||||
|
||||
-- Place the rail
|
||||
return minetest.item_place_node(itemstack, placer, pointed_thing)
|
||||
end,
|
||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||
update_rail_connections(pos)
|
||||
end,
|
||||
_mcl_minecarts = {
|
||||
get_next_dir = rail_dir_straight,
|
||||
},
|
||||
_mcl_blast_resistance = 0.7,
|
||||
_mcl_hardness = 0.7,
|
||||
}
|
||||
|
||||
local SLOPED_RAIL_DEF = table.copy(BASE_DEF)
|
||||
table_merge(SLOPED_RAIL_DEF,{
|
||||
drawtype = "mesh",
|
||||
mesh = "sloped_track.obj",
|
||||
groups = {
|
||||
rail_slope = 1,
|
||||
not_in_creative_inventory = 1,
|
||||
},
|
||||
collision_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{ -0.5, -0.5, -0.5, 0.5, 0.0, 0.5 },
|
||||
{ -0.5, 0.0, 0.0, 0.5, 0.5, 0.5 }
|
||||
}
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{ -0.5, -0.5, -0.5, 0.5, 0.0, 0.5 },
|
||||
{ -0.5, 0.0, 0.0, 0.5, 0.5, 0.5 }
|
||||
}
|
||||
},
|
||||
_mcl_minecarts = {
|
||||
get_next_dir = rail_dir_sloped,
|
||||
},
|
||||
})
|
||||
|
||||
function mod.register_rail(itemstring, ndef)
|
||||
assert(ndef.tiles)
|
||||
assert(ndef.description)
|
||||
|
||||
-- Extract out the craft recipe
|
||||
local craft = ndef.craft
|
||||
ndef.craft = nil
|
||||
|
||||
-- Add sensible defaults
|
||||
if not ndef.inventory_image then ndef.inventory_image = ndef.tiles[1] end
|
||||
if not ndef.wield_image then ndef.wield_image = ndef.tiles[1] end
|
||||
|
||||
--print("registering rail "..itemstring.." with definition: "..dump(ndef))
|
||||
|
||||
-- Make registrations
|
||||
minetest.register_node(itemstring, ndef)
|
||||
if craft then minetest.register_craft(craft) end
|
||||
end
|
||||
|
||||
local function make_mesecons(base_name, suffix, base_mesecons)
|
||||
if not base_mesecons then
|
||||
if suffix == "_tee_off" or suffix == "_tee_on" then
|
||||
base_mesecons = {}
|
||||
else
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local mesecons = table.copy(base_mesecons)
|
||||
|
||||
if suffix == "_tee_off" then
|
||||
mesecons.effector = base_mesecons.effector and table.copy(base_mesecons.effector) or {}
|
||||
|
||||
local old_action_on = base_mesecons.effector and base_mesecons.effector.action_on
|
||||
mesecons.effector.action_on = function(pos, node)
|
||||
if old_action_on then old_action_on(pos, node) end
|
||||
|
||||
node.name = base_name.."_tee_on"
|
||||
minetest.set_node(pos, node)
|
||||
end
|
||||
mesecons.effector.rules = mesecons.effector.rules or mesecon.rules.alldirs
|
||||
elseif suffix == "_tee_on" then
|
||||
mesecons.effector = base_mesecons.effector and table.copy(base_mesecons.effector) or {}
|
||||
|
||||
local old_action_off = base_mesecons.effector and base_mesecons.effector.action_off
|
||||
mesecons.effector.action_off = function(pos, node)
|
||||
if old_action_off then old_action_off(pos, node) end
|
||||
|
||||
node.name = base_name.."_tee_off"
|
||||
minetest.set_node(pos, node)
|
||||
end
|
||||
mesecons.effector.rules = mesecons.effector.rules or mesecon.rules.alldirs
|
||||
end
|
||||
|
||||
if mesecons.conductor then
|
||||
mesecons.conductor = table.copy(base_mesecons.conductor)
|
||||
|
||||
if mesecons.conductor.onstate then
|
||||
mesecons.conductor.onstate = base_mesecons.conductor.onstate..suffix
|
||||
end
|
||||
if base_mesecons.conductor.offstate then
|
||||
mesecons.conductor.offstate = base_mesecons.conductor.offstate..suffix
|
||||
end
|
||||
end
|
||||
|
||||
return mesecons
|
||||
end
|
||||
|
||||
|
||||
function mod.register_straight_rail(base_name, tiles, def)
|
||||
def = def or {}
|
||||
local base_def = table.copy(BASE_DEF)
|
||||
local sloped_def = table.copy(SLOPED_RAIL_DEF)
|
||||
local add = {
|
||||
tiles = { tiles[1] },
|
||||
drop = base_name,
|
||||
groups = {
|
||||
rail = mod.RAIL_GROUPS.STANDARD,
|
||||
},
|
||||
_mcl_minecarts = {
|
||||
base_name = base_name,
|
||||
can_slope = true,
|
||||
},
|
||||
}
|
||||
table_merge(base_def, add); table_merge(sloped_def, add)
|
||||
table_merge(base_def, def); table_merge(sloped_def, def)
|
||||
|
||||
-- Register the base node
|
||||
mod.register_rail(base_name, base_def)
|
||||
base_def.craft = nil; sloped_def.craft = nil
|
||||
table_merge(base_def,{
|
||||
_mcl_minecarts = {
|
||||
railtype = "straight",
|
||||
suffix = "",
|
||||
},
|
||||
})
|
||||
|
||||
-- Sloped variant
|
||||
mod.register_rail_sloped(base_name.."_sloped", table_merge(table.copy(sloped_def),{
|
||||
_mcl_minecarts = {
|
||||
get_next_dir = rail_dir_sloped,
|
||||
suffix = "_sloped",
|
||||
},
|
||||
mesecons = make_mesecons(base_name, "_sloped", def.mesecons),
|
||||
tiles = { tiles[1] },
|
||||
_mcl_minecarts = {
|
||||
railtype = "sloped",
|
||||
},
|
||||
}))
|
||||
end
|
||||
|
||||
function mod.register_curves_rail(base_name, tiles, def)
|
||||
def = def or {}
|
||||
local base_def = table.copy(BASE_DEF)
|
||||
local sloped_def = table.copy(SLOPED_RAIL_DEF)
|
||||
local add = {
|
||||
_mcl_minecarts = { base_name = base_name },
|
||||
groups = {
|
||||
rail = mod.RAIL_GROUPS.CURVES
|
||||
},
|
||||
drop = base_name,
|
||||
}
|
||||
table_merge(base_def, add); table_merge(sloped_def, add)
|
||||
table_merge(base_def, def); table_merge(sloped_def, def)
|
||||
|
||||
-- Register the base node
|
||||
mod.register_rail(base_name, table_merge(table.copy(base_def),{
|
||||
tiles = { tiles[1] },
|
||||
_mcl_minecarts = {
|
||||
get_next_dir = rail_dir_straight,
|
||||
railtype = "straight",
|
||||
can_slope = true,
|
||||
suffix = "",
|
||||
},
|
||||
}))
|
||||
|
||||
-- Update for other variants
|
||||
base_def.craft = nil
|
||||
table_merge(base_def, {
|
||||
groups = {
|
||||
not_in_creative_inventory = 1
|
||||
}
|
||||
})
|
||||
|
||||
-- Corner variants
|
||||
mod.register_rail(base_name.."_corner", table_merge(table.copy(base_def),{
|
||||
tiles = { tiles[2] },
|
||||
_mcl_minecarts = {
|
||||
get_next_dir = rail_dir_curve,
|
||||
railtype = "corner",
|
||||
suffix = "_corner",
|
||||
},
|
||||
mesecons = make_mesecons(base_name, "_corner", def.mesecons),
|
||||
}))
|
||||
|
||||
-- Tee variants
|
||||
mod.register_rail(base_name.."_tee_off", table_merge(table.copy(base_def),{
|
||||
tiles = { tiles[3] },
|
||||
mesecons = make_mesecons(base_name, "_tee_off", def.mesecons),
|
||||
_mcl_minecarts = {
|
||||
get_next_dir = rail_dir_tee_off,
|
||||
railtype = "tee",
|
||||
suffix = "_tee_off",
|
||||
},
|
||||
}))
|
||||
mod.register_rail(base_name.."_tee_on", table_merge(table.copy(base_def),{
|
||||
tiles = { tiles[4] },
|
||||
_mcl_minecarts = {
|
||||
get_next_dir = rail_dir_tee_on,
|
||||
railtype = "tee",
|
||||
suffix = "_tee_on",
|
||||
},
|
||||
mesecons = make_mesecons(base_name, "_tee_on", def.mesecons),
|
||||
}))
|
||||
|
||||
-- Sloped variant
|
||||
mod.register_rail_sloped(base_name.."_sloped", table_merge(table.copy(sloped_def),{
|
||||
description = S("Sloped Rail"), -- Temporary name to make debugging easier
|
||||
_mcl_minecarts = {
|
||||
get_next_dir = rail_dir_sloped,
|
||||
railtype = "tee",
|
||||
suffix = "_sloped",
|
||||
},
|
||||
mesecons = make_mesecons(base_name, "_sloped", def.mesecons),
|
||||
tiles = { tiles[1] },
|
||||
}))
|
||||
|
||||
-- Cross variant
|
||||
mod.register_rail(base_name.."_cross", table_merge(table.copy(base_def),{
|
||||
tiles = { tiles[5] },
|
||||
_mcl_minecarts = {
|
||||
get_next_dir = rail_dir_cross,
|
||||
railtype = "cross",
|
||||
suffix = "_cross",
|
||||
},
|
||||
mesecons = make_mesecons(base_name, "_cross", def.mesecons),
|
||||
}))
|
||||
end
|
||||
|
||||
function mod.register_rail_sloped(itemstring, def)
|
||||
assert(def.tiles)
|
||||
|
||||
-- Build the node definition
|
||||
local ndef = table.copy(SLOPED_RAIL_DEF)
|
||||
table_merge(ndef, def)
|
||||
|
||||
-- Add sensible defaults
|
||||
if not ndef.inventory_image then ndef.inventory_image = ndef.tiles[1] end
|
||||
if not ndef.wield_image then ndef.wield_image = ndef.tiles[1] end
|
||||
|
||||
--print("registering sloped rail "..itemstring.." with definition: "..dump(ndef))
|
||||
|
||||
-- Make registrations
|
||||
minetest.register_node(itemstring, ndef)
|
||||
end
|
||||
|
||||
-- Redstone rules
|
||||
local rail_rules_long =
|
||||
mod.rail_rules_long =
|
||||
{{x=-1, y= 0, z= 0, spread=true},
|
||||
{x= 1, y= 0, z= 0, spread=true},
|
||||
{x= 0, y=-1, z= 0, spread=true},
|
||||
@ -64,202 +417,73 @@ local rail_rules_long =
|
||||
{x= 0, y= 1, z=-1},
|
||||
{x= 0, y=-1, z=-1}}
|
||||
|
||||
local rail_rules_short = mesecon.rules.pplate
|
||||
|
||||
local railuse = S("Place them on the ground to build your railway, the rails will automatically connect to each other and will turn into curves, T-junctions, crossings and slopes as needed.")
|
||||
|
||||
-- Normal rail
|
||||
register_rail("mcl_minecarts:rail",
|
||||
{"default_rail.png", "default_rail_curved.png", "default_rail_t_junction.png", "default_rail_crossing.png"},
|
||||
{
|
||||
description = S("Rail"),
|
||||
_tt_help = S("Track for minecarts"),
|
||||
_doc_items_longdesc = S("Rails can be used to build transport tracks for minecarts. Normal rails slightly slow down minecarts due to friction."),
|
||||
_doc_items_usagehelp = railuse,
|
||||
}
|
||||
)
|
||||
|
||||
-- Powered rail (off = brake mode)
|
||||
register_rail("mcl_minecarts:golden_rail",
|
||||
{"mcl_minecarts_rail_golden.png", "mcl_minecarts_rail_golden_curved.png", "mcl_minecarts_rail_golden_t_junction.png", "mcl_minecarts_rail_golden_crossing.png"},
|
||||
{
|
||||
description = S("Powered Rail"),
|
||||
_tt_help = S("Track for minecarts").."\n"..S("Speed up when powered, slow down when not powered"),
|
||||
_doc_items_longdesc = S("Rails can be used to build transport tracks for minecarts. Powered rails are able to accelerate and brake minecarts."),
|
||||
_doc_items_usagehelp = railuse .. "\n" .. S("Without redstone power, the rail will brake minecarts. To make this rail accelerate minecarts, power it with redstone power."),
|
||||
_rail_acceleration = -3,
|
||||
mesecons = {
|
||||
conductor = {
|
||||
state = mesecon.state.off,
|
||||
offstate = "mcl_minecarts:golden_rail",
|
||||
onstate = "mcl_minecarts:golden_rail_on",
|
||||
rules = rail_rules_long,
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
-- Powered rail (on = acceleration mode)
|
||||
register_rail("mcl_minecarts:golden_rail_on",
|
||||
{"mcl_minecarts_rail_golden_powered.png", "mcl_minecarts_rail_golden_curved_powered.png", "mcl_minecarts_rail_golden_t_junction_powered.png", "mcl_minecarts_rail_golden_crossing_powered.png"},
|
||||
{
|
||||
_doc_items_create_entry = false,
|
||||
_rail_acceleration = 4,
|
||||
mesecons = {
|
||||
conductor = {
|
||||
state = mesecon.state.on,
|
||||
offstate = "mcl_minecarts:golden_rail",
|
||||
onstate = "mcl_minecarts:golden_rail_on",
|
||||
rules = rail_rules_long,
|
||||
},
|
||||
effector = {
|
||||
action_on = function(pos, node)
|
||||
local dir = mcl_minecarts:get_start_direction(pos)
|
||||
if not dir then return end
|
||||
local objs = minetest.get_objects_inside_radius(pos, 1)
|
||||
for _, o in pairs(objs) do
|
||||
local l = o:get_luaentity()
|
||||
local v = o:get_velocity()
|
||||
if l and string.sub(l.name, 1, 14) == "mcl_minecarts:"
|
||||
and v and vector.equals(v, vector.zero())
|
||||
then
|
||||
mcl_minecarts:set_velocity(l, dir)
|
||||
end
|
||||
end
|
||||
end,
|
||||
},
|
||||
},
|
||||
drop = "mcl_minecarts:golden_rail",
|
||||
},
|
||||
false
|
||||
)
|
||||
|
||||
-- Activator rail (off)
|
||||
register_rail("mcl_minecarts:activator_rail",
|
||||
{"mcl_minecarts_rail_activator.png", "mcl_minecarts_rail_activator_curved.png", "mcl_minecarts_rail_activator_t_junction.png", "mcl_minecarts_rail_activator_crossing.png"},
|
||||
{
|
||||
description = S("Activator Rail"),
|
||||
_tt_help = S("Track for minecarts").."\n"..S("Activates minecarts when powered"),
|
||||
_doc_items_longdesc = S("Rails can be used to build transport tracks for minecarts. Activator rails are used to activate special minecarts."),
|
||||
_doc_items_usagehelp = railuse .. "\n" .. S("To make this rail activate minecarts, power it with redstone power and send a minecart over this piece of rail."),
|
||||
mesecons = {
|
||||
conductor = {
|
||||
state = mesecon.state.off,
|
||||
offstate = "mcl_minecarts:activator_rail",
|
||||
onstate = "mcl_minecarts:activator_rail_on",
|
||||
rules = rail_rules_long,
|
||||
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
-- Activator rail (on)
|
||||
register_rail("mcl_minecarts:activator_rail_on",
|
||||
{"mcl_minecarts_rail_activator_powered.png", "mcl_minecarts_rail_activator_curved_powered.png", "mcl_minecarts_rail_activator_t_junction_powered.png", "mcl_minecarts_rail_activator_crossing_powered.png"},
|
||||
{
|
||||
_doc_items_create_entry = false,
|
||||
mesecons = {
|
||||
conductor = {
|
||||
state = mesecon.state.on,
|
||||
offstate = "mcl_minecarts:activator_rail",
|
||||
onstate = "mcl_minecarts:activator_rail_on",
|
||||
rules = rail_rules_long,
|
||||
},
|
||||
effector = {
|
||||
-- Activate minecarts
|
||||
action_on = function(pos, node)
|
||||
local pos2 = { x = pos.x, y =pos.y + 1, z = pos.z }
|
||||
local objs = minetest.get_objects_inside_radius(pos2, 1)
|
||||
for _, o in pairs(objs) do
|
||||
local l = o:get_luaentity()
|
||||
if l and string.sub(l.name, 1, 14) == "mcl_minecarts:" and l.on_activate_by_rail then
|
||||
l:on_activate_by_rail()
|
||||
end
|
||||
end
|
||||
end,
|
||||
},
|
||||
|
||||
},
|
||||
drop = "mcl_minecarts:activator_rail",
|
||||
},
|
||||
false
|
||||
)
|
||||
|
||||
-- Detector rail (off)
|
||||
register_rail("mcl_minecarts:detector_rail",
|
||||
{"mcl_minecarts_rail_detector.png", "mcl_minecarts_rail_detector_curved.png", "mcl_minecarts_rail_detector_t_junction.png", "mcl_minecarts_rail_detector_crossing.png"},
|
||||
{
|
||||
description = S("Detector Rail"),
|
||||
_tt_help = S("Track for minecarts").."\n"..S("Emits redstone power when a minecart is detected"),
|
||||
_doc_items_longdesc = S("Rails can be used to build transport tracks for minecarts. A detector rail is able to detect a minecart above it and powers redstone mechanisms."),
|
||||
_doc_items_usagehelp = railuse .. "\n" .. S("To detect a minecart and provide redstone power, connect it to redstone trails or redstone mechanisms and send any minecart over the rail."),
|
||||
mesecons = {
|
||||
receptor = {
|
||||
state = mesecon.state.off,
|
||||
rules = rail_rules_short,
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
-- Detector rail (on)
|
||||
register_rail("mcl_minecarts:detector_rail_on",
|
||||
{"mcl_minecarts_rail_detector_powered.png", "mcl_minecarts_rail_detector_curved_powered.png", "mcl_minecarts_rail_detector_t_junction_powered.png", "mcl_minecarts_rail_detector_crossing_powered.png"},
|
||||
{
|
||||
_doc_items_create_entry = false,
|
||||
mesecons = {
|
||||
receptor = {
|
||||
state = mesecon.state.on,
|
||||
rules = rail_rules_short,
|
||||
},
|
||||
},
|
||||
drop = "mcl_minecarts:detector_rail",
|
||||
},
|
||||
false
|
||||
)
|
||||
|
||||
|
||||
-- Crafting
|
||||
minetest.register_craft({
|
||||
output = "mcl_minecarts:rail 16",
|
||||
recipe = {
|
||||
{"mcl_core:iron_ingot", "", "mcl_core:iron_ingot"},
|
||||
{"mcl_core:iron_ingot", "mcl_core:stick", "mcl_core:iron_ingot"},
|
||||
{"mcl_core:iron_ingot", "", "mcl_core:iron_ingot"},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "mcl_minecarts:golden_rail 6",
|
||||
recipe = {
|
||||
{"mcl_core:gold_ingot", "", "mcl_core:gold_ingot"},
|
||||
{"mcl_core:gold_ingot", "mcl_core:stick", "mcl_core:gold_ingot"},
|
||||
{"mcl_core:gold_ingot", "mesecons:redstone", "mcl_core:gold_ingot"},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "mcl_minecarts:activator_rail 6",
|
||||
recipe = {
|
||||
{"mcl_core:iron_ingot", "mcl_core:stick", "mcl_core:iron_ingot"},
|
||||
{"mcl_core:iron_ingot", "mesecons_torch:mesecon_torch_on", "mcl_core:iron_ingot"},
|
||||
{"mcl_core:iron_ingot", "mcl_core:stick", "mcl_core:iron_ingot"},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "mcl_minecarts:detector_rail 6",
|
||||
recipe = {
|
||||
{"mcl_core:iron_ingot", "", "mcl_core:iron_ingot"},
|
||||
{"mcl_core:iron_ingot", "mesecons_pressureplates:pressure_plate_stone_off", "mcl_core:iron_ingot"},
|
||||
{"mcl_core:iron_ingot", "mesecons:redstone", "mcl_core:iron_ingot"},
|
||||
}
|
||||
})
|
||||
|
||||
dofile(modpath.."/rails/normal.lua")
|
||||
dofile(modpath.."/rails/activator.lua")
|
||||
dofile(modpath.."/rails/detector.lua")
|
||||
dofile(modpath.."/rails/powered.lua")
|
||||
|
||||
-- Aliases
|
||||
if minetest.get_modpath("doc") then
|
||||
doc.add_entry_alias("nodes", "mcl_minecarts:golden_rail", "nodes", "mcl_minecarts:golden_rail_on")
|
||||
end
|
||||
|
||||
local CURVY_RAILS_MAP = {
|
||||
["mcl_minecarts:rail"] = "mcl_minecarts:rail_v2",
|
||||
["mcl_minecarts:golden_rail"] = "mcl_minecarts:golden_rail_v2",
|
||||
["mcl_minecarts:golden_rail_on"] = "mcl_minecarts:golden_rail_v2_on",
|
||||
["mcl_minecarts:activator_rail"] = "mcl_minecarts:activator_rail_v2",
|
||||
["mcl_minecarts:activator_rail_on"] = "mcl_minecarts:activator_rail_v2_on",
|
||||
["mcl_minecarts:detector_rail"] = "mcl_minecarts:detector_rail_v2",
|
||||
["mcl_minecarts:detector_rail_on"] = "mcl_minecarts:detector_rail_v2_on",
|
||||
}
|
||||
local function convert_legacy_curvy_rails(pos, node)
|
||||
node.name = CURVY_RAILS_MAP[node.name]
|
||||
if node.name then
|
||||
minetest.swap_node(pos, node)
|
||||
mod.update_rail_connections(pos, { legacy = true, ignore_neighbor_connections = true })
|
||||
end
|
||||
end
|
||||
for old,new in pairs(CURVY_RAILS_MAP) do
|
||||
local new_def = minetest.registered_nodes[new]
|
||||
minetest.register_node(old, {
|
||||
drawtype = "raillike",
|
||||
inventory_image = new_def.inventory_image,
|
||||
groups = { rail = 1, legacy = 1 },
|
||||
tiles = { new_def.tiles[1], new_def.tiles[1], new_def.tiles[1], new_def.tiles[1] },
|
||||
_vl_legacy_convert_node = convert_legacy_curvy_rails
|
||||
})
|
||||
vl_legacy.register_item_conversion(old, new)
|
||||
end
|
||||
local STRAIGHT_RAILS_MAP ={
|
||||
}
|
||||
local function convert_legacy_straight_rail(pos, node)
|
||||
node.name = STRAIGHT_RAILS_MAP[node.name]
|
||||
if node.name then
|
||||
local connections = mod.get_rail_connections(pos, { legacy = true, ignore_neighbor_connections = true })
|
||||
if not mod.HORIZONTAL_STANDARD_RULES[connections] then
|
||||
-- Drop an immortal object at this location
|
||||
local item_entity = minetest.add_item(pos, ItemStack(node.name))
|
||||
if item_entity then
|
||||
item_entity:get_luaentity()._immortal = true
|
||||
end
|
||||
|
||||
-- This is a configuration that doesn't exist in the new rail
|
||||
-- Replace with a standard rail
|
||||
node.name = "mcl_minecarts:rail_v2"
|
||||
end
|
||||
minetest.swap_node(pos, node)
|
||||
mod.update_rail_connections(pos, { legacy = true, ignore_neighbor_connections = true })
|
||||
end
|
||||
end
|
||||
for old,new in pairs(STRAIGHT_RAILS_MAP) do
|
||||
local new_def = minetest.registered_nodes[new]
|
||||
minetest.register_node(old, {
|
||||
drawtype = "raillike",
|
||||
inventory_image = new_def.inventory_image,
|
||||
groups = { rail = 1, legacy = 1 },
|
||||
tiles = { new_def.tiles[1], new_def.tiles[1], new_def.tiles[1], new_def.tiles[1] },
|
||||
_vl_legacy_convert_node = convert_legacy_straight_rail,
|
||||
})
|
||||
vl_legacy.register_item_conversion(old, new)
|
||||
end
|
||||
|
||||
|
78
mods/ENTITIES/mcl_minecarts/rails/activator.lua
Normal file
78
mods/ENTITIES/mcl_minecarts/rails/activator.lua
Normal file
@ -0,0 +1,78 @@
|
||||
local modname = minetest.get_current_modname()
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
local mod = mcl_minecarts
|
||||
local S = minetest.get_translator(modname)
|
||||
|
||||
-- Activator rail (off)
|
||||
mod.register_curves_rail("mcl_minecarts:activator_rail_v2", {
|
||||
"mcl_minecarts_rail_activator.png",
|
||||
"mcl_minecarts_rail_activator_curved.png",
|
||||
"mcl_minecarts_rail_activator_t_junction.png",
|
||||
"mcl_minecarts_rail_activator_t_junction.png",
|
||||
"mcl_minecarts_rail_activator_crossing.png"
|
||||
},{
|
||||
description = S("Activator Rail"),
|
||||
_tt_help = S("Track for minecarts").."\n"..S("Activates minecarts when powered"),
|
||||
_doc_items_longdesc = S("Rails can be used to build transport tracks for minecarts. Activator rails are used to activate special minecarts."),
|
||||
_doc_items_usagehelp = mod.text.railuse .. "\n" .. S("To make this rail activate minecarts, power it with redstone power and send a minecart over this piece of rail."),
|
||||
mesecons = {
|
||||
conductor = {
|
||||
state = mesecon.state.off,
|
||||
offstate = "mcl_minecarts:activator_rail_v2",
|
||||
onstate = "mcl_minecarts:activator_rail_v2_on",
|
||||
rules = mod.rail_rules_long,
|
||||
},
|
||||
},
|
||||
craft = {
|
||||
output = "mcl_minecarts:activator_rail_v2 6",
|
||||
recipe = {
|
||||
{"mcl_core:iron_ingot", "mcl_core:stick", "mcl_core:iron_ingot"},
|
||||
{"mcl_core:iron_ingot", "mesecons_torch:mesecon_torch_on", "mcl_core:iron_ingot"},
|
||||
{"mcl_core:iron_ingot", "mcl_core:stick", "mcl_core:iron_ingot"},
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
-- Activator rail (on)
|
||||
local function activator_rail_action_on(pos, node)
|
||||
local pos2 = { x = pos.x, y =pos.y + 1, z = pos.z }
|
||||
local objs = minetest.get_objects_inside_radius(pos2, 1)
|
||||
for _, o in pairs(objs) do
|
||||
local l = o:get_luaentity()
|
||||
if l and string.sub(l.name, 1, 14) == "mcl_minecarts:" and l.on_activate_by_rail then
|
||||
l:on_activate_by_rail()
|
||||
end
|
||||
end
|
||||
end
|
||||
mod.register_curves_rail("mcl_minecarts:activator_rail_v2_on", {
|
||||
"mcl_minecarts_rail_activator_powered.png",
|
||||
"mcl_minecarts_rail_activator_curved_powered.png",
|
||||
"mcl_minecarts_rail_activator_t_junction_powered.png",
|
||||
"mcl_minecarts_rail_activator_t_junction_powered.png",
|
||||
"mcl_minecarts_rail_activator_crossing_powered.png"
|
||||
},{
|
||||
description = S("Activator Rail"),
|
||||
_doc_items_create_entry = false,
|
||||
groups = {
|
||||
not_in_creative_inventory = 1,
|
||||
},
|
||||
mesecons = {
|
||||
conductor = {
|
||||
state = mesecon.state.on,
|
||||
offstate = "mcl_minecarts:activator_rail_v2",
|
||||
onstate = "mcl_minecarts:activator_rail_v2_on",
|
||||
rules = mod.rail_rules_long,
|
||||
},
|
||||
effector = {
|
||||
-- Activate minecarts
|
||||
action_on = activator_rail_action_on,
|
||||
},
|
||||
},
|
||||
_mcl_minecarts_on_enter = function(pos, cart)
|
||||
if cart.on_activate_by_rail then
|
||||
cart:on_activate_by_rail()
|
||||
end
|
||||
end,
|
||||
drop = "mcl_minecarts:activator_rail_v2",
|
||||
})
|
||||
|
71
mods/ENTITIES/mcl_minecarts/rails/detector.lua
Normal file
71
mods/ENTITIES/mcl_minecarts/rails/detector.lua
Normal file
@ -0,0 +1,71 @@
|
||||
local modname = minetest.get_current_modname()
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
local mod = mcl_minecarts
|
||||
local S = minetest.get_translator(modname)
|
||||
|
||||
local rail_rules_short = mesecon.rules.pplate
|
||||
|
||||
-- Detector rail (off)
|
||||
mod.register_curves_rail("mcl_minecarts:detector_rail_v2",{
|
||||
"mcl_minecarts_rail_detector.png",
|
||||
"mcl_minecarts_rail_detector_curved.png",
|
||||
"mcl_minecarts_rail_detector_t_junction.png",
|
||||
"mcl_minecarts_rail_detector_t_junction.png",
|
||||
"mcl_minecarts_rail_detector_crossing.png"
|
||||
},{
|
||||
description = S("Detector Rail"),
|
||||
_tt_help = S("Track for minecarts").."\n"..S("Emits redstone power when a minecart is detected"),
|
||||
_doc_items_longdesc = S("Rails can be used to build transport tracks for minecarts. A detector rail is able to detect a minecart above it and powers redstone mechanisms."),
|
||||
_doc_items_usagehelp = mod.text.railuse .. "\n" .. S("To detect a minecart and provide redstone power, connect it to redstone trails or redstone mechanisms and send any minecart over the rail."),
|
||||
mesecons = {
|
||||
receptor = {
|
||||
state = mesecon.state.off,
|
||||
rules = rail_rules_short,
|
||||
},
|
||||
},
|
||||
_mcl_minecarts_on_enter = function(pos, cart)
|
||||
local node = minetest.get_node(pos)
|
||||
local node_def = minetest.registered_nodes[node.name]
|
||||
node.name = "mcl_minecarts:detector_rail_v2_on"..node_def._mcl_minecarts.suffix
|
||||
minetest.set_node( pos, node )
|
||||
mesecon.receptor_on(pos)
|
||||
end,
|
||||
craft = {
|
||||
output = "mcl_minecarts:detector_rail_v2 6",
|
||||
recipe = {
|
||||
{"mcl_core:iron_ingot", "", "mcl_core:iron_ingot"},
|
||||
{"mcl_core:iron_ingot", "mesecons_pressureplates:pressure_plate_stone_off", "mcl_core:iron_ingot"},
|
||||
{"mcl_core:iron_ingot", "mesecons:redstone", "mcl_core:iron_ingot"},
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
-- Detector rail (on)
|
||||
mod.register_curves_rail("mcl_minecarts:detector_rail_v2_on",{
|
||||
"mcl_minecarts_rail_detector_powered.png",
|
||||
"mcl_minecarts_rail_detector_curved_powered.png",
|
||||
"mcl_minecarts_rail_detector_t_junction_powered.png",
|
||||
"mcl_minecarts_rail_detector_t_junction_powered.png",
|
||||
"mcl_minecarts_rail_detector_crossing_powered.png"
|
||||
},{
|
||||
description = S("Detector Rail"),
|
||||
groups = {
|
||||
not_in_creative_inventory = 1,
|
||||
},
|
||||
_doc_items_create_entry = false,
|
||||
mesecons = {
|
||||
receptor = {
|
||||
state = mesecon.state.on,
|
||||
rules = rail_rules_short,
|
||||
},
|
||||
},
|
||||
_mcl_minecarts_on_leave = function(pos, cart)
|
||||
local node = minetest.get_node(pos)
|
||||
local node_def = minetest.registered_nodes[node.name]
|
||||
node.name = "mcl_minecarts:detector_rail_v2"..node_def._mcl_minecarts.suffix
|
||||
minetest.set_node( pos, node )
|
||||
mesecon.receptor_off(pos)
|
||||
end,
|
||||
drop = "mcl_minecarts:detector_rail_v2",
|
||||
})
|
||||
|
27
mods/ENTITIES/mcl_minecarts/rails/normal.lua
Normal file
27
mods/ENTITIES/mcl_minecarts/rails/normal.lua
Normal file
@ -0,0 +1,27 @@
|
||||
local modname = minetest.get_current_modname()
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
local mod = mcl_minecarts
|
||||
local S = minetest.get_translator(modname)
|
||||
|
||||
-- Normal rail
|
||||
mod.register_curves_rail("mcl_minecarts:rail_v2", {
|
||||
"default_rail.png",
|
||||
"default_rail_curved.png",
|
||||
"default_rail_t_junction.png",
|
||||
"default_rail_t_junction_on.png",
|
||||
"default_rail_crossing.png"
|
||||
},{
|
||||
description = S("Rail"),
|
||||
_tt_help = S("Track for minecarts"),
|
||||
_doc_items_longdesc = S("Rails can be used to build transport tracks for minecarts. Normal rails slightly slow down minecarts due to friction."),
|
||||
_doc_items_usagehelp = mod.text.railuse,
|
||||
craft = {
|
||||
output = "mcl_minecarts:rail_v2 16",
|
||||
recipe = {
|
||||
{"mcl_core:iron_ingot", "", "mcl_core:iron_ingot"},
|
||||
{"mcl_core:iron_ingot", "mcl_core:stick", "mcl_core:iron_ingot"},
|
||||
{"mcl_core:iron_ingot", "", "mcl_core:iron_ingot"},
|
||||
}
|
||||
},
|
||||
})
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user