├── .github └── workflows │ └── luacheck.yml ├── .gitignore ├── .luacheckrc ├── LICENSE.txt ├── README.md ├── description.txt ├── modpack.txt ├── moremesecons_adjustable_blinkyplant ├── init.lua ├── mod.conf └── textures │ ├── moremesecons_blinky_plant_off.png │ └── moremesecons_blinky_plant_on.png ├── moremesecons_adjustable_player_detector ├── init.lua ├── mod.conf └── textures │ ├── moremesecons_player_detector_off.png │ └── moremesecons_player_detector_on.png ├── moremesecons_commandblock ├── init.lua ├── mod.conf └── textures │ ├── moremesecons_commandblock_off.png │ └── moremesecons_commandblock_on.png ├── moremesecons_conductor_signalchanger ├── init.lua ├── mod.conf └── textures │ ├── moremesecons_conductor_signalchanger_off.png │ └── moremesecons_conductor_signalchanger_on.png ├── moremesecons_dual_delayer ├── init.lua ├── mod.conf └── textures │ ├── moremesecons_dual_delayer_bottom.png │ ├── moremesecons_dual_delayer_ends.png │ ├── moremesecons_dual_delayer_overlay.png │ ├── moremesecons_dual_delayer_side_left.png │ └── moremesecons_dual_delayer_side_right.png ├── moremesecons_entity_detector ├── init.lua ├── mod.conf └── textures │ ├── moremesecons_entity_detector_off.png │ └── moremesecons_entity_detector_on.png ├── moremesecons_igniter ├── init.lua ├── mod.conf └── textures │ └── moremesecons_igniter.png ├── moremesecons_induction_transmitter ├── init.lua └── mod.conf ├── moremesecons_injector_controller ├── init.lua ├── mod.conf └── textures │ ├── moremesecons_injector_controller_off.png │ ├── moremesecons_injector_controller_on.png │ └── moremesecons_injector_controller_side.png ├── moremesecons_jammer ├── init.lua ├── mod.conf ├── sounds │ └── moremesecons_jammer.ogg └── textures │ ├── moremesecons_jammer_off.png │ └── moremesecons_jammer_on.png ├── moremesecons_luablock ├── init.lua ├── mod.conf └── textures │ └── moremesecons_luablock.png ├── moremesecons_luacontroller_tool ├── init.lua ├── mod.conf └── textures │ └── moremesecons_luacontroller_tool.png ├── moremesecons_mesechest ├── init.lua └── mod.conf ├── moremesecons_playerkiller ├── init.lua ├── mod.conf └── textures │ ├── moremesecons_playerkiller_side.png │ └── moremesecons_playerkiller_top.png ├── moremesecons_sayer ├── init.lua └── mod.conf ├── moremesecons_signalchanger ├── init.lua ├── mod.conf └── textures │ ├── moremesecons_signalchanger_off.png │ └── moremesecons_signalchanger_on.png ├── moremesecons_switchtorch ├── init.lua ├── mod.conf └── textures │ ├── moremesecons_switchtorch_off.png │ ├── moremesecons_switchtorch_off_ceiling.png │ ├── moremesecons_switchtorch_off_side.png │ ├── moremesecons_switchtorch_on.png │ ├── moremesecons_switchtorch_on_ceiling.png │ └── moremesecons_switchtorch_on_side.png ├── moremesecons_teleporter ├── init.lua ├── mod.conf └── textures │ └── moremesecons_teleporter.png ├── moremesecons_timegate ├── init.lua ├── mod.conf └── textures │ ├── moremesecons_timegate_bottom.png │ ├── moremesecons_timegate_ends_off.png │ ├── moremesecons_timegate_ends_on.png │ ├── moremesecons_timegate_off.png │ ├── moremesecons_timegate_on.png │ ├── moremesecons_timegate_sides_off.png │ └── moremesecons_timegate_sides_on.png ├── moremesecons_utils ├── init.lua └── mod.conf ├── moremesecons_wireless ├── init.lua ├── mod.conf └── textures │ ├── moremesecons_jammer_bottom.png │ ├── moremesecons_jammer_side_off.png │ ├── moremesecons_jammer_side_on.png │ ├── moremesecons_jammer_top.png │ ├── moremesecons_wireless_off.png │ └── moremesecons_wireless_on.png └── settingtypes.txt /.github/workflows/luacheck.yml: -------------------------------------------------------------------------------- 1 | name: luacheck 2 | on: [push, pull_request] 3 | jobs: 4 | luacheck: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - name: Checkout 8 | uses: actions/checkout@master 9 | - name: Luacheck 10 | uses: lunarmodules/luacheck@master 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Generic ignorable patterns and files 2 | *~ 3 | debug.txt 4 | 5 | ## Eclipse project files & directories 6 | .project 7 | .settings 8 | -------------------------------------------------------------------------------- /.luacheckrc: -------------------------------------------------------------------------------- 1 | read_globals = { 2 | -- Defined by Minetest 3 | "minetest", "vector", "PseudoRandom", "VoxelArea", "table", 4 | 5 | -- Mods 6 | "digiline", "default", "creative", 7 | } 8 | globals = {"moremesecons", "mesecon"} 9 | ignore = {"212", "631", "422", "432"} 10 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. 374 | 375 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MoreMesecons 2 | 3 | Based on Mesecons by Jeija
4 | By @paly2 and @HybridDog
5 | With the participation of @LeMagnesium (bugfix), @Ataron (textures), @JAPP (texture). 6 | 7 | Dependencies: [Mesecons](https://github.com/Jeija/minetest-mod-mesecons/)
8 | Optional dependencies: [digilines](https://github.com/minetest-mods/digilines) 9 | 10 | MoreMesecons is a mod for minetest which adds some mesecons items. 11 | 12 | [Here](http://github.com/minetest-mods/MoreMesecons/wiki)'s the wiki ! 13 | 14 | ## New items 15 | 16 | * `Adjustable Blinky plant` : Like a mesecons blinky plant, but... adjustable. Right-click to change the interval. 17 | * `Adjustable Player Detector` : Like a mesecons player detector, but you can change its detection radius by right-click. 18 | * `Craftable Command Block` : A command block with just some commands accepted. The admin can change the accepted command (first line of the init.lua), default "tell". Only "@nearest" can be used in the commands, and the admin can change the maximum distance of "@nearest" (default 8 blocks). 19 | * `Conductor Signal Changer` : Like a diode which can be activated by sending a signal on its pin "F", and deactivated by sending a signal on its pin "O". 20 | * `Dual Delayer` : If it receives a mesecons signal, port 1 turns on immediatly and port 2 turns on 0.4 seconds later. At the end of the signal, port 2 turns off immediatly and port 1 turns off 0.4 secondes later. For example, this is useful for double extenders. 21 | * `Entity Detector` : You can use it to detect an entity. You can choose the entity to detect by right-click (use itemstring, for example "mobs:rat". To detect a dropped item, write "__builtin:item". To detect a specific dropped item, write its itemstring (for example "default:cobble")). 22 | * `Igniter` : This node is a lighter that ignites its adjacent flammable nodes (including TNT). 23 | * `Injector Controller` : This node is useful to activate/deactivate a pipeworks filter injector : it sends a blinky signal. 24 | * `Jammer` : If turned on, this node stops mesecons in a radius of 10 nodes. 25 | * `LuaBlock`: This block allows its owner to execute any Lua code in the global environment when turned on. Using it requires the server privilege. 26 | * `Luacontroller Template Tool` : This tool is very useful to manipulate templates with luacontrollers. Just click with it on a luacontroller, then you'll see a formspec. 27 | * `Player Killer` : This block kills the nearest player (with a maximal distance of 8 blocks by default) (if this player isn't its owner) when it receives a mesecons signal. 28 | * `Sayer` : This node sends a message to every players inside a radius of 8 nodes. 29 | * `Signal Changer` : If it receives a signal on its pin "F", it turns on. If it receives a signal on its pin "O", it turns off. Note : an inverted signal is sended at the other end of the arrow. 30 | * `Switch Torch` : It connects just like Mesecons Torch. If it receives a signal, it turns on, and if it receives a second signal, it turns off. 31 | * `Teleporter` : If you place one teleporter, it teleports the nearest player on itself when it receives a mesecons signal. If you place two teleporters on the same axis, when one receives a mesecons signal, it teleports the nearest player on the second (with a maximal distance of 50 nodes by default). The player teleporter must be inside a radius of 25 nodes. 32 | * `Time Gate` : If it receives a mesecons signal, whatever its duration, a mesecons signal is send with a fixed duration. You can change it in the formspec by right-clicking on the gate. 33 | * `Wireless` : Place 2 (or more) wireless somewhere. Change their channel by right-click. If you send a signal to a wireless, every wireless wich have the same channel will send the signal. Compatible with digiline mod. 34 | * `Wireless Jammer` : If it receives a mesecons signal, it deactivates all wireless (receptors) in a radius of 15 nodes. 35 | 36 | ## Settings 37 | 38 | You can set the settings by using the Minetest GUI ("Settings" tab -> Advanced settings -> Mods -> MoreMesecons). 39 | 40 | ## The Sayer and the Speech Dispatcher 41 | 42 | [Speech Dispatcher project](http://freecode.com/projects/speech-dispatcher) 43 | 44 | The Sayer item is able to speak on your speakers using the speech dispatcher, under these conditions: 45 | 1. The moremesecons_sayer mod is present in your trusted_mods setting 46 | 2. You are playing in singleplayer. 47 | 3. You are using a POSIX-compliant system and a sh-compatible shell (such as bash, dash, zsh...). Microsoft Windows is NOT POSIX-compliant. 48 | 4. The speech dispatcher is installed on your system. 49 | 50 | The mod is able to detect issues 1, 2, and 4 by itself and then disable the speech dispatcher ; however, if you are using a non-POSIX-compliant system, the mod will crash on startup and you will need to disable the speech dispatcher manually (Settings tab -> Advanced settings -> Mods -> MoreMesecons -> Sayer -> Use the Speech Dispatcher). 51 | -------------------------------------------------------------------------------- /description.txt: -------------------------------------------------------------------------------- 1 | Adds more Mesecons items. 2 | -------------------------------------------------------------------------------- /modpack.txt: -------------------------------------------------------------------------------- 1 | The presence of this file indicates that the current folder is a modpack. -------------------------------------------------------------------------------- /moremesecons_adjustable_blinkyplant/init.lua: -------------------------------------------------------------------------------- 1 | local toggle_timer = function (pos, restart) 2 | local timer = minetest.get_node_timer(pos) 3 | if timer:is_started() 4 | and not restart then 5 | timer:stop() 6 | else 7 | local interval = tonumber(minetest.get_meta(pos):get_string("interval")) or 1 8 | if interval < moremesecons.setting("adjustable_blinky_plant", "min_interval", 0.5) then 9 | interval = moremesecons.setting("adjustable_blinky_plant", "min_interval", 0.5) 10 | end 11 | timer:start(interval) 12 | end 13 | end 14 | 15 | local on_timer = function(pos) 16 | if mesecon.flipstate(pos, minetest.get_node(pos)) == "on" then 17 | mesecon.receptor_on(pos) 18 | else 19 | mesecon.receptor_off(pos) 20 | end 21 | toggle_timer(pos, false) 22 | end 23 | 24 | mesecon.register_node("moremesecons_adjustable_blinkyplant:adjustable_blinky_plant", { 25 | description="Adjustable Blinky Plant", 26 | drawtype = "plantlike", 27 | inventory_image = "moremesecons_blinky_plant_off.png", 28 | paramtype = "light", 29 | walkable = false, 30 | sounds = default.node_sound_leaves_defaults(), 31 | selection_box = { 32 | type = "fixed", 33 | fixed = {-0.3, -0.5, -0.3, 0.3, -0.5+0.7, 0.3}, 34 | }, 35 | on_timer = on_timer, 36 | on_construct = function(pos) 37 | local meta = minetest.get_meta(pos) 38 | meta:set_string("interval", "1") 39 | meta:set_string("formspec", "field[interval;interval;${interval}]") 40 | toggle_timer(pos, true) 41 | end, 42 | on_receive_fields = function(pos, _, fields, player) 43 | local interval = tonumber(fields.interval) 44 | if interval 45 | and not minetest.is_protected(pos, player:get_player_name()) then 46 | minetest.get_meta(pos):set_string("interval", interval) 47 | toggle_timer(pos, true) 48 | end 49 | end, 50 | },{ 51 | tiles = {"moremesecons_blinky_plant_off.png"}, 52 | groups = {dig_immediate=3}, 53 | mesecons = {receptor = { state = mesecon.state.off }} 54 | },{ 55 | tiles = {"moremesecons_blinky_plant_off.png^moremesecons_blinky_plant_on.png"}, 56 | groups = {dig_immediate=3, not_in_creative_inventory=1}, 57 | sunlight_propagates = true, 58 | mesecons = {receptor = { state = mesecon.state.on }}, 59 | }) 60 | 61 | 62 | minetest.register_craft({ 63 | output = "moremesecons_adjustable_blinkyplant:adjustable_blinky_plant_off 1", 64 | recipe = { {"mesecons_blinkyplant:blinky_plant_off"}, 65 | {"default:mese_crystal_fragment"},} 66 | }) 67 | -------------------------------------------------------------------------------- /moremesecons_adjustable_blinkyplant/mod.conf: -------------------------------------------------------------------------------- 1 | name = moremesecons_adjustable_blinkyplant 2 | depends = mesecons,moremesecons_utils 3 | optional_depends = craft_guide 4 | -------------------------------------------------------------------------------- /moremesecons_adjustable_blinkyplant/textures/moremesecons_blinky_plant_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_adjustable_blinkyplant/textures/moremesecons_blinky_plant_off.png -------------------------------------------------------------------------------- /moremesecons_adjustable_blinkyplant/textures/moremesecons_blinky_plant_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_adjustable_blinkyplant/textures/moremesecons_blinky_plant_on.png -------------------------------------------------------------------------------- /moremesecons_adjustable_player_detector/init.lua: -------------------------------------------------------------------------------- 1 | -- Adjustable Player Detector 2 | -- Detects players in a certain radius 3 | -- The radius can be changes by right-click (by default 6) 4 | 5 | local MAX_RADIUS = moremesecons.setting("adjustable_player_detector", "max_radius", 16, 0) 6 | 7 | local function make_formspec(meta) 8 | meta:set_string("formspec", "size[9,5]" .. 9 | "field[0.3, 0;9,2;scanname;Comma-separated list of the names of players to scan for (empty for any):;${scanname}]".. 10 | "field[0.3,1.5;4,2;digiline_channel;Digiline Channel (optional):;${digiline_channel}]".. 11 | "field[0.3,3;4,2;radius;Detection radius:;${radius}]".. 12 | "button_exit[3.5,3.5;2,3;;Save]") 13 | end 14 | 15 | local function object_detector_make_formspec(pos) 16 | make_formspec(minetest.get_meta(pos)) 17 | end 18 | 19 | local function object_detector_on_receive_fields(pos, _, fields, player) 20 | if not fields.scanname 21 | or not fields.digiline_channel 22 | or minetest.is_protected(pos, player:get_player_name()) then 23 | return 24 | end 25 | 26 | local meta = minetest.get_meta(pos) 27 | meta:set_string("scanname", fields.scanname) 28 | meta:set_string("digiline_channel", fields.digiline_channel) 29 | local r = tonumber(fields.radius) 30 | if r then 31 | meta:set_int("radius", r) 32 | end 33 | end 34 | 35 | -- returns true if player was found, false if not 36 | local object_detector_scan = function (pos) 37 | local meta = minetest.get_meta(pos) 38 | local scanname = meta:get_string("scanname") 39 | local scan_all = scanname == "" 40 | local scan_names = scanname:split(',') 41 | local radius = math.min(meta:get_int("radius"), MAX_RADIUS) 42 | if radius <= 0 then 43 | radius = 6 44 | end 45 | for _,obj in pairs(minetest.get_objects_inside_radius(pos, radius)) do 46 | local isname = obj:get_player_name() -- "" is returned if it is not a player; "" ~= nil! 47 | if isname ~= "" then 48 | if scan_all then 49 | return true, isname 50 | end 51 | for _, name in ipairs(scan_names) do 52 | if isname == name then 53 | return true, isname 54 | end 55 | end 56 | end 57 | end 58 | return false 59 | end 60 | 61 | -- set player name when receiving a digiline signal on a specific channel 62 | local object_detector_digiline = { 63 | effector = { 64 | action = function (pos, node, channel, msg) 65 | local meta = minetest.get_meta(pos) 66 | local active_channel = meta:get_string("digiline_channel") 67 | if channel ~= active_channel then 68 | return 69 | end 70 | if type(msg) == "string" then 71 | meta:set_string("scanname", msg) 72 | make_formspec(meta) 73 | elseif type(msg) == "table" then 74 | if msg.radius then 75 | local r = tonumber(msg.radius) 76 | if r then 77 | meta:set_int("radius", tonumber(msg.radius)) 78 | make_formspec(meta) 79 | end 80 | end 81 | if type(msg.scanname) == "string" then 82 | meta:set_string("scanname", msg.scanname) 83 | make_formspec(meta) 84 | end 85 | if msg.command == "get" then 86 | local found, name = object_detector_scan(pos) 87 | if not found then 88 | name = "" 89 | end 90 | digiline:receptor_send(pos, digiline.rules.default, channel, name) 91 | end 92 | end 93 | end, 94 | }, 95 | receptor = {} 96 | } 97 | 98 | minetest.register_node("moremesecons_adjustable_player_detector:player_detector_off", { 99 | tiles = {"default_steel_block.png", "default_steel_block.png", "moremesecons_player_detector_off.png"}, 100 | paramtype = "light", 101 | walkable = true, 102 | groups = {cracky=3}, 103 | description="Adjustable Player Detector", 104 | mesecons = {receptor = { 105 | state = mesecon.state.off, 106 | rules = mesecon.rules.pplate 107 | }}, 108 | on_construct = object_detector_make_formspec, 109 | on_receive_fields = object_detector_on_receive_fields, 110 | sounds = default.node_sound_stone_defaults(), 111 | digiline = object_detector_digiline 112 | }) 113 | 114 | minetest.register_node("moremesecons_adjustable_player_detector:player_detector_on", { 115 | tiles = {"default_steel_block.png", "default_steel_block.png", "moremesecons_player_detector_on.png"}, 116 | paramtype = "light", 117 | walkable = true, 118 | groups = {cracky=3,not_in_creative_inventory=1}, 119 | drop = 'moremesecons_adjustable_player_detector:player_detector_off', 120 | mesecons = {receptor = { 121 | state = mesecon.state.on, 122 | rules = mesecon.rules.pplate 123 | }}, 124 | on_construct = object_detector_make_formspec, 125 | on_receive_fields = object_detector_on_receive_fields, 126 | sounds = default.node_sound_stone_defaults(), 127 | digiline = object_detector_digiline 128 | }) 129 | 130 | minetest.register_craft({ 131 | output = 'moremesecons_adjustable_player_detector:player_detector_off', 132 | recipe = { 133 | {"mesecons_detector:object_detector_off"}, 134 | {"default:mese_crystal_fragment"} 135 | } 136 | }) 137 | 138 | minetest.register_abm({ 139 | nodenames = {"moremesecons_adjustable_player_detector:player_detector_off"}, 140 | interval = 1.0, 141 | chance = 1, 142 | action = function(pos) 143 | if object_detector_scan(pos) then 144 | minetest.swap_node(pos, {name = "moremesecons_adjustable_player_detector:player_detector_on"}) 145 | mesecon.receptor_on(pos, mesecon.rules.pplate) 146 | end 147 | end, 148 | }) 149 | 150 | minetest.register_abm({ 151 | nodenames = {"moremesecons_adjustable_player_detector:player_detector_on"}, 152 | interval = 1.0, 153 | chance = 1, 154 | action = function(pos) 155 | if not object_detector_scan(pos) then 156 | minetest.swap_node(pos, {name = "moremesecons_adjustable_player_detector:player_detector_off"}) 157 | mesecon.receptor_off(pos, mesecon.rules.pplate) 158 | end 159 | end, 160 | }) 161 | -------------------------------------------------------------------------------- /moremesecons_adjustable_player_detector/mod.conf: -------------------------------------------------------------------------------- 1 | name = moremesecons_adjustable_player_detector 2 | depends = mesecons 3 | optional_depends = craft_guide 4 | -------------------------------------------------------------------------------- /moremesecons_adjustable_player_detector/textures/moremesecons_player_detector_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_adjustable_player_detector/textures/moremesecons_player_detector_off.png -------------------------------------------------------------------------------- /moremesecons_adjustable_player_detector/textures/moremesecons_player_detector_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_adjustable_player_detector/textures/moremesecons_player_detector_on.png -------------------------------------------------------------------------------- /moremesecons_commandblock/init.lua: -------------------------------------------------------------------------------- 1 | local strip_color_codes = minetest.settings:get_bool("strip_color_codes", false) 2 | 3 | local function initialize_data(meta) 4 | local NEAREST_MAX_DISTANCE = moremesecons.setting("commandblock", "nearest_max_distance", 8, 1) 5 | 6 | local commands = meta:get_string("commands") 7 | meta:set_string("formspec", 8 | "size[9,5]" .. 9 | "textarea[0.5,0.5;8.5,4;commands;Commands;"..minetest.formspec_escape(commands).."]" .. 10 | "label[1,3.8;@nearest is replaced by the nearest player name ("..tostring(NEAREST_MAX_DISTANCE).." nodes max for the nearest distance)".."]" .. 11 | "button_exit[3.3,4.5;2,1;submit;Submit]") 12 | local owner = meta:get_string("owner") 13 | if owner == "" then 14 | owner = "not owned" 15 | else 16 | owner = "owned by " .. owner 17 | end 18 | meta:set_string("infotext", "Command Block\n" .. 19 | "(" .. owner .. ")\n" .. 20 | "Commands: "..commands) 21 | end 22 | 23 | local function construct(pos) 24 | local meta = minetest.get_meta(pos) 25 | 26 | meta:set_string("commands", "tell @nearest Commandblock unconfigured") 27 | 28 | meta:set_string("owner", "") 29 | 30 | initialize_data(meta) 31 | end 32 | 33 | local function after_place(pos, placer) 34 | if placer then 35 | local meta = minetest.get_meta(pos) 36 | meta:set_string("owner", placer:get_player_name()) 37 | initialize_data(meta) 38 | end 39 | end 40 | 41 | local function receive_fields(pos, _, fields, player) 42 | if not fields.submit then 43 | return 44 | end 45 | local meta = minetest.get_meta(pos) 46 | local owner = meta:get_string("owner") 47 | if owner ~= "" 48 | and player:get_player_name() ~= owner then 49 | return 50 | end 51 | if strip_color_codes then 52 | meta:set_string("commands", minetest.strip_colors(fields.commands)) 53 | else 54 | meta:set_string("commands", fields.commands) 55 | end 56 | 57 | initialize_data(meta) 58 | end 59 | 60 | local function resolve_commands(commands, pos) 61 | local nearest = "" 62 | local min_distance = math.huge 63 | local players = minetest.get_connected_players() 64 | for _, player in pairs(players) do 65 | local distance = vector.distance(pos, player:get_pos()) 66 | if distance < min_distance then 67 | min_distance = distance 68 | nearest = player:get_player_name() 69 | end 70 | end 71 | local new_commands = commands:gsub("@nearest", nearest) 72 | return new_commands, min_distance, new_commands ~= commands 73 | end 74 | 75 | local function commandblock_action_on(pos, node) 76 | local NEAREST_MAX_DISTANCE = moremesecons.setting("commandblock", "nearest_max_distance", 8, 1) 77 | 78 | local accepted_commands = {} 79 | do 80 | local commands_str = moremesecons.setting("commandblock", "authorized_commands", "tell") 81 | for command in string.gmatch(commands_str, "([^ ]+)") do 82 | accepted_commands[command] = true 83 | end 84 | end 85 | 86 | if node.name ~= "moremesecons_commandblock:commandblock_off" then 87 | return 88 | end 89 | 90 | minetest.swap_node(pos, {name = "moremesecons_commandblock:commandblock_on"}) 91 | 92 | local meta = minetest.get_meta(pos) 93 | local owner = meta:get_string("owner") 94 | if owner == "" then 95 | return 96 | end 97 | 98 | local commands, distance, nearest_in_commands = resolve_commands(meta:get_string("commands"), pos) 99 | if distance > NEAREST_MAX_DISTANCE and nearest_in_commands then 100 | minetest.chat_send_player(owner, "The nearest player is too far to use his name in the commands of a craftable command block.") 101 | return 102 | end 103 | for _, command in pairs(commands:split("\n")) do 104 | local pos = command:find(" ") 105 | local cmd, param = command, "" 106 | if pos then 107 | cmd = command:sub(1, pos - 1) 108 | param = command:sub(pos + 1) 109 | end 110 | local cmddef = minetest.chatcommands[cmd] 111 | if not accepted_commands[cmd] and next(accepted_commands) then 112 | minetest.chat_send_player(owner, "You can not execute the command "..cmd.." with a craftable command block ! This event will be reported.") 113 | minetest.log("action", "Player "..owner.." tryed to execute an unauthorized command with a craftable command block.") 114 | return 115 | end 116 | if not cmddef then 117 | minetest.chat_send_player(owner, "The command "..cmd.." does not exist") 118 | return 119 | end 120 | local has_privs, missing_privs = minetest.check_player_privs(owner, cmddef.privs) 121 | if not has_privs then 122 | minetest.chat_send_player(owner, "You don't have permission " 123 | .."to run "..cmd 124 | .." (missing privileges: " 125 | ..table.concat(missing_privs, ", ")..")") 126 | return 127 | end 128 | cmddef.func(owner, param) 129 | end 130 | end 131 | 132 | local function commandblock_action_off(pos, node) 133 | if node.name == "moremesecons_commandblock:commandblock_on" then 134 | minetest.swap_node(pos, {name = "moremesecons_commandblock:commandblock_off"}) 135 | end 136 | end 137 | 138 | local function can_dig(pos, player) 139 | local meta = minetest.get_meta(pos) 140 | local owner = meta:get_string("owner") 141 | return owner == "" or owner == player:get_player_name() 142 | end 143 | 144 | minetest.register_node("moremesecons_commandblock:commandblock_off", { 145 | description = "Craftable Command Block", 146 | tiles = {"moremesecons_commandblock_off.png"}, 147 | groups = {cracky=2, mesecon_effector_off=1}, 148 | on_construct = construct, 149 | after_place_node = after_place, 150 | on_receive_fields = receive_fields, 151 | can_dig = can_dig, 152 | sounds = default.node_sound_stone_defaults(), 153 | mesecons = {effector = { 154 | action_on = commandblock_action_on 155 | }} 156 | }) 157 | 158 | minetest.register_node("moremesecons_commandblock:commandblock_on", { 159 | tiles = {"moremesecons_commandblock_on.png"}, 160 | groups = {cracky=2, mesecon_effector_on=1, not_in_creative_inventory=1}, 161 | light_source = 10, 162 | drop = "moremesecons_commandblock:commandblock_off", 163 | on_construct = construct, 164 | after_place_node = after_place, 165 | on_receive_fields = receive_fields, 166 | can_dig = can_dig, 167 | sounds = default.node_sound_stone_defaults(), 168 | mesecons = {effector = { 169 | action_off = commandblock_action_off 170 | }} 171 | }) 172 | 173 | minetest.register_craft({ 174 | output = "moremesecons_commandblock:commandblock_off", 175 | recipe = { 176 | {"group:mesecon_conductor_craftable","default:mese_crystal","group:mesecon_conductor_craftable"}, 177 | {"default:mese_crystal","group:mesecon_conductor_craftable","default:mese_crystal"}, 178 | {"group:mesecon_conductor_craftable","default:mese_crystal","group:mesecon_conductor_craftable"} 179 | } 180 | }) 181 | -------------------------------------------------------------------------------- /moremesecons_commandblock/mod.conf: -------------------------------------------------------------------------------- 1 | name = moremesecons_commandblock 2 | depends = mesecons,moremesecons_utils 3 | optional_depends = craft_guide 4 | -------------------------------------------------------------------------------- /moremesecons_commandblock/textures/moremesecons_commandblock_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_commandblock/textures/moremesecons_commandblock_off.png -------------------------------------------------------------------------------- /moremesecons_commandblock/textures/moremesecons_commandblock_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_commandblock/textures/moremesecons_commandblock_on.png -------------------------------------------------------------------------------- /moremesecons_conductor_signalchanger/init.lua: -------------------------------------------------------------------------------- 1 | local nodebox = { 2 | type = "fixed", 3 | fixed = {{-8/16, -8/16, -8/16, 8/16, -7/16, 8/16 }}, 4 | } 5 | 6 | local function signalchanger_get_output_rules(node) 7 | local rules = {{x=-1, y=0, z=0}} 8 | for _ = 0, node.param2 do 9 | rules = mesecon.rotate_rules_left(rules) 10 | end 11 | return rules 12 | end 13 | 14 | local function signalchanger_get_input_rules(node) 15 | local rules = {{x=0, y=0, z=-1, name="input_on"}, {x=0, y=0, z=1, name="input_off"}, {x=1, y=0, z=0, name="input_signal"}} 16 | for _ = 0, node.param2 do 17 | rules = mesecon.rotate_rules_left(rules) 18 | end 19 | return rules 20 | end 21 | 22 | local update = function(pos, node, link, newstate) 23 | local meta = minetest.get_meta(pos) 24 | meta:set_int(link.name, newstate == "on" and 1 or 0) 25 | local input_on = meta:get_int("input_on") == 1 26 | local input_off = meta:get_int("input_off") == 1 27 | local input_signal = meta:get_int("input_signal") == 1 28 | 29 | if input_on then 30 | minetest.swap_node(pos, {name = "moremesecons_conductor_signalchanger:conductor_signalchanger_on", param2 = node.param2}) 31 | elseif input_off then 32 | mesecon.receptor_off(pos, signalchanger_get_output_rules(node)) 33 | minetest.swap_node(pos, {name = "moremesecons_conductor_signalchanger:conductor_signalchanger_off", param2 = node.param2}) 34 | end 35 | 36 | if input_signal and minetest.get_node(pos).name == "moremesecons_conductor_signalchanger:conductor_signalchanger_on" then -- Note : we must use "minetest.get_node(pos)" and not "node" because the node may have been changed 37 | mesecon.receptor_on(pos, signalchanger_get_output_rules(node)) 38 | else 39 | mesecon.receptor_off(pos, signalchanger_get_output_rules(node)) 40 | end 41 | end 42 | 43 | mesecon.register_node("moremesecons_conductor_signalchanger:conductor_signalchanger", { 44 | description = "Conductor Signal Changer", 45 | inventory_image = "moremesecons_conductor_signalchanger_off.png", 46 | groups = {dig_immediate = 2}, 47 | paramtype = "light", 48 | paramtype2 = "facedir", 49 | drawtype = "nodebox", 50 | selection_box = nodebox, 51 | node_box = nodebox, 52 | },{ 53 | groups = {dig_immediate = 2}, 54 | mesecons = { 55 | receptor = { 56 | rules = signalchanger_get_output_rules 57 | }, 58 | effector = { 59 | rules = signalchanger_get_input_rules, 60 | action_change = update 61 | }, 62 | }, 63 | tiles = {"moremesecons_conductor_signalchanger_off.png"}, 64 | },{ 65 | groups = {dig_immediate = 2, not_in_creative_inventory = 1}, 66 | mesecons = { 67 | receptor = { 68 | rules = signalchanger_get_output_rules, 69 | }, 70 | effector = { 71 | rules = signalchanger_get_input_rules, 72 | action_change = update, 73 | }, 74 | }, 75 | tiles = {"moremesecons_conductor_signalchanger_on.png"}, 76 | }) 77 | 78 | minetest.register_craft({ 79 | output = "moremesecons_conductor_signalchanger:conductor_signalchanger_off", 80 | recipe = {{"group:mesecon_conductor_craftable","moremesecons_signalchanger:signalchanger_off"}} 81 | }) 82 | -------------------------------------------------------------------------------- /moremesecons_conductor_signalchanger/mod.conf: -------------------------------------------------------------------------------- 1 | name = moremesecons_conductor_signalchanger 2 | depends = mesecons 3 | optional_depends = craft_guide 4 | -------------------------------------------------------------------------------- /moremesecons_conductor_signalchanger/textures/moremesecons_conductor_signalchanger_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_conductor_signalchanger/textures/moremesecons_conductor_signalchanger_off.png -------------------------------------------------------------------------------- /moremesecons_conductor_signalchanger/textures/moremesecons_conductor_signalchanger_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_conductor_signalchanger/textures/moremesecons_conductor_signalchanger_on.png -------------------------------------------------------------------------------- /moremesecons_dual_delayer/init.lua: -------------------------------------------------------------------------------- 1 | local function dual_delayer_get_input_rules(node) 2 | local rules = {{x=1, y=0, z=0}} 3 | for _ = 0, node.param2 do 4 | rules = mesecon.rotate_rules_left(rules) 5 | end 6 | return rules 7 | end 8 | 9 | local function dual_delayer_get_output_rules(node) 10 | local rules = {{x=0, y=0, z=1}, {x=0, y=0, z=-1}} 11 | for _ = 0, node.param2 do 12 | rules = mesecon.rotate_rules_left(rules) 13 | end 14 | return rules 15 | end 16 | 17 | local dual_delayer_activate = function(pos, node) 18 | mesecon.receptor_on(pos, {dual_delayer_get_output_rules(node)[1]}) -- Turn on the port 1 19 | minetest.swap_node(pos, {name = "moremesecons_dual_delayer:dual_delayer_10", param2 = node.param2}) 20 | minetest.after(0.4, function() 21 | mesecon.receptor_on(pos, {dual_delayer_get_output_rules(node)[2]}) -- Turn on the port 2 22 | minetest.swap_node(pos, {name = "moremesecons_dual_delayer:dual_delayer_11", param2 = node.param2}) 23 | end) 24 | end 25 | 26 | local dual_delayer_deactivate = function(pos, node, link) 27 | mesecon.receptor_off(pos, {dual_delayer_get_output_rules(node)[2]}) -- Turn off the port 2 28 | minetest.swap_node(pos, {name = "moremesecons_dual_delayer:dual_delayer_10", param2 = node.param2}) 29 | minetest.after(0.4, function() 30 | mesecon.receptor_off(pos, {dual_delayer_get_output_rules(node)[1]}) -- Turn off the port 1 31 | minetest.swap_node(pos, {name = "moremesecons_dual_delayer:dual_delayer_00", param2 = node.param2}) 32 | end) 33 | end 34 | 35 | 36 | for n,i in pairs({{0,0},{1,0},{1,1}}) do 37 | local i1,i2 = unpack(i) 38 | 39 | local groups = {dig_immediate = 2} 40 | if n ~= 1 then 41 | groups.not_in_creative_inventory = 1 42 | end 43 | 44 | local top_texture = "^moremesecons_dual_delayer_overlay.png^[makealpha:255,126,126" 45 | if i1 == i2 then 46 | if i1 == 0 then 47 | top_texture = "mesecons_wire_off.png"..top_texture 48 | else 49 | top_texture = "mesecons_wire_on.png"..top_texture 50 | end 51 | else 52 | local pre = "mesecons_wire_off.png^[lowpart:50:mesecons_wire_on.png^[transformR" 53 | if i1 == 0 then 54 | pre = pre.. 90 55 | else 56 | pre = pre.. 270 57 | end 58 | top_texture = pre..top_texture 59 | end 60 | 61 | local use_texture_alpha 62 | if minetest.features.use_texture_alpha_string_modes then 63 | use_texture_alpha = "opaque" 64 | end 65 | minetest.register_node("moremesecons_dual_delayer:dual_delayer_"..i1 ..i2, { 66 | description = "Dual Delayer", 67 | drop = "moremesecons_dual_delayer:dual_delayer_00", 68 | inventory_image = top_texture, 69 | wield_image = top_texture, 70 | paramtype = "light", 71 | paramtype2 = "facedir", 72 | drawtype = "nodebox", 73 | node_box = { 74 | type = "fixed", 75 | fixed = {{-6/16, -8/16, -8/16, 6/16, -7/16, 1/16 }, 76 | {-8/16, -8/16, 1/16, -6/16, -7/16, -1/16}, 77 | {8/16, -8/16, -1/16, 6/16, -7/16, 1/16}} 78 | }, 79 | groups = groups, 80 | tiles = {top_texture, "moremesecons_dual_delayer_bottom.png", "moremesecons_dual_delayer_side_left.png", "moremesecons_dual_delayer_side_right.png", "moremesecons_dual_delayer_ends.png", "moremesecons_dual_delayer_ends.png"}, 81 | use_texture_alpha = use_texture_alpha, 82 | mesecons = { 83 | receptor = { 84 | state = mesecon.state.off, 85 | rules = dual_delayer_get_output_rules 86 | }, 87 | effector = { 88 | rules = dual_delayer_get_input_rules, 89 | action_on = dual_delayer_activate, 90 | action_off = dual_delayer_deactivate 91 | } 92 | } 93 | }) 94 | end 95 | 96 | minetest.register_craft({ 97 | type = "shapeless", 98 | output = "moremesecons_dual_delayer:dual_delayer_00 2", 99 | recipe = {"mesecons_delayer:delayer_off_1", "mesecons_delayer:delayer_off_1"} 100 | }) 101 | -------------------------------------------------------------------------------- /moremesecons_dual_delayer/mod.conf: -------------------------------------------------------------------------------- 1 | name = moremesecons_dual_delayer 2 | depends = mesecons 3 | optional_depends = craft_guide 4 | -------------------------------------------------------------------------------- /moremesecons_dual_delayer/textures/moremesecons_dual_delayer_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_dual_delayer/textures/moremesecons_dual_delayer_bottom.png -------------------------------------------------------------------------------- /moremesecons_dual_delayer/textures/moremesecons_dual_delayer_ends.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_dual_delayer/textures/moremesecons_dual_delayer_ends.png -------------------------------------------------------------------------------- /moremesecons_dual_delayer/textures/moremesecons_dual_delayer_overlay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_dual_delayer/textures/moremesecons_dual_delayer_overlay.png -------------------------------------------------------------------------------- /moremesecons_dual_delayer/textures/moremesecons_dual_delayer_side_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_dual_delayer/textures/moremesecons_dual_delayer_side_left.png -------------------------------------------------------------------------------- /moremesecons_dual_delayer/textures/moremesecons_dual_delayer_side_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_dual_delayer/textures/moremesecons_dual_delayer_side_right.png -------------------------------------------------------------------------------- /moremesecons_entity_detector/init.lua: -------------------------------------------------------------------------------- 1 | -- Entity detector 2 | -- Detects entitys in a certain radius 3 | -- The radius can be changes by right-click (by default 6) 4 | 5 | local MAX_RADIUS = moremesecons.setting("entity_detector", "max_radius", 16, 0) 6 | 7 | local function make_formspec(meta) 8 | meta:set_string("formspec", "size[9,5]" .. 9 | "field[0.3, 0;9,2;scanname;Comma-separated list of the names (itemstring) of entities to scan for (empty for any):;${scanname}]".. 10 | "field[0.3,1.5;4,2;digiline_channel;Digiline Channel (optional):;${digiline_channel}]".. 11 | "field[0.3,3;2,2;radius;Detection radius:;${radius}]".. 12 | "button_exit[3.5,3.5;2,3;;Save]") 13 | end 14 | 15 | local function object_detector_make_formspec(pos) 16 | make_formspec(minetest.get_meta(pos)) 17 | end 18 | 19 | local function object_detector_on_receive_fields(pos, _, fields, player) 20 | if not fields.scanname 21 | or not fields.digiline_channel 22 | or minetest.is_protected(pos, player:get_player_name()) then 23 | return 24 | end 25 | 26 | local meta = minetest.get_meta(pos) 27 | meta:set_string("scanname", fields.scanname) 28 | meta:set_string("digiline_channel", fields.digiline_channel) 29 | local r = tonumber(fields.radius) 30 | if r then 31 | meta:set_int("radius", math.min(r, MAX_RADIUS)) 32 | end 33 | end 34 | 35 | -- returns true if entity was found, false if not 36 | local object_detector_scan = function (pos) 37 | local meta = minetest.get_meta(pos) 38 | local scanname = meta:get_string("scanname") 39 | local scan_all = scanname == "" 40 | local scan_names = scanname:split(',') 41 | local radius = math.min(tonumber(meta:get("radius")) or 6, MAX_RADIUS) 42 | for _,obj in pairs(minetest.get_objects_inside_radius(pos, radius)) do 43 | local luaentity = obj:get_luaentity() 44 | if luaentity then 45 | if scan_all then 46 | return true 47 | end 48 | local isname = luaentity.name 49 | for _, name in ipairs(scan_names) do 50 | if isname == name or (isname == "__builtin:item" and luaentity.itemstring == name) then 51 | return true 52 | end 53 | end 54 | end 55 | end 56 | return false 57 | end 58 | 59 | -- set entity name when receiving a digiline signal on a specific channel 60 | local object_detector_digiline = { 61 | effector = { 62 | action = function (pos, node, channel, msg) 63 | local meta = minetest.get_meta(pos) 64 | local active_channel = meta:get_string("digiline_channel") 65 | if channel ~= active_channel or type(msg) ~= "string" then 66 | return 67 | end 68 | meta:set_string("scanname", msg) 69 | if meta:get_string("formspec") ~= "" then 70 | make_formspec(meta) 71 | end 72 | end, 73 | } 74 | } 75 | 76 | minetest.register_node("moremesecons_entity_detector:entity_detector_off", { 77 | tiles = {"default_steel_block.png", "default_steel_block.png", "moremesecons_entity_detector_off.png"}, 78 | paramtype = "light", 79 | walkable = true, 80 | groups = {cracky=3}, 81 | description="Entity Detector", 82 | mesecons = {receptor = { 83 | state = mesecon.state.off, 84 | rules = mesecon.rules.pplate 85 | }}, 86 | on_construct = object_detector_make_formspec, 87 | on_receive_fields = object_detector_on_receive_fields, 88 | sounds = default.node_sound_stone_defaults(), 89 | digiline = object_detector_digiline 90 | }) 91 | 92 | minetest.register_node("moremesecons_entity_detector:entity_detector_on", { 93 | tiles = {"default_steel_block.png", "default_steel_block.png", "moremesecons_entity_detector_on.png"}, 94 | paramtype = "light", 95 | walkable = true, 96 | groups = {cracky=3,not_in_creative_inventory=1}, 97 | drop = 'moremesecons_entity_detector:entity_detector_off', 98 | mesecons = {receptor = { 99 | state = mesecon.state.on, 100 | rules = mesecon.rules.pplate 101 | }}, 102 | on_construct = object_detector_make_formspec, 103 | on_receive_fields = object_detector_on_receive_fields, 104 | sounds = default.node_sound_stone_defaults(), 105 | digiline = object_detector_digiline 106 | }) 107 | 108 | minetest.register_craft({ 109 | output = 'moremesecons_entity_detector:entity_detector_off', 110 | recipe = { 111 | {"default:mese_crystal_fragment"}, 112 | {"mesecons_detector:object_detector_off"} 113 | } 114 | }) 115 | 116 | minetest.register_abm({ 117 | nodenames = {"moremesecons_entity_detector:entity_detector_off"}, 118 | interval = 1.0, 119 | chance = 1, 120 | action = function(pos) 121 | if object_detector_scan(pos) then 122 | minetest.swap_node(pos, {name = "moremesecons_entity_detector:entity_detector_on"}) 123 | mesecon.receptor_on(pos, mesecon.rules.pplate) 124 | end 125 | end, 126 | }) 127 | 128 | minetest.register_abm({ 129 | nodenames = {"moremesecons_entity_detector:entity_detector_on"}, 130 | interval = 1.0, 131 | chance = 1, 132 | action = function(pos) 133 | if not object_detector_scan(pos) then 134 | minetest.swap_node(pos, {name = "moremesecons_entity_detector:entity_detector_off"}) 135 | mesecon.receptor_off(pos, mesecon.rules.pplate) 136 | end 137 | end, 138 | }) 139 | -------------------------------------------------------------------------------- /moremesecons_entity_detector/mod.conf: -------------------------------------------------------------------------------- 1 | name = moremesecons_entity_detector 2 | depends = mesecons 3 | optional_depends = craft_guide 4 | -------------------------------------------------------------------------------- /moremesecons_entity_detector/textures/moremesecons_entity_detector_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_entity_detector/textures/moremesecons_entity_detector_off.png -------------------------------------------------------------------------------- /moremesecons_entity_detector/textures/moremesecons_entity_detector_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_entity_detector/textures/moremesecons_entity_detector_on.png -------------------------------------------------------------------------------- /moremesecons_igniter/init.lua: -------------------------------------------------------------------------------- 1 | local function add_back_igniter(pos) 2 | local name = minetest.get_node(pos).name 3 | 4 | if name == "moremesecons_igniter:igniter" then 5 | -- this should not happen 6 | minetest.log("error", "[moremesecons_igniter] igniter is already back") 7 | return 8 | end 9 | 10 | if name == "ignore" then 11 | -- in case of unloaded chunk 12 | minetest.get_voxel_manip():read_from_map(pos, pos) 13 | name = minetest.get_node(pos).name 14 | end 15 | 16 | if name == "air" 17 | or name == "fire:basic_flame" then 18 | minetest.set_node(pos, {name="moremesecons_igniter:igniter"}) 19 | else 20 | -- drop it as item if something took place there in the 0.8 seconds 21 | pos.y = pos.y+1 22 | minetest.add_item(pos, "moremesecons_igniter:igniter") 23 | pos.y = pos.y-1 24 | end 25 | end 26 | 27 | local function igniter_on(pos) 28 | minetest.set_node(pos, {name="fire:basic_flame"}) 29 | minetest.after(0.8, add_back_igniter, pos) 30 | end 31 | 32 | minetest.register_node("moremesecons_igniter:igniter", { 33 | description = "Igniter", 34 | paramtype = "light", 35 | tiles = {"moremesecons_igniter.png"}, 36 | groups = {cracky=3}, 37 | mesecons = { 38 | effector = { 39 | action_on = igniter_on 40 | }} 41 | }) 42 | 43 | 44 | minetest.register_craft({ 45 | output = "moremesecons_igniter:igniter", 46 | recipe = { {"default:torch"}, 47 | {"default:mese_crystal_fragment"},} 48 | }) 49 | -------------------------------------------------------------------------------- /moremesecons_igniter/mod.conf: -------------------------------------------------------------------------------- 1 | name = moremesecons_igniter 2 | depends = mesecons,fire 3 | optional_depends = craft_guide 4 | -------------------------------------------------------------------------------- /moremesecons_igniter/textures/moremesecons_igniter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_igniter/textures/moremesecons_igniter.png -------------------------------------------------------------------------------- /moremesecons_induction_transmitter/init.lua: -------------------------------------------------------------------------------- 1 | local function induction_transmitter_get_input_rules(node) 2 | -- All horizontal rules, except the output 3 | local rules = { 4 | {x=-1,y=0,z=0}, 5 | {x=1,y=0,z=0}, 6 | {x=0,y=0,z=-1}, 7 | {x=0,y=0,z=1} 8 | } 9 | for i, r in ipairs(rules) do 10 | if vector.equals(r, minetest.facedir_to_dir(node.param2)) then 11 | table.remove(rules, i) 12 | end 13 | end 14 | return rules 15 | end 16 | 17 | local function induction_transmitter_get_output_rules(node) 18 | return {vector.multiply(minetest.facedir_to_dir(node.param2), 2)} 19 | end 20 | 21 | local function act(pos, node, state) 22 | minetest.swap_node(pos, {name = "moremesecons_induction_transmitter:induction_transmitter_"..state, param2 = node.param2}) 23 | 24 | local dir = minetest.facedir_to_dir(node.param2) 25 | local target_pos = vector.add(pos, vector.multiply(dir, 2)) 26 | local target_node = minetest.get_node(target_pos) 27 | if mesecon.is_effector(target_node.name) then 28 | -- Switch on an aside node, so it sends a signal to the target node 29 | local aside_rule = mesecon.effector_get_rules(target_node)[1] 30 | if not aside_rule then 31 | return 32 | end 33 | mesecon["receptor_"..state](vector.add(target_pos, aside_rule), {vector.multiply(aside_rule, -1)}) 34 | elseif mesecon.is_conductor(target_node.name) then 35 | -- Switch on the conductor itself 36 | mesecon["receptor_"..state](target_pos, mesecon.conductor_get_rules(target_node)) 37 | end 38 | end 39 | 40 | mesecon.register_node("moremesecons_induction_transmitter:induction_transmitter", { 41 | description = "Induction Transmitter", 42 | drawtype = "nodebox", 43 | paramtype = "light", 44 | paramtype2 = "facedir", 45 | node_box = { 46 | type = "fixed", 47 | fixed = { 48 | {-0.5, -0.5, 0.125, 0.5, 0.5, 0.5}, 49 | {-0.375, -0.375, -0.1875, 0.375, 0.375, 0.125}, 50 | {-0.25, -0.25, -0.5, 0.25, 0.25, -0.1875}, 51 | } 52 | }, 53 | selection_box = { 54 | type = "fixed", 55 | fixed = { 56 | {-0.5, -0.5, 0.125, 0.5, 0.5, 0.5}, 57 | {-0.375, -0.375, -0.1875, 0.375, 0.375, 0.125}, 58 | {-0.25, -0.25, -0.5, 0.25, 0.25, -0.1875}, 59 | }, 60 | }, 61 | }, { 62 | tiles = {"default_mese_block.png"}, 63 | groups = {cracky = 3}, 64 | mesecons = { 65 | receptor = { 66 | state = mesecon.state.off, 67 | rules = induction_transmitter_get_output_rules 68 | }, 69 | effector = { 70 | rules = induction_transmitter_get_input_rules, 71 | action_on = function(pos, node) 72 | act(pos, node, "on") 73 | end 74 | } 75 | } 76 | }, { 77 | light_source = 5, 78 | tiles = {"default_mese_block.png^[brighten"}, 79 | groups = {cracky = 3, not_in_creative_inventory = 1}, 80 | mesecons = { 81 | receptor = { 82 | state = mesecon.state.on, 83 | rules = induction_transmitter_get_output_rules 84 | }, 85 | effector = { 86 | rules = induction_transmitter_get_input_rules, 87 | action_off = function(pos, node) 88 | act(pos, node, "off") 89 | end 90 | } 91 | } 92 | }) 93 | 94 | minetest.register_craft({ 95 | output = "moremesecons_induction_transmitter:induction_transmitter_off", 96 | recipe = { 97 | {"default:mese_crystal_fragment", "mesecons_torch:mesecon_torch_on", "default:mese_crystal_fragment"}, 98 | {"", "default:mese_crystal_fragment", ""} 99 | } 100 | }) 101 | -------------------------------------------------------------------------------- /moremesecons_induction_transmitter/mod.conf: -------------------------------------------------------------------------------- 1 | name = moremesecons_induction_transmitter 2 | depends = mesecons,mesecons_torch,default 3 | -------------------------------------------------------------------------------- /moremesecons_injector_controller/init.lua: -------------------------------------------------------------------------------- 1 | local injector_controller_get_output_rules = function(node) 2 | local rules = {{x = 0, y = 0, z = 1}} 3 | for _ = 0, node.param2 do 4 | rules = mesecon.rotate_rules_left(rules) 5 | end 6 | return rules 7 | end 8 | 9 | local injector_controller_get_input_rules = function(node) 10 | local rules = {{x = 0, y = 0, z = -1}, 11 | {x = 1, y = 0, z = 0}, 12 | {x = -1, y = 0, z = 0}} 13 | for _ = 0, node.param2 do 14 | rules = mesecon.rotate_rules_left(rules) 15 | end 16 | return rules 17 | end 18 | 19 | local start_timer = function(pos) 20 | local timer = minetest.get_node_timer(pos) 21 | timer:start(1) 22 | end 23 | local stop_timer = function(pos, node) 24 | local timer = minetest.get_node_timer(pos) 25 | timer:stop() 26 | mesecon.receptor_off(pos, injector_controller_get_output_rules(node)) 27 | minetest.swap_node(pos, {name="moremesecons_injector_controller:injector_controller_off", param2=node.param2}) 28 | end 29 | 30 | local on_timer = function(pos) 31 | local node = minetest.get_node(pos) 32 | if(mesecon.flipstate(pos, node) == "on") then 33 | mesecon.receptor_on(pos, injector_controller_get_output_rules(node)) 34 | else 35 | mesecon.receptor_off(pos, injector_controller_get_output_rules(node)) 36 | end 37 | start_timer(pos) 38 | end 39 | 40 | mesecon.register_node("moremesecons_injector_controller:injector_controller", { 41 | description="Injector Controller", 42 | drawtype = "nodebox", 43 | inventory_image = "moremesecons_injector_controller_off.png", 44 | paramtype = "light", 45 | paramtype2 = "facedir", 46 | node_box = { 47 | type = "fixed", 48 | fixed = {{-8/16, -8/16, -8/16, 8/16, -7/16, 8/16 }}, 49 | }, 50 | on_timer = on_timer, 51 | },{ 52 | tiles = {"moremesecons_injector_controller_off.png", "moremesecons_injector_controller_side.png", "moremesecons_injector_controller_side.png"}, 53 | groups = {dig_immediate=2}, 54 | mesecons = { 55 | receptor = { 56 | state = mesecon.state.off, 57 | rules = injector_controller_get_output_rules 58 | }, 59 | effector = { 60 | rules = injector_controller_get_input_rules, 61 | action_on = start_timer, 62 | action_off = stop_timer, 63 | } 64 | } 65 | },{ 66 | tiles = {"moremesecons_injector_controller_on.png", "moremesecons_injector_controller_side.png", "moremesecons_injector_controller_side.png"}, 67 | groups = {dig_immediate=2, not_in_creative_inventory=1}, 68 | mesecons = { 69 | receptor = { 70 | state = mesecon.state.on, 71 | rules = injector_controller_get_output_rules 72 | }, 73 | effector = { 74 | rules = injector_controller_get_input_rules, 75 | action_off = stop_timer, 76 | action_on = start_timer, 77 | } 78 | } 79 | }) 80 | 81 | minetest.register_craft({ 82 | output = "moremesecons_injector_controller:injector_controller_off", 83 | recipe = {{"mesecons_blinkyplant:blinky_plant_off","mesecons_gates:and_off"}} 84 | }) 85 | -------------------------------------------------------------------------------- /moremesecons_injector_controller/mod.conf: -------------------------------------------------------------------------------- 1 | name = moremesecons_injector_controller 2 | depends = mesecons 3 | optional_depends = craft_guide 4 | -------------------------------------------------------------------------------- /moremesecons_injector_controller/textures/moremesecons_injector_controller_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_injector_controller/textures/moremesecons_injector_controller_off.png -------------------------------------------------------------------------------- /moremesecons_injector_controller/textures/moremesecons_injector_controller_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_injector_controller/textures/moremesecons_injector_controller_on.png -------------------------------------------------------------------------------- /moremesecons_injector_controller/textures/moremesecons_injector_controller_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_injector_controller/textures/moremesecons_injector_controller_side.png -------------------------------------------------------------------------------- /moremesecons_jammer/init.lua: -------------------------------------------------------------------------------- 1 | -- see wireless jammer 2 | local storage = minetest.get_mod_storage() 3 | 4 | local jammers = moremesecons.load_MapDataStorage_legacy(storage, "jammers_v2", 5 | "jammers") 6 | 7 | local function update_mod_storage() 8 | storage:set_string("jammers_v2", jammers:serialize()) 9 | end 10 | 11 | local function add_jammer(pos) 12 | if jammers:getAt(pos) then 13 | return 14 | end 15 | jammers:setAt(pos, true) 16 | update_mod_storage() 17 | end 18 | 19 | local function remove_jammer(pos) 20 | jammers:removeAt(pos) 21 | update_mod_storage() 22 | end 23 | 24 | local function is_jammed(pos) 25 | local JAMMER_MAX_DISTANCE = moremesecons.setting("jammer", "max_distance", 10, 1) 26 | 27 | local minp = vector.subtract(pos, JAMMER_MAX_DISTANCE) 28 | local maxp = vector.add(pos, JAMMER_MAX_DISTANCE) 29 | for p in jammers:iter(minp, maxp) do 30 | local d = vector.subtract(pos, p) 31 | if d.x ^ 2 + d.y ^ 2 + d.z ^ 2 <= JAMMER_MAX_DISTANCE^2 then 32 | return true 33 | end 34 | end 35 | return false 36 | end 37 | 38 | minetest.after(0, function() -- After loading all mods, override some functions 39 | local jammed 40 | 41 | local actual_node_get = mesecon.get_node_force 42 | local function temp_node_get(pos, ...) 43 | local node = actual_node_get(pos, ...) 44 | if jammed == nil 45 | and node then 46 | jammed = is_jammed(pos) 47 | end 48 | return node 49 | end 50 | 51 | local actual_is_conductor_off = mesecon.is_conductor_off 52 | local function temp_is_conductor_off(...) 53 | if jammed then 54 | -- go to the next elseif, there's is_effector 55 | return 56 | end 57 | local v = actual_is_conductor_off(...) 58 | if v then 59 | -- it continues to the next frontier 60 | jammed = nil 61 | end 62 | return v 63 | end 64 | 65 | local actual_is_effector = mesecon.is_effector 66 | local function temp_is_effector(...) 67 | local abort_here = jammed 68 | -- the last elseif before continuing, jammed needs to be nil then 69 | jammed = nil 70 | if abort_here then 71 | return 72 | end 73 | return actual_is_effector(...) 74 | end 75 | 76 | local actual_turnon = mesecon.turnon 77 | function mesecon.turnon(...) 78 | --set those to the temporary functions 79 | mesecon.get_node_force = temp_node_get 80 | mesecon.is_conductor_off = temp_is_conductor_off 81 | mesecon.is_effector = temp_is_effector 82 | 83 | actual_turnon(...) 84 | 85 | mesecon.get_node_force = actual_node_get 86 | mesecon.is_conductor_off = actual_is_conductor_off 87 | mesecon.is_effector = actual_is_effector 88 | 89 | -- safety 90 | jammed = nil 91 | end 92 | end) 93 | 94 | mesecon.register_node("moremesecons_jammer:jammer", { 95 | description = "Mesecons Jammer", 96 | paramtype = "light", 97 | },{ 98 | tiles = {"moremesecons_jammer_off.png"}, 99 | groups = {dig_immediate=2}, 100 | mesecons = {effector = { 101 | action_on = function(pos) 102 | add_jammer(pos) 103 | minetest.sound_play("moremesecons_jammer", {pos = pos}) 104 | minetest.swap_node(pos, {name="moremesecons_jammer:jammer_on"}) 105 | end 106 | }}, 107 | },{ 108 | tiles = {"moremesecons_jammer_on.png"}, 109 | groups = {dig_immediate=2, not_in_creative_inventory=1}, 110 | mesecons = {effector = { 111 | action_off = function(pos) 112 | remove_jammer(pos) 113 | minetest.swap_node(pos, {name="moremesecons_jammer:jammer_off"}) 114 | end 115 | }}, 116 | on_destruct = remove_jammer, 117 | on_construct = add_jammer, 118 | }) 119 | 120 | minetest.register_craft({ 121 | output = "moremesecons_jammer:jammer_off", 122 | recipe = {{"group:mesecon_conductor_craftable", "default:mese", "group:mesecon_conductor_craftable"}, 123 | {"", "moremesecons_wireless:jammer_off", ""}} 124 | }) 125 | 126 | if moremesecons.setting("jammer", "enable_lbm", false) then 127 | minetest.register_lbm({ 128 | name = "moremesecons_jammer:add_jammer", 129 | nodenames = {"moremesecons_jammer:jammer_on"}, 130 | run_at_every_load = true, 131 | action = add_jammer 132 | }) 133 | end 134 | -------------------------------------------------------------------------------- /moremesecons_jammer/mod.conf: -------------------------------------------------------------------------------- 1 | name = moremesecons_jammer 2 | depends = mesecons,moremesecons_utils 3 | optional_depends = craft_guide 4 | -------------------------------------------------------------------------------- /moremesecons_jammer/sounds/moremesecons_jammer.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_jammer/sounds/moremesecons_jammer.ogg -------------------------------------------------------------------------------- /moremesecons_jammer/textures/moremesecons_jammer_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_jammer/textures/moremesecons_jammer_off.png -------------------------------------------------------------------------------- /moremesecons_jammer/textures/moremesecons_jammer_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_jammer/textures/moremesecons_jammer_on.png -------------------------------------------------------------------------------- /moremesecons_luablock/init.lua: -------------------------------------------------------------------------------- 1 | local storage = minetest.get_mod_storage() 2 | local pos_data = moremesecons.get_storage_data(storage, "pos_data") 3 | 4 | local function set_data(pos, code, owner) 5 | local data = { 6 | code = code, 7 | owner = owner 8 | } 9 | moremesecons.set_data_to_pos(pos_data, pos, data) 10 | end 11 | 12 | local function check_data(pos, code, owner) 13 | local stored_data = moremesecons.get_data_from_pos(pos_data, pos) 14 | if not stored_data then 15 | return false 16 | end 17 | if code ~= stored_data.code 18 | or owner ~= stored_data.owner then 19 | return false 20 | end 21 | return true 22 | end 23 | 24 | 25 | local function make_formspec(meta, pos) 26 | local code = minetest.formspec_escape(meta:get_string("code")) 27 | local errmsg = minetest.formspec_escape(meta:get_string("errmsg")) 28 | meta:set_string("formspec", 29 | "size[10,8;]" .. 30 | "textarea[0.5,0.5;9.5,7;code;Code;"..code.."]" .. 31 | "label[0.1,7;"..errmsg.."]" .. 32 | "button_exit[4,7.5;2,1;submit;Submit]") 33 | end 34 | 35 | minetest.register_node("moremesecons_luablock:luablock", { 36 | description = "Lua Block", 37 | tiles = {"moremesecons_luablock.png"}, 38 | groups = {cracky = 2}, 39 | on_place = function(itemstack, placer, pointed_thing) 40 | local under = pointed_thing.under 41 | local node = minetest.get_node(under) 42 | local udef = minetest.registered_nodes[node.name] 43 | if udef and udef.on_rightclick and 44 | not (placer and placer:get_player_control().sneak) then 45 | return udef.on_rightclick(under, node, placer, itemstack, 46 | pointed_thing) or itemstack 47 | end 48 | 49 | local pos 50 | if minetest.registered_items[minetest.get_node(under).name].buildable_to then 51 | pos = under 52 | else 53 | pos = pointed_thing.above 54 | end 55 | 56 | local name = placer:get_player_name() 57 | if minetest.is_protected(pos, name) and 58 | not minetest.check_player_privs(name, {protection_bypass = true}) then 59 | minetest.record_protection_violation(pos, name) 60 | return itemstack 61 | end 62 | if not minetest.check_player_privs(name, {server = true}) then 63 | minetest.chat_send_player(name, "You can't use a LuaBlock without the server privilege.") 64 | return itemstack 65 | end 66 | 67 | local node_def = minetest.registered_nodes[minetest.get_node(pos).name] 68 | if not node_def or not node_def.buildable_to then 69 | return itemstack 70 | end 71 | 72 | minetest.set_node(pos, {name = "moremesecons_luablock:luablock"}) 73 | 74 | local meta = minetest.get_meta(pos) 75 | meta:set_string("owner", name) 76 | meta:set_string("infotext", "LuaBlock owned by " .. name) 77 | make_formspec(meta, pos) 78 | 79 | if not (creative and creative.is_enabled_for 80 | and creative.is_enabled_for(placer:get_player_name())) then 81 | itemstack:take_item() 82 | end 83 | return itemstack 84 | end, 85 | on_receive_fields = function(pos, form_name, fields, sender) 86 | if not fields.submit then 87 | return 88 | end 89 | local name = sender:get_player_name() 90 | local meta = minetest.get_meta(pos) 91 | if name ~= meta:get_string("owner") then 92 | minetest.chat_send_player(name, "You don't own this LuaBlock.") 93 | return 94 | end 95 | if not minetest.check_player_privs(name, {server = true}) then 96 | minetest.chat_send_player(name, "You can't use a LuaBlock without the server privilege.") 97 | return 98 | end 99 | 100 | meta:set_string("code", fields.code) 101 | set_data(pos, fields.code, name) 102 | make_formspec(meta, pos) 103 | end, 104 | can_dig = function(pos, player) 105 | local meta = minetest.get_meta(pos) 106 | return meta:get_string("owner") == player:get_player_name() 107 | end, 108 | on_destruct = function(pos) 109 | moremesecons.remove_data_from_pos(pos_data, pos) 110 | end, 111 | mesecons = {effector = { 112 | action_on = function(npos, node) 113 | local meta = minetest.get_meta(npos) 114 | local code = meta:get_string("code") 115 | local owner = meta:get_string("owner") 116 | if code == "" then 117 | return 118 | end 119 | if not check_data(npos, code, owner) then 120 | minetest.log("warning", "[moremesecons_luablock] Metadata of LuaBlock at pos "..minetest.pos_to_string(npos).." does not match its mod storage data!") 121 | return 122 | end 123 | 124 | local env = {} 125 | for k, v in pairs(_G) do 126 | env[k] = v 127 | end 128 | env.pos = table.copy(npos) 129 | env.mem = minetest.deserialize(meta:get_string("mem")) or {} 130 | 131 | local func, err_syntax 132 | if _VERSION == "Lua 5.1" then 133 | func, err_syntax = loadstring(code) 134 | if func then 135 | setfenv(func, env) 136 | end 137 | else 138 | func, err_syntax = load(code, nil, "t", env) 139 | end 140 | if not func then 141 | meta:set_string("errmsg", err_syntax) 142 | make_formspec(meta, npos) 143 | return 144 | end 145 | 146 | local good, err_runtime = pcall(func) 147 | 148 | if not good then 149 | meta:set_string("errmsg", err_runtime) 150 | make_formspec(meta, npos) 151 | return 152 | end 153 | 154 | meta:set_string("mem", minetest.serialize(env.mem)) 155 | 156 | meta:set_string("errmsg", "") 157 | make_formspec(meta, npos) 158 | end 159 | }} 160 | }) 161 | -------------------------------------------------------------------------------- /moremesecons_luablock/mod.conf: -------------------------------------------------------------------------------- 1 | name = moremesecons_luablock 2 | depends = mesecons,moremesecons_utils 3 | -------------------------------------------------------------------------------- /moremesecons_luablock/textures/moremesecons_luablock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_luablock/textures/moremesecons_luablock.png -------------------------------------------------------------------------------- /moremesecons_luacontroller_tool/init.lua: -------------------------------------------------------------------------------- 1 | local templates = {MoreMesecons = { 2 | logic = [[-- AND 3 | port.a = pin.b and pin.c 4 | -- OR 5 | port.a = pin.b or pin.c 6 | -- NOT 7 | port.a = not pin.b 8 | -- NAND 9 | port.a = not (pin.b and pin.c) 10 | -- NOR 11 | port.a = not (pin.b or pin.c) 12 | -- XOR 13 | port.a = pin.b ~= pin.c 14 | -- XNOR / NXOR 15 | port.a = pin.b == pin.c]], 16 | 17 | digilinesth = [[digiline_send(channel, msg) 18 | if event.type == "digiline" then 19 | print(event.channel) 20 | print(event.msg) 21 | end]], 22 | 23 | clock = [[number_of_oscillations = 0 -- 0 for infinity 24 | interval = 1 25 | input_port = "A" 26 | output_port = "C" 27 | 28 | if event.type == "on" and event.pin.name == input_port and not mem.running then 29 | if not mem.counter then 30 | mem.counter = 0 31 | end 32 | mem.running = true 33 | port[string.lower(output_port)] = true 34 | interrupt(interval) 35 | mem.counter = mem.counter + 1 36 | elseif event.type == "off" and event.pin.name == input_port and mem.running and number_of_oscillations == 0 then 37 | mem.running = false 38 | mem.counter = 0 39 | elseif event.type == "interrupt" then 40 | if not port[string.lower(output_port)] and mem.running then 41 | port[string.lower(output_port)] = true 42 | interrupt(interval) 43 | mem.counter = mem.counter + 1 44 | else 45 | port[string.lower(output_port)] = false 46 | if mem.counter < number_of_oscillations or number_of_oscillations == 0 and mem.running then 47 | interrupt(interval) 48 | else 49 | mem.running = false 50 | mem.counter = 0 51 | end 52 | end 53 | end]], 54 | 55 | counter = [[counter_limit = 5 56 | output_time = 0.5 57 | input_port = "A" 58 | output_port = "C" 59 | 60 | if event.type == "on" and event.pin.name == input_port then 61 | if not mem.counter then 62 | mem.counter = 0 63 | end 64 | mem.counter = mem.counter + 1 65 | if mem.counter >= counter_limit then 66 | port[string.lower(output_port)] = true 67 | interrupt(output_time) 68 | mem.counter = 0 69 | end 70 | elseif event.type == "interrupt" then 71 | port[string.lower(output_port)] = false 72 | end]] 73 | }} 74 | 75 | 76 | local file_path = minetest.get_worldpath().."/MoreMesecons_lctt" 77 | 78 | -- load templates from a compressed file 79 | do 80 | local templates_file = io.open(file_path, "rb") 81 | if templates_file then 82 | local templates_raw = templates_file:read("*all") 83 | io.close(templates_file) 84 | if templates_raw 85 | and templates_raw ~= "" then 86 | local data = minetest.deserialize(minetest.decompress(templates_raw)) 87 | for name,t in pairs(data) do 88 | templates[name] = t 89 | end 90 | end 91 | end 92 | end 93 | 94 | -- the save function 95 | local function save_to_file() 96 | local templates_file = io.open(file_path, "w") 97 | if not templates_file then 98 | minetest.log("error", "[MoreMesecons] Could not open file for saving!") 99 | return 100 | end 101 | local player_templates = table.copy(templates) 102 | player_templates.MoreMesecons = nil 103 | templates_file:write(minetest.compress(minetest.serialize(player_templates))) 104 | io.close(templates_file) 105 | end 106 | 107 | -- save doesn't save more than every 10s to disallow spamming 108 | local saving 109 | local function save() 110 | if saving then 111 | return 112 | end 113 | saving = true 114 | minetest.after(16, function() 115 | save_to_file() 116 | saving = false 117 | end) 118 | end 119 | 120 | minetest.register_on_shutdown(function() 121 | if saving then 122 | save_to_file() 123 | end 124 | end) 125 | 126 | 127 | -- used for the dropdown formspec element 128 | local function fill_formspec_dropdown_list(t, selected) 129 | local it,num = {},1 130 | for i in pairs(t) do 131 | it[num] = i 132 | num = num+1 133 | end 134 | num = num-1 135 | table.sort(it) 136 | local txt = "" 137 | local selected_id 138 | for i = 1,num do 139 | local t = it[i] 140 | if not selected_id 141 | and t == selected then 142 | selected_id = i 143 | end 144 | txt = txt..t -- add available indices 145 | if i ~= num then 146 | txt = txt.."," 147 | end 148 | end 149 | return txt..";"..(selected_id or 1).."]" 150 | --spec = string.sub(spec, 1, -2) 151 | end 152 | 153 | local pdata = {} 154 | 155 | local function get_selection_formspec(pname, selected_template) 156 | -- templates might be removed by someone while changing sth in formspec 157 | local pl_templates = templates[pname] 158 | if not pl_templates then 159 | pname = next(templates) 160 | pl_templates = templates[pname] 161 | end 162 | 163 | local template_code = pl_templates[selected_template] 164 | if not template_code then 165 | selected_template = next(pl_templates) 166 | template_code = pl_templates[selected_template] 167 | end 168 | 169 | local spec = "size[10,10]".. 170 | 171 | -- show available players, field player_name, current player name is the selected one 172 | "dropdown[0,0;5;player_name;".. 173 | fill_formspec_dropdown_list(templates, pname).. 174 | 175 | -- show templates of pname 176 | "dropdown[5,0;5;template_name;".. 177 | fill_formspec_dropdown_list(pl_templates, selected_template).. 178 | 179 | -- show selected template 180 | "textarea[0,1;10.5,8.5;template_code;template code:;"..minetest.formspec_escape(template_code).."]".. 181 | 182 | -- save name 183 | "field[5,9.5;5,0;save_name;savename;"..selected_template.."]".. 184 | 185 | "button[0,10;2,0;button;set]".. 186 | 187 | "button[2,10;2,0;button;add]".. 188 | 189 | "button[5,10;2,0;button;save]" 190 | 191 | return spec 192 | end 193 | 194 | -- tests if the node is a luacontroller 195 | local function is_luacontroller(pos) 196 | if not pos then 197 | return false 198 | end 199 | return string.match(minetest.get_node(pos).name, "mesecons_luacontroller:luacontroller%d%d%d%d") 200 | end 201 | 202 | -- do not localize the function directly here to support possible overwritten luacontrollers 203 | local luac_def = minetest.registered_nodes["mesecons_luacontroller:luacontroller0000"] 204 | local function set_luacontroller_code(pos, code, sender) 205 | luac_def.on_receive_fields(pos, nil, {code=code, program=""}, sender) 206 | end 207 | 208 | minetest.register_tool("moremesecons_luacontroller_tool:lctt", { 209 | description = "luacontroller template tool", 210 | inventory_image = "moremesecons_luacontroller_tool.png", 211 | 212 | on_use = function(_, player, pt) 213 | if not player 214 | or not pt then 215 | return 216 | end 217 | 218 | local pname = player:get_player_name() 219 | local pos = pt.under 220 | if not is_luacontroller(pos) then 221 | minetest.chat_send_player(pname, "You can use the luacontroller template tool only on luacontroller nodes.") 222 | return 223 | end 224 | 225 | pdata[pname] = { 226 | pos = pos, 227 | player_name = pname, 228 | template_name = pdata[pname] and pdata[pname].template_name or next(templates[pname] or templates[next(templates)]), 229 | } 230 | minetest.show_formspec(pname, "moremesecons:luacontroller_tool", get_selection_formspec(pdata[pname].player_name, pdata[pname].template_name)) 231 | end, 232 | }) 233 | 234 | --[[ Luacontroller reset_meta function, by Jeija 235 | local function reset_meta(pos, code, errmsg) 236 | local meta = minetest.get_meta(pos) 237 | meta:set_string("code", code) 238 | code = minetest.formspec_escape(code or "") 239 | errmsg = minetest.formspec_escape(errmsg or "") 240 | meta:set_string("formspec", "size[10,8]".. 241 | "background[-0.2,-0.25;10.4,8.75;jeija_luac_background.png]".. 242 | "textarea[0.2,0.6;10.2,5;code;;"..code.."]".. 243 | "image_button[3.75,6;2.5,1;jeija_luac_runbutton.png;program;]".. 244 | "image_button_exit[9.72,-0.25;0.425,0.4;jeija_close_window.png;exit;]".. 245 | "label[0.1,5;"..errmsg.."]") 246 | meta:set_int("heat", 0) 247 | meta:set_int("luac_id", math.random(1, 65535)) 248 | end--]] 249 | 250 | -- used to avoid possibly crashes 251 | local function get_code_or_nil(pname, player_name, template_name) 252 | local player_templates = templates[player_name] 253 | if not player_templates then 254 | minetest.chat_send_player(pname, "error: "..player_name.." doesn't have templates now") 255 | return 256 | end 257 | local code = player_templates[template_name] 258 | if not code then 259 | minetest.chat_send_player(pname, "error: "..template_name.." doesn't exist now") 260 | return 261 | end 262 | return code 263 | end 264 | 265 | minetest.register_on_player_receive_fields(function(player, formname, fields) 266 | if formname ~= "moremesecons:luacontroller_tool" 267 | or fields.quit 268 | or not player then 269 | return 270 | end 271 | 272 | --minetest.chat_send_all(dump(fields)) 273 | 274 | local pname = player:get_player_name() 275 | 276 | if fields.player_name 277 | and fields.player_name ~= pdata[pname].player_name then 278 | -- show available templates of that player 279 | minetest.show_formspec(pname, "moremesecons:luacontroller_tool", 280 | get_selection_formspec(fields.player_name, pdata[pname].template_name) 281 | ) 282 | pdata[pname].player_name = fields.player_name 283 | return 284 | end 285 | 286 | if fields.template_name 287 | and fields.template_name ~= pdata[pname].template_name then 288 | -- show selected template of that player 289 | minetest.show_formspec(pname, "moremesecons:luacontroller_tool", 290 | get_selection_formspec(pdata[pname].player_name, fields.template_name) 291 | ) 292 | pdata[pname].template_name = fields.template_name 293 | return 294 | end 295 | 296 | local pos = pdata[pname].pos 297 | if not is_luacontroller(pos) then 298 | -- this can happen 299 | return 300 | end 301 | 302 | local meta = minetest.get_meta(pos) 303 | 304 | if fields.button == "set" then 305 | -- replace the code of the luacontroller with the template 306 | local code = get_code_or_nil(pname, fields.player_name, fields.template_name) 307 | if code then 308 | set_luacontroller_code(pos, code, player) 309 | minetest.chat_send_player(pname, "code set to template at "..minetest.pos_to_string(pos)) 310 | end 311 | return 312 | end 313 | 314 | if fields.button == "add" then 315 | -- add the template to the end of the code of the luacontroller 316 | local code = get_code_or_nil(pname, fields.player_name, fields.template_name) 317 | if code then 318 | set_luacontroller_code(pos, meta:get_string("code").."\r"..code, player) 319 | minetest.chat_send_player(pname, "code added to luacontroller at "..minetest.pos_to_string(pos)) 320 | end 321 | return 322 | end 323 | 324 | if fields.button == "save" then 325 | -- save the template, when you try to change others' templates, yours become changed 326 | local savename = fields.template_name 327 | if fields.save_name 328 | and fields.save_name ~= "" 329 | and fields.save_name ~= savename then 330 | savename = minetest.formspec_escape(fields.save_name) 331 | end 332 | local code = fields.template_code 333 | if not code then 334 | minetest.chat_send_player(pname, "error: template code missing") 335 | return 336 | end 337 | templates[pname] = templates[pname] or {} 338 | if code == "" then 339 | templates[pname][savename] = nil 340 | if not next(templates[pname]) then 341 | templates[pname] = nil 342 | end 343 | minetest.chat_send_player(pname, "template removed") 344 | save() 345 | return 346 | end 347 | code = minetest.formspec_escape(code) 348 | if templates[pname][savename] == code then 349 | minetest.chat_send_player(pname, "template not saved because it didn't change") 350 | return 351 | end 352 | templates[pname][savename] = code 353 | save() 354 | minetest.chat_send_player(pname, "template "..pname.."/"..savename.." saved") 355 | return 356 | end 357 | end) 358 | -------------------------------------------------------------------------------- /moremesecons_luacontroller_tool/mod.conf: -------------------------------------------------------------------------------- 1 | name = moremesecons_luacontroller_tool 2 | depends = mesecons,mesecons_luacontroller,moremesecons_utils 3 | -------------------------------------------------------------------------------- /moremesecons_luacontroller_tool/textures/moremesecons_luacontroller_tool.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_luacontroller_tool/textures/moremesecons_luacontroller_tool.png -------------------------------------------------------------------------------- /moremesecons_mesechest/init.lua: -------------------------------------------------------------------------------- 1 | local function mesechest_get_output_rules(node) 2 | local rules = {{x=-1, y=0, z=0}, 3 | {x=0, y=0, z=-1}, 4 | {x=0, y=0, z=1}} 5 | for _ = 0, node.param2 do 6 | rules = mesecon.rotate_rules_left(rules) 7 | end 8 | return rules 9 | end 10 | 11 | -- default.chest.register_chest() doesn't allow to register most of the callbacks we need 12 | -- we have to override the chest node we registered again 13 | default.chest.register_chest("moremesecons_mesechest:mesechest", { 14 | description = "Mese Chest", 15 | tiles = { 16 | "default_chest_top.png^[colorize:#d8e002:70", 17 | "default_chest_top.png^[colorize:#d8e002:70", 18 | "default_chest_side.png^[colorize:#d8e002:70", 19 | "default_chest_side.png^[colorize:#d8e002:70", 20 | "default_chest_front.png^[colorize:#d8e002:70", 21 | "default_chest_inside.png^[colorize:#d8e002:70" 22 | }, 23 | sounds = default.node_sound_wood_defaults(), 24 | sound_open = "default_chest_open", 25 | sound_close = "default_chest_close", 26 | groups = {choppy = 2, oddly_breakable_by_hand = 2}, 27 | mesecons = { 28 | receptor = { 29 | rules = mesechest_get_output_rules 30 | } 31 | } 32 | }) 33 | 34 | default.chest.register_chest("moremesecons_mesechest:mesechest_locked", { 35 | description = "Locked Mese Chest", 36 | tiles = { 37 | "default_chest_top.png^[colorize:#d8e002:70", 38 | "default_chest_top.png^[colorize:#d8e002:70", 39 | "default_chest_side.png^[colorize:#d8e002:70", 40 | "default_chest_side.png^[colorize:#d8e002:70", 41 | "default_chest_lock.png^[colorize:#d8e002:70", 42 | "default_chest_inside.png^[colorize:#d8e002:70" 43 | }, 44 | sounds = default.node_sound_wood_defaults(), 45 | sound_open = "default_chest_open", 46 | sound_close = "default_chest_close", 47 | groups = {choppy = 2, oddly_breakable_by_hand = 2}, 48 | protected = true, 49 | mesecons = { 50 | receptor = { 51 | rules = mesechest_get_output_rules 52 | } 53 | } 54 | }) 55 | 56 | local moremesecons_chests = {} 57 | 58 | for _, chest in ipairs({"moremesecons_mesechest:mesechest", "moremesecons_mesechest:mesechest_locked", 59 | "moremesecons_mesechest:mesechest_open", "moremesecons_mesechest:mesechest_locked_open"}) do 60 | local old_def = minetest.registered_nodes[chest] 61 | 62 | local old_on_metadata_inventory_put = old_def.on_metadata_inventory_put 63 | local old_on_metadata_inventory_take = old_def.on_metadata_inventory_take 64 | local old_on_rightclick = old_def.on_rightclick 65 | 66 | local override = {} 67 | override.on_metadata_inventory_put = function(pos, ...) 68 | old_on_metadata_inventory_put(pos, ...) 69 | mesecon.receptor_on(pos, {mesechest_get_output_rules(minetest.get_node(pos))[2]}) 70 | minetest.after(1, function(pos) 71 | mesecon.receptor_off(pos, {mesechest_get_output_rules(minetest.get_node(pos))[2]}) 72 | end, pos) 73 | end 74 | override.on_metadata_inventory_take = function(pos, ...) 75 | old_on_metadata_inventory_take(pos, ...) 76 | mesecon.receptor_on(pos, {mesechest_get_output_rules(minetest.get_node(pos))[3]}) 77 | minetest.after(1, function(pos) 78 | mesecon.receptor_off(pos, {mesechest_get_output_rules(minetest.get_node(pos))[3]}) 79 | end, pos) 80 | end 81 | override.on_rightclick = function(pos, node, clicker, ...) 82 | if old_on_rightclick(pos, node, clicker, ...) == nil then 83 | mesecon.receptor_on(pos, {mesechest_get_output_rules(node)[1]}) 84 | end 85 | end 86 | 87 | minetest.override_item(chest, override) 88 | moremesecons_chests[chest] = true 89 | end 90 | 91 | -- if the chest is getting closed, turn the signal off 92 | -- luacheck: ignore 122 93 | local old_lid_close = default.chest.chest_lid_close 94 | function default.chest.chest_lid_close(pn) 95 | local pos = default.chest.open_chests[pn].pos 96 | -- old_lid_close will return true if the chest won't be closed 97 | if old_lid_close(pn) then 98 | return true 99 | end 100 | local node = minetest.get_node(pos) 101 | if moremesecons_chests[node.name] then 102 | mesecon.receptor_off(pos, {mesechest_get_output_rules(node)[1]}) 103 | end 104 | end 105 | 106 | minetest.register_craft({ 107 | output = "moremesecons_mesechest:mesechest", 108 | recipe = {{"group:mesecon_conductor_craftable", "default:chest", "group:mesecon_conductor_craftable"}} 109 | }) 110 | 111 | minetest.register_craft({ 112 | output = "moremesecons_mesechest:mesechest_locked", 113 | recipe = {{"group:mesecon_conductor_craftable", "default:chest_locked", "group:mesecon_conductor_craftable"}} 114 | }) 115 | 116 | -- Legacy 117 | minetest.register_alias("default:mesechest", "moremesecons_mesechest:mesechest") 118 | minetest.register_alias("mesechest", "moremesecons_mesechest:mesechest") 119 | minetest.register_alias("default:mesechest_locked", "moremesecons_mesechest:mesechest") 120 | minetest.register_alias("mesechest_locked", "moremesecons_mesechest:mesechest_locked") 121 | -------------------------------------------------------------------------------- /moremesecons_mesechest/mod.conf: -------------------------------------------------------------------------------- 1 | name = moremesecons_mesechest 2 | depends = default,mesecons 3 | -------------------------------------------------------------------------------- /moremesecons_playerkiller/init.lua: -------------------------------------------------------------------------------- 1 | local kill_nearest_player = function(pos) 2 | local MAX_DISTANCE = moremesecons.setting("playerkiller", "max_distance", 8, 1) 3 | 4 | -- Search the nearest player 5 | local nearest 6 | local min_distance = MAX_DISTANCE 7 | for _, player in pairs(minetest.get_connected_players()) do 8 | local distance = vector.distance(pos, player:getpos()) 9 | if distance < min_distance then 10 | min_distance = distance 11 | nearest = player 12 | end 13 | end 14 | 15 | if not nearest then 16 | -- no nearby player 17 | return 18 | end 19 | 20 | local owner = minetest.get_meta(pos):get_string("owner") 21 | if not owner then 22 | -- maybe some mod placed it 23 | return 24 | end 25 | 26 | if owner == nearest:get_player_name() then 27 | -- don't kill the owner ! 28 | return 29 | end 30 | 31 | -- And kill him 32 | nearest:set_hp(0) 33 | minetest.log("action", "Player "..owner.." kills player "..nearest:get_player_name().." using a MoreMesecons Player Killer.") 34 | end 35 | 36 | minetest.register_craft({ 37 | output = "moremesecons_playerkiller:playerkiller", 38 | recipe = { {"","default:mese",""}, 39 | {"default:apple","mesecons_detector:object_detector_off","default:apple"}, 40 | {"","default:apple",""}} 41 | }) 42 | 43 | minetest.register_node("moremesecons_playerkiller:playerkiller", { 44 | description = "Player Killer", 45 | tiles = {"moremesecons_playerkiller_top.png", "moremesecons_playerkiller_top.png", "moremesecons_playerkiller_side.png"}, 46 | paramtype = "light", 47 | walkable = true, 48 | groups = {cracky=3}, 49 | mesecons = {effector = { 50 | state = mesecon.state.off, 51 | action_on = kill_nearest_player 52 | }}, 53 | after_place_node = function(pos, placer) 54 | if not placer then 55 | return 56 | end 57 | local meta = minetest.get_meta(pos) 58 | meta:set_string("owner", placer:get_player_name()) 59 | meta:set_string("infotext", "PlayerKiller owned by " .. meta:get_string("owner")) 60 | end, 61 | sounds = default.node_sound_stone_defaults(), 62 | }) 63 | -------------------------------------------------------------------------------- /moremesecons_playerkiller/mod.conf: -------------------------------------------------------------------------------- 1 | name = moremesecons_playerkiller 2 | depends = mesecons,mesecons_materials,moremesecons_utils 3 | optional_depends = craft_guide 4 | -------------------------------------------------------------------------------- /moremesecons_playerkiller/textures/moremesecons_playerkiller_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_playerkiller/textures/moremesecons_playerkiller_side.png -------------------------------------------------------------------------------- /moremesecons_playerkiller/textures/moremesecons_playerkiller_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_playerkiller/textures/moremesecons_playerkiller_top.png -------------------------------------------------------------------------------- /moremesecons_sayer/init.lua: -------------------------------------------------------------------------------- 1 | local use_speech_dispatcher = moremesecons.setting("sayer", "use_speech_dispatcher", true) 2 | 3 | local popen, execute = io.popen, os.execute 4 | if use_speech_dispatcher then 5 | if not minetest.is_singleplayer() then 6 | minetest.log("warning", "[moremesecons_sayer] use_speech_dispatcher = true, but the speech dispatcher can only be used in singleplayer") 7 | use_speech_dispatcher = false 8 | else 9 | local ie = {} 10 | if minetest.request_insecure_environment then 11 | ie = minetest.request_insecure_environment() 12 | end 13 | if not ie then 14 | minetest.log("warning", "[moremesecons_sayer] This mod needs access to insecure functions in order to use the speech dispatcher. Please add the moremesecons_sayer mod to your secure.trusted_mods settings or disable the speech dispatcher.") 15 | use_speech_dispatcher = false 16 | else 17 | popen = ie.io.popen 18 | execute = ie.os.execute 19 | end 20 | end 21 | 22 | if use_speech_dispatcher then 23 | if popen("if hash spd-say 2>/dev/null; then printf yes; fi"):read("*all") ~= "yes" then 24 | minetest.log("warning", "[moremesecons_sayer] use_speech_dispatcher = true, but it seems the speech dispatcher isn't installed on your system") 25 | use_speech_dispatcher = false 26 | end 27 | end 28 | end 29 | 30 | local sayer_activate 31 | if use_speech_dispatcher then 32 | minetest.log("info", "[moremesecons_sayer] using speech dispatcher") 33 | local tab = { 34 | "spd-say", 35 | nil, 36 | "" 37 | } 38 | local language = minetest.settings:get("language") or "en" 39 | if language ~= "en" then 40 | tab[3] = "-l "..language 41 | end 42 | 43 | function sayer_activate(pos) 44 | local MAX_DISTANCE = moremesecons.setting("sayer", "max_distance", 8, 1) ^ 2 45 | 46 | local text = minetest.get_meta(pos):get_string("text") 47 | if text == "" then 48 | -- nothing to say 49 | return 50 | end 51 | if string.find(text, '"') then 52 | text = "So, singleplayer, you want to use me to execute commands? Writing quotes is not allowed!" 53 | end 54 | tab[2] = '"'..text..'"' 55 | local ppos = minetest.get_player_by_name("singleplayer"):getpos() 56 | ppos.y = ppos.y+1.625 -- camera position (without bobbing) 57 | -- that here's just 1 volume means that it's mono 58 | local volume = math.floor(-100*( 59 | 1-MAX_DISTANCE/vector.distance(pos, ppos)^2 60 | +0.5)) 61 | if volume <= -100 then 62 | -- nothing to hear 63 | return 64 | end 65 | if volume > 0 then 66 | --volume = "+"..math.min(100, volume) 67 | -- volume bigger 0 somehow isn't louder, it rather tries to scream 68 | volume = "+"..math.min(100, math.floor(volume/(MAX_DISTANCE-1)+0.5)) 69 | end 70 | if volume == 0 then 71 | tab[4] = nil 72 | else 73 | tab[4] = "-i "..volume 74 | end 75 | execute(table.concat(tab, " ")) 76 | end 77 | else 78 | function sayer_activate(pos) 79 | local MAX_DISTANCE = moremesecons.setting("sayer", "max_distance", 8, 1) 80 | 81 | local tab = { 82 | "Sayer at pos", 83 | nil, 84 | "says : "..minetest.get_meta(pos):get_string("text") 85 | } 86 | for _,player in pairs(minetest.get_connected_players()) do 87 | if vector.distance(pos, player:getpos()) <= MAX_DISTANCE then 88 | tab[2] = minetest.pos_to_string(pos) 89 | minetest.chat_send_player(player:get_player_name(), table.concat(tab, " ")) 90 | end 91 | end 92 | end 93 | end 94 | 95 | minetest.register_node("moremesecons_sayer:sayer", { 96 | description = "sayer", 97 | tiles = {"mesecons_noteblock.png", "default_wood.png"}, 98 | drawtype = "nodebox", 99 | paramtype = "light", 100 | node_box = { 101 | type = "fixed", 102 | fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5}, 103 | }, 104 | groups = {dig_immediate = 2}, 105 | on_construct = function(pos) 106 | minetest.get_meta(pos):set_string("formspec", "field[text;text;${text}]") 107 | end, 108 | on_receive_fields = function(pos, _, fields, player) 109 | if fields.text 110 | and not minetest.is_protected(pos, player:get_player_name()) then 111 | minetest.get_meta(pos):set_string("text", fields.text) 112 | end 113 | end, 114 | mesecons = {effector = { 115 | action_on = sayer_activate 116 | }} 117 | }) 118 | 119 | minetest.register_craft({ 120 | output = "moremesecons_sayer:sayer 2", 121 | recipe = {{"mesecons_luacontroller:luacontroller0000", "mesecons_noteblock:noteblock"}, 122 | {"group:wood", "group:wood"}} 123 | }) 124 | -------------------------------------------------------------------------------- /moremesecons_sayer/mod.conf: -------------------------------------------------------------------------------- 1 | name = moremesecons_sayer 2 | depends = mesecons,mesecons_noteblock,moremesecons_utils,default 3 | optional_depends = craft_guide 4 | -------------------------------------------------------------------------------- /moremesecons_signalchanger/init.lua: -------------------------------------------------------------------------------- 1 | local nodebox = { 2 | type = "fixed", 3 | fixed = {{-8/16, -8/16, -8/16, 8/16, -7/16, 8/16 }}, 4 | } 5 | 6 | local function signalchanger_get_output_rules(node) 7 | local rules = {{x=-1, y=0, z=0}, 8 | {x=1, y=0, z=0}} 9 | for _ = 0, node.param2 do 10 | rules = mesecon.rotate_rules_left(rules) 11 | end 12 | return rules 13 | end 14 | 15 | local function signalchanger_get_input_rules(node) 16 | local rules = {{x=0, y=0, z=-1, name="input_on"}, {x=0, y=0, z=1, name="input_off"}} 17 | for _ = 0, node.param2 do 18 | rules = mesecon.rotate_rules_left(rules) 19 | end 20 | return rules 21 | end 22 | 23 | local update = function(pos, node, link, newstate) 24 | local meta = minetest.get_meta(pos) 25 | meta:set_int(link.name, newstate == "on" and 1 or 0) 26 | local input_on = meta:get_int("input_on") == 1 27 | local input_off = meta:get_int("input_off") == 1 28 | if input_on then 29 | mesecon.receptor_on(pos, {signalchanger_get_output_rules(node)[1]}) 30 | mesecon.receptor_off(pos, {signalchanger_get_output_rules(node)[2]}) 31 | minetest.swap_node(pos, {name = "moremesecons_signalchanger:signalchanger_on", param2 = node.param2}) 32 | elseif input_off then 33 | mesecon.receptor_off(pos, {signalchanger_get_output_rules(node)[1]}) 34 | mesecon.receptor_on(pos, {signalchanger_get_output_rules(node)[2]}) 35 | minetest.swap_node(pos, {name = "moremesecons_signalchanger:signalchanger_off", param2 = node.param2}) 36 | end 37 | end 38 | 39 | mesecon.register_node("moremesecons_signalchanger:signalchanger", { 40 | description = "Signal Changer", 41 | inventory_image = "moremesecons_signalchanger_off.png", 42 | groups = {dig_immediate = 2}, 43 | paramtype = "light", 44 | paramtype2 = "facedir", 45 | drawtype = "nodebox", 46 | selection_box = nodebox, 47 | node_box = nodebox, 48 | },{ 49 | groups = {dig_immediate = 2}, 50 | mesecons = { 51 | receptor = { 52 | rules = signalchanger_get_output_rules 53 | }, 54 | effector = { 55 | rules = signalchanger_get_input_rules, 56 | action_change = update 57 | }, 58 | }, 59 | tiles = {"moremesecons_signalchanger_off.png"}, 60 | on_construct = function(pos) 61 | local node = minetest.get_node(pos) 62 | mesecon.receptor_on(pos, {signalchanger_get_output_rules(node)[2]}) 63 | end 64 | },{ 65 | groups = {dig_immediate = 2, not_in_creative_inventory = 1}, 66 | mesecons = { 67 | receptor = { 68 | rules = signalchanger_get_output_rules, 69 | }, 70 | effector = { 71 | rules = signalchanger_get_input_rules, 72 | action_change = update, 73 | }, 74 | }, 75 | tiles = {"moremesecons_signalchanger_on.png"}, 76 | }) 77 | 78 | minetest.register_craft({ 79 | output = "moremesecons_signalchanger:signalchanger_off", 80 | recipe = {{"group:mesecon_conductor_craftable","moremesecons_switchtorch:switchtorch_off","group:mesecon_conductor_craftable"}} 81 | }) 82 | -------------------------------------------------------------------------------- /moremesecons_signalchanger/mod.conf: -------------------------------------------------------------------------------- 1 | name = moremesecons_signalchanger 2 | depends = mesecons 3 | optional_depends = craft_guide 4 | -------------------------------------------------------------------------------- /moremesecons_signalchanger/textures/moremesecons_signalchanger_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_signalchanger/textures/moremesecons_signalchanger_off.png -------------------------------------------------------------------------------- /moremesecons_signalchanger/textures/moremesecons_signalchanger_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_signalchanger/textures/moremesecons_signalchanger_on.png -------------------------------------------------------------------------------- /moremesecons_switchtorch/init.lua: -------------------------------------------------------------------------------- 1 | local rotate_torch_rules = function (rules, param2) 2 | if param2 == 5 then 3 | return mesecon.rotate_rules_right(rules) 4 | elseif param2 == 2 then 5 | return mesecon.rotate_rules_right(mesecon.rotate_rules_right(rules)) --180 degrees 6 | elseif param2 == 4 then 7 | return mesecon.rotate_rules_left(rules) 8 | elseif param2 == 1 then 9 | return mesecon.rotate_rules_down(rules) 10 | elseif param2 == 0 then 11 | return mesecon.rotate_rules_up(rules) 12 | else 13 | return rules 14 | end 15 | end 16 | 17 | local output_rules = { 18 | {x = 1, y = 0, z = 0}, 19 | {x = 0, y = 0, z = 1}, 20 | {x = 0, y = 0, z =-1}, 21 | {x = 0, y = 1, z = 0}, 22 | {x = 0, y =-1, z = 0} 23 | } 24 | local torch_get_output_rules = function(node) 25 | return rotate_torch_rules(output_rules, node.param2) 26 | end 27 | 28 | local input_rules = { 29 | {x = -2, y = 0, z = 0}, 30 | {x = -1, y = 1, z = 0} 31 | } 32 | local torch_get_input_rules = function(node) 33 | return rotate_torch_rules(input_rules, node.param2) 34 | end 35 | 36 | minetest.register_craft({ 37 | output = "moremesecons_switchtorch:switchtorch_off 4", 38 | recipe = { 39 | {"default:stick"}, 40 | {"group:mesecon_conductor_craftable"}, 41 | } 42 | }) 43 | 44 | local torch_selectionbox = 45 | { 46 | type = "wallmounted", 47 | wall_top = {-0.1, 0.5-0.6, -0.1, 0.1, 0.5, 0.1}, 48 | wall_bottom = {-0.1, -0.5, -0.1, 0.1, -0.5+0.6, 0.1}, 49 | wall_side = {-0.5, -0.1, -0.1, -0.5+0.6, 0.1, 0.1}, 50 | } 51 | 52 | minetest.register_node("moremesecons_switchtorch:switchtorch_off", { 53 | description = "Switch Torch", 54 | inventory_image = "moremesecons_switchtorch_on.png", 55 | wield_image = "moremesecons_switchtorch_on.png", 56 | drawtype = "torchlike", 57 | tiles = {"moremesecons_switchtorch_off.png", "moremesecons_switchtorch_off_ceiling.png", "moremesecons_switchtorch_off_side.png"}, 58 | paramtype = "light", 59 | walkable = false, 60 | paramtype2 = "wallmounted", 61 | selection_box = torch_selectionbox, 62 | groups = {dig_immediate = 3}, 63 | mesecons = {receptor = { 64 | state = mesecon.state.off, 65 | rules = torch_get_output_rules 66 | }}, 67 | 68 | on_construct = function(pos)-- For EndPower 69 | minetest.get_meta(pos):set_int("EndPower", 1) -- 1 for true, 0 for false 70 | end 71 | }) 72 | 73 | minetest.register_node("moremesecons_switchtorch:switchtorch_on", { 74 | drawtype = "torchlike", 75 | tiles = {"moremesecons_switchtorch_on.png", "moremesecons_switchtorch_on_ceiling.png", "moremesecons_switchtorch_on_side.png"}, 76 | paramtype = "light", 77 | sunlight_propagates = true, 78 | walkable = false, 79 | paramtype2 = "wallmounted", 80 | selection_box = torch_selectionbox, 81 | groups = {dig_immediate=3, not_in_creative_inventory = 1}, 82 | drop = "moremesecons_switchtorch:switchtorch_off", 83 | light_source = 9, 84 | mesecons = {receptor = { 85 | state = mesecon.state.on, 86 | rules = torch_get_output_rules 87 | }}, 88 | }) 89 | 90 | minetest.register_abm({ 91 | nodenames = {"moremesecons_switchtorch:switchtorch_off","moremesecons_switchtorch:switchtorch_on"}, 92 | interval = 1, 93 | chance = 1, 94 | action = function(pos, node) 95 | local is_powered = false 96 | for _, rule in ipairs(torch_get_input_rules(node)) do 97 | local src = vector.add(pos, rule) 98 | if mesecon.is_power_on(src) then 99 | is_powered = true 100 | break 101 | end 102 | end 103 | 104 | local meta = minetest.get_meta(pos) 105 | if meta:get_int("EndPower") == 0 == is_powered then 106 | return 107 | end 108 | if not is_powered then 109 | meta:set_int("EndPower", 1) 110 | return 111 | end 112 | if node.name == "moremesecons_switchtorch:switchtorch_on" then 113 | minetest.swap_node(pos, {name = "moremesecons_switchtorch:switchtorch_off", param2 = node.param2}) 114 | mesecon.receptor_off(pos, torch_get_output_rules(node)) 115 | elseif node.name == "moremesecons_switchtorch:switchtorch_off" then 116 | minetest.swap_node(pos, {name = "moremesecons_switchtorch:switchtorch_on", param2 = node.param2}) 117 | mesecon.receptor_on(pos, torch_get_output_rules(node)) 118 | end 119 | meta:set_int("EndPower", 0) 120 | end 121 | }) 122 | 123 | -- Param2 Table (Block Attached To) 124 | -- 5 = z-1 125 | -- 3 = x-1 126 | -- 4 = z+1 127 | -- 2 = x+1 128 | -- 0 = y+1 129 | -- 1 = y-1 130 | -------------------------------------------------------------------------------- /moremesecons_switchtorch/mod.conf: -------------------------------------------------------------------------------- 1 | name = moremesecons_switchtorch 2 | depends = mesecons 3 | optional_depends = craft_guide 4 | -------------------------------------------------------------------------------- /moremesecons_switchtorch/textures/moremesecons_switchtorch_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_switchtorch/textures/moremesecons_switchtorch_off.png -------------------------------------------------------------------------------- /moremesecons_switchtorch/textures/moremesecons_switchtorch_off_ceiling.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_switchtorch/textures/moremesecons_switchtorch_off_ceiling.png -------------------------------------------------------------------------------- /moremesecons_switchtorch/textures/moremesecons_switchtorch_off_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_switchtorch/textures/moremesecons_switchtorch_off_side.png -------------------------------------------------------------------------------- /moremesecons_switchtorch/textures/moremesecons_switchtorch_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_switchtorch/textures/moremesecons_switchtorch_on.png -------------------------------------------------------------------------------- /moremesecons_switchtorch/textures/moremesecons_switchtorch_on_ceiling.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_switchtorch/textures/moremesecons_switchtorch_on_ceiling.png -------------------------------------------------------------------------------- /moremesecons_switchtorch/textures/moremesecons_switchtorch_on_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_switchtorch/textures/moremesecons_switchtorch_on_side.png -------------------------------------------------------------------------------- /moremesecons_teleporter/init.lua: -------------------------------------------------------------------------------- 1 | local storage = minetest.get_mod_storage() 2 | 3 | local teleporters = minetest.deserialize(storage:get_string("teleporters")) or {} 4 | local teleporters_rids = moremesecons.load_MapDataStorage_legacy(storage, 5 | "teleporters_rids_v2", "teleporters_rids") 6 | 7 | local function update_mod_storage() 8 | storage:set_string("teleporters", minetest.serialize(teleporters)) 9 | storage:set_string("teleporters_rids_v2", teleporters_rids:serialize()) 10 | end 11 | 12 | 13 | local function register(pos) 14 | if not teleporters_rids:getAt(pos) then 15 | table.insert(teleporters, pos) 16 | teleporters_rids:setAt(pos, #teleporters) 17 | update_mod_storage() 18 | end 19 | end 20 | 21 | local function teleport_nearest(pos) 22 | local MAX_TELEPORTATION_DISTANCE = moremesecons.setting("teleporter", "max_t2t_distance", 50, 1) 23 | local MAX_PLAYER_DISTANCE = moremesecons.setting("teleporter", "max_p2t_distance", 25, 1) 24 | 25 | -- Search for the nearest player 26 | local nearest = nil 27 | local min_distance_player = MAX_PLAYER_DISTANCE 28 | local players = minetest.get_connected_players() 29 | for _, player in pairs(players) do 30 | local distance = vector.distance(pos, player:getpos()) 31 | if distance <= min_distance_player then 32 | min_distance_player = distance 33 | nearest = player 34 | end 35 | end 36 | 37 | if not nearest then 38 | -- If there is no nearest player (maybe too far away...) 39 | return 40 | end 41 | 42 | -- Search for the corresponding teleporter and teleport 43 | if not minetest.registered_nodes["moremesecons_teleporter:teleporter"] then return end 44 | 45 | local newpos = {} 46 | local min_distance = MAX_TELEPORTATION_DISTANCE 47 | for i = 1, #teleporters do 48 | if minetest.get_node(teleporters[i]).name == "moremesecons_teleporter:teleporter" then 49 | local tel_pos 50 | if teleporters[i].y == pos.y and teleporters[i].x == pos.x and teleporters[i].z ~= pos.z then 51 | tel_pos = {x=teleporters[i].x, y=teleporters[i].y+1, z=teleporters[i].z} 52 | elseif teleporters[i].z == pos.z and teleporters[i].x == pos.x and teleporters[i].y ~= pos.y then 53 | tel_pos = {x=teleporters[i].x, y=teleporters[i].y+1, z=teleporters[i].z} 54 | elseif teleporters[i].z == pos.z and teleporters[i].y == pos.y and teleporters[i].x ~= pos.x then 55 | tel_pos = {x=teleporters[i].x, y=teleporters[i].y+1, z=teleporters[i].z} 56 | end 57 | 58 | if tel_pos then 59 | local distance = vector.distance(tel_pos, pos) 60 | if distance <= min_distance then 61 | min_distance = distance 62 | newpos = tel_pos 63 | end 64 | end 65 | end 66 | end 67 | if not newpos.x then 68 | newpos = {x=pos.x, y=pos.y+1, z=pos.z} -- If newpos doesn't exist, teleport on the current teleporter 69 | end 70 | 71 | nearest:moveto(newpos) 72 | minetest.log("action", "Player "..nearest:get_player_name().." was teleported using a MoreMesecons Teleporter.") 73 | end 74 | 75 | minetest.register_craft({ 76 | output = "moremesecons_teleporter:teleporter 2", 77 | recipe = {{"default:diamond","default:stick","default:mese"}} 78 | }) 79 | minetest.register_node("moremesecons_teleporter:teleporter", { 80 | tiles = {"moremesecons_teleporter.png"}, 81 | paramtype = "light", 82 | walkable = true, 83 | groups = {cracky=3}, 84 | description="Teleporter", 85 | mesecons = {effector = { 86 | state = mesecon.state.off, 87 | action_on = teleport_nearest 88 | }}, 89 | sounds = default.node_sound_stone_defaults(), 90 | on_construct = register, 91 | on_destruct = function(pos) 92 | local RID = teleporters_rids:getAt(pos) 93 | if RID then 94 | table.remove(teleporters, RID) 95 | teleporters_rids:removeAt(pos) 96 | update_mod_storage() 97 | end 98 | end, 99 | }) 100 | 101 | if moremesecons.setting("teleporter", "enable_lbm", false) then 102 | minetest.register_lbm({ 103 | name = "moremesecons_teleporter:add_teleporter", 104 | nodenames = {"moremesecons_teleporter:teleporter"}, 105 | run_at_every_load = true, 106 | action = register 107 | }) 108 | end 109 | -------------------------------------------------------------------------------- /moremesecons_teleporter/mod.conf: -------------------------------------------------------------------------------- 1 | name = moremesecons_teleporter 2 | depends = mesecons,moremesecons_utils 3 | optional_depends = craft_guide 4 | -------------------------------------------------------------------------------- /moremesecons_teleporter/textures/moremesecons_teleporter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_teleporter/textures/moremesecons_teleporter.png -------------------------------------------------------------------------------- /moremesecons_timegate/init.lua: -------------------------------------------------------------------------------- 1 | local timegate_get_output_rules = function(node) 2 | local rules = {{x = 0, y = 0, z = 1}} 3 | for _ = 0, node.param2 do 4 | rules = mesecon.rotate_rules_left(rules) 5 | end 6 | return rules 7 | end 8 | 9 | local timegate_get_input_rules = function(node) 10 | local rules = {{x = 0, y = 0, z = -1}} 11 | for _ = 0, node.param2 do 12 | rules = mesecon.rotate_rules_left(rules) 13 | end 14 | return rules 15 | end 16 | 17 | -- Functions that are called after the delay time 18 | 19 | local function timegate_activate(pos, node) 20 | -- using a meta string allows writing the time in hexadecimals 21 | local time = tonumber(minetest.get_meta(pos):get_string("time")) 22 | if not time then 23 | return 24 | end 25 | node.name = "moremesecons_timegate:timegate_on" 26 | minetest.swap_node(pos, node) 27 | mesecon.receptor_on(pos) 28 | minetest.after(time, function() 29 | local node = minetest.get_node(pos) 30 | if node.name == "moremesecons_timegate:timegate_on" then 31 | mesecon.receptor_off(pos) 32 | node.name = "moremesecons_timegate:timegate_off" 33 | minetest.swap_node(pos, node) 34 | end 35 | end) 36 | end 37 | 38 | local boxes = {{ -6/16, -8/16, -6/16, 6/16, -7/16, 6/16 }, -- the main slab 39 | 40 | { -2/16, -7/16, -4/16, 2/16, -26/64, -3/16 }, -- the jeweled "on" indicator 41 | { -3/16, -7/16, -3/16, 3/16, -26/64, -2/16 }, 42 | { -4/16, -7/16, -2/16, 4/16, -26/64, 2/16 }, 43 | { -3/16, -7/16, 2/16, 3/16, -26/64, 3/16 }, 44 | { -2/16, -7/16, 3/16, 2/16, -26/64, 4/16 }, 45 | 46 | { -6/16, -7/16, -6/16, -4/16, -27/64, -4/16 }, -- the timer indicator 47 | { -8/16, -8/16, -1/16, -6/16, -7/16, 1/16 }, -- the two wire stubs 48 | { 6/16, -8/16, -1/16, 8/16, -7/16, 1/16 }} 49 | 50 | local use_texture_alpha 51 | if minetest.features.use_texture_alpha_string_modes then 52 | use_texture_alpha = "opaque" 53 | end 54 | mesecon.register_node("moremesecons_timegate:timegate", { 55 | description = "Time Gate", 56 | drawtype = "nodebox", 57 | inventory_image = "moremesecons_timegate_off.png", 58 | wield_image = "moremesecons_timegate_off.png", 59 | walkable = true, 60 | selection_box = { 61 | type = "fixed", 62 | fixed = { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 }, 63 | }, 64 | node_box = { 65 | type = "fixed", 66 | fixed = boxes 67 | }, 68 | paramtype = "light", 69 | paramtype2 = "facedir", 70 | sunlight_propagates = true, 71 | is_ground_content = true, 72 | sounds = default.node_sound_stone_defaults(), 73 | on_construct = function(pos) 74 | minetest.get_meta(pos):set_string("formspec", "field[time;time;${time}]") 75 | end, 76 | on_receive_fields = function(pos, _, fields, player) 77 | if fields.time 78 | and not minetest.is_protected(pos, player:get_player_name()) then 79 | minetest.get_meta(pos):set_string("time", fields.time) 80 | end 81 | end 82 | },{ 83 | tiles = { 84 | "moremesecons_timegate_off.png", 85 | "moremesecons_timegate_bottom.png", 86 | "moremesecons_timegate_ends_off.png", 87 | "moremesecons_timegate_ends_off.png", 88 | "moremesecons_timegate_sides_off.png", 89 | "moremesecons_timegate_sides_off.png" 90 | }, 91 | use_texture_alpha = use_texture_alpha, 92 | groups = {bendy=2,snappy=1,dig_immediate=2}, 93 | mesecons = { 94 | receptor = 95 | { 96 | state = mesecon.state.off, 97 | rules = timegate_get_output_rules 98 | }, 99 | effector = 100 | { 101 | rules = timegate_get_input_rules, 102 | action_on = timegate_activate 103 | } 104 | }, 105 | },{ 106 | tiles = { 107 | "moremesecons_timegate_on.png", 108 | "moremesecons_timegate_bottom.png", 109 | "moremesecons_timegate_ends_on.png", 110 | "moremesecons_timegate_ends_on.png", 111 | "moremesecons_timegate_sides_on.png", 112 | "moremesecons_timegate_sides_on.png" 113 | }, 114 | use_texture_alpha = use_texture_alpha, 115 | groups = {bendy=2,snappy=1,dig_immediate=2, not_in_creative_inventory=1}, 116 | mesecons = { 117 | receptor = { 118 | state = mesecon.state.on, 119 | rules = timegate_get_output_rules 120 | }, 121 | effector = { 122 | rules = timegate_get_input_rules, 123 | } 124 | }, 125 | }) 126 | 127 | minetest.register_craft({ 128 | output = "moremesecons_timegate:timegate_off 2", 129 | recipe = { 130 | {"group:mesecon_conductor_craftable", "mesecons_delayer:delayer_off_1", "group:mesecon_conductor_craftable"}, 131 | {"default:wood","default:wood", "default:wood"}, 132 | } 133 | }) 134 | 135 | minetest.register_alias("moremesecons_temporarygate:temporarygate_off", "moremesecons_timegate:timegate_off") 136 | minetest.register_alias("moremesecons_temporarygate:temporarygate_on", "moremesecons_timegate:timegate_on") 137 | -------------------------------------------------------------------------------- /moremesecons_timegate/mod.conf: -------------------------------------------------------------------------------- 1 | name = moremesecons_timegate 2 | depends = mesecons 3 | optional_depends = craft_guide 4 | -------------------------------------------------------------------------------- /moremesecons_timegate/textures/moremesecons_timegate_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_timegate/textures/moremesecons_timegate_bottom.png -------------------------------------------------------------------------------- /moremesecons_timegate/textures/moremesecons_timegate_ends_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_timegate/textures/moremesecons_timegate_ends_off.png -------------------------------------------------------------------------------- /moremesecons_timegate/textures/moremesecons_timegate_ends_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_timegate/textures/moremesecons_timegate_ends_on.png -------------------------------------------------------------------------------- /moremesecons_timegate/textures/moremesecons_timegate_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_timegate/textures/moremesecons_timegate_off.png -------------------------------------------------------------------------------- /moremesecons_timegate/textures/moremesecons_timegate_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_timegate/textures/moremesecons_timegate_on.png -------------------------------------------------------------------------------- /moremesecons_timegate/textures/moremesecons_timegate_sides_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_timegate/textures/moremesecons_timegate_sides_off.png -------------------------------------------------------------------------------- /moremesecons_timegate/textures/moremesecons_timegate_sides_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_timegate/textures/moremesecons_timegate_sides_on.png -------------------------------------------------------------------------------- /moremesecons_utils/init.lua: -------------------------------------------------------------------------------- 1 | moremesecons = {} 2 | 3 | function moremesecons.setting(modname, settingname, default, min) 4 | local setting = "moremesecons_" .. modname .. "." .. settingname 5 | 6 | if type(default) == "boolean" then 7 | local ret = minetest.settings:get_bool(setting) 8 | if ret == nil then 9 | ret = default 10 | end 11 | return ret 12 | elseif type(default) == "string" then 13 | return minetest.settings:get(setting) or default 14 | elseif type(default) == "number" then 15 | local ret = tonumber(minetest.settings:get(setting)) or default 16 | if not ret then 17 | minetest.log("warning", "[moremesecons_"..modname.."]: setting '"..setting.."' must be a number. Set to default value ("..tostring(default)..").") 18 | ret = default 19 | elseif ret ~= ret then -- NaN 20 | minetest.log("warning", "[moremesecons_"..modname.."]: setting '"..setting.."' is NaN. Set to default value ("..tostring(default)..").") 21 | ret = default 22 | end 23 | if min and ret < min then 24 | minetest.log("warning", "[moremesecons_"..modname.."]: setting '"..setting.."' is under minimum value "..tostring(min)..". Set to minimum value ("..tostring(min)..").") 25 | ret = min 26 | end 27 | return ret 28 | end 29 | end 30 | 31 | -- Storage helpers 32 | 33 | function moremesecons.get_storage_data(storage, name) 34 | return { 35 | tab = minetest.deserialize(storage:get_string(name)) or {}, 36 | name = name, 37 | storage = storage 38 | } 39 | end 40 | 41 | function moremesecons.set_data_to_pos(sto, pos, data) 42 | sto.tab[minetest.hash_node_position(pos)] = data 43 | sto.storage:set_string(sto.name, minetest.serialize(sto.tab)) 44 | end 45 | 46 | function moremesecons.get_data_from_pos(sto, pos) 47 | return sto.tab[minetest.hash_node_position(pos)] 48 | end 49 | 50 | function moremesecons.remove_data_from_pos(sto, pos) 51 | sto.tab[minetest.hash_node_position(pos)] = nil 52 | sto.storage:set_string(sto.name, minetest.serialize(sto.tab)) 53 | end 54 | 55 | -- Some additional vector helpers 56 | 57 | -- The same as minetest.hash_node_position; I copied it to ensure backwards 58 | -- compatibility and used hexadecimal number notation 59 | local function node_position_key(pos) 60 | return (pos.z + 0x8000) * 0x10000 * 0x10000 61 | + (pos.y + 0x8000) * 0x10000 62 | + pos.x + 0x8000 63 | end 64 | 65 | local MapDataStorage = {} 66 | setmetatable(MapDataStorage, {__call = function() 67 | local obj = {} 68 | setmetatable(obj, MapDataStorage) 69 | return obj 70 | end}) 71 | MapDataStorage.__index = { 72 | getAt = function(self, pos) 73 | return self[node_position_key(pos)] 74 | end, 75 | setAt = function(self, pos, data) 76 | -- If x, y or z is omitted, the key corresponds to a position outside 77 | -- of the map (hopefully), so it can be used to skip lines and planes 78 | local vi_z = (pos.z + 0x8000) * 0x10000 * 0x10000 79 | local vi_zy = vi_z + (pos.y + 0x8000) * 0x10000 80 | local vi = vi_zy + pos.x + 0x8000 81 | local is_new = self[vi] == nil 82 | self[vi] = data 83 | if is_new then 84 | self[vi_z] = (self[vi_z] or 0) + 1 85 | self[vi_zy] = (self[vi_zy] or 0) + 1 86 | end 87 | end, 88 | setAtI = function(self, vi, data) 89 | local vi_zy = vi - vi % 0x10000 90 | local vi_z = vi - vi % (0x10000 * 0x10000) 91 | local is_new = self[vi] == nil 92 | self[vi] = data 93 | if is_new then 94 | self[vi_z] = (self[vi_z] or 0) + 1 95 | self[vi_zy] = (self[vi_zy] or 0) + 1 96 | end 97 | end, 98 | removeAt = function(self, pos) 99 | local vi_z = (pos.z + 0x8000) * 0x10000 * 0x10000 100 | local vi_zy = vi_z + (pos.y + 0x8000) * 0x10000 101 | local vi = vi_zy + pos.x + 0x8000 102 | if self[vi] == nil then 103 | -- Nothing to remove 104 | return 105 | end 106 | self[vi] = nil 107 | -- Update existence information for the xy plane and x line 108 | self[vi_z] = self[vi_z] - 1 109 | if self[vi_z] == 0 then 110 | self[vi_z] = nil 111 | self[vi_zy] = nil 112 | return 113 | end 114 | self[vi_zy] = self[vi_zy] - 1 115 | if self[vi_zy] == 0 then 116 | self[vi_zy] = nil 117 | end 118 | end, 119 | iter = function(self, pos1, pos2) 120 | local ystride = 0x10000 121 | local zstride = 0x10000 * 0x10000 122 | 123 | -- Skip z values where no data can be found 124 | pos1 = vector.new(pos1) 125 | local vi_z = (pos1.z + 0x8000) * 0x10000 * 0x10000 126 | while not self[vi_z] do 127 | pos1.z = pos1.z + 1 128 | vi_z = vi_z + zstride 129 | if pos1.z > pos2.z then 130 | -- There are no values to iterate through 131 | return function() return end 132 | end 133 | end 134 | -- Skipping y values is not yet implemented and may require much code 135 | 136 | local xrange = pos2.x - pos1.x + 1 137 | local yrange = pos2.y - pos1.y + 1 138 | local zrange = pos2.z - pos1.z + 1 139 | 140 | -- x-only and y-only parts of the vector index of pos1 141 | local vi_y = (pos1.y + 0x8000) * 0x10000 142 | local vi_x = pos1.x + 0x8000 143 | 144 | local y = 0 145 | local z = 0 146 | 147 | local vi = node_position_key(pos1) 148 | local pos = vector.new(pos1) 149 | local nextaction = vi + xrange 150 | pos.x = pos.x - 1 151 | vi = vi - 1 152 | local function iterfunc() 153 | -- continue along x until it needs to jump 154 | vi = vi + 1 155 | pos.x = pos.x + 1 156 | if vi ~= nextaction then 157 | local v = self[vi] 158 | if v == nil then 159 | -- No data here 160 | return iterfunc() 161 | end 162 | -- The returned position must not be changed 163 | return pos, v 164 | end 165 | 166 | -- Reset x position 167 | vi = vi - xrange 168 | -- Go along y until pos2.y is exceeded 169 | while true do 170 | y = y + 1 171 | pos.y = pos.y + 1 172 | -- Set vi to index(pos1.x, pos1.y + y, pos1.z + z) 173 | vi = vi + ystride 174 | if y == yrange then 175 | break 176 | end 177 | if self[vi - vi_x] then 178 | nextaction = vi + xrange 179 | 180 | vi = vi - 1 181 | pos.x = pos1.x - 1 182 | return iterfunc() 183 | end 184 | -- Nothing along this x line, so increase y again 185 | end 186 | 187 | -- Go back along y 188 | vi = vi - yrange * ystride 189 | y = 0 190 | pos.y = pos1.y 191 | -- Go along z until pos2.z is exceeded 192 | while true do 193 | z = z + 1 194 | pos.z = pos.z + 1 195 | vi = vi + zstride 196 | if z == zrange then 197 | -- Cuboid finished, return nil 198 | return 199 | end 200 | if self[vi - vi_x - vi_y] then 201 | y = 0 202 | nextaction = vi + xrange 203 | 204 | vi = vi - 1 205 | pos.x = pos1.x - 1 206 | return iterfunc() 207 | end 208 | -- Nothing in this xy plane, so increase z again 209 | end 210 | end 211 | return iterfunc 212 | end, 213 | iterAll = function(self) 214 | local previous_vi = nil 215 | local function iterfunc() 216 | local vi, v = next(self, previous_vi) 217 | previous_vi = vi 218 | if not vi then 219 | return 220 | end 221 | local z = math.floor(vi / (0x10000 * 0x10000)) 222 | vi = vi - z * 0x10000 * 0x10000 223 | local y = math.floor(vi / 0x10000) 224 | if y == 0 or z == 0 then 225 | -- The index does not refer to a position inside the map 226 | return iterfunc() 227 | end 228 | local x = vi - y * 0x10000 - 0x8000 229 | y = y - 0x8000 230 | z = z - 0x8000 231 | return {x=x, y=y, z=z}, v 232 | end 233 | return iterfunc 234 | end, 235 | serialize = function(self) 236 | local indices = {} 237 | local values = {} 238 | local i = 1 239 | for pos, v in self:iterAll() do 240 | local vi = node_position_key(pos) 241 | -- Convert the double reversible to a string; 242 | -- minetest.serialize does not (yet) do this 243 | indices[i] = ("%.17g"):format(vi) 244 | values[i] = v 245 | end 246 | return minetest.serialize({ 247 | version = "MapDataStorage_v1", 248 | indices = "return {" .. table.concat(indices, ",") .. "}", 249 | values = minetest.serialize(values), 250 | }) 251 | end, 252 | } 253 | MapDataStorage.deserialize = function(txtdata) 254 | local data = minetest.deserialize(txtdata) 255 | if data.version ~= "MapDataStorage_v1" then 256 | minetest.log("error", "Unknown MapDataStorage version: " .. 257 | data.version) 258 | end 259 | -- I assume that minetest.deserialize correctly deserializes the indices, 260 | -- which are in the %a format 261 | local indices = minetest.deserialize(data.indices) 262 | local values = minetest.deserialize(data.values) 263 | if not indices or not values then 264 | return MapDataStorage() 265 | end 266 | data = MapDataStorage() 267 | for i = 1,#indices do 268 | local vi = indices[i] 269 | local v = values[i] 270 | data:setAtI(vi, v) 271 | end 272 | return data 273 | end 274 | moremesecons.MapDataStorage = MapDataStorage 275 | 276 | 277 | -- Legacy 278 | 279 | -- vector_extras there: https://github.com/HybridDog/vector_extras 280 | -- Creates a MapDataStorage object from old vector_extras generated table 281 | function moremesecons.load_old_data_from_pos(t) 282 | local data = MapDataStorage() 283 | for z, yxv in pairs(t) do 284 | for y, xv in pairs(yxv) do 285 | for x, v in pairs(xv) do 286 | data:setAt({x=x, y=y, z=z}, v) 287 | end 288 | end 289 | end 290 | return data 291 | end 292 | 293 | function moremesecons.load_old_dfp_storage(modstorage, name) 294 | local data = minetest.deserialize(modstorage:get_string(name)) 295 | if not data then 296 | return 297 | end 298 | return moremesecons.load_old_data_from_pos(data) 299 | end 300 | 301 | function moremesecons.load_MapDataStorage_legacy(modstorage, name, oldname) 302 | local t_old = moremesecons.load_old_dfp_storage(modstorage, oldname) 303 | local t 304 | if t_old and t_old ~= "" then 305 | t = t_old 306 | modstorage:set_string(name, t:serialize()) 307 | modstorage:set_string(oldname, nil) 308 | return t 309 | end 310 | t = modstorage:get_string(name) 311 | if t and t ~= "" then 312 | return MapDataStorage.deserialize(t) 313 | end 314 | return MapDataStorage() 315 | end 316 | 317 | 318 | 319 | --[[ 320 | -- This testing code shows an example usage of the MapDataStorage code 321 | local function do_test() 322 | print("Test if iter returns correct positions when a lot is set") 323 | local data = MapDataStorage() 324 | local k = 0 325 | for x = -5, 3 do 326 | for y = -5, 3 do 327 | for z = -5, 3 do 328 | k = k + 1 329 | data:setAt({x=x, y=y, z=z}, k) 330 | end 331 | end 332 | end 333 | local expected_positions = {} 334 | for z = -4, 2 do 335 | for y = -4, 2 do 336 | for x = -4, 2 do 337 | expected_positions[#expected_positions+1] = {x=x, y=y, z=z} 338 | end 339 | end 340 | end 341 | local i = 0 342 | for pos in data:iter({x=-4, y=-4, z=-4}, {x=2, y=2, z=2}) do 343 | i = i + 1 344 | assert(vector.equals(pos, expected_positions[i])) 345 | end 346 | 347 | print("Test if iter works correctly on a corner") 348 | local found = false 349 | for pos in data:iter({x=-8, y=-7, z=-80}, {x=-5, y=-5, z=-5}) do 350 | assert(not found) 351 | found = true 352 | assert(vector.equals(pos, {x=-5, y=-5, z=-5})) 353 | end 354 | assert(found) 355 | 356 | print("Test if iter finds all corners") 357 | local expected_positions = {} 358 | local k = 1 359 | for _, z in ipairs({-9, -6}) do 360 | for _, y in ipairs({-9, -6}) do 361 | for _, x in ipairs({-8, -6}) do 362 | local pos = {x=x, y=y, z=z} 363 | expected_positions[#expected_positions+1] = pos 364 | data:setAt(pos, k) 365 | k = k + 1 366 | end 367 | end 368 | end 369 | local i = 1 370 | for pos, v in data:iter({x=-8, y=-9, z=-9}, {x=-6, y=-6, z=-6}) do 371 | assert(v == i) 372 | assert(vector.equals(pos, expected_positions[i])) 373 | i = i + 1 374 | --~ print("found " .. minetest.pos_to_string(pos)) 375 | end 376 | assert(i == 8 + 1, "Not enough or too many corners found") 377 | 378 | --~ data:iterAll() 379 | end 380 | do_test() 381 | --]] 382 | -------------------------------------------------------------------------------- /moremesecons_utils/mod.conf: -------------------------------------------------------------------------------- 1 | name = moremesecons_utils 2 | description = Various helping functions for moremesecons 3 | -------------------------------------------------------------------------------- /moremesecons_wireless/init.lua: -------------------------------------------------------------------------------- 1 | local storage = minetest.get_mod_storage() 2 | 3 | -- Names wireless_meta, and jammers were used in old versions of this mod. 4 | -- There is legacy code at the end of this file to migrate the mod storage. 5 | local wireless = minetest.deserialize(storage:get_string("networks")) or {} 6 | local wireless_meta = moremesecons.get_storage_data(storage, "wireless_meta_2") 7 | local jammers = moremesecons.get_storage_data(storage, "jammers_2") 8 | 9 | local function update_mod_storage() 10 | storage:set_string("networks", minetest.serialize(wireless)) 11 | end 12 | 13 | local wireless_effector_off 14 | local function remove_wireless(pos) 15 | local wls = moremesecons.get_data_from_pos(wireless_meta, pos) 16 | if not wls then 17 | return 18 | end 19 | 20 | if not wls.owner or wls.owner == "" then 21 | moremesecons.remove_data_from_pos(wireless_meta, pos) 22 | return 23 | end 24 | 25 | if not wireless[wls.owner] or not next(wireless[wls.owner]) then 26 | wireless[wls.owner] = nil 27 | moremesecons.remove_data_from_pos(wireless_meta, pos) 28 | return 29 | end 30 | 31 | if not wls.channel or wls.channel == "" then 32 | moremesecons.remove_data_from_pos(wireless_meta, pos) 33 | return 34 | end 35 | 36 | local network = wireless[wls.owner][wls.channel] 37 | 38 | if network.sources[wls.id] then 39 | wireless_effector_off(pos) 40 | end 41 | 42 | moremesecons.remove_data_from_pos(wireless_meta, pos) 43 | 44 | network.members[wls.id] = nil 45 | if not next(network.members) then 46 | wireless[wls.owner][wls.channel] = nil 47 | if not next(wireless[wls.owner]) then 48 | wireless[wls.owner] = nil 49 | end 50 | end 51 | update_mod_storage() 52 | end 53 | 54 | local function set_owner(pos, owner) 55 | if not owner or owner == "" then 56 | return 57 | end 58 | 59 | remove_wireless(pos) 60 | 61 | local meta = minetest.get_meta(pos) 62 | if meta then 63 | meta:set_string("owner", owner) 64 | end 65 | 66 | local wls = moremesecons.get_data_from_pos(wireless_meta, pos) or {} 67 | wls.owner = owner 68 | moremesecons.set_data_to_pos(wireless_meta, pos, wls) 69 | 70 | if not wireless[owner] then 71 | wireless[owner] = {} 72 | end 73 | 74 | if meta then 75 | meta:set_string("infotext", "Wireless owned by " .. owner .. " on " .. ((wls.channel and wls.channel ~= "") and "channel " .. wls.channel or "undefined channel")) 76 | end 77 | end 78 | 79 | local wireless_receptor_on 80 | local wireless_receptor_off 81 | local wireless_effector_on 82 | local function set_channel(pos, channel) 83 | if not channel or channel == "" then 84 | return 85 | end 86 | 87 | local meta = minetest.get_meta(pos) 88 | 89 | local wls = moremesecons.get_data_from_pos(wireless_meta, pos) 90 | if not wls or wls.owner == "" then 91 | return 92 | end 93 | 94 | if wls.id then 95 | remove_wireless(pos) 96 | end 97 | 98 | if meta then 99 | meta:set_string("channel", channel) 100 | end 101 | wls.channel = channel 102 | moremesecons.set_data_to_pos(wireless_meta, pos, wls) 103 | 104 | if not wireless[wls.owner] then 105 | wireless[wls.owner] = {} 106 | end 107 | if not wireless[wls.owner][channel] then 108 | wireless[wls.owner][channel] = { 109 | members = {}, 110 | sources = {} 111 | } 112 | end 113 | 114 | -- Find the first free ID 115 | local id = 1 116 | while wireless[wls.owner][channel].members[id] do 117 | id = id + 1 118 | end 119 | wls.id = id 120 | moremesecons.set_data_to_pos(wireless_meta, pos, wls) 121 | 122 | local network = wireless[wls.owner][channel] 123 | 124 | network.members[id] = pos 125 | 126 | if meta then 127 | meta:set_int("id", id) 128 | end 129 | 130 | update_mod_storage() 131 | 132 | if meta then 133 | meta:set_string("infotext", "Wireless owned by " .. wls.owner .. " on channel " .. channel) 134 | end 135 | 136 | if wls.effector then 137 | wireless_effector_on(pos) 138 | elseif next(network.sources) then 139 | wireless_receptor_on(pos, id, network, false) 140 | else 141 | wireless_receptor_off(pos, id, network, false) 142 | end 143 | end 144 | 145 | local function register_wireless(pos) 146 | local meta = minetest.get_meta(pos) 147 | local owner = meta:get_string("owner") 148 | if owner == "" then 149 | return 150 | end 151 | remove_wireless(pos) 152 | 153 | set_owner(pos, owner) 154 | 155 | local channel = meta:get_string("channel") 156 | if channel ~= "" then 157 | set_channel(pos, channel) 158 | end 159 | end 160 | 161 | local function check_wireless_exists(pos) 162 | local nn = minetest.get_node(pos).name 163 | if nn:sub(1, 30) == "moremesecons_wireless:wireless" then 164 | return true 165 | elseif nn ~= "ignore" then 166 | -- Defer the remove_wireless() call so it doesn't interfere 167 | -- with pairs(). 168 | minetest.after(0, remove_wireless, pos) 169 | return false 170 | end 171 | end 172 | 173 | function wireless_receptor_on(pos, id, network, check) 174 | if check == false or check_wireless_exists(pos) then 175 | minetest.swap_node(pos, {name = "moremesecons_wireless:wireless_on"}) 176 | if not network.sources[id] then 177 | mesecon.receptor_on(pos) 178 | end 179 | end 180 | end 181 | 182 | function wireless_receptor_off(pos, id, network, check) 183 | if check == false or check_wireless_exists(pos) then 184 | minetest.swap_node(pos, {name = "moremesecons_wireless:wireless_off"}) 185 | mesecon.receptor_off(pos) 186 | end 187 | end 188 | 189 | local function activate_network(owner, channel) 190 | local network = wireless[owner][channel] 191 | for i, wl_pos in pairs(network.members) do 192 | wireless_receptor_on(wl_pos, i, network) 193 | end 194 | end 195 | 196 | local function deactivate_network(owner, channel) 197 | local network = wireless[owner][channel] 198 | for i, wl_pos in pairs(network.members) do 199 | wireless_receptor_off(wl_pos, i, network) 200 | end 201 | end 202 | 203 | local is_jammed 204 | function wireless_effector_on(pos) 205 | if is_jammed(pos) then 206 | -- jamming doesn't disallow receiving signals, only sending them 207 | return 208 | end 209 | 210 | local wls = moremesecons.get_data_from_pos(wireless_meta, pos) 211 | if not wls then 212 | return 213 | end 214 | 215 | wls.effector = true 216 | 217 | moremesecons.set_data_to_pos(wireless_meta, pos, wls) 218 | 219 | if wls.owner == "" or not wireless[wls.owner] or wls.channel == "" or not wireless[wls.owner][wls.channel] then 220 | return 221 | end 222 | 223 | local network = wireless[wls.owner][wls.channel] 224 | network.sources[wls.id] = true 225 | activate_network(wls.owner, wls.channel) 226 | 227 | update_mod_storage() 228 | end 229 | 230 | function wireless_effector_off(pos) 231 | local wls = moremesecons.get_data_from_pos(wireless_meta, pos) 232 | if not wls then 233 | return 234 | end 235 | 236 | wls.effector = nil 237 | moremesecons.set_data_to_pos(wireless_meta, pos, wls) 238 | 239 | if wls.owner == "" or not wireless[wls.owner] or wls.channel == "" or not wireless[wls.owner][wls.channel] then 240 | return 241 | end 242 | 243 | local network = wireless[wls.owner][wls.channel] 244 | network.sources[wls.id] = nil 245 | if not next(network.sources) then 246 | deactivate_network(wls.owner, wls.channel) 247 | else 248 | -- There is another source in the network. Turn this wireless into 249 | -- a receptor. 250 | mesecon.receptor_on(pos) 251 | end 252 | 253 | update_mod_storage() 254 | end 255 | 256 | -- This table is required to prevent a message from being sent in loop between wireless nodes 257 | local sending_digilines = {} 258 | 259 | local function on_digiline_receive(pos, node, channel, msg) 260 | if is_jammed(pos) then 261 | return 262 | end 263 | 264 | local wls = moremesecons.get_data_from_pos(wireless_meta, pos) 265 | if not wls then 266 | return 267 | end 268 | 269 | if wls.owner == "" or not wireless[wls.owner] or channel == "" or not wireless[wls.owner][wls.channel] then 270 | return 271 | end 272 | 273 | local pos_hash = minetest.hash_node_position(pos) 274 | if sending_digilines[pos_hash] then 275 | return 276 | end 277 | 278 | sending_digilines[pos_hash] = true 279 | for i, wl_pos in pairs(wireless[wls.owner][wls.channel].members) do 280 | if i ~= wls.id then 281 | digiline:receptor_send(wl_pos, digiline.rules.default, channel, msg) 282 | end 283 | end 284 | sending_digilines[pos_hash] = nil 285 | end 286 | 287 | mesecon.register_node("moremesecons_wireless:wireless", { 288 | paramtype = "light", 289 | paramtype2 = "facedir", 290 | description = "Wireless", 291 | digiline = { 292 | receptor = {}, 293 | effector = { 294 | action = on_digiline_receive 295 | }, 296 | }, 297 | sounds = default.node_sound_stone_defaults(), 298 | on_construct = function(pos) 299 | minetest.get_meta(pos):set_string("formspec", "field[channel;channel;${channel}]") 300 | end, 301 | on_destruct = function(pos) 302 | remove_wireless(pos) 303 | mesecon.receptor_off(pos) 304 | end, 305 | after_place_node = function(pos, placer) 306 | set_owner(pos, placer:get_player_name()) 307 | end, 308 | on_receive_fields = function(pos, _, fields, player) 309 | local meta = minetest.get_meta(pos) 310 | local playername = player:get_player_name() 311 | 312 | local owner = meta:get_string("owner") 313 | if not owner or owner == "" then 314 | -- Old wireless 315 | if not minetest.is_protected(pos, playername) then 316 | set_owner(pos, playername) 317 | else 318 | return 319 | end 320 | end 321 | 322 | if playername == owner then 323 | set_channel(pos, fields.channel) 324 | end 325 | end, 326 | }, { 327 | tiles = {"moremesecons_wireless_off.png"}, 328 | groups = {cracky=3}, 329 | mesecons = {effector = { 330 | action_on = wireless_effector_on 331 | }}, 332 | }, { 333 | tiles = {"moremesecons_wireless_on.png"}, 334 | groups = {cracky=3, not_in_creative_inventory=1}, 335 | mesecons = {effector = { 336 | action_off = wireless_effector_off 337 | }}, 338 | }) 339 | 340 | minetest.register_alias("moremesecons_wireless:wireless", "moremesecons_wireless:wireless_off") 341 | 342 | minetest.register_craft({ 343 | output = "moremesecons_wireless:wireless_off 2", 344 | recipe = { 345 | {"group:mesecon_conductor_craftable", "", "group:mesecon_conductor_craftable"}, 346 | {"", "mesecons_torch:mesecon_torch_on", ""}, 347 | {"group:mesecon_conductor_craftable", "", "group:mesecon_conductor_craftable"}, 348 | } 349 | }) 350 | 351 | local function remove_jammer(pos) 352 | moremesecons.remove_data_from_pos(jammers, pos) 353 | end 354 | 355 | local function add_jammer(pos) 356 | remove_jammer(pos) 357 | moremesecons.set_data_to_pos(jammers, pos, true) 358 | end 359 | 360 | function is_jammed(pos) 361 | local JAMMER_MAX_DISTANCE = moremesecons.setting("wireless", "jammer_max_distance", 15, 1) 362 | local JAMMER_MAX_DISTANCE_SQUARE = JAMMER_MAX_DISTANCE^2 -- Cache this result 363 | 364 | for pos_hash, _ in pairs(jammers.tab) do 365 | local j_pos = minetest.get_position_from_hash(pos_hash) 366 | -- Fast comparisons first 367 | if math.abs(pos.x - j_pos.x) <= JAMMER_MAX_DISTANCE and 368 | math.abs(pos.y - j_pos.y) <= JAMMER_MAX_DISTANCE and 369 | math.abs(pos.z - j_pos.z) <= JAMMER_MAX_DISTANCE and 370 | (pos.x - j_pos.x)^2 + (pos.y - j_pos.y)^2 + (pos.z - j_pos.z)^2 <= JAMMER_MAX_DISTANCE_SQUARE then 371 | return true 372 | end 373 | end 374 | 375 | return false 376 | end 377 | 378 | if moremesecons.setting("wireless", "enable_jammer", true) then 379 | mesecon.register_node("moremesecons_wireless:jammer", { 380 | description = "Wireless Jammer", 381 | paramtype = "light", 382 | drawtype = "nodebox", 383 | },{ 384 | tiles = {"mesecons_wire_off.png^moremesecons_jammer_top.png", "moremesecons_jammer_bottom.png", "mesecons_wire_off.png^moremesecons_jammer_side_off.png"}, 385 | node_box = { 386 | type = "fixed", 387 | fixed = { 388 | -- connection 389 | {-1/16, -0.5, -0.5, 1/16, -7/16, 0.5}, 390 | {-0.5, -0.5, -1/16, 0.5, -7/16, 1/16}, 391 | 392 | --stabilization 393 | {-1/16, -7/16, -1/16, 1/16, -6/16, 1/16}, 394 | 395 | -- fields 396 | {-7/16, -6/16, -7/16, 7/16, -4/16, 7/16}, 397 | {-5/16, -4/16, -5/16, 5/16, -3/16, 5/16}, 398 | {-3/16, -3/16, -3/16, 3/16, -2/16, 3/16}, 399 | {-1/16, -2/16, -1/16, 1/16, -1/16, 1/16}, 400 | }, 401 | }, 402 | groups = {dig_immediate=2}, 403 | mesecons = {effector = { 404 | rules = mesecon.rules.flat, 405 | action_on = function(pos) 406 | add_jammer(pos) 407 | minetest.swap_node(pos, {name="moremesecons_wireless:jammer_on"}) 408 | end 409 | }} 410 | },{ 411 | tiles = {"mesecons_wire_on.png^moremesecons_jammer_top.png", "moremesecons_jammer_bottom.png", "mesecons_wire_on.png^moremesecons_jammer_side_on.png"}, 412 | node_box = { 413 | type = "fixed", 414 | fixed = { 415 | -- connection 416 | {-1/16, -0.5, -0.5, 1/16, -7/16, 0.5}, 417 | {-0.5, -0.5, -1/16, 0.5, -7/16, 1/16}, 418 | 419 | --stabilization 420 | {-1/16, -7/16, -1/16, 1/16, 5/16, 1/16}, 421 | 422 | -- fields 423 | {-7/16, -6/16, -7/16, 7/16, -4/16, 7/16}, 424 | {-5/16, -3/16, -5/16, 5/16, -1/16, 5/16}, 425 | {-3/16, 0, -3/16, 3/16, 2/16, 3/16}, 426 | {-1/16, 3/16, -1/16, 1/16, 5/16, 1/16}, 427 | }, 428 | }, 429 | groups = {dig_immediate=2, not_in_creative_inventory=1}, 430 | mesecons = {effector = { 431 | rules = mesecon.rules.flat, 432 | action_off = function(pos) 433 | remove_jammer(pos) 434 | minetest.swap_node(pos, {name="moremesecons_wireless:jammer_off"}) 435 | end 436 | }}, 437 | on_destruct = remove_jammer, 438 | on_construct = add_jammer, 439 | }) 440 | 441 | minetest.register_craft({ 442 | output = "moremesecons_wireless:jammer_off", 443 | recipe = { 444 | {"moremesecons_wireless:wireless", "mesecons_torch:mesecon_torch_on", "moremesecons_wireless:wireless"} 445 | } 446 | }) 447 | end 448 | 449 | if moremesecons.setting("wireless", "enable_lbm", false) then 450 | minetest.register_lbm({ 451 | name = "moremesecons_wireless:add_jammer", 452 | nodenames = {"moremesecons_wireless:jammer_on"}, 453 | run_at_every_load = true, 454 | action = add_jammer 455 | }) 456 | 457 | minetest.register_lbm({ 458 | name = "moremesecons_wireless:add_wireless", 459 | nodenames = {"moremesecons_wireless:wireless"}, 460 | run_at_every_load = true, 461 | action = register_wireless 462 | }) 463 | end 464 | 465 | -- Legacy 466 | if storage:get_string("wireless_meta_2") == "" then 467 | local wireless_meta_1 = minetest.deserialize(storage:get_string("wireless_meta")) 468 | if not wireless_meta_1 then 469 | return 470 | end 471 | 472 | minetest.log("action", "[moremesecons_wireless] Migrating mod storage data...") 473 | local jammers_1 = minetest.deserialize(storage:get_string("jammers")) 474 | 475 | local get = function(t, pos) 476 | -- FIXME: this does not test explicitly for false, 477 | -- but channel is never false 478 | return t[pos.z] and t[pos.z][pos.y] and t[pos.z][pos.y][pos.x] 479 | end 480 | 481 | for z, data_z in pairs(wireless_meta_1.owners) do 482 | for y, data_y in pairs(data_z) do 483 | for x, owner in pairs(data_y) do 484 | local pos = {x = x, y = y, z = z} 485 | set_owner(pos, owner) 486 | set_channel(pos, get(wireless_meta_1.channels, pos)) 487 | end 488 | end 489 | end 490 | 491 | for z, data_z in pairs(jammers_1) do 492 | for y, data_y in pairs(data_z) do 493 | for x, jammer in pairs(data_y) do 494 | local pos = {x = x, y = y, z = z} 495 | moremesecons.set_data_to_pos(jammers, pos, jammer) 496 | end 497 | end 498 | end 499 | minetest.log("action", "[moremesecons_wireless] Done!") 500 | end 501 | -------------------------------------------------------------------------------- /moremesecons_wireless/mod.conf: -------------------------------------------------------------------------------- 1 | name = moremesecons_wireless 2 | depends = mesecons,moremesecons_utils 3 | optional_depends = digilines,craft_guide 4 | -------------------------------------------------------------------------------- /moremesecons_wireless/textures/moremesecons_jammer_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_wireless/textures/moremesecons_jammer_bottom.png -------------------------------------------------------------------------------- /moremesecons_wireless/textures/moremesecons_jammer_side_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_wireless/textures/moremesecons_jammer_side_off.png -------------------------------------------------------------------------------- /moremesecons_wireless/textures/moremesecons_jammer_side_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_wireless/textures/moremesecons_jammer_side_on.png -------------------------------------------------------------------------------- /moremesecons_wireless/textures/moremesecons_jammer_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_wireless/textures/moremesecons_jammer_top.png -------------------------------------------------------------------------------- /moremesecons_wireless/textures/moremesecons_wireless_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_wireless/textures/moremesecons_wireless_off.png -------------------------------------------------------------------------------- /moremesecons_wireless/textures/moremesecons_wireless_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minetest-mods/MoreMesecons/3e93b939f3bae14fb7a8c3f94e8db5d8fc0b2c24/moremesecons_wireless/textures/moremesecons_wireless_on.png -------------------------------------------------------------------------------- /settingtypes.txt: -------------------------------------------------------------------------------- 1 | [Adjustable Blinky Plant] 2 | 3 | # Minimal interval authorized. Any lower will be set to it. 4 | moremesecons_adjustable_blinky_plant.min_interval (Minimum Interval) float 0.5 5 | 6 | [Adjustable Player Detector] 7 | 8 | moremesecons_adjustable_player_detector.max_radius (Maximum adjustable player detector radius) float 16 0 9 | 10 | [Craftable Commandblock] 11 | 12 | # Space-separated list of authorized commands 13 | # Empty to authorize all 14 | moremesecons_commandblock.authorized_commands (Authorized commands) string tell 15 | 16 | # Maximum distance of the @nearest player 17 | # Any value less than or equal to 0 will be changed to 1 and a NaN value will be changed to the default value 18 | moremesecons_commandblock.nearest_max_distance (Nearest player maximum distance) float 8 19 | 20 | [Entity Detector] 21 | 22 | moremesecons_entity_detector.max_radius (Maximum entity detector radius) float 16 0 23 | 24 | [Signal Jammer] 25 | 26 | # Jammer action range 27 | # Any value less than or equal to 0 will be changed to 1 and a NaN value will be changed to the default value 28 | moremesecons_jammer.max_distance (Jammer action range) float 10 29 | 30 | # Whether to enable the registration LBM. 31 | # The registration LBM will recover the jammer database if the moremesecons_jammer 32 | # mod storage has been removed, and will create that mod storage after an update 33 | # from an older version which did not use it. 34 | moremesecons_jammer.enable_lbm (Enable Registration LBM) bool false 35 | 36 | [Player Killer] 37 | 38 | # Player Killer action range 39 | # Any value less than or equal to 0 will be changed to 1 and a NaN value will be changed to the default value 40 | moremesecons_playerkiller.max_distance (Player Killer action range) float 8 41 | 42 | [Sayer] 43 | 44 | # Whether to use the Speech Dispatcher 45 | # It will work only if: 46 | # * moremesecons_sayer is present in your trusted_mods setting 47 | # * you are playing in singleplayer 48 | # * the speech-dispatcher is installed on your system 49 | # * you are using a POSIX-compliant system and a sh-compatible shell (such as bash, dash, zsh...) 50 | moremesecons_sayer.use_speech_dispatcher (Use the Speech Dispatcher) bool true 51 | 52 | # Sayer range 53 | # Any value less than or equal to 0 will be changed to 1 and a NaN value will be changed to the default value 54 | moremesecons_sayer.max_distance (Range) float 8 55 | 56 | [Teleporter] 57 | 58 | # Maximum Teleporter To Teleporter distance 59 | # Any value less than or equal to 0 will be changed to 1 and a NaN value will be changed to the default value 60 | moremesecons_teleporter.max_t2t_distance (Maximum Teleporter To Teleporter distance) float 50 61 | 62 | # Maximum Player To Teleporter distance 63 | # Any value less than or equal to 0 will be set to 1 64 | moremesecons_teleporter.max_p2t_distance (Maximum Player To Teleporter distance) float 25 65 | 66 | # Whether to enable the registration LBM. 67 | # The registration LBM will recover a teleporter network if the moremesecons_teleporter 68 | # mod storage has been removed, and will create that mod storage after an update 69 | # from an older version which did not use it. 70 | moremesecons_teleporter.enable_lbm (Enable Registration LBM) bool false 71 | 72 | [Wireless] 73 | 74 | # Whether to enable the wireless jammer node 75 | moremesecons_wireless.enable_jammer (Enable wireless jammer) bool true 76 | 77 | # Wireless Jammer action range 78 | # Any value less than or equal to 0 will be changed to 1 and a NaN value will be changed to the default value 79 | moremesecons_wireless.jammer_max_distance (Wireless Jammer action range) float 15 80 | 81 | # Whether to enable the registration LBM. 82 | # The registration LBM will recover a wireless network if the moremesecons_wireless 83 | # mod storage has been removed, and will create that mod storage after an update 84 | # from an older version which did not use it. 85 | moremesecons_wireless.enable_lbm (Enable Registration LBM) bool false 86 | --------------------------------------------------------------------------------