diff --git a/mods/mesecons_x/LICENSE.txt b/mods/mesecons_x/LICENSE.txt new file mode 100644 index 00000000..0d2fd188 --- /dev/null +++ b/mods/mesecons_x/LICENSE.txt @@ -0,0 +1,532 @@ +The LGPLv3 applies to all code in this project. +The CC-BY-SA-3.0 license applies to textures and any other content in this project which is not source code. + +================================================================= + +GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. + +================================================================= + +Creative Commons Legal Code + +Attribution-ShareAlike 3.0 Unported + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR + DAMAGES RESULTING FROM ITS USE. + +License + +THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE +COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY +COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS +AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. + +BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE +TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY +BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS +CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND +CONDITIONS. + +1. Definitions + + a. "Adaptation" means a work based upon the Work, or upon the Work and + other pre-existing works, such as a translation, adaptation, + derivative work, arrangement of music or other alterations of a + literary or artistic work, or phonogram or performance and includes + cinematographic adaptations or any other form in which the Work may be + recast, transformed, or adapted including in any form recognizably + derived from the original, except that a work that constitutes a + Collection will not be considered an Adaptation for the purpose of + this License. For the avoidance of doubt, where the Work is a musical + work, performance or phonogram, the synchronization of the Work in + timed-relation with a moving image ("synching") will be considered an + Adaptation for the purpose of this License. + b. "Collection" means a collection of literary or artistic works, such as + encyclopedias and anthologies, or performances, phonograms or + broadcasts, or other works or subject matter other than works listed + in Section 1(f) below, which, by reason of the selection and + arrangement of their contents, constitute intellectual creations, in + which the Work is included in its entirety in unmodified form along + with one or more other contributions, each constituting separate and + independent works in themselves, which together are assembled into a + collective whole. A work that constitutes a Collection will not be + considered an Adaptation (as defined below) for the purposes of this + License. + c. "Creative Commons Compatible License" means a license that is listed + at http://creativecommons.org/compatiblelicenses that has been + approved by Creative Commons as being essentially equivalent to this + License, including, at a minimum, because that license: (i) contains + terms that have the same purpose, meaning and effect as the License + Elements of this License; and, (ii) explicitly permits the relicensing + of adaptations of works made available under that license under this + License or a Creative Commons jurisdiction license with the same + License Elements as this License. + d. "Distribute" means to make available to the public the original and + copies of the Work or Adaptation, as appropriate, through sale or + other transfer of ownership. + e. "License Elements" means the following high-level license attributes + as selected by Licensor and indicated in the title of this License: + Attribution, ShareAlike. + f. "Licensor" means the individual, individuals, entity or entities that + offer(s) the Work under the terms of this License. + g. "Original Author" means, in the case of a literary or artistic work, + the individual, individuals, entity or entities who created the Work + or if no individual or entity can be identified, the publisher; and in + addition (i) in the case of a performance the actors, singers, + musicians, dancers, and other persons who act, sing, deliver, declaim, + play in, interpret or otherwise perform literary or artistic works or + expressions of folklore; (ii) in the case of a phonogram the producer + being the person or legal entity who first fixes the sounds of a + performance or other sounds; and, (iii) in the case of broadcasts, the + organization that transmits the broadcast. + h. "Work" means the literary and/or artistic work offered under the terms + of this License including without limitation any production in the + literary, scientific and artistic domain, whatever may be the mode or + form of its expression including digital form, such as a book, + pamphlet and other writing; a lecture, address, sermon or other work + of the same nature; a dramatic or dramatico-musical work; a + choreographic work or entertainment in dumb show; a musical + composition with or without words; a cinematographic work to which are + assimilated works expressed by a process analogous to cinematography; + a work of drawing, painting, architecture, sculpture, engraving or + lithography; a photographic work to which are assimilated works + expressed by a process analogous to photography; a work of applied + art; an illustration, map, plan, sketch or three-dimensional work + relative to geography, topography, architecture or science; a + performance; a broadcast; a phonogram; a compilation of data to the + extent it is protected as a copyrightable work; or a work performed by + a variety or circus performer to the extent it is not otherwise + considered a literary or artistic work. + i. "You" means an individual or entity exercising rights under this + License who has not previously violated the terms of this License with + respect to the Work, or who has received express permission from the + Licensor to exercise rights under this License despite a previous + violation. + j. "Publicly Perform" means to perform public recitations of the Work and + to communicate to the public those public recitations, by any means or + process, including by wire or wireless means or public digital + performances; to make available to the public Works in such a way that + members of the public may access these Works from a place and at a + place individually chosen by them; to perform the Work to the public + by any means or process and the communication to the public of the + performances of the Work, including by public digital performance; to + broadcast and rebroadcast the Work by any means including signs, + sounds or images. + k. "Reproduce" means to make copies of the Work by any means including + without limitation by sound or visual recordings and the right of + fixation and reproducing fixations of the Work, including storage of a + protected performance or phonogram in digital form or other electronic + medium. + +2. Fair Dealing Rights. Nothing in this License is intended to reduce, +limit, or restrict any uses free from copyright or rights arising from +limitations or exceptions that are provided for in connection with the +copyright protection under copyright law or other applicable laws. + +3. License Grant. Subject to the terms and conditions of this License, +Licensor hereby grants You a worldwide, royalty-free, non-exclusive, +perpetual (for the duration of the applicable copyright) license to +exercise the rights in the Work as stated below: + + a. to Reproduce the Work, to incorporate the Work into one or more + Collections, and to Reproduce the Work as incorporated in the + Collections; + b. to create and Reproduce Adaptations provided that any such Adaptation, + including any translation in any medium, takes reasonable steps to + clearly label, demarcate or otherwise identify that changes were made + to the original Work. For example, a translation could be marked "The + original work was translated from English to Spanish," or a + modification could indicate "The original work has been modified."; + c. to Distribute and Publicly Perform the Work including as incorporated + in Collections; and, + d. to Distribute and Publicly Perform Adaptations. + e. For the avoidance of doubt: + + i. Non-waivable Compulsory License Schemes. In those jurisdictions in + which the right to collect royalties through any statutory or + compulsory licensing scheme cannot be waived, the Licensor + reserves the exclusive right to collect such royalties for any + exercise by You of the rights granted under this License; + ii. Waivable Compulsory License Schemes. In those jurisdictions in + which the right to collect royalties through any statutory or + compulsory licensing scheme can be waived, the Licensor waives the + exclusive right to collect such royalties for any exercise by You + of the rights granted under this License; and, + iii. Voluntary License Schemes. The Licensor waives the right to + collect royalties, whether individually or, in the event that the + Licensor is a member of a collecting society that administers + voluntary licensing schemes, via that society, from any exercise + by You of the rights granted under this License. + +The above rights may be exercised in all media and formats whether now +known or hereafter devised. The above rights include the right to make +such modifications as are technically necessary to exercise the rights in +other media and formats. Subject to Section 8(f), all rights not expressly +granted by Licensor are hereby reserved. + +4. Restrictions. The license granted in Section 3 above is expressly made +subject to and limited by the following restrictions: + + a. You may Distribute or Publicly Perform the Work only under the terms + of this License. You must include a copy of, or the Uniform Resource + Identifier (URI) for, this License with every copy of the Work You + Distribute or Publicly Perform. You may not offer or impose any terms + on the Work that restrict the terms of this License or the ability of + the recipient of the Work to exercise the rights granted to that + recipient under the terms of the License. You may not sublicense the + Work. You must keep intact all notices that refer to this License and + to the disclaimer of warranties with every copy of the Work You + Distribute or Publicly Perform. When You Distribute or Publicly + Perform the Work, You may not impose any effective technological + measures on the Work that restrict the ability of a recipient of the + Work from You to exercise the rights granted to that recipient under + the terms of the License. This Section 4(a) applies to the Work as + incorporated in a Collection, but this does not require the Collection + apart from the Work itself to be made subject to the terms of this + License. If You create a Collection, upon notice from any Licensor You + must, to the extent practicable, remove from the Collection any credit + as required by Section 4(c), as requested. If You create an + Adaptation, upon notice from any Licensor You must, to the extent + practicable, remove from the Adaptation any credit as required by + Section 4(c), as requested. + b. You may Distribute or Publicly Perform an Adaptation only under the + terms of: (i) this License; (ii) a later version of this License with + the same License Elements as this License; (iii) a Creative Commons + jurisdiction license (either this or a later license version) that + contains the same License Elements as this License (e.g., + Attribution-ShareAlike 3.0 US)); (iv) a Creative Commons Compatible + License. If you license the Adaptation under one of the licenses + mentioned in (iv), you must comply with the terms of that license. If + you license the Adaptation under the terms of any of the licenses + mentioned in (i), (ii) or (iii) (the "Applicable License"), you must + comply with the terms of the Applicable License generally and the + following provisions: (I) You must include a copy of, or the URI for, + the Applicable License with every copy of each Adaptation You + Distribute or Publicly Perform; (II) You may not offer or impose any + terms on the Adaptation that restrict the terms of the Applicable + License or the ability of the recipient of the Adaptation to exercise + the rights granted to that recipient under the terms of the Applicable + License; (III) You must keep intact all notices that refer to the + Applicable License and to the disclaimer of warranties with every copy + of the Work as included in the Adaptation You Distribute or Publicly + Perform; (IV) when You Distribute or Publicly Perform the Adaptation, + You may not impose any effective technological measures on the + Adaptation that restrict the ability of a recipient of the Adaptation + from You to exercise the rights granted to that recipient under the + terms of the Applicable License. This Section 4(b) applies to the + Adaptation as incorporated in a Collection, but this does not require + the Collection apart from the Adaptation itself to be made subject to + the terms of the Applicable License. + c. If You Distribute, or Publicly Perform the Work or any Adaptations or + Collections, You must, unless a request has been made pursuant to + Section 4(a), keep intact all copyright notices for the Work and + provide, reasonable to the medium or means You are utilizing: (i) the + name of the Original Author (or pseudonym, if applicable) if supplied, + and/or if the Original Author and/or Licensor designate another party + or parties (e.g., a sponsor institute, publishing entity, journal) for + attribution ("Attribution Parties") in Licensor's copyright notice, + terms of service or by other reasonable means, the name of such party + or parties; (ii) the title of the Work if supplied; (iii) to the + extent reasonably practicable, the URI, if any, that Licensor + specifies to be associated with the Work, unless such URI does not + refer to the copyright notice or licensing information for the Work; + and (iv) , consistent with Ssection 3(b), in the case of an + Adaptation, a credit identifying the use of the Work in the Adaptation + (e.g., "French translation of the Work by Original Author," or + "Screenplay based on original Work by Original Author"). The credit + required by this Section 4(c) may be implemented in any reasonable + manner; provided, however, that in the case of a Adaptation or + Collection, at a minimum such credit will appear, if a credit for all + contributing authors of the Adaptation or Collection appears, then as + part of these credits and in a manner at least as prominent as the + credits for the other contributing authors. For the avoidance of + doubt, You may only use the credit required by this Section for the + purpose of attribution in the manner set out above and, by exercising + Your rights under this License, You may not implicitly or explicitly + assert or imply any connection with, sponsorship or endorsement by the + Original Author, Licensor and/or Attribution Parties, as appropriate, + of You or Your use of the Work, without the separate, express prior + written permission of the Original Author, Licensor and/or Attribution + Parties. + d. Except as otherwise agreed in writing by the Licensor or as may be + otherwise permitted by applicable law, if You Reproduce, Distribute or + Publicly Perform the Work either by itself or as part of any + Adaptations or Collections, You must not distort, mutilate, modify or + take other derogatory action in relation to the Work which would be + prejudicial to the Original Author's honor or reputation. Licensor + agrees that in those jurisdictions (e.g. Japan), in which any exercise + of the right granted in Section 3(b) of this License (the right to + make Adaptations) would be deemed to be a distortion, mutilation, + modification or other derogatory action prejudicial to the Original + Author's honor and reputation, the Licensor will waive or not assert, + as appropriate, this Section, to the fullest extent permitted by the + applicable national law, to enable You to reasonably exercise Your + right under Section 3(b) of this License (right to make Adaptations) + but not otherwise. + +5. Representations, Warranties and Disclaimer + +UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR +OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY +KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, +INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, +FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF +LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, +WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION +OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU. + +6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE +LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR +ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES +ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +7. Termination + + a. This License and the rights granted hereunder will terminate + automatically upon any breach by You of the terms of this License. + Individuals or entities who have received Adaptations or Collections + from You under this License, however, will not have their licenses + terminated provided such individuals or entities remain in full + compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will + survive any termination of this License. + b. Subject to the above terms and conditions, the license granted here is + perpetual (for the duration of the applicable copyright in the Work). + Notwithstanding the above, Licensor reserves the right to release the + Work under different license terms or to stop distributing the Work at + any time; provided, however that any such election will not serve to + withdraw this License (or any other license that has been, or is + required to be, granted under the terms of this License), and this + License will continue in full force and effect unless terminated as + stated above. + +8. Miscellaneous + + a. Each time You Distribute or Publicly Perform the Work or a Collection, + the Licensor offers to the recipient a license to the Work on the same + terms and conditions as the license granted to You under this License. + b. Each time You Distribute or Publicly Perform an Adaptation, Licensor + offers to the recipient a license to the original Work on the same + terms and conditions as the license granted to You under this License. + c. If any provision of this License is invalid or unenforceable under + applicable law, it shall not affect the validity or enforceability of + the remainder of the terms of this License, and without further action + by the parties to this agreement, such provision shall be reformed to + the minimum extent necessary to make such provision valid and + enforceable. + d. No term or provision of this License shall be deemed waived and no + breach consented to unless such waiver or consent shall be in writing + and signed by the party to be charged with such waiver or consent. + e. This License constitutes the entire agreement between the parties with + respect to the Work licensed here. There are no understandings, + agreements or representations with respect to the Work not specified + here. Licensor shall not be bound by any additional provisions that + may appear in any communication from You. This License may not be + modified without the mutual written agreement of the Licensor and You. + f. The rights granted under, and the subject matter referenced, in this + License were drafted utilizing the terminology of the Berne Convention + for the Protection of Literary and Artistic Works (as amended on + September 28, 1979), the Rome Convention of 1961, the WIPO Copyright + Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 + and the Universal Copyright Convention (as revised on July 24, 1971). + These rights and subject matter take effect in the relevant + jurisdiction in which the License terms are sought to be enforced + according to the corresponding provisions of the implementation of + those treaty provisions in the applicable national law. If the + standard suite of rights granted under applicable copyright law + includes additional rights not granted under this License, such + additional rights are deemed to be included in the License; this + License is not intended to restrict the license of any rights under + applicable law. + + +Creative Commons Notice + + Creative Commons is not a party to this License, and makes no warranty + whatsoever in connection with the Work. Creative Commons will not be + liable to You or any party on any legal theory for any damages + whatsoever, including without limitation any general, special, + incidental or consequential damages arising in connection to this + license. Notwithstanding the foregoing two (2) sentences, if Creative + Commons has expressly identified itself as the Licensor hereunder, it + shall have all rights and obligations of Licensor. + + Except for the limited purpose of indicating to the public that the + Work is licensed under the CCPL, Creative Commons does not authorize + the use by either party of the trademark "Creative Commons" or any + related trademark or logo of Creative Commons without the prior + written consent of Creative Commons. Any permitted use will be in + compliance with Creative Commons' then-current trademark usage + guidelines, as may be published on its website or otherwise made + available upon request from time to time. For the avoidance of doubt, + this trademark restriction does not form part of the License. + + Creative Commons may be contacted at http://creativecommons.org/. diff --git a/mods/mesecons_x/README.md b/mods/mesecons_x/README.md new file mode 100644 index 00000000..f360387b --- /dev/null +++ b/mods/mesecons_x/README.md @@ -0,0 +1,85 @@ +mesecons_x by marek + + +Adds some new elements to Mesecons mod, to make it easier to build more complex circuits. + + +[Youtube](https://www.youtube.com/channel/UCohaNk7q3MfTdl5LwiTjB5Q) + +[Discord](https://discord.gg/eGHkdQj) + +![picture](https://gitlab.com/deetmit/mesecons_x/-/raw/master/picture.png) + + +New elements: + +**Tools.** +- black tool + + Creates wires automaticaly by selectin starting position (left click) and ending position (right click). + You can keep clicking right, to continue the wire. The wire will automaticaly bend and go over other wires + if possible. Click on other wire to connect to the existing wire. + + If you select more than one block, then multiple wires will be created. If you select existing circuit, the + wires will be automatically connected to the existing blocks. + +- red tool + + Removes wires automaticaly. Left click is simple puch. Right click removes the entire wire + to the next junction. + + If you click on a junction, it will delete all wires that goes out of the junction. + If you click on a gate, it will remove the gate and all adjacent (=connected) wires. + + If you click right on the air, it will remove the selected area. + If you click right on a wire withing selection, it will remove the selection and all wires that are going out from the selection. + +- blue tool + + Selects the area. Left click selects pos1, right click selects pos2. + Left click on air uses the position of the player. + +- yellow tool + + Allows you to move circuit, or part of the circuit without disconnecting wires. + Left click moves to the left, right click moves to the right. You must face proper direction. + Use blue tool to select region. + + IF you use up/down yellow tool, left always mean down, right click always means up. + +- orange tool + + Stacks the selected circuit. You can "undo" the stacking by clicking left mouse. Note, if you change the selection, "undo" is + not possible. + +- white tool + + Changes selection borders. Right click always means expand, left click always means contract. + + +- circuit (blue book) + + Allows you to store your circuit, and paste it in other places. + Left click on air saves the circuit (selecion must be active). + Left click on block creates selection of the circuit. + Right click paste the circuit. + +**Other elements.** +- 3 input logic gates: and, or, nand, nor +- latch and flipflop +- insulated xjunction + +**Example** +This circuit was built in 60 seconds using circuit books. + +![4bit](https://gitlab.com/deetmit/mesecons_x/-/raw/master/picture_4bit_incrementer.png) + + + + +TODO list: +- copy metadata while moving blocks +- add page and book to keep multiple circuits in one place +- improve algorithm for autoconnection of the wires when the circuit is moved +- load nodes before reading + diff --git a/mods/mesecons_x/TODO b/mods/mesecons_x/TODO new file mode 100644 index 00000000..9a195bcb --- /dev/null +++ b/mods/mesecons_x/TODO @@ -0,0 +1,142 @@ +Here is a list of things I plan to implement. + + +[FSM generator](status: after first release) +Description: A tool which generates circuit based on code. You use special lanugae +to describe FSM (finite state machine), and based on this code circuit is +generated. Example of the code: + +#pinA = a ~b c +#pinB = a c d +@state_left = lem li +@state_pause = pause0 pause1 + +[[start]] +[lem] a b ~d +[li] d pause sel #pinB + +[start] pause #pinA -> [start] +[@state_pause] ~pause sel -> [some_state] + +etc. + + + +[Fromula generator](status: not started) +Description: A tool that generates circuit based on formula. Formula is in special +language (similar to logic formula in math). It is also possible to generate +formulas using numbers. Example: +if pin0 = true and counter > 10 then + output = counter + 10 + pin1 = true +else + outpue = counter / 2 + 1 + pin2 = true + pin3 = false +end + + + + +[Module generator](status: not started) +Description: A tool that has a list of preprogrammed circuits. Allows you to choose and +use it. For some of them you can generate different versions based +on the input size or other parameters. Example: you can generate adder by setting the size +of the input. Example: you can generate incrementer by +8, where the number +8 you set as a parameter for generation algorithm. + +A tool also contains the following modules/circuits: incrementer, decrementer, adder, +substracter, multiplier, divider, shift registers, comparators, wire transfomation, +number generation (from dec to hex/bin) etc + + +As and advanced option, the tool should also be able to generate circuit based on +the current selection. Example. if you selected 5 wires and want to generate +an adder that should be connected to these wires, the generator should generate +circuit with inputs and outpus connected (so the circuit may be streched if necessary) +Example. If you are building a cpu with pipes, and need from time to time add a registers +to store partial computation, you just select the wires, use generator, and +the registers are connected to the wires (you dont have to connect the wires manualy)) +etc. + + + +[Book of circuits](status: not started) +Description: a tool that stores multiple circuits built by player (blue books). Allows +to search, and put in different directories. The tool should be able to store aprox 1000 +circuits and it should be easy to find and manage any of them ( adding, removing, renaming, +moving etc). Search would use name and descriptinos of the circuits. You can use some +tags (i.e. simple string formated like #tagname) in circuits description. You should also +be able to duplicate the circuit, and there should be some mechanism to put a group +of circuits in the inventory at once (a previously prepared groups of circuits +that are used often). + + + + + +[Gate move tool] (status: not started) +Description: tool that moves one gate or piece of wire from one place to another. +The connections are rearranged, but the whole circuits stays the same (in terms of +functional equivalence). +You have to select the circuit (using blue tool) first. This is the area that is going +to be changed. During the process, the circuit may grow, so you must be sure that other things are not deleted. +The purpouse of these tool is to optimise your circuit in terms of size. + + + +[Delete and change tool](status: not started) +Description: If you use circuits templates (ex. adders) sometimes you set some wires +to fixed value (eg. using general adder of two numbers, to create incrementer ++2. +by seting one numner to 2). +This tool should allow you to remove the unnecessary gates and wires, that never change. +You click on power plants (generating alway 1, or 0) or empty wires (generating always 0), +then the wire is deleted and all gates that just lost one of the connections are also +deleted (or changed to other gate accordingly). Proces is continued till there are no more changes to do. + +Note that this tool will remove only one starting wire or plant. It could change the whole +circuit in the process (as a chain of removal reaction), but if you have another power plants, +you must click at all of them on by one. +This tool is not ment to be a whole circuit optymalization tool. + + + +[Streching tool](status: not stared) +Description: There is a need to shrink the circuit when possible. I'm not sure yet if +this feature should be as a separte tool, or just automatically done in other tools. + + + +[Reverse Generation](status: not started) +Description: Tool that generates a code in special language based on the circuit. +You select some circuit, and use the tool. The tool generates logic formula or FSM. +This tool is kind of opposite to the FSM Generator and Formula Generator. + + + +[Input & Output blocs](status: not started) +Description: just a simple node, to let know all the other tools that the wire +is input or output. You can add a name, so some tools can use it to name wires +in code or descriptions. Very userful for Reverse Generator tool. +Blocks can also be used by generators, so that the player can see which wire is which. + +[undo tool](status: not started) +Description: a list per user of deleted regions, that can by recovered, or put in +a blue book. It's a simple list of + +data (before circuit) (after circuit) (position+teleport button) (to book button) + +Circuits are stores in files, in minetest data structures (let's cool it 'a trash book') +is only a list of name s of last deletes. + +It will track the following: +- cable generate (black tool) +- remove regions and wires (red tools) +- orange tools +- grey tool +- pasting blue books +- pasting fsm books (orange book) + + + + diff --git a/mods/mesecons_x/circuit_previeew.png b/mods/mesecons_x/circuit_previeew.png new file mode 100644 index 00000000..fa3fb119 Binary files /dev/null and b/mods/mesecons_x/circuit_previeew.png differ diff --git a/mods/mesecons_x/mesecons_autotools/book/circuit.lua b/mods/mesecons_x/mesecons_autotools/book/circuit.lua new file mode 100644 index 00000000..652186aa --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/book/circuit.lua @@ -0,0 +1,470 @@ +dofile(minetest.get_modpath("mesecons_autotools").."/book/mx.lua"); +dofile(minetest.get_modpath("mesecons_autotools").."/book/m3.lua"); + +dofile(minetest.get_modpath("mesecons_autotools").."/book/formspec.lua"); +dofile(minetest.get_modpath("mesecons_autotools").."/book/image.lua"); + +dofile(minetest.get_modpath("mesecons_autotools").."/book/misc.lua"); +dofile(minetest.get_modpath("mesecons_autotools").."/book/stats.lua"); + +local esc = minetest.formspec_escape + + + + +local function show_dialog_new(user,direction) + + local pos1 = mesecons_autotools.get_pos(user,1) + local pos2 = mesecons_autotools.get_pos(user,2) + local sel = {pos1=pos1,pos2=pos2} + + if not mesecons_autotools.is_full_selection(user) then return end + + local nodes = selection_to_m3(pos1,pos2,direction) + local view = m3_to_mx(nodes) + + local db = { + title = "", + text = "", + nodes = nodes, + direction = direction, + view = view, + } + local formspec = fs_all(db) + + minetest.show_formspec(user, "mesecons_autotools:circuit_new", formspec) + +end + + +local function show_dialog_full(user,file) + local info = read_table_from_file(file) + local view = m3_to_mx(info.nodes) + + local db = { + title = info.title, + text = info.text, + nodes = info.nodes, + direction = info.direction, + view = view, + } + + local formspec = fs_all(db) + minetest.show_formspec(user, "mesecons_autotools:circuit_edit", formspec) +end + + +minetest.register_on_player_receive_fields(function(player, formname, fields) + + if formname ~= "mesecons_autotools:circuit_new" then return end + + if (fields.save) or fields.key_enter_field == "title" then + + local user = player:get_player_name() + local file = generate_file_name(user) + local rad = player:get_look_horizontal() + local direction = radians_to_direction_looking_forward(rad) + + local stack = player:get_wielded_item() + local inv = player:get_inventory() + + local new_stack = nil + local info = {} + local data = {} + + if( stack:get_name() == "mesecons_autotools:circuit_empty" ) then + + new_stack = ItemStack("mesecons_autotools:circuit_full") + data.file = file + data.description = fields.title + new_stack:get_meta():from_table({ fields = data}) + + if inv:room_for_item("main", new_stack) then + inv:add_item("main", new_stack) + else + minetest.add_item(player:get_pos(), new_stack) + end + + -- standart info + info.title = fields.title + info.text = fields.text + + -- direction + info.direction = direction + + --info.direction = direction + + -- selection + + local pos1 = mesecons_autotools.get_pos(user,1) + local pos2 = mesecons_autotools.get_pos(user,2) + local nodes = selection_to_m3(pos1,pos2,direction) + + local metas = selection_to_m3_meta(pos1,pos2,direction) + + + info.nodes = nodes + info.metas = metas + save_table_to_file(file,info) + end + end + +end) + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname ~= "mesecons_autotools:circuit_edit" then return end + + if (fields.save) or fields.key_enter_field == "title" then + local user = player:get_player_name() + local rad = player:get_look_horizontal() + local direction = radians_to_direction_looking_forward(rad) + + local stack = player:get_wielded_item() + local data = stack:get_meta():to_table().fields + --local inv = player:get_inventory() + + local info = {} + local file = data.file + + + info = read_table_from_file(file) + info.title = fields.title + info.text = fields.text + save_table_to_file(file,info) + + + data.title = fields.title + data.text = fields.text + + + + data.description = fields.title + stack:get_meta():from_table({ fields = data}) + + + + + player:set_wielded_item(stack) + + end +end) + + +function rotate_direction_right(direction) + local d = {x=0,y=0,z=0} + if direction.z == 1 then + d.x = 1 + end + if direction.x == 1 then + d.z = -1 + end + if direction.z == -1 then + d.x = -1 + end + if direction.x == -1 then + d.z = 1 + end + return d +end + +function rotate_direction_left(direction) + return rotate_direction_right(rotate_direction_right(rotate_direction_right(direction))) +end + +function make_pos2(pos1,direction,sx,sy,sz) + + local right = rotate_direction_right(direction) + + local hv = vector.multiply(direction,sz-1) + local vv = vector.multiply(right,sx-1) + local uv = vector.multiply({x=0,y=1,z=0},sy-1) + local shift = vector.add(hv, vector.add(vv,uv)) + + local pos2 = vector.add(pos1, shift) + + return pos2 +end + +function get_all_corners_flat(sel) + local pos = {} + pos[1] = sel.pos1 + pos[2] = sel.pos2 + + local xmax = math.max(pos[1].x, pos[2].x) + local xmin = math.min(pos[1].x, pos[2].x) + + local ymax = math.max(pos[1].y, pos[2].y) + local ymin = math.min(pos[1].y, pos[2].y) + + local zmax = math.max(pos[1].z, pos[2].z) + local zmin = math.min(pos[1].z, pos[2].z) + + local pos00 = vector.new(xmin,ymin,zmin) + local pos11 = vector.new(xmax,ymin,zmax) + local pos10 = vector.new(xmax,ymin,zmin) + local pos01 = vector.new(xmin,ymin,zmax) + return {pos00=pos00,pos01=pos01,pos10=pos10,pos11=pos11} +end + + + +function get_corner00(sel,direction) + local crs = get_all_corners_flat(sel) + + + + if direction.z == 1 then + return crs.pos00 + end + if direction.x == 1 then + return crs.pos01 + end + if direction.z == -1 then + return crs.pos11 + end + if direction.x == -1 then + return crs.pos10 + end + + +end + +function add_vectors(a,b,c) + return vector.add(a,vector.add(b,c)) +end + + + + +function direction_to_number(direction) + if direction.z == 1 then return 0 end + if direction.x == 1 then return 1 end + if direction.z == -1 then return 2 end + if direction.x == - 1 then return 3 end +end + +function number_to_direction(nr) + if nr == 0 then return {x=0,y=0,z=1} end + if nr == 1 then return {x=1,y=0,z=0} end + if nr == 2 then return {x=0,y=0,z=-1} end + if nr == 3 then return {x=-1,y=0,z=0} end +end + + + + +function diff_directions(d1,d2) + local p1 = direction_to_number(d1) + local p2 = direction_to_number(d2) + + return number_to_direction( (p2-p1+4)%4 ) +end + +function flip(v) + if v == nil then return nil end + return vector.multiply(v,-1) +end + + +function paste_circuit_from_table(sel,circ,direction) + if sel.pos1 == nil then return end + if sel.pos2 == nil then return end + + + local nodes = circ.nodes + local metas = circ.metas + + local sx = nodes.sx + local sy = nodes.sy + local sz = nodes.sz + + local right = rotate_direction_right(direction) + + local start_pos = get_corner00(sel,direction) + + for xi=1,sx do + for zi=1,sz do + for yi=1,sy do + local shift= add_vectors( + vector.multiply(right,xi-1), + vector.multiply(direction,zi-1), + vector.multiply({x=0,y=1,z=0},yi-1)) + + local pos = vector.add(start_pos, shift) + + if is_in_selection(sel,pos) then + + local node = m3_get(nodes,xi,yi,zi) if node ~= nil then + local meta = m3_get(metas,xi,yi,zi) + node = rotate_node(node,{x=0,y=0,z=1},direction) + --minetest.set_node(pos, node) + --mesecons_autotools.set_node(pos,node,"paste_circuit") + minetest.set_node(pos,node) + minetest.get_meta(pos):from_table(meta) + end + + end + + end + + end + end + +end + +function paste_circuit(sel,file,direction) + if sel.pos1 == nil then return end + if sel.pos2 == nil then return end + + local circ = read_table_from_file(file) + paste_circuit_from_table(sel,circ,direction) + +end + +--[[ +function paste_circuit(sel,file,direction) + if sel.pos1 == nil then return end + if sel.pos2 == nil then return end + + local info = read_table_from_file(file) + + --local rotate_direction = diff_directions(direction) + --local nodes = rotate_m3(info.nodes,direction) + local nodes = info.nodes + local metas = info.metas + + local sx = nodes.sx + local sy = nodes.sy + local sz = nodes.sz + + local right = rotate_direction_right(direction) + + local start_pos = get_corner00(sel,direction) + + for xi=1,sx do + for zi=1,sz do + for yi=1,sy do + local shift= add_vectors( + vector.multiply(right,xi-1), + vector.multiply(direction,zi-1), + vector.multiply({x=0,y=1,z=0},yi-1)) + + local pos = vector.add(start_pos, shift) + + if is_in_selection(sel,pos) then + + local node = m3_get(nodes,xi,yi,zi) + local meta = m3_get(metas,xi,yi,zi) + node = rotate_node(node,{x=0,y=0,z=1},direction) + --minetest.set_node(pos, node) + --mesecons_autotools.set_node(pos,node,"paste_circuit") + minetest.set_node(pos,node) + minetest.get_meta(pos):from_table(meta) + end + + end + + end + end +end + ]]-- + + +local function make_selection(user,file,direction,pos) + local info = read_table_from_file(file) + --local rotate_direction = diff_directions(info.direction,direction) + local rotate_direction= info.direction + + local nodes = info.nodes + local sx = nodes.sx + local sy = nodes.sy + local sz = nodes.sz + + + local pos2 = make_pos2(pos,direction,sx,sy,sz) + + -- Update + mesecons_autotools.set_pos(user,1,pos) + mesecons_autotools.set_pos(user,2,pos2) + mesecons_autotools.render(user) + mesecons_autotools.zero_stack_counter(user) + mesecons_autotools.zero_stack_direction(user) +end + +local function on_place_full_circuit(itemstack, player, pointed_thing) + local user = player:get_player_name() + local rad = player:get_look_horizontal() + local direction = radians_to_direction_looking_forward(rad) + local fields = itemstack:get_meta():to_table().fields + local file = fields.file + + if not mesecons_autotools.is_full_selection(user) then return nil end + local pos1 = mesecons_autotools.get_pos(user,1) + local pos2 = mesecons_autotools.get_pos(user,2) + local sel = {pos1=pos1,pos2=pos2} + paste_circuit(sel,file,direction) + +end + + +local function on_use_new_circuit(itemstack, player, pointed_thing) + local user = player:get_player_name() + local rad = player:get_look_horizontal() + local direction = radians_to_direction_looking_forward(rad) + + if not mesecons_autotools.is_full_selection(user) then + -- show dialog with info or chat info + return + end + show_dialog_new(user,direction) + + return nil +end + +local function on_use_full_circuit(itemstack, player, pointed_thing) + local user = player:get_player_name() + local rad = player:get_look_horizontal() + local direction = radians_to_direction_looking_forward(rad) + local fields = itemstack:get_meta():to_table().fields + local file = fields.file + + + if( pointed_thing.type == "node" ) then + make_selection(user,file,direction,pointed_thing.above) + else + show_dialog_full(user,file,player) + end + + return nil +end + +local function none(itemstack, player, pointed_thing) + return nil +end + + + +--minetest.register_craftitem("mesecons_autotools:circuit_empty", { +minetest.register_tool("mesecons_autotools:circuit_empty", { + description = "Circuit Empty", + inventory_image = "circuit_empty.png", + stack_max = 1, + + on_use = on_use_new_circuit, + on_place = none, + on_secondary_use = none, + + }) + +--minetest.register_craftitem("mesecons_autotools:circuit_full", { +minetest.register_tool("mesecons_autotools:circuit_full", { + description = "Circuit saved", + inventory_image = "circuit_full.png", + groups = {not_in_creative_inventory = 1}, + stack_max = 1, + on_use = on_use_full_circuit, + on_place = on_place_full_circuit, + --on_secondary_use = on_place_full_circuit, + + + }) diff --git a/mods/mesecons_x/mesecons_autotools/book/file.lua b/mods/mesecons_x/mesecons_autotools/book/file.lua new file mode 100644 index 00000000..d19d0846 --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/book/file.lua @@ -0,0 +1,64 @@ +mesecons_autotools.rand = PcgRandom(2); + + +function generate_file_name(user) + local days = minetest.get_day_count() + local sec = minetest.get_gametime() + local rand = math.abs(mesecons_autotools.rand:next()) + local file = "circuit-"..user.."-"..sec.."-" .. rand + return file +end + +function generate_file_name_fsm(user) + local days = minetest.get_day_count() + local sec = minetest.get_gametime() + local rand = math.abs(mesecons_autotools.rand:next()) + local file = "fsm-"..user.."-"..sec.."-" .. rand + return file +end + + +function generate_file_name_library(user) + local days = minetest.get_day_count() + local sec = minetest.get_gametime() + local rand = math.abs(mesecons_autotools.rand:next()) + local file = "library-"..user.."-"..sec.."-" .. rand + return file +end + +local path = minetest.get_worldpath() .. "/circuits/" + +function save_table_to_file(filename,tab) + minetest.mkdir(path) + local file, err = io.open(path .. filename, "wb") + if err ~= nil then + -- player_notify(name, "Could not save file to \"" .. filename .. "\"") + print ("mesecons_autotools: ERROR: file save error") + return + end + local result = minetest.serialize(tab) + + file:write(result) + file:flush() + file:close() +end + + +function read_table_from_file(filename) + minetest.mkdir(path) + local file, err = io.open(path .. filename, "rb") + if err ~= nil then + -- notify + print ("mesecons_autotools: ERROR: file read error") + return nil + end + + local value = file:read("*a") + file:close() + + local tab = minetest.deserialize(value) + return tab +end + + + diff --git a/mods/mesecons_x/mesecons_autotools/book/formspec.lua b/mods/mesecons_x/mesecons_autotools/book/formspec.lua new file mode 100644 index 00000000..64e0df17 --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/book/formspec.lua @@ -0,0 +1,88 @@ +local esc = minetest.formspec_escape + +function fs_all(db) + local info = fs_info(db.title,db.text,db) + local stats = fs_stats(db.nodes, db.direction) + local circuit = fs_circuit(db.view) + + local spec = info .. stats .. circuit + return spec +end + + + +function fs_info(title,text) + local formspec = + "formspec_version[3]".. + "size[32,25]".. + "field[0.5,1;8,1;title;".."Name"..";"..esc(title).."]".. + "label[15,0.7;Circuit Preview]".. + "textarea[0.5,3;8,15;text;" .. "Description:" .. ";" .. + esc(text) .. "]" .. + "button_exit[2.5,18;3,1;save;" .. "Save" .. "]" + + return formspec +end + + +function fs_circuit(mx_view) + local W = 20 + local H = 20 + local startx = 10 + local starty = 2 + + local imagew = W/(mx_view.w) + local imageh = H/(mx_view.h) + + if imageh > 1 then imageh = 1 end + if imagew > 1 then imagew = 1 end + + local minsize = math.min(imageh,imagew) + imageh = minsize + imagew = minsize + + local epsilon = 0.07 + + + local spec = "" + for ix=1,mx_view.w do + for iy=1,mx_view.h do + local n = mx_get(mx_view,ix,iy) + if n == nil then n = {name="air",param2=0} end + local img = node_to_image( n ) + + + spec = spec .. "image[".. + startx+ix*imagew .. "," .. + starty+(mx_view.h-iy+1)*imageh .. ";" .. + imagew +epsilon .. "," .. + imageh +epsilon .. ";" .. + img .. "]" + + end + end + + return spec + +end + +function fs_stats(nodes,direction) + local block, gate, wire = get_stats(nodes) + + + + + local sx = nodes.sx + local sy = nodes.sy + local sz = nodes.sz + + local stats = "size : " .. sx .. "x"..sy .. "x"..sz .. "(=".. sx*sy*sz .. ")\n" .. + "wires : " .. wire .. "\n" .. + "gates : " .. gate .. "\n" .. + "others : ".. block - wire - gate .. "\n" .. + "blocks: " .. block + local spec = "textarea[0.5,19;8,5;;;" .. esc(stats) .. "]" + return spec +end + + diff --git a/mods/mesecons_x/mesecons_autotools/book/image.lua b/mods/mesecons_x/mesecons_autotools/book/image.lua new file mode 100644 index 00000000..bded8759 --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/book/image.lua @@ -0,0 +1,125 @@ + + +function node_to_image(node) + if node == nil then + return "empty.png" + end + + local name = node.name + local param2 = node.param2 or 0 + + + if( name == "air" ) then + return "empty.png" + end + + + if (name == "mesecons_insulated:insulated_off") or + (name == "mesecons_insulated:insulated_on" ) then + if( param2 % 2 == 0 ) then + return "wireh.png" + else + return "wirev.png" + end + end + + if (name == "mesecons_extrawires:crossover_off") or + (name == "mesecons_extrawires:crossover_on") or + (name == "mesecons_extrawires:crossover_01") or + (name == "mesecons_extrawires:crossover_10" ) then + return "corssover.png" + end + + if (name == "mesecons_extrawires:corner_off" ) or + (name == "mesecons_extrawires:corner_on" ) then + + return "corner"..param2 .. ".png" + end + + if (name == "mesecons_extrawires:tjunction_off" ) or + (name == "mesecons_extrawires:tjunction_on" ) then + + return "tjunction"..param2 .. ".png" + end + + if ( name == "mesecons_morewires:xjunction_off" ) or + ( name == "mesecons_morewires:xjunction_on" ) then + return "xjunction.png" + end + + + if( name == "mesecons_regs:flipflop_off" ) or ( name == "mesecons_regs:flipflop_on") then + return "ff"..param2..".png" + end + if( name == "mesecons_regs:latch_off" ) or ( name == "mesecons_regs:latch_on") then + return "latch"..param2..".png" + end + + + if( name == "mesecons_gates:and_off" ) or ( name =="mesecons_gates:and_on" )then + return "and".. param2 .. ".png" + end + if( name == "mesecons_gates:nand_off" ) or ( name =="mesecons_gates:nand_on" )then + return "nand".. param2 .. ".png" + end + + if( name == "mesecons_gates:nor_off" ) or ( name =="mesecons_gates:nor_on" )then + return "nor".. param2 .. ".png" + end + if( name == "mesecons_gates:or_off" ) or ( name =="mesecons_gates:or_on" )then + return "or".. param2 .. ".png" + end + if( name == "mesecons_gates:xor_off" ) or ( name =="mesecons_gates:xor_on" )then + return "xor".. param2 .. ".png" + end + + + if( name == "mesecons_gates:diode_off" ) or ( name =="mesecons_gates:diode_on" )then + return "diode".. param2 .. ".png" + end + + if( name == "mesecons_gates:not_off" ) or ( name =="mesecons_gates:not_on" )then + return "not".. param2 .. ".png" + end + + if( name == "mesecons_switch:mesecon_switch_off" ) or ( name =="mesecons_switch:mesecon_switch_on" )then + return "mesecons_switch_off.png" + end + + if ( name == "mesecons_lightstone:lightstone_white_off" ) or ( name == "mesecons_lightstone:lightstone_white_on" ) then + return "jeija_lightstone_white_on.png" + end + + if (name == "mesecons_walllever:wall_lever_off" ) or (name == "mesecons_walllever:wall_lever_on" ) then + + return "jeija_wall_lever_inv.png" + end + + if (name == "default:mese" ) or (name == "mesecons_extrawires:mese_powered" )then + return "default_mese_block.png" + end + + if (name == "mesecons_powerplant:power_plant") then + return "jeija_power_plant.png" + end + + + if (name == "mesecons_gates3:and3_off") or (name == "mesecons_gates3:and3_on" ) then + return "jeija_gate3_and3r"..param2..".png" + end + + + if (name == "mesecons_gates3:nand3_off") or (name == "mesecons_gates3:nand3_on" ) then + return "jeija_gate3_nand3r"..param2..".png" + end + + if (name == "mesecons_gates3:or3_off") or (name == "mesecons_gates3:or3_on" ) then + return "jeija_gate3_or3r"..param2..".png" + end + + if (name == "mesecons_gates3:nor3_off") or (name == "mesecons_gates3:nor3_on" ) then + return "jeija_gate3_nor3r"..param2..".png" + end + + return "unknown.png" +end diff --git a/mods/mesecons_x/mesecons_autotools/book/library.lua b/mods/mesecons_x/mesecons_autotools/book/library.lua new file mode 100644 index 00000000..268571d6 --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/book/library.lua @@ -0,0 +1,255 @@ + + + +function render_circuit(circ,start_x,start_y) + circ.title = circ.title or "" +-- local spec = "button["..start_x..","..start_y..";10,1;".. "title_" .. circ.id .. ";"..circ.title.."]" + local spec = "image_button["..start_x+1 ..","..start_y..";1,1;circuit_full.png;;;;]" + + spec = spec .. "label[" .. start_x+2 .. "," .. start_y+0.5 .. ";" .. circ.title .. "]" + spec = spec .. "image_button[".. start_x ..","..start_y..";1,1;drop_btn.png;;;;]" + + return spec,1 +end + + +function f_fold(id,x,y,folded) + local fold_sign + if folded == true then + fold_sign = "+" + else + fold_sign = "-" + end + + local spec = "button["..x..","..y..";1,1;".. "fold_" .. id ..";".. fold_sign.."]" + + return spec, 1, 0 +end + + +function render_lib(lib,start_x,start_y) + local xshift = 1 + local yshift = 1 + local total_yshift = 0 + local total_xshift = 0 + local id = lib.id + + lib.title = lib.title or "" + lib.folded = lib.folded or false + + + local spec = "" + + -- fold button + local ss,shx,shy = f_fold(id,start_x+total_xshift, start_y+total_yshift, lib.folded) + total_xshift = total_xshift+shx + total_yshift = total_yshift+shy + spec = spec .. ss + + + spec = spec .. + "button[".. start_x + total_xshift ..",".. start_y + total_yshift.. + ";10,1;".. "title_"..lib.id .. ";"..lib.title.."]" + total_xshift = start_x + 1 + total_yshift = total_yshift+1 + + + + + if lib.folded == false then + for _,v in ipairs(lib.list) do + if v.type == "library" then + local sp, ys = render_lib(v, start_x+total_xshift, start_y+total_yshift) + spec = spec .. sp + total_yshift = total_yshift + ys + elseif v.type == "circuit" then + local sp, ys = render_circuit(v,start_x+total_xshift, start_y+total_yshift) + spec = spec .. sp + total_yshift = total_yshift + ys + end + + end + end + + return spec, total_yshift + +end + +function traverse_list(list,action) + if list == nil then return end + + for _,v in ipairs(list) do + if v.type == "circuit" then + action(v) + elseif v.type == "library" then + action(v) + traverse_list(v.list,action) + end + + end + + +end + +function foreach_id(list,action) + if list == nil then return end + traverse_list(list, function(elem) + action(elem.id) + end) +end + +function get_elem_by_id(list,id) + local found + traverse_list(list,function(e) + if e.id == id then + found = e + end + + end) + return found +end + + + + + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname ~= "mesecons_autotools:library_view" then return end + local user = player:get_player_name() +-- local stack = player:get_wielded_item() +-- local data = stack:get_meta():to_table().fields +-- local lib = data.lib + + +-- print("lib="..dump(lib)) +-- print("fields="..dump(fields)) + + +-- if fields.quit then return end + + + +--[[ + lib = lib or { id = "", list = {}, title = "empty" , type = "library" } + traverse_list(lib.list,function(elem) + print("#") + if fields["fold_".. elem.id] == true then + elem.folded = not elem.folded + end + end) + + data.lib = lib + stack:get_meta():from_table({ fields = data}) + player:set_wielded_item(stack) + + local formspec = render_formspec(lib) + minetest.show_formspec(user, "mesecons_autotools:library_view", formspec) + ]]-- +end) + +function render_formspec(lib) + local formspec = "formspec_version[3]".. + "size[32,25]" + + formspec = formspec .. render_lib(lib,1,1) + return formspec +end + + + lib = { + id = "l1", title = "library bla bla ", type = "library", + list = { + {id = "c1", type="circuit", title="somethign something"}, + {id = "c2", type="circuit", title="somethign something2"}, + {id = "l2", type="library", title="wooihoihoh/", folded = false, + list = { + {id = "c11", type="circuit", title="somethign something"}, + {id = "c21", type="circuit", title="somethign something2"}, + } + + }, + {id = "c111", type="circuit", title="circuit sak/32/d0"}, + {id = "c1x", type="circuit", title="somethign something"}, + {id = "c2x", type="circuit", title="somethign something2"}, + {id = "l2x", type="library", title="wooihoihoh/", folded = false, + list = { + {id = "c11x", type="circuit", title="somethign something"}, + {id = "c21x", type="circuit", title="somethign something2"}, + } + + }, + {id = "c111x", type="circuit", title="circuit sak/32/d0"}, + {id = "c111x", type="circuit", title="circuit sak/32/d0"}, + {id = "c111x", type="circuit", title="circuit sak/32/d0"}, + {id = "c111x", type="circuit", title="circuit sak/32/d0"}, + {id = "c111x", type="circuit", title="circuit sak/32/d0"}, + {id = "c111x", type="circuit", title="circuit sak/32/d0"}, + {id = "c111x", type="circuit", title="circuit sak/32/d0"}, + {id = "c111x", type="circuit", title="circuit sak/32/d0"}, + {id = "c111x", type="circuit", title="circuit sak/32/d0"}, + {id = "c111x", type="circuit", title="circuit sak/32/d0"}, + {id = "c111x", type="circuit", title="circuit sak/32/d0"}, + {id = "c111x", type="circuit", title="circuit sak/32/d0"}, + {id = "c111x", type="circuit", title="circuit sak/32/d0"}, + {id = "c111x", type="circuit", title="circuit sak/32/d0"}, + {id = "c111x", type="circuit", title="circuit sak/32/d0"}, + {id = "c111x", type="circuit", title="ostatni ak/32/d0"}, + + + } + } + +function generate_empty_library(file) + local lib = { + id = file, list = {} , title = "" , type = "library" , folded = false + } + return lib +end + +function on_place_library(itemstack, player, pointed_thing) + local user = player:get_player_name() + local stack = player:get_wielded_item() + local fields = stack:get_meta():to_table().fields + + +-- print("DU:"..dump(itemstack:get_meta():to_table())) +-- print("item stackc:" .. dump(itemstack)) + +-- if data.count == nil then data.count = 0 end +-- data.count = data.count + 1 +--[[ local lib = {} + if fields.file == nil then + fields.file = generate_file_name_library(user) + lib = generate_empty_library(fields.file) + save_table_to_file(fields.file,lib) + end + ]]-- + stack:get_meta():from_table({ fields = fields}) +-- player:set_wielded_item(stack) + + --lib = lib + local formspec = render_formspec(lib) +-- print("formtspec="..formspec) + + + minetest.show_formspec(user, "mesecons_autotools:library_view", formspec) + +end + + + +minetest.register_tool("mesecons_autotools:library", { + description = "Library of Circuits", + inventory_image = "library.png", + stack_max = 1, + + + -- on_place = on_place_library, + on_use = on_place_library, +--[[ + on_use = on_use_new_circuit, + + on_secondary_use = none, + ]]-- + }) + \ No newline at end of file diff --git a/mods/mesecons_x/mesecons_autotools/book/m3.lua b/mods/mesecons_x/mesecons_autotools/book/m3.lua new file mode 100644 index 00000000..28c52a2a --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/book/m3.lua @@ -0,0 +1,306 @@ + + +function m3_get(m,x,y,z) + if m == nil then return nil end + if m[x] == nil then return nil end + if m[x][y] == nil then return nil end + if m[x][y][z] == nil then return nil end + return m[x][y][z] +end + +function m3_set(m,x,y,z,value) + if m == nil then m = {} end + if m[x] == nil then m[x] = {} end + if m[x][y] == nil then m[x][y] = {} end + if m[x][y][z] == nil then m[x][y][z] = {} end + m[x][y][z] = value +end +--[[ +function m3_set_pos(m,pos1,pos2) + m.pos1 = pos1 + m.pos2 = pos2 +end +]]-- + +function m3_flip_xy(m) + local new_m = {} + for ix=1,m.sx do + for iz=1,m.sz do + for iy=1,m.sy do + m3_set(new_m,iz,iy,ix, m3_get(m,ix,iy,iz)) + end + end + end + --[[ + -- Rotate node + for ix=1,m.sx do + for iz=1,m.sz do + for iy=1,m.sy do + local node = m3_get(m,ix,iy,iz) + + local rotated_node = + rotate_node_to_direction(node,{x=1,y=0,z=0}) + m3_set(m,ix,iy,iz,rotated_node) + end + end + end + ]]-- + new_m.sx = m.sz + new_m.sz = m.sx + new_m.sy = m.sy + return new_m +end + +function m3_flip_x(m) + local new_m = {} + for ix=1,m.sx do + for iz=1,m.sz do + for iy=1,m.sy do + m3_set(new_m,ix,iy,m.sz-iz+1, m3_get(m,ix,iy,iz)) + end + end + end + + --[[ + for ix=1,m.sx do + for iz=1,m.sz do + for iy=1,m.sy do + local node = m3_get(m,ix,iy,iz) + + local rotated_node = + rotate_node_to_direction(node,{x=0,y=0,z=-1}) + m3_set(m,ix,iy,iz,rotated_node) + end + end + end + +]]-- + new_m.sx = m.sx + new_m.sz = m.sz + new_m.sy = m.sy + return new_m +end + + +function m3_rotate90(m) + return m3_flip_x( m3_flip_xy (m)) +end + +function m3_rotate180(m) + return m3_rotate90(m3_rotate90(m)) +end + +function m3_rotate270(m) + return m3_rotate90(m3_rotate90(m3_rotate90(m))) +end + +function rotate_m3(m,direction) + + if direction.x == 1 then + return m3_rotate270(m) + end + if direction.x == -1 then + return m3_rotate90(m) + end + if direction.z == 1 then + return m + end + if direction.z == -1 then + return m3_rotate180(m) + end + return m +end + + + +function m3_move_to_000(m) + local new_m = {} + + local pos1 = m.pos1 + local pos2 = m.pos2 + + local xmin = math.min(pos1.x,pos2.x) + local ymin = math.min(pos1.y,pos2.y) + local zmin = math.min(pos1.z,pos2.z) + + local xmax = math.max(pos1.x,pos2.x) + local ymax = math.max(pos1.y,pos2.y) + local zmax = math.max(pos1.z,pos2.z) + + + + local sx = xmax - xmin + 1 + local sy = ymax - ymin + 1 + local sz = zmax - zmin + 1 + + for x=1,sx,1 do + for y=1,sy,1 do + for z=1,sz,1 do + m3_set(new_m,x,y,z, + m3_get(m, x-1 + xmin, y-1 + ymin, z-1+zmin)) + end + end + end + + new_m.sx = sx + new_m.sy = sy + new_m.sz = sz + return new_m +end + + + + + +function selection_to_m3(pos1,pos2,direction) + local m = {} + iterate_selection(pos1,pos2,function(pos) + local node = minetest.get_node(pos) + m3_set(m,pos.x,pos.y,pos.z,node) + end) + m.pos1 = pos1 + m.pos2 = pos2 + + m = m3_move_to_000(m) + + m = rotate_m3(m,direction) + + for ix=1,m.sx do + for iz=1,m.sz do + for iy=m.sy,1,-1 do + local node = m3_get(m,ix,iy,iz) + local rotated_node = rotate_node_to_direction(node,direction) + m3_set(m,ix,iy,iz,rotated_node) + end + end + end + + + + return m +end + +function selection_to_m3_meta(pos1,pos2,direction) + local m = {} + iterate_selection(pos1,pos2,function(pos) + local meta = minetest.get_meta(pos):to_table() + m3_set(m,pos.x,pos.y,pos.z,meta) + end) + m.pos1 = pos1 + m.pos2 = pos2 + + m = m3_move_to_000(m) + + m = rotate_m3(m,direction) + return m +end + + + +function m3_to_mx(m) + local mx={} + for ix=1,m.sx do + for iz=1,m.sz do + for iy=m.sy,1,-1 do + local pos = { x = ix, y=iy, z = iz } + local node = m3_get(m,ix,iy,iz) + + if node.name ~= "air" then + mx_set(mx,ix,iz,node) + break + end + + end + end + end + mx.w = m.sx + mx.h = m.sz + return mx +end + + +local function lmin(a,b) + if a == nil then + return b + else + if b == nil then + return a + else + return math.min(a,b) + end + end +end +local function lmax(a,b) + if a == nil then + return b + else + if b == nil then + return a + else + return math.max(a,b) + end + end +end + +function list_to_m3(list) + local m = {} + + local xmin,xmax,ymin,ymax,zmin,zmax + + for _,v in pairs(list) do + local pos = v.pos + local node = v.node + + m3_set(m,pos.x,pos.y,pos.z, node) + + xmin = lmin(xmin, pos.x) + ymin = lmin(ymin, pos.y) + zmin = lmin(zmin, pos.z) + + xmax = lmax(xmax, pos.x) + ymax = lmax(ymax, pos.y) + zmax = lmax(zmax, pos.z) + + + end + + m.pos1 = {x=xmin,y=ymin,z=zmin} + m.pos2 = {x=xmax,y=ymax,z=zmax} + return m +end + + +function iterate_m3(m,action) + for x=1,m.sx do + for y=1,m.sy do + for z=1,m.sz do + action(m3_get(m,x,y,z)) + end + end + end +end + + +function m3_insert(mbase, melement, x,y,z) + local sx = melement.sx + local sy = melement.sy + local sz = melement.sz + + for xi=1,sx do + for yi=1,sy do + for zi=1,sz do + if m3_get(melement,xi,yi,zi) ~= nil then + m3_set(mbase,x+xi-1,y+yi-1,z+zi-1, m3_get(melement,xi,yi,zi)) + end + end + end + end + mbase.sx = math.max(mbase.sx, x+sx-1) + mbase.sy = math.max(mbase.sy, y+sy-1) + mbase.sz = math.max(mbase.sz, z+sz-1) +end + + + + + diff --git a/mods/mesecons_x/mesecons_autotools/book/misc.lua b/mods/mesecons_x/mesecons_autotools/book/misc.lua new file mode 100644 index 00000000..31df79a1 --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/book/misc.lua @@ -0,0 +1,81 @@ + +local n01 = "mesecons_extrawires:crossover_01" +local n10 = "mesecons_extrawires:crossover_10" + +-- axuliary function +function switch (name) + if( name == n01 ) then + return n10 + else + return n01 + end +end + +function rotate_node_to_direction(node,direction) + local add = 0 + if direction.x == 1 then add = 3 end + if direction.x == -1 then add = 1 end + if direction.z == 1 then add = 0 end + if direction.z == -1 then add = 2 end + + local param2 = node.param2 + + param2 = (param2+add)% 4 + + -- special treatement for crossover wire + if( node.name == n01 or node.name == n10 ) then + if( add % 2 == 0 ) then + return { name = node.name, param2=param2} + else + return { name = switch(node.name), param2=param2} + end + end + + + return { name = node.name , param2 = param2 } +end + +local function direction_to_number(direction) + if( direction.z == 1 ) then + return 1 + elseif( direction.x == 1 ) then + return 2 + elseif(direction.z == -1 )then + return 3 + else + return 4 + end + +end + + + +function rotate_node(node, saved_direction,direction) + if node == nil then return nil end + local values = + { + {0,1,2,3}, + {3,0,1,2}, + {2,3,0,1}, + {1,2,3,0} + } + + local rotate = + values[direction_to_number(saved_direction)][direction_to_number(direction)] + + local new_node = {} + new_node.name = node.name + new_node.param2 = (node.param2+rotate)%4 + + -- an exception, special treatement of crossover wire + if( node.name == n01 or node.name == n10 ) then + + if( rotate % 2 == 0 ) then + new_node = node + else + new_node = {name = switch(node.name), param2=node.param2} + end + end + + return new_node +end diff --git a/mods/mesecons_x/mesecons_autotools/book/mx.lua b/mods/mesecons_x/mesecons_autotools/book/mx.lua new file mode 100644 index 00000000..876d6e9a --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/book/mx.lua @@ -0,0 +1,109 @@ + + +function mx_get(m,x,y) + if m == nil then return nil end + if m[x] == nil then return nil end + if m[x][y] == nil then return nil end + return m[x][y] +end + +function mx_set(m,x,y,value) + if m == nil then m = {} end + if m[x] == nil then m[x] = {} end + if m[x][y] == nil then m[x][y] = {} end + m[x][y] = value +end + +function mx_flip_xy(m) + local new_m = {} + for i=1,m.w do + for k=1,m.h do + mx_set(new_m,k,i, mx_get(m,i,k)) + end + end + new_m.h = m.w + new_m.w = m.h + return new_m +end + +function mx_flip_y(m) + local new_m = {} + for i=1,m.w do + for k=1,m.h do + mx_set(new_m,m.w+1-i,k, mx_get(m,i,k)) + end + end + new_m.h = m.h + new_m.w = m.w + return new_m +end + +function mx_flip_x(m) + local new_m = {} + for i=1,m.w do + for k=1,m.h do + mx_set(new_m,i,m.h+1-k, mx_get(m,i,k)) + end + end + new_m.h = m.h + new_m.w = m.w + return new_m +end + + +function mx_rotate90(m) + return mx_flip_x( mx_flip_xy (m)) +end + +function mx_rotate180(m) + return mx_rotate90(mx_rotate90(m)) +end + +function mx_rotate270(m) + return mx_rotate90(mx_rotate90(mx_rotate90(m))) +end + +function rotate_mx(mx,direction) + + if direction.x == 1 then + return mx_rotate270(mx) + end + if direction.x == -1 then + return mx_rotate90(mx) + end + if direction.z == 1 then + return mx + end + if direction.z == -1 then + return mx_rotate180(mx) + end + return mx +end + + + +function move_mx_to_00(mx) + local new_mx = {} + + local xmax = mx.xmax + local xmin = mx.xmin + + local ymax = mx.ymax + local ymin = mx.ymin + + + local sx = xmax - xmin + 1 + local sy = ymax - ymin + 1 + + for x=1,sx,1 do + for y=1,sy,1 do + mx_set(new_mx,x,y, mx_get(mx, x-1 + xmin, y-1 + ymin)) + end + end + + new_mx.w = sx + new_mx.h = sy + return new_mx + +end + diff --git a/mods/mesecons_x/mesecons_autotools/book/stats.lua b/mods/mesecons_x/mesecons_autotools/book/stats.lua new file mode 100644 index 00000000..51f95d83 --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/book/stats.lua @@ -0,0 +1,74 @@ +function is_gate(node) + if node == nil then return false end + local gates = { + "mesecons_gates:and", + "mesecons_gates:or", + "mesecons_gates:xor", + "mesecons_gates:nand", + "mesecons_gates:nor", + "mesecons_gates:not", + "mesecons_gates:diode", + "mesecons_gates3:and3", + "mesecons_gates3:or3", + "mesecons_gates3:nor3", + "mesecons_gates3:nand3", + "mesecons_regs:flipflop", + "mesecons_regs:latch" + } + + local gates_with_states = {} + for _,v in ipairs(gates) do + table.insert(gates_with_states,v.."_on") + table.insert(gates_with_states,v.."_off") + end + + for _,v in ipairs(gates_with_states) do + if node.name == v then + return true + end + end + return false +end + +function is_wire_node(node) + local list = { + "mesecons_insulated:insulated_off", "mesecons_insulated:insulated_on", + "mesecons_extrawires:corner_off", "mesecons_extrawires:corner_on", + "mesecons_extrawires:tjunction_off", "mesecons_extrawires:tjunction_on", + "mesecons_extrawires:crossover_off", "mesecons_extrawires:crossover_on", + "mesecons_extrawires:crossover_10", "mesecons_extrawires:crossover_01", + "mesecons_morewires:xjunction_off", "mesecons_morewires:xjunction_on", + } + + if node == nil then return false end + local pos_name = node.name + for i,name in ipairs(list) do + if name == pos_name then + return true + end + end + return false +end + + + + +function get_stats(m) + local blocks,gates,wires = 0,0,0 + iterate_m3(m, function(node) + if node == nil then return end + if is_wire_node(node) then + wires = wires + 1 + end + if is_gate(node) then + gates = gates+1 + end + if node.name ~= "air" then + blocks = blocks + 1 + end + + end) + + return blocks,gates,wires + +end diff --git a/mods/mesecons_x/mesecons_autotools/commands/all_commands.lua b/mods/mesecons_x/mesecons_autotools/commands/all_commands.lua new file mode 100644 index 00000000..e69de29b diff --git a/mods/mesecons_x/mesecons_autotools/debug.lua b/mods/mesecons_x/mesecons_autotools/debug.lua new file mode 100644 index 00000000..221f67c5 --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/debug.lua @@ -0,0 +1,16 @@ + +-- Debug + +function dump(o) + if type(o) == 'table' then + local s = '{ ' + for k,v in pairs(o) do + if type(k) ~= 'number' then k = '"'..k..'"' end + s = s .. '['..k..'] = ' .. dump(v) .. ',' + end + return s .. '} ' + else + return tostring(o) + end +end + diff --git a/mods/mesecons_x/mesecons_autotools/formula/README b/mods/mesecons_x/mesecons_autotools/formula/README new file mode 100644 index 00000000..00aac668 --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/formula/README @@ -0,0 +1 @@ +Formula tool (still in progress, not published in mod) diff --git a/mods/mesecons_x/mesecons_autotools/formula/formula.lua b/mods/mesecons_x/mesecons_autotools/formula/formula.lua new file mode 100644 index 00000000..06b4b0e5 --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/formula/formula.lua @@ -0,0 +1,33 @@ +local function on_use_formula_book(itemstack, player, pointed_thing) + local user = player:get_player_name() + local formspec = + "formspec_version[3]".. + "size[32,25]".. + "label[15,0.7;FSM generator]".. + + + "field[0.5,2;15,1;title;Name;]".. + "textarea[0.5,4;15,15;text;" .. "Code:" .. ";" .. "" .. "]" .. + "textarea[16.5,2;15,17;d;" .. "Compilation Logs:" .. ";" .. "" .. "]" .. + + + "button_exit[0.5,19;3,1;save;" .. "Save" .. "]" .. + "button_exit[14.5,20;3,1;compile;" .. "Compile" .. "]" .. + "button_exit[28.5,20;3,1;generate;" .. "Generate" .. "]" .. + "" + minetest.show_formspec(user, "mesecons_autotools:formula_show", formspec) +end + +--minetest.register_craftitem("mesecons_autotools:circuit_empty", { +minetest.register_tool("mesecons_autotools:formula", { + description = "Logic formula generator", + inventory_image = "formula_book.png", + stack_max = 1, + + on_use = on_use_formula_book, + + --[[ + on_place = none, + on_secondary_use = none, + --]] + }) diff --git a/mods/mesecons_x/mesecons_autotools/fsm/alg.lua b/mods/mesecons_x/mesecons_autotools/fsm/alg.lua new file mode 100644 index 00000000..654b7e52 --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/fsm/alg.lua @@ -0,0 +1,163 @@ +------------------------------------------------------------------------ +-- logic functions +------------------------------------------------------------------------ + + +function show(area) + local vars = area.vars + local s = "" + dump(area) + if #area.parts == 0 then + s = "(none)" + else + + for _,part in pairs(area.parts) do + for _,v in ipairs(vars) do + if ( part[v] == true ) then s = s .. " " .. v end + if part[v] == false then s = s .. " ~" .. v end + if part[v] == nil then s = s .. " x" end + end + s = s .. "\n" + end + return s + end +end + + +function area_add(a1,a2) + local a3 = area_copy(a1) + + for _,v in pairs(a2.parts) do + table.insert(a3.parts,v) + end + return a3 +end + + +function drop_negation_list(list) + local l = {} + for _,v in pairs(list) do + table.insert(l, drop_negation(v)) + end + return l +end + +function swap_truefalse(v) + if v == true then return false end + return true +end + + +function part_sub_part(a,b) + + local vars = {} + + for keya,_ in pairs(b) do + if (a[keya] == true and b[keya] == false ) or + ( a[keya] == false and b[keya] == true ) then + local ll = {} + table.insert(ll,a) + return ll + end + + if a[keya] == nil and b[keya] ~= nil then + vars[keya] = swap_truefalse(b[keya]) + end + end + + local parts = {} + for k,v in pairs(vars) do + local new = copy_list(a) + new[k] = v + table.insert(parts,new) + end + return parts +end + +function insert_parts_in_area(a,list) + local c = {} + c = area_copy(a) + for _,v in pairs(list) do + table.insert(c.parts, v) + end + return c +end + + +function area_sub_part(a,p) + local c = {} + c.vars = copy_list(a.vars) + c.parts = {} + + for _,part in pairs(a.parts) do + local l = part_sub_part(part,p) + c = insert_parts_in_area(c,l) + end + return c +end + +--[[ +function copy_list(l) + local nl = {} + for k,v in pairs(l) do + nl[k] = v + end + return nl +end +]]-- +function copy_list(l) + return DeepCopy(l) +end + + + +function area_copy(a) + return DeepCopy(a) +end + +--[[ +function area_copy(a) + local c = {} + c.vars = copy_list(a.vars) + c.parts = {} + for _,v in pairs(a.parts) do + table.insert(c.parts, copy_list(v)) + end + return c +end +]]-- + +function area_sub(a,b) + local c = {} + c = area_copy(a) + + for _,v in pairs(b.parts) do + c = area_sub_part(c,v) + end + return c +end + + + +--[[ +local a1 = { + vars={"a","b","c","d"}, + parts = { + { d = true} , + --{c = true } + } + } +local a2 = { + vars={"a","b","c","d"}, + parts = { { a=false, b =true,c = true} } + } + + ]]-- +--local a = area_sub(a1,a2) + + +--[[ +print(show(a1)) +print(show(a2)) +print(show(a)) +--]] \ No newline at end of file diff --git a/mods/mesecons_x/mesecons_autotools/fsm/compiler.lua b/mods/mesecons_x/mesecons_autotools/fsm/compiler.lua new file mode 100644 index 00000000..7a179d82 --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/fsm/compiler.lua @@ -0,0 +1,470 @@ + +dofile(minetest.get_modpath("mesecons_autotools").."/fsm/compiler_general.lua"); +dofile(minetest.get_modpath("mesecons_autotools").."/fsm/compiler_parsing.lua"); +dofile(minetest.get_modpath("mesecons_autotools").."/fsm/compiler_generating.lua"); +dofile(minetest.get_modpath("mesecons_autotools").."/fsm/compiler_checking.lua"); + +------------------------------------------------------------------------ +-- compilation functions +------------------------------------------------------------------------ + +function compile_init(inits) + if empty(inits) then return nil,"no init state" end + if #inits ~= 1 then return nil,"more than one init states" end + return inits[1] +end + +function compile_pin_assigns(pins_assigns) + local db = {} + for _,v in ipairs(pins_assigns) do + + -- check if already defined + if e(db,v.pin) then + return nil, "pin " .. v.pin .. " defined two times" + end + + -- check if self loop + if is_in_list(v.pins,drop_negation(v.pin)) then + return nil, "self reference in definition " .. v.pin + end + if is_in_list(v.pins,add_negation(v.pin)) then + return nil, "self reference in definition " .. v.pin + end + + -- expand pins + local pins_expanded = {} + for _,p in ipairs(v.pins) do + if is_pin_name_n(p) then + table.insert(pins_expanded,p) + elseif is_pin_group_name_n(p) then + local gr = drop_negation(p) + if e(db,gr) then + for _,pp in ipairs(db[gr]) do + if( is_negated(p) ) then + table.insert(pins_expanded,swap_negation(pp)) + else + table.insert(pins_expanded,pp) + end + end + else + return nil, "pin " .. p .. " no defined in " .. v.pin .. " definition" + end + end + end + db[v.pin] = remove_duplicates( pins_expanded ) + end + return db +end + + +function compile_state_assigns(state_assigns) + local db = {} + for _,v in ipairs(state_assigns) do + + -- check if already defined + if e(db,v.state) then + return nil, "state group " .. v.state .. " defined two times" + end + + -- check if self loop + if is_in_list(v.states,v.state) then + return nil, "self reference in definition " .. v.state + end + + -- expand pins + local states_expanded = {} + for _,p in ipairs(v.states) do + if is_state_name(p) then + table.insert(states_expanded,p) + elseif is_state_group_name(p) then + if e(db,p) then + for _,pp in ipairs(db[p]) do + table.insert(states_expanded,pp) + end + else + return nil, "state " .. p .. " no defined in definition " .. v.state + end + end + end + db[v.state] =remove_duplicates( states_expanded ) + end + + return db +end + +function expand_pin(pin,db) + if is_negated(pin) then + local pure = drop_negation(pin) + if db[pin] == nil then + local l = {} + table.insert(l,pin) + return l + else + local l = {} + for _,v in pairs(db[pure]) do + table.insert(l,swap_negation(v)) + end + return l + end + else + if db[pin] == nil then + local l = {} + table.insert(l,pin) + return l + else + return db[pin] + end + end +end + + + +function expand_pins(list, db) + local l = {} + for _,pin in ipairs(list) do + for _,p in ipairs( expand_pin(pin,db) ) do + table.insert(l,p) + end + end + return l +end + +function expand_state(s,db) + local l = {} + if db[s] == nil then + table.insert(l,s) + return l + else + return db[s] + end +end + +function expand_states(list, db) + local l = {} + for _,state in ipairs(list) do + for _,p in ipairs( expand_state( state, db) ) do + table.insert(l,p) + end + end + return l +end + + +function all_defined_states(db,list) + for _,v in pairs(list) do + if is_state_group_name(v) then + if not e(db, v) then + return false,v + end + end + end + return true +end + +function all_defined_pins(db,list) + for _,v in pairs(list) do + if is_pin_group_name(v) then + if not e(db, v) then + return false,v + end + end + end + return true +end + + +function compile_state_outputs(state_outputs, db_pins, db_states) + local db = {} + for _,v in ipairs(state_outputs) do + local states = v.states + local pins = v.pins + + + local df,err + -- expanding pins + local pins_exp = expand_pins(pins,db_pins) + df,err = all_defined_pins(db_pins,pins_exp) + if df == false then + return nil, "pin '" .. err .. "' not defined in line: " .. v.line + end + + + --expand states + local states_exp = expand_states(states, db_states) + df,err = all_defined_states(db_states,states_exp) + if df == false then + return nil, "state '" .. err .. "' not defined, error in line: " .. v.line + end + + + -- check if state already defined + for _,w in pairs(states_exp) do + if e(db,w) then + return nil, "state output '" .. w .. "' already defined, duplicate in line: " .. v.line + else + db[w] = pins_exp + end + end + end + return db +end + + +function compile_state_transitions(state_transitions, db_pins, db_states) + local db = {} + if state_transitions == nil then + return nil,"no transitions" + end + if #state_transitions == 0 then + return nil, "no transitions" + end + for _,v in pairs(state_transitions) do + local states = v.states + local pins = v.pins + local state = v.state + + --expand + local df,err + -- expanding pins + local pins_exp = expand_pins(pins,db_pins) + df,err = all_defined_pins(db_pins,pins_exp) + if df == false then + return nil, "pin " .. err .. " not defined, error in line: " .. v.line + end + + --expand states + local states_exp = expand_states(states, db_states) + df,err = all_defined_states(db_states,states_exp) + if df == false then + return nil, "state " .. err .. " not defined, error in line: " .. v.line + end + + -- building db + for _,w in ipairs(states_exp) do + if db[w] == nil then db[w] = {} end + table.insert(db[w], { pins = pins_exp, state = state } ) + end + end + + if count_hash(db) == 0 then + return nil,"coudn't find any transitions" + end + + return db +end + +function compile_state_values(state_values) + local db = {} + if state_values == nil then return db end + + for _,v in pairs(state_values) do + local state = v.state + local value = v.value + if db[state] ~= nil then + return nil, "duplicate state value definition, ".. state .. + " := " .. db[state] .. " and " .. state .. " := " .. v.value + else + db[state] = value + end + end + + -- checking if all values the same length + + local min = 0 + -- seting initial value of min (bigger than any of the elment) + for k,v in pairs(db) do + min = min + string.len(v) + end + + local max = 0 + local maxs,mins + for k,v in pairs(db) do + if string.len(v) < min then + min = string.len(v) + mins = k + end + if string.len(v) > max then + max = string.len(v) + maxs = k + end + end + + if (min ~= 0 and min ~= max) then + return nil, "values of states have different length, " .. mins .. " := " .. db[mins] .. + " and " .. maxs .. " := " .. db[maxs] + end + + -- checking if values are uniq + local vdb = {} + for k,v in pairs(db) do + if vdb[v] ~= nil then + return nil, "duplicate state value, " .. k .. " := " .. v .. " and " .. vdb[v] .. " := " .. v + else + vdb[v] = k + end + end + + return db +end + + + + + +function compile_in_pins(in_pins) + if #in_pins > 1 then return nil, "multiple input pins definitions" end + + local duplicate = get_duplicate(in_pins[1]) + if duplicate == nil then + return (in_pins[1] or {}) + else + return nil, "input pins duplicated: " .. duplicate + end +end + +function compile_out_pins(out_pins) + if #out_pins > 1 then return nil, "multiple output pins definitions" end + + local duplicate = get_duplicate(out_pins[1]) + if duplicate == nil then + return (out_pins[1] or {} ) + else + return nil, "output pins duplicated: " .. duplicate + end +end + + + + +function compile_code(code) + + local data = parse_code(code) + local db = {} + + + local init,erroi = compile_init(data.inits) + local bin_pins,errop = compile_pin_assigns(data.pin_assigns) + local bin_states,erros = compile_state_assigns(data.state_assigns) + local bin_outputs,erroo = compile_state_outputs(data.state_outputs, bin_pins,bin_states) + local bin_trans,errot = compile_state_transitions(data.state_transitions, bin_pins,bin_states) + local bin_state_values, errosv = compile_state_values(data.state_values) + local bin_in_pins,erroip = compile_in_pins(data.in_pins) + local bin_out_pins,erroop = compile_out_pins(data.out_pins) + + db.init = init + db.init_err = erroi + + db.pins = bin_pins + db.pins_err = errop + + db.states = bin_states + db.states_err = erros + + db.outputs = bin_outputs + db.outputs_err = erroo + + db.trans = bin_trans + db.trans_err = errot + + db.state_values = bin_state_values + db.state_values_err = errosv + + db.in_pins = bin_in_pins + db.in_pins_err = erroip + + db.out_pins = bin_out_pins + db.out_pins_err = erroop + + db.unknowns = data.unknowns + + + if not is_compilation_success(db) then + return nil,generate_compilation_error_message(db) + end + + + -- further processing + + -- warning: orders of executing functions is important, they depend on the db data + -- I know, it's a huge weld :) + local errs = {} + local err + local msg = "" + function insert_error(err) + if err ~= nil then + if type(err) == "table" then + for _,i in pairs(err) do + table.insert(errs,i) + end + else + table.insert(errs,err) + end + end + end + function err_string() + -- show errors + if #errs > 0 then + msg = "" + for _,v in pairs(errs) do + msg = msg .. "error: " .. v .. "\n" + end + msg = "Errors(".. #errs .. "):\n" .. msg + return msg + end + return "" + end + + + + db.reachables = get_all_reachable_states(db) + + _,err = get_not_used_states(db) + insert_error(err); if #errs ~= 0 then return nil, err_string() end + + db.state_bitsize,err = compute_bitsize_of_state(db) + insert_error(err); if #errs ~= 0 then return nil, err_string() end + + db.state_values = only_reachable_state_values(db) + + _,err = check_dead_states(db) + insert_error(err); if #errs ~= 0 then return nil, err_string() end + + db.state_values,err = fill_states_values(db) + insert_error(err); if #errs ~= 0 then return nil, err_string() end + + db.inputs_used,err = get_inputs(db) + insert_error(err); if #errs ~= 0 then return nil, err_string() end + + db.outputs_used,err = get_outputs(db) + insert_error(err); if #errs ~= 0 then return nil, err_string() end + + + + + --- further checking: applying priority and others + add_default_loops(db) + apply_priority(db) + clear_empty_transitions(db) + + -- the part above must be rewritten, too many welds here + -- additionally, algorithm does not remove all unused states, + -- therefore sometimes it generates dead transistions + -- the FSM is correct, but when generated has unused subcircuits + -- TODO: fix this + + ---------------------------------------- + + + + + + return db,"\nCompilation successful\n\n" .. + msg_state_values(db) .. "\n" .. + "\n" .. msg_inout_values(db) + +end + + + + + diff --git a/mods/mesecons_x/mesecons_autotools/fsm/compiler_checking.lua b/mods/mesecons_x/mesecons_autotools/fsm/compiler_checking.lua new file mode 100644 index 00000000..499a173e --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/fsm/compiler_checking.lua @@ -0,0 +1,386 @@ + +function msg_state_values(db) + + local l = db.state_values + if l == nil then return "" end + + local msg = "" + for k,v in pairs(l) do + msg = msg .. k .. ":=" .. v .. "\n" + end + return msg +end + +function msg_inout_values(db) + local mi = "Inputs: " .. table.concat(db.inputs_used,", ") + local mo = "Outputs: " .. table.concat(db.outputs_used,", ") + return mi .. "\n" .. mo +end + + +function is_compilation_success(db) + local list = { "init_err" , "pins_err", "states_err" ,"trans_err", + "state_values_err", "in_pins_err" , "out_pins_err", "outputs_err" } + + for _,v in pairs(list) do + if db[v] ~= nil then return false end + end + + if db.unknowns ~= nil then + if #db.unknowns ~= 0 then return false end + end + + return true +end + + +function generate_compilation_error_message(db) + local list = { "init_err" , "pins_err", "states_err" ,"trans_err", + "state_values_err", "in_pins_err" , "out_pins_err" , "outputs_err" } + + local counter = 0 + local msg = "" + for _,v in pairs(list) do + if db[v] ~= nil then + counter = counter + 1 + msg = msg .. "error: " .. db[v] .. "\n" + end + end + + -- adding unknows lines + if db.unknowns ~= nil then + if #db.unknowns ~= 0 then + for _,v in pairs(db.unknowns) do + msg = msg .. "error: unknown line '" .. v.line .. "'\n" + counter = counter + 1 + end + end + end + return "Errors (" .. counter .. ")\n" .. msg +end + + + + +------------------------------------------------------------------------ +-- checking fsm functions +------------------------------------------------------------------------ + +-- TODO: redesign queue functions +function is_empty_queue(q) + local count = 0 + for _,v in pairs(q) do + count = count +1 + end + if count == 0 then return true end + return false +end + +-- TODO: redesign queue functions +function push_on_queue(q,e) + local qq = DeepCopy(q) + table.insert(qq,e) + return qq +end + +-- TODO: redesign queue functions +function pop_from_queue(q) + local e = DeepCopy(q[1]) + q[1] = nil + local newq = {} + for _,v in pairs(q) do + table.insert(newq,v) + end + return e,newq +end + +function get_all_reachable_states(db) + local init = db.init + local queue = {} + local color = {} + local next_state = {} + local curr + + queue = push_on_queue(queue,init) + while not is_empty_queue(queue) do + curr,queue = pop_from_queue(queue) + if color[curr] ~= true then + color[curr] = true + if( db.trans[curr] ~= nil ) then + for _,ifthen in pairs(db.trans[curr]) do + next_state = ifthen.state + queue = push_on_queue(queue,next_state) + end + end + end + end + return color +end + + +function count_hash(h) + local c = 0 + for _,_ in pairs(h) do + c=c+1 + end + return c +end + +-- math.log is computins some trash!!!!!! +-- is that a bug or something +-- making my own binary log function +function lg2(n) + local c = 0 + local mul = 1 + while (mul < n ) do + mul = 2* mul + c=c+1 + end + return c +end + +function get_first_hash_element(h) + if h == nil then return nil end + local e = nil + for k,v in pairs(h) do + return k,v + end + return nil,nil +end + + +function compute_bitsize_of_state(db) + local reachable = get_all_reachable_states(db) + local count = count_hash(reachable) + local bits_reachable = lg2(count) + + local state_values = db.state_values + local count_values = count_hash(state_values) + + if( count_values == 0 ) then + if bits_reachable == 0 then + return nil,"no reachable states or only one state" + end + return bits_reachable + end + + -- check if all values have the same size + local fk,fv = get_first_hash_element(state_values) + local flen = string.len(fv) + for k,v in pairs(state_values) do + if string.len(v) ~= flen then + return nil, "states valuse do not have the same length, eg " .. + fk .. " := " .. fv .. " and " .. k .. " := " .. v + end + end + + -- checking if enoguth bits for reachable states + if ( bits_reachable > flen ) then + return nil, "lenght of state value is too small, need " .. + bits_reachable .. " bits to code " .. + count .. " states, but got only " .. flen .. + "eg. " .. fk .. " := " .. fv + + end + + if flen == 0 then + return nil,"no reachable states or only one state" + end + + return flen +end + + +function list_to_hash(list) + local hash = {} + for _,v in pairs(list) do + hash[v] = true + end + return hash +end + +function hash_in_hash(h1,h2) + for k,_ in pairs(h1) do + if h2[k] == nil then return false end + end + return true +end + + +function same_hash(h1,h2) + if hash_in_hash(h1,h2) and hash_in_hash(h2,h1) then return true else return false end +end +--[[ not used +function hash_cut_hash(h1,h2) + local h3 = {} + for k,_ in pairs(h1) do + if h2[k] ~= nil then + h3[k] = true + end + end + return h3 +end +]]-- +function hash_minus_hash(h1,h2) + local out = {} + for k,_ in pairs(h1) do + if h2[k] == nil then + out[k] = true + end + end + return out +end + + +function hash_to_list(h) + local list = {} + for k,v in pairs(h) do + table.insert(list,k) + end + return list +end + + +function check_dead_states(db) + -- states reachable from init + local hreachable = db.reachables + local trans = {} + + -- all states in trans + for state,v in pairs(db.trans) do + table.insert(trans,state) + end + + local htrans = list_to_hash(trans) + + if same_hash(hreachable,htrans) then + return nil,nil + else + local hdiff = hash_minus_hash(htrans,hreachable) + if count_hash(hdiff) ~= 0 then + local ldiff = hash_to_list(hdiff) + return nil, "following states '" .. table.concat(ldiff,", ") .. + "' are used in transitions but are not reachable from init state" + end + return nil,nil + end +end + +function cmp_list_eq(a,b) + local ha = list_to_hash(a) + local hb = list_to_hash(b) + + return same_hash(ha,hb) +end + + +function list_minus_list(l1,l2) + local h1 = list_to_hash(l1) + local h2 = list_to_hash(l2) + local minus = hash_minus_hash(h1,h2) + return hash_to_list(minus) +end + +function get_all_inputs_from_reachable_transitions(db) + local list = {} + for state,v in pairs(db.trans) do + if db.reachables[state] then + for _,w in pairs(v) do + append(list,drop_negation_list(w.pins)) + end + end + end + local sorted_by_name = DeepCopy(remove_duplicates(list)) + table.sort(sorted_by_name) + return sorted_by_name +end + +function get_inpus_from_transistions_and_check_with_declared(db) + local ins_from_trans = get_all_inputs_from_reachable_transitions(db) + local ins_from_def = db.in_pins + + if cmp_list_eq(ins_from_def,ins_from_trans) then + return ins_from_def + else + local more_in_def = list_minus_list(ins_from_def,ins_from_trans) + local more_in_trans = list_minus_list(ins_from_trans, ins_from_def) + + + if #more_in_def ~= 0 then + return nil, "pins '" .. table.concat(more_in_def, ", ") .. + "' declared in 'in:' but never used in transitions"; + end + if #more_in_trans ~= 0 then + return nil, "pins '" .. table.concat(more_in_trans, ", " ) .. + "' used in transitions, but not declared in 'in:'" + end + + return nil, {"pins declared and pins used in transitions are not the same"} + end +end + +function get_inputs(db) + -- checking if input pins are not declared + if db.in_pins == nil or #db.in_pins == 0 then + return get_all_inputs_from_reachable_transitions(db) + end + + -- checing if the same as from transistion + return get_inpus_from_transistions_and_check_with_declared(db) +end + +function get_all_output_from_reachable_transitions(db) + local list = {} + for state,v in pairs(db.trans) do + if db.reachables[state] then + for _,w in pairs(v) do + if db.outputs[w.state] ~= nil then + append(list,db.outputs[w.state]) + end + end + end + end + + -- adding also outpus of init state + append(list, db.outputs[db.init]) + + local sorted_by_name = DeepCopy(remove_duplicates(list)) + table.sort(sorted_by_name) + return sorted_by_name +end + + +function get_outputs_from_transistions_and_check_with_declared(db) + local outs_from_trans = get_all_output_from_reachable_transitions(db) + local outs_from_def = db.out_pins + + if cmp_list_eq(outs_from_trans,outs_from_def) then + return outs_from_def + else + local more_in_def = list_minus_list(outs_from_def,outs_from_trans) + local more_in_trans = list_minus_list(outs_from_trans, outs_from_def) + + + if #more_in_def ~= 0 then + return nil, "pins '" .. table.concat(more_in_def, ", ") .. + "' declared in 'out:' but never used in output states"; + end + if #more_in_trans ~= 0 then + return nil, "pins '" .. table.concat(more_in_trans, ", " ) .. + "' used in output state definitons, but not declared in 'out:'" + end + + return nil, {"pins declared and pins used in transitions are not the same"} + end +end + +function get_outputs(db) + -- check if output pins are declared + if db.out_pins == nil or #db.out_pins == 0 then + return get_all_output_from_reachable_transitions(db) + end + return get_outputs_from_transistions_and_check_with_declared(db) +end + + + diff --git a/mods/mesecons_x/mesecons_autotools/fsm/compiler_general.lua b/mods/mesecons_x/mesecons_autotools/fsm/compiler_general.lua new file mode 100644 index 00000000..39183cba --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/fsm/compiler_general.lua @@ -0,0 +1,191 @@ +------------------------------------------------------------------------ +-- general functions +------------------------------------------------------------------------ + +function trim(s) + return s:match( "^%s*(.-)%s*$" ) +end + + +function get_list_from_string(str) + local l = {} + for i in string.gmatch(str,"%S+") do + table.insert(l,trim(i)) + end + return l +end + +function get_lines_from_string(str) + local l = {} + for i in string.gmatch(str,"[^\n]+") do + table.insert(l,trim(i)) + end + return l +end + +function empty(list) + if #list == 0 then return true end + return false +end + +-- exists +function e(db,key) + if db == nil then return false end + if db[key] ~= nil then return true end + return false +end + +function is_in_list(list,elem) + for _,v in ipairs(list) do + if v == elem then return true end + end + return false +end + +function remove_duplicates(list) + local l = {} + local db = {} + for key,value in pairs(list) do + db[value] = true + end + for key,_ in pairs(db) do + table.insert(l,key) + end + return l +end + +------------------------------------------------------------------------ +-- help functions +------------------------------------------------------------------------ +local name_reg = "[a-zA-Z][a-zA-Z0-9_]*" + +function is_name(str) + return string.match(str,"^" .. name_reg .. "$") +end + +function is_negated(n) + if string.match(n,"^~.*$") == nil then + return false + else + return true + end +end + +function drop_negation(n) + local name = string.match(n,"^~?(.*)$") + return name +end + +function add_negation(n) + return "~" .. drop_negation(n) +end + +function swap_negation(n) + if is_negated(n) then + return drop_negation(n) + else + return add_negation(n) + end +end + + +function is_pin_name(n) + if is_name(n) == nil then return false end + return true +end + +function is_pin_group_name(n) + local name = string.match(n,"^#(.*)") + if name == nil then return false end + return is_pin_name(name) +end + +function is_pin_name_n(n) + if is_pin_name(n) then return true end + + local name = string.match(n,"^~(.*)$") + if name == nil then return false end + return is_pin_name(name) +end + +function is_pin_group_name_n(n) + if is_pin_group_name(n) then return true end + + local name = string.match(n,"^~(.*)$") + if name == nil then return false end + return is_pin_group_name(name) +end + + +function is_pin_and_group_list(list) + for _,v in pairs(list) do + if not is_pin_name(v) and not is_pin_group_name(v) then return false end + end + return true +end + +function is_pin_name_list(list) + for _,v in pairs(list) do + if not is_pin_name(v) then return false end + end + return true +end + + +function is_pin_and_group_list_n(list) + for _,v in pairs(list) do + if not is_pin_name_n(v) and + not is_pin_group_name_n(v) then + return false + end + end + return true +end + +function is_state_name(n) + if is_name(n) == nil then return false end + return true +end + +function is_state_group_name(n) + local name = string.match(n,"^@(.*)") + if name == nil then return false end + return is_state_name(name) +end + +function is_state_and_group_list(list) + for _,v in pairs(list) do + if (not is_state_name(v)) and + (not is_state_group_name(v)) then + return false + end + end + return true +end + + +--[[ not used, for delete +function is_uniq_list(list) + local db = {} + for _,v in pairs(list) do + if db[v] == nil then + db[v] = true + else + return false + end + end +end +]]-- +-- find first duplicate +function get_duplicate(list) + if list == nil then return nil end + local db = {} + for _,v in pairs(list) do + if db[v] == nil then + db[v] = true + else + return v + end + end + return nil +end \ No newline at end of file diff --git a/mods/mesecons_x/mesecons_autotools/fsm/compiler_generating.lua b/mods/mesecons_x/mesecons_autotools/fsm/compiler_generating.lua new file mode 100644 index 00000000..02b9b5cd --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/fsm/compiler_generating.lua @@ -0,0 +1,232 @@ + + +------------------------------------------------------------------------ +-- generating fsm functions +------------------------------------------------------------------------ +function get_list(list) + if list == nil then + return {} + else + return list + end +end + +--[[ +function fsm_generate_trans(db) + -- from ins -> to outs + local results = {} + local states = get_all_reachable_states(db) + for state,_ in pairs(states) do + if( db.trans[state] == nilv) then + table.insert(results, { from = state, to = state, ins = {} , outs = {} }) + else + for _,ifthens in pairs(db.trans[state]) do + local pins_in = ifthens.pins + local next_state = ifthens.state + local pins_out = db.outputs[next_state] + if pins_out == nil then pins_out = {} end + table.insert(results, { from = state, to = next_state, ins = pins_in, outs = pins_out } ) + end + end + end + return results +end + +]]-- + +function value_inc(v) + local len = #v + local carry = true + local new = "" + + for i=len,1,-1 do + local ch = string.sub(v,i,i) + if carry == false then + new = ch .. new + else + if ch == "0" then + new = "1" .. new + carry = false + else + new = "0" .. new + carry = true + end + end + end + return new +end + +function next_free_value(len,db) + local nv = string.rep("0",len) + + vals = {} + -- get only vlaues + for k,v in pairs(db) do + vals[v] = true + end + + for i=1,math.pow(2,len) do + if vals[nv] == nil then + return nv + end + nv = value_inc(nv) + end + + -- should never get here + return nil +end + +function get_not_used_states(db) + local reachables = db.reachables + local state_values = db.state_values + local not_used_states = {} + + -- checking if some states are not used + for k,v in pairs(state_values) do + if reachables[k] == nil then + table.insert(not_used_states,k) + end + end + + if #not_used_states == 0 then + return {} + end + + local list = {} + for _,v in pairs(not_used_states) do + table.insert(list, "state '" .. v .. "' is not used, but declared " .. v .. + " := " .. state_values[v]) + end + + return nil,list +end + + +function fill_states_values(db) + local states_values = db.state_values + local states = db.reachables + local filled = {} + + -- filling existing values + for k,_ in pairs(states) do + filled[k] = states_values[k] + end + + local len = db.state_bitsize + local zerostate = string.rep("0",len) + + -- checkint if init already has value, and if it is 0000 + if filled[init] ~= nil and filled[init] ~= zerostate then + return nil, "init state " .. filled[init] .. " has value " .. + filled[init] .. ", only value 0 is allovwd for init state" + end + + -- checking if state 0000 is used by other state + for k,v in pairs(filled) do + if v == zerostate then + if k ~= db.init then + return nil, "value " .. zerostate .. + " is reserved for init state, but already used by " .. + k .. " := " .. v + end + end + end + + -- adding default init state as 0000 + local init = db.init + if filled[init] ~= nil then + if filled[init] ~= zerostate then + return nil,"init state must be " .. zerostate .. ", but is " .. + init .. " := " .. filled[init] + end + end + + if filled[init] == nil then + filled[init] = zerostate + end + + -- adding rest + + for k,v in pairs(states) do + if filled[k] == nil then + filled[k] = next_free_value(len,filled) + end + end + return filled +end + +function only_reachable_state_values(db) + local reach = db.reachables + local values = db.state_values + + local new = {} + + for k,_ in pairs(values) do + if reach[k] ~= nil then + new[k] = values[k] + end + end + return new +end + + +function fsm_get_all_used_inputs(db) + local pins = {} + + for _,v in pairs(db.trans) do + local ins = v.ins + for _,pin in pairs(ins) do + pins[drop_negation(pin)] = true + end + end + return pins +end + +-- appends list 2 to lits 1 +-- probably there is a function for that +-- couldn't bother to find it +function append(list1,list2) + if list2 == nil then + return list1 + end + if list1 == nil then + return nil + end + + for _,v in pairs(list2) do + table.insert(list1,v) + end + return list1 +end + +function fsm_get_all_used_outputs(reachable_trans,db) + local list = {} + + -- get all pins + for _,v in pairs(reachable_trans) do + local ps = db.outputs[v.to] + apend(list,ps) + end + + -- remove negations + local list2 = {} + for _,v in pairs(list) do + table.insert(list2, drop_negation(v)) + end + return remove_duplicates(list2) +end + +function check_inputs(db) + +end + +------------------------------------------------------------------------ +-- generating error messages +------------------------------------------------------------------------ +function error_unknows(unknows) + local msg = "" + for _,v in pairs(unknows) do + msg = msg .. "line: .. " .. v.nr .. " " .. v.line .. "\n" + end + return msg +end diff --git a/mods/mesecons_x/mesecons_autotools/fsm/compiler_parsing.lua b/mods/mesecons_x/mesecons_autotools/fsm/compiler_parsing.lua new file mode 100644 index 00000000..b39ebf5b --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/fsm/compiler_parsing.lua @@ -0,0 +1,216 @@ + +------------------------------------------------------------------------ +-- parsing functions +------------------------------------------------------------------------ + +function is_pin_assign(line) + if line == nil then return nil end + local pin,pins = string.match(line,"^%s*([#].*)%s*=(.*)$") + if pin == nil or pins == nil then return nil end + pin = trim(pin) + + if( is_pin_group_name(trim(pin)) ~= true ) then return nil end + + local list = get_list_from_string(pins) + if( not is_pin_and_group_list_n(list) ) then return nil end + + local data = {} + data.pin = pin + data.pins = list + return data + end + + +function is_state_assign(line) + if line == nil then return nil end + local state,states = string.match(line, "^%s*(@.*)%s*=(.*)$") + if state == nil or states == nil then return nil end + state = trim(state) + + if( not is_state_group_name(state) ) then return nil end + + local list = get_list_from_string(states) + if( not is_state_and_group_list(list) ) then return nil end + + local data = {} + data.state = state + data.states = list + data.line = line + return data +end + +function is_bin_value(value) + if value == nil then return false end + for i=1,#value do + local ch = string.sub(value,i,i) + if (ch ~= "0" ) and (ch ~= "1" ) then return false end + end + return true +end + + +function is_state_value_assign(line) + if line == nil then return nil end + local state,value = string.match(line, "^%s*(.*)%s*:=(.*)$") + + if state == nil then return nil end + if value == nil then return nil end + state = trim(state) + value = trim(value) + + if not is_state_name(state) then return nil end + if not is_bin_value(value) then return nil end + + local data = {} + data.state = state + data.value = value + return data +end + + +function is_in_assign(line) + if line == nil then return nil end + local ins = string.match(line, "^%s*in:(.*)$") + + if ins == nil then return nil end + local list = get_list_from_string(ins) + if( not is_pin_name_list(list) ) then return nil end + + local data = {} + data = list + return data +end + +function is_out_assign(line) + if line == nil then return nil end + local ins = string.match(line, "^%s*out:(.*)$") + + if ins == nil then return nil end + local list = get_list_from_string(ins) + if( not is_pin_name_list(list) ) then return nil end + + local data = {} + data = list + return data +end + + +function is_init_assign(line) + if line == nil then return nil end + local init = string.match(line,"^%s*[[][[]%s*(.*)%s*[]][]]%s*$") + if init == nil then return nil end + if( not is_state_name(init)) then return nil end + return trim(init) +end + + +function is_state_output_assign(line) + if line == nil then return nil end + local states,pins = string.match(line, "^%s*[[]%s*(.*)%s*[]](.*)$") + if( states == nil or pins == nil ) then return nil end + + local state_list = get_list_from_string(states) + if empty(state_list) then return nil end + if not is_state_and_group_list(state_list) then return nil end + + local pin_list = get_list_from_string(pins) + if empty(pin_list) then return nil end + --if not is_pin_and_group_list_n(pin_list) then return nil end + if not is_pin_and_group_list(pin_list) then return nil end + --if not is_pin_name_list(pin_list) then return nil end + + local data = {} + data.states = state_list + data.pins = pin_list + data.line = line + return data +end + +function is_state_transition_assign(line) + if line == nil then return nil end + local states,pins,state = string.match(line,"^%s*[[](.*)[]](.*)->%s*[[](.*)[]]%s*$") + if states == nil or state == nil or pins == nil then return nil end + + local state_list = get_list_from_string(states) + if empty(state_list) then return nil end + if not is_state_and_group_list(state_list) then return nil end + + local pin_list = get_list_from_string(pins) + if not is_pin_and_group_list_n(pin_list) then return nil end + + if not is_state_name(trim(state)) then return nil end + + local data = {} + data.states = state_list + data.pins = pin_list + data.state = trim(state) + data.line = line + return data +end + +function is_comment(line) + if line == nil then return nil end + local comment = string.match(line,"^%s*;.*$") + return comment +end + + + +function parse_code(text) + local inits = {} + local pin_assigns = {} + local state_assigns = {} + local state_outputs = {} + local state_transitions = {} + local state_values = {} + local in_pins = {} + local out_pins = {} + local unknowns = {} + + local lines = get_lines_from_string(text) + for i,line in ipairs(lines) do + local init = is_init_assign(line) + local pin_assgn = is_pin_assign(line) + local state_assign = is_state_assign(line) + local state_output = is_state_output_assign(line) + local state_transition = is_state_transition_assign(line) + local state_value = is_state_value_assign(line) + local in_pin = is_in_assign(line) + local out_pin = is_out_assign(line) + local comment = is_comment(line) + + if( init ~= nil ) then + table.insert(inits,init) + elseif pin_assgn ~= nil then + table.insert(pin_assigns,pin_assgn) + elseif state_assign ~= nil then + table.insert(state_assigns,state_assign) + elseif state_output ~=nil then + table.insert(state_outputs,state_output) + elseif state_transition ~= nil then + table.insert(state_transitions, state_transition) + elseif state_value ~= nil then + table.insert(state_values,state_value) + elseif in_pin ~= nil then + table.insert(in_pins,in_pin) + elseif out_pin ~= nil then + table.insert(out_pins,out_pin) + elseif comment ~= nil then + -- drop comment + else + table.insert(unknowns,{nr=i, line = line}) + end + end + + local data = {} + data.inits = inits + data.pin_assigns = pin_assigns + data.state_assigns = state_assigns + data.state_outputs = state_outputs + data.state_transitions = state_transitions + data.state_values = state_values + data.in_pins = in_pins + data.out_pins = out_pins + data.unknowns = unknowns + return data +end diff --git a/mods/mesecons_x/mesecons_autotools/fsm/fsm.lua b/mods/mesecons_x/mesecons_autotools/fsm/fsm.lua new file mode 100644 index 00000000..89d954c2 --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/fsm/fsm.lua @@ -0,0 +1,470 @@ +dofile(minetest.get_modpath("mesecons_autotools").."/fsm/lib.lua"); +dofile(minetest.get_modpath("mesecons_autotools").."/fsm/alg.lua"); +dofile(minetest.get_modpath("mesecons_autotools").."/fsm/compiler.lua"); +dofile(minetest.get_modpath("mesecons_autotools").."/fsm/generate.lua"); +dofile(minetest.get_modpath("mesecons_autotools").."/fsm/priority.lua"); + +local esc = minetest.formspec_escape + +function get_stats_string(data) + if data == nil then return "" end + if data.circ == nil then return "" end + if data.circ.nodes == nil then return "" end + + local nodes = data.circ.nodes + local stats = "" + local block, gate, wire + local sx,xy,sz + + block, gate, wire = get_stats(nodes) + sx = nodes.sx + sy = nodes.sy + sz = nodes.sz + + stats = "size : " .. sx .. "x"..sy .. "x"..sz .. "(=".. sx*sy*sz .. ")\n" .. + "wires : " .. wire .. "\n" .. + "gates : " .. gate .. "\n" .. + "others : ".. block - wire - gate .. "\n" .. + "blocks: " .. block + return stats +end + + +local function get_fromspec_help() + local formspec = + + "formspec_version[3]".. + + "size[32,25]".. + "style_type[textarea;font=mono]" .. + + "label[15,0.7;FSM generator]".. + --"label[20,0.7;" .. file .. "]" .. + + + "" + return formspec +end + + +local function get_formspec(data) + local code = minetest.formspec_escape(data.code or "") + local name = minetest.formspec_escape(data.name or "") + local log = minetest.formspec_escape(data.log or "") + + local stats_string = get_stats_string(data) + + local create_button = "" + if data.circ ~= nil then + if data.circ.nodes ~= nil then + create_button = "image[27.5,23;1,1;circuit_full.png]" .. + "button[28.5,23;3,1;create;" .. "Create" .. "]" + end + end + + + + local formspec = + "formspec_version[3]".. + + "size[32,25]".. + "style_type[textarea;font=mono]" .. + + "style[question;fgimg=question.png;fgimg_hovered=question_hovered.png;border=false]" .. + "image_button[30.8,0.2;1,1;;question;]" .. + + + "label[15,0.7;FSM generator]".. + --"label[20,0.7;" .. file .. "]" .. + "field[0.5,2;15,1;name;Name;" .. name .. "]".. + "textarea[0.5,4;15,15;code;" .. "Code:;" .. code .. "]" .. + "textarea[16.5,2;15,17;;" .. "Compilation Logs:" .. ";" .. log .. "]" .. + "button[0.5,19;3,1;save;" .. "Save" .. "]" .. + "button[14.5,20;3,1;compile;" .. "Compile" .. "]" .. + + + "textarea[23.5,21;8,5;;Circuit Parameters;" .. esc(stats_string) .. "]" .. + + + "label[0.5,21;Generation Options:]" .. + "label[1,22;Circuit Type:]" .. + "dropdown[4,21.5;5,1;type;flat_raw;1]" .. + + create_button .. + + "" + return formspec +end + +local help = [==[ + + +[General Info] +This is a Moore State Machine generator. + +Each state has a name, built out of the letters (A-Z,a-Z), numbers (0-9), and underscore. Name must begin with a letter. + +Each pin has a name, built out of the letters (A-Z,a-Z), numbers (0-9), and underscore. Name must begin with a letter. + +[Comments] +Line that begins with ';' is a comment. White characters at the beginning are ignored. + +[Init State] +Init state is declared with double square bracket '[[' and ']]'. Eg. [[init]], [[init_state]] +You must have exacly one init state. + +You dont have to declare states, just use them in transitions or outputs declarations. + +[Transitions] +Transitions have the following form: + [list_of_states] list_of_pins -> [state] +where + 'list_of_states' is a list of input state names separated by space, list must contain at least one state + 'list_of_pins' is a list of pin names separated by space, list can be empty + 'state' is output state, ie. next transition state + +Eg. + [a] -> [b] + [a b] -> [c] + [a] pin1 ~pin2 -> [c] + +Pins can be negated by ~. If there is no pin on the list, the value of the pin is not considered. [a] -> [b] means go from state 'a' to 'b' no matter what input pins are. [a] p1 -> [b] means, if in state 'a' and inputs pins have the following values: p1='1' and rest input pins have any value, then go to state 'b'. [a] ~p1 -> [b] means, if in state 'a' and pin 'p1' is '0', then go to state 'b' (we dont care about other input pins). [a] p1 ~p2 -> [b] means, if in state 'a' and p1='1' and p2='0' and we dont care about rest pins, then go to state 'b'. + +Transition [a b] p1 -> [c] is equivalent to: + [a] p1 -> [c] + [b] p1 -> [c] + +There must be at least one transition. + +[Priority] +Transitions declared first, have highter priority. If there is more than one transition, that satisfies pin conditions, only the first one would be applied. + +Eg. + +[a] -> [b] +[a] -> [c] + +meas, FSM would go to state 'b'. + +Eg. Consider the following situation: + +[a] p1 p2 -> [b] +[a] p1 p3 -> [c] + +and pins are (p1,p2,p3)=(1,1,1). Both transitions apply, but because [a] p1 p2 -> [b] is declared first, only this one would be applied, and FSM would transition to sate 'b'. + +[Defalut Loop Transition] +Each state has automatically added self loop transition: +[state] -> [state] +This means, that if any of your conditions do not apply, the FSM stays in the same state. + +Eg. +[a] pin -> [b] + +is equivalent to: + +[a] pin -> [b] +[a] -> [a] +[b] -> [b] +meaning, if in state 'a' and pin=0 then FSM stays in state 'a'. If in state 'b', stay in state 'b'. + +[Outputs] +Output values are declared as follows: + [list_of_states] list_of_pins +If a pin is on the list, the value is '1'. If the pin is not on the list, the value of this pin is '0'. + +Eg. + [a] pin1 pin2 + [a b c] pin_light +Eg. + [a] p1 +means that when the FSM is in the state 'a' then the output pin 'p1' would have value '1', and the rest of the output pins would have the value '0'. +Not declared states would automatically have output pins set to '0'. + + +[Fixing Input/Output Order] +Declaring input/output pins order is optional. You can declare only 'in:', only 'out:', both, or none. If you dont specify input/output pins order, then they are generated automatically, and showed on compilation logs. Syntax is: + +in: list_of_pins +out: list_of_pins + +where 'list_of_pins' is a list of pins separated by space. + +Eg. +in: a b d +out: x y z + +[State Groups] +You can declare state groups as follows: + +@group_name = list_of_states + +Eg. +@all = state1 state2 state3 +@gr1 = state1 state2 +@gr2 = state3 state4 state5 +@allgrs = @gr1 @gr2 super_state + +You use state group as normal state, but only where multiple states are allowed. + +[@all] pin1 ~pin2 -> [state] +[@all another_state] out1 out2 + +Eg. +@gr = s1 s2 +[@gr] -> [b] + +is equivalent to: + +[s1 s2] -> [b] + +which is the same as: +[s1] -> [b] +[s2] -> [b] + + +[Pin Groups] +You can declare pin groups as follows: + +#pins = pin1 pin2 ~pin4 + +and use them as normal pins. You cannot negate it though. + +[a] #pins some_pin -> [b] +[b] out1 out2 #pins + +Eg. +#pins = p1 ~p2 +[a] #pins p3 -> [b] + +is the same as: + +[a] p1 ~p2 p3 -> [b] + + +]==] +local function get_formspec_help() + local formspec = + "formspec_version[3]".. + + "size[32,25]".. + "style_type[textarea;font=mono]" .. + + "style[question;fgimg=question.png;fgimg_hovered=question_hovered.png;border=false]" .. + "style[exit;fgimg=cancel.png;fgimg_hovered=cancel.png;border=false]" .. + "image[0.2,0.2;1,1;question.png]" .. + "image_button_exit[30.8,0.2;1,1;;exit;]" .. + "textarea[1,2;30,22;;;" .. esc(help) .. "]" .. + "" + return formspec +end + + +function on_place_fsm_book(itemstack, player, pointed_thing) + local user = player:get_player_name() + local rad = player:get_look_horizontal() + local direction = radians_to_direction_looking_forward(rad) + local fields = itemstack:get_meta():to_table().fields + local file = fields.file + + if not mesecons_autotools.is_full_selection(user) then return nil end + local pos1 = mesecons_autotools.get_pos(user,1) + local pos2 = mesecons_autotools.get_pos(user,2) + local sel = {pos1=pos1,pos2=pos2} + + local data = read_table_from_file(file) + if data.circ == nil then return end + local circ = data.circ + + + paste_circuit_from_table(sel,circ,direction) +end + + +local function show_dialog_fsm(player,itemstack) + local user = player:get_player_name() + local fields = itemstack:get_meta():to_table().fields + local file = fields.file + local stack = player:get_wielded_item() + local db = {} + local data = {} + + if file == nil then + file = generate_file_name_fsm(user) + fields.file = file + stack:get_meta():from_table({ fields = fields}) + player:set_wielded_item(stack) + + data.code = "" + data.name = "" + data.log = "" + save_table_to_file(file,data) + else + data = read_table_from_file(file) + if data == nil then data = {} end + end + + local formspec = get_formspec(data) + + minetest.show_formspec(user, "mesecons_autotools:fsm_show", formspec) +end + + +function fsm_make_selection(user,file,direction,pos) + if file == nil then return end + + local data = read_table_from_file(file) + if data.circ == nil then return end + local nodes = data.circ.nodes + + if nodes == nil then return end + + local sx = nodes.sx + local sy = nodes.sy + local sz = nodes.sz + + local pos2 = make_pos2(pos,direction,sx,sy,sz) + + -- Updatecd + mesecons_autotools.set_pos(user,1,pos) + mesecons_autotools.set_pos(user,2,pos2) + mesecons_autotools.render(user) + mesecons_autotools.zero_stack_counter(user) + mesecons_autotools.zero_stack_direction(user) +end + + +local function on_use_fsm_book(itemstack, player, pointed_thing) + local user = player:get_player_name() + local data = itemstack:get_meta():to_table().fields + local rad = player:get_look_horizontal() + local direction = radians_to_direction_looking_forward(rad) + local file = data.file +-- local stack = player:get_wielded_item() + + if( pointed_thing.type == "node" ) then + fsm_make_selection(user,file,direction,pointed_thing.above) + else + show_dialog_fsm(player,itemstack) + end + + return nil +end + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname ~= "mesecons_autotools:fsm_show" then return end + local user = player:get_player_name() + local stack = player:get_wielded_item() + local ffields = stack:get_meta():to_table().fields + + if( fields.question ) then + local fs = get_formspec_help() + minetest.show_formspec(user, "mesecons_autotools:fsm_show", fs) + return + end + + + + local data = {} + local file = ffields.file + + if file == nil then + file = generate_file_name_fsm(user) + ffields.file = file + data.name ="" + data.code ="" + data.log ="" + + save_table_to_file(file,data) -- just to generate file + else + data = read_table_from_file(file) + if data == nil then data = {} end + end + + data.name = fields.name or "" + data.code = fields.code or "" + + + if (fields.save) or fields.key_enter_field == "name" then + ffields.description = data.name + stack:get_meta():from_table({ fields = ffields}) + player:set_wielded_item(stack) + save_table_to_file(file,data) + + elseif fields.compile then + ffields.description = data.name + stack:get_meta():from_table({ fields = ffields}) + player:set_wielded_item(stack) + + + -- saving code before compiling + -- (just in case the game crashes during compilation) + data.log = "\ngame crashed?\nkeep the code and report bug :)" + save_table_to_file(file,data) + + --compilation area + + + local bin,err = compile_code(data.code) + if bin == nil then + data.log = err + data.circ = nil + else + local circ = generate_circuit(bin,{}) + data.circ = circ + data.log = err + end + + --end of copmilation area + + save_table_to_file(file,data) + + local formspec = get_formspec(data) + minetest.show_formspec(user, "mesecons_autotools:fsm_show", formspec) + + elseif fields.create then + if data.circ == nil then return end + if data.circ.nodes == nil then return end + + -- create file + local blue = {} + blue.nodes = data.circ.nodes + blue.metas = data.circ.metas + blue.title = data.name + blue.text = "" + blue.direction = {x=0,y=0,z=1} + + -- save file + + local blue_file = generate_file_name(user) + save_table_to_file(blue_file,blue) + + -- create item in inventory + + local new_stack = ItemStack("mesecons_autotools:circuit_full") + local b = {} + b.file = blue_file + b.description = blue.title + new_stack:get_meta():from_table({ fields = b}) + + local inv = player:get_inventory() + if inv:room_for_item("main", new_stack) then + inv:add_item("main", new_stack) + else + minetest.add_item(player:get_pos(), new_stack) + end + end + + + end) + +minetest.register_tool("mesecons_autotools:fsm", { + description = "FSM generator", + inventory_image = "fsm_book.png", + stack_max = 1, + + on_use = on_use_fsm_book, + on_place = on_place_fsm_book, + on_secondary_use = none, + + }) diff --git a/mods/mesecons_x/mesecons_autotools/fsm/generate.lua b/mods/mesecons_x/mesecons_autotools/fsm/generate.lua new file mode 100644 index 00000000..5c311305 --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/fsm/generate.lua @@ -0,0 +1,742 @@ +------------------------------------------------------------------------ +-- generating wires +------------------------------------------------------------------------ +function g_wire_line(rotation,state) + local r = 0 + if rotation == "h" then + r = 0 + else -- == "v" + r = 1 + end + return { + node = {name="mesecons_insulated:insulated_".. state , param2 = r}, + meta = {} + } +end + +function g_wire_bend(rotation,state) + local rot = 0 + if rotation == "lu" then + rot = 1 + elseif rotation == "ru" then + rot = 2 + elseif rotation == "rd" then + rot = 3 + elseif rotation == "ld" then + rot = 0 + else + rot = 0 + end + return { + node = {name="mesecons_extrawires:corner_" .. state, param2=rot}, + meta = {} + } +end + +function g_wire_cross(state) + local s = "off" + if state == "off" then + s = "off" + elseif state == "on" then + s = "on" + elseif state == "h" then + s = "01" + elseif state == "v" then + s = "10" + else + s = "off" + end + return { + node = {name="mesecons_extrawires:crossover_" .. s, param2=0}, + meta = {} + } +end + +function g_wire_t(rotation,state) + local p = 0 + if rotation == "u" then + p = 2 + elseif rotation == "d" then + p = 0 + elseif rotation == "l" then + p = 1 + else -- "r" + p = 3 + end + return { + node = {name="mesecons_extrawires:tjunction_" .. state, param2=p}, + meta = {} + } +end + +function g_wire_xjunction(state) + return { + node = {name="mesecons_morewires:xjunction_" .. state, param2=0}, + meta = {} + } +end + +------------------------------------------------------------------------ +-- generating gates +------------------------------------------------------------------------ + + +function g_gate_not(state,rot) + local p + if rot == "up" then + p = 3 + elseif rot == "left" then + p = 2 + elseif rot == "right" then + p = 0 + else --down + p = 1 + end + + return { + node = {name="mesecons_gates:not_" .. state,param2=p}, + meta = { ["inventory"] = { } ,["fields"] = { } ,} + } +end + +function g_gate_diode(state,rot) + local p + if rot == "up" then + p = 3 + elseif rot == "left" then + p = 2 + elseif rot == "right" then + p = 0 + else --down + p = 1 + end + return { + node = {name="mesecons_gates:diode_" .. state, param2=p}, + meta = { ["inventory"] = { } ,["fields"] = { } ,} + } +end + +function g_ff(state,rot,data) -- din = data in + local p + if rot == "up" then + p = 3 + elseif rot == "left" then + p = 2 + elseif rot == "right" then + p = 0 + else --down + p = 1 + end + local din + if data == "off" then din = 0 else din =1 end + return { + node={ name = "mesecons_regs:flipflop_off" ,param2 = p} , + meta={ ["inventory"] = { } ,["fields"] = { ["enable"] = 0,["data"] = din,} } + } +end + + +------------------------------------------------------------------------ +-- help functions +------------------------------------------------------------------------ + +function set(circ,x,z,elem) + local node = elem.node + local meta = elem.meta + m3_set(circ.nodes,x,1,z,node) + m3_set(circ.metas,x,1,z,meta) +end + + +function is_bl_empty(c) + if c == nil then return true end + if c.nodes == nil then return true end + if c.nodes.sx == 0 or c.nodes.sy == 0 or c.nodes.sz==0 then return true end + return false +end + + +-- block insert +function blinsert(chost,celem,x,y,z) + if is_bl_empty(celem) then return end + m3_insert(chost.nodes,celem.nodes,x,y,z) + m3_insert(chost.metas,celem.metas,x,y,z) +end + + + + +function is_all_zeros(v) + for i=1,string.len(v) do + if string.sub(v,i,i) ~= "0" then + return false + end + end + return true +end + +function new_circ() + return { nodes = { sx=0,sy=0,sz=0} , metas = {sx=0,sy=0,sz=0} } +end + +function gnode_to_circ(n) + local c = new_circ() + set(c,1,1,n) + c.nodes.sx = 1 + c.nodes.sy = 1 + c.nodes.sz = 1 + c.metas.sx = 1 + c.metas.sy = 1 + c.metas.sz = 1 + return c +end + + +function inverse_state(v) + if v == "on" then return "off" else return "on" end +end + + +function switch_01_to_onoff(c) + if c == "0" then + return "off" + else + return "on" + end +end + +--[[ not used +function has_negation(list) + for _,v in pairs(list) do + if is_negated(v) then + return true + end + end + return false +end +]]-- +function has_positive_pin(list) + for _,v in pairs(list) do + if not is_negated(v) then + return true + end + end + return false +end + + +function or_state(s1,s2) + if s1 == "off" and s2 == "off" then return "off" else return "on" end +end + +function or_value(v1,v2) + local s = "" + for i=1,string.len(v1) do + if string.sub(v1,i,i) == "0" and string.sub(v2,i,i) == "0" then + s = s .. "0" + else + s = s .. "1" + end + end + return s +end + +------------------------------------------------------------------------ +-- generating bundles of wires +------------------------------------------------------------------------ + +function bl_bend_1wire_from_down_to_right(x0,y0, x1,y1) + -- (x0,y0) to (x1,y1) first going up, then going right + local c = new_circ() + + -- vertical + for i=y0,y1-1 do + blinsert(c,gnode_to_circ( g_wire_line("v","off") ), x0,1,i) + end + + -- curve + blinsert(c,gnode_to_circ(g_wire_bend("rd","off")), x0,1,y1) + + -- horizontal + for i=x0+1,x1 do + blinsert(c,gnode_to_circ(g_wire_line("h","off")),i,1,y1) + end + return c +end + + +function bl_bend_bundle_from_down_to_right_step2(size) + local c = new_circ() + + for i=1,size do + local shifth = (i-1)*2+1 + local shiftv = size - i +1 + local maxshift = size*2-1 + blinsert(c, bl_bend_1wire_from_down_to_right(shifth,1,maxshift,shiftv),1,1,1) + end + return c +end + + +function bl_t_bundle_to_down_step2(size) + -- crossing + local c = new_circ() + for i=1,size do + local hshift = (i-1)*2+1 + + for k=1,size-i do + blinsert(c,gnode_to_circ(g_wire_cross("off")),hshift,1,k) + end + + local vstart = size-i+1 + blinsert(c,gnode_to_circ(g_wire_t("d","off")),hshift,1,vstart) + + for k=size-i+2,size do + blinsert(c, gnode_to_circ(g_wire_line("h","off")),hshift,1,k) + end + end + + for i=1,size do + local hsift = (i-1)*2+1+1 + for k=1,size do + blinsert(c,gnode_to_circ(g_wire_line("h","off")),hsift,1,k) + end + end + return c +end + + +function add_left_connection(size) + -- adding connections + local left = new_circ() + for i=1,size do + blinsert(left,gnode_to_circ(g_wire_line("h","off")),1,1,i) + blinsert(left,gnode_to_circ(g_wire_line("h","off")),2,1,i) + end + return left +end + +function bl_bundle_horisontal(count,length) + local c = new_circ() + for x=1,length do + for y=1,count do + blinsert(c,gnode_to_circ(g_wire_line("h","off")),x,1,y) + end + end + return c +end + + +function add_down_connection(size) + local down = new_circ() + for i=1,size do + local hshift = (i-1)*2+1 + blinsert(down,gnode_to_circ(g_wire_line("v","off")),hshift,1,1) + blinsert(down,gnode_to_circ(g_wire_line("v","off")),hshift,1,2) + end + return down +end + +function bl_t_bundle_to_down_step2_and_down_conn(size) + -- crossing + local c = bl_t_bundle_to_down_step2(size) + + -- adding connections + local down = add_down_connection(size) + + local all = new_circ() + blinsert(all,down,1,1,1) + blinsert(all,c,1,1,3) + return all + +end + + +function bl_t_bundle_to_down_step2_and_connections(size) + + -- crossing + local c = bl_t_bundle_to_down_step2(size) + + -- connections + local left = add_left_connection(size) + local down = add_down_connection(size) + + local all = new_circ() + blinsert(all,left,1,1,3) + blinsert(all,down,3,1,1) + blinsert(all,c,3,1,3) + return all + +end + + + +------------------------------------------------------------------------ +-- generating circuits +------------------------------------------------------------------------ + + +function bl_frame(gate, gstate, vstate, hstate,rot) + -- rot = "up" | "down" + + local c = {} + c.nodes = {} + c.metas = {} + + if gate == "diode" or gate == "not" then + -- vertical wires + set(c,1,1, g_wire_t("r",vstate)) + set(c,2,1, g_wire_bend("lu",vstate)) + set(c,1,2, g_wire_line("v",vstate)) + + if gate == "diode" then + set(c,2,2, g_gate_diode(gstate,rot)) + else + set(c,2,2, g_gate_not(gstate,rot)) + end + + --horizontal wires + set(c,2,3, g_wire_t("d",hstate)) + + else -- wire + set(c,1,1, g_wire_line("v",vstate)) + set(c,1,2, g_wire_line("v",vstate)) + set(c,2,3, g_wire_line("h",hstate)) + end + + -- crossing + if hstate == "off" and vstate == "off" then + set(c,1,3, g_wire_cross("off")) + elseif hstate == "on" and vstate == "off" then + set(c,1,3, g_wire_cross("h")) + elseif hstate == "off" and vstate == "on" then + set(c,1,3, g_wire_cross("v")) + else + set(c,1,3, g_wire_cross("on")) + end + + c.nodes.sx = 2 + c.nodes.sy = 1 + c.nodes.sz = 3 + c.metas.sx = 2 + c.metas.sy = 1 + c.metas.sz = 3 + return c +end + + +function bl_ff(data) + local c = new_circ() + set(c,1,1,g_ff("off","up",data)) + set(c,1,2,g_wire_cross("off")) + set(c,2,2,g_wire_t("d","off")) + set(c,2,1,g_wire_bend("lu","off")) + c.nodes.sx = 2 + c.nodes.sy = 1 + c.nodes.sz = 2 + c.metas.sx = 2 + c.metas.sy = 1 + c.metas.sz = 2 + return c +end + + +function bl_register(vvalue) + local c = new_circ() + for i=1,#vvalue do + local char = string.sub(vvalue,i,i) + if char == "0" then + blinsert(c,bl_ff("off"),(i-1)*2+1,1,1) + else + blinsert(c,bl_ff("on"),(i-1)*2+1,1,1) + end + end + return c +end + + +function bl_state_value_in(v,hstate) + -- eg. v = "01011" + local len = string.len(v) + local vstate = "off" + local c = new_circ() + local rot = "up" + + local curri = 1 + for i=1,len do + local char = string.sub(v,i,i) + if char == "0" then + blinsert(c,bl_frame("diode",vstate, vstate,hstate,rot), (i-1)*2+1,1,1 ) + else + blinsert(c,bl_frame("not",inverse_state(vstate), vstate,hstate,rot), (i-1)*2+1,1,1 ) + end + end + + return c +end + +function bl_state_value_out(v,hv,vvalue) + -- eg. v = "01011" + -- eg. hv = "on" | "off" + -- eg. vvalue "010110" + local len = string.len(v) + local c = new_circ() + local rot = "down" + + local curri = 1 + for i=1,len do + local char = string.sub(v,i,i) + local out_wire_state = switch_01_to_onoff(string.sub(vvalue,i,i)) + if char == "1" then + blinsert(c,bl_frame("diode",hv, out_wire_state, hv, rot), (i-1)*2+1,1,1 ) + else + blinsert(c,bl_frame("wire",hv, out_wire_state, hv, rot), (i-1)*2+1,1,1 ) + end + end + return c +end + + +function bl_pin_value(pins, defined_pins,hstate) + local hpins = list_to_hash(pins) + local c = new_circ() + local rot = "up" + local vstate = "off" + for i=1,#defined_pins do + local v = defined_pins[i] + local p = (i-1)*2+1 + if hpins[v] ~= nil then + blinsert(c,bl_frame("not",inverse_state(vstate), vstate, hstate,rot),p,1,1) + elseif hpins[add_negation(v)] ~= nil then + blinsert(c,bl_frame("diode",vstate, vstate, hstate,rot), p,1,1) + else + blinsert(c,bl_frame("wire",vstate, vstate, hstate,rot), p,1,1) + end + end + return c +end + + + +function generate_ifthens(db) + local c = new_circ() + + -- computing output state + local cumulative_state = string.rep("0", db.state_bitsize) + for state,ifs in pairs(db.trans) do + for _,v in pairs(ifs) do + local pins = v.pins + local valuein = db.state_values[state] + local valueout = db.state_values[v.state] + local if_pin_state + if has_positive_pin(pins) then + if_pin_state = "on" + else + if_pin_state = "off" + end + + local if_state_state + if is_all_zeros(valuein) then + if_state_state = "off" + else + if_state_state = "on" + end + local if_state = or_state(if_pin_state, if_state_state) + + if if_state == "off" then -- because of negation in front of it + -- so this one is active + cumulative_state = or_value(cumulative_state,valueout) + end + end + end + + -- generating + local thens = new_circ() + local ifs = new_circ() + local i = 1 + for state,ife in pairs(db.trans) do + for _,v in pairs(ife) do + local pins = v.pins + local valuein = db.state_values[state] + local valueout = db.state_values[v.state] + local defined_pins = db.inputs_used + + -- if state == 0000 then skip generating + if not is_all_zeros(valueout) then + + local if_pin_state + if has_positive_pin(pins) then + if_pin_state = "on" + else + if_pin_state = "off" + end + + local if_state_state + if is_all_zeros(valuein) then + if_state_state = "off" + else + if_state_state = "on" + end + + local if_state = or_state(if_pin_state, if_state_state) + + + local bl_statein = bl_state_value_in(valuein,if_state) + local bl_pinsin = bl_pin_value(pins, defined_pins, if_state) + local bl_stateout = bl_state_value_out(valueout,inverse_state(if_state), cumulative_state) + + -- putting all together + local curr_pos = (i-1)*3+1 + blinsert(thens,bl_stateout,1,1,curr_pos) + + blinsert(ifs, gnode_to_circ(g_gate_not(inverse_state(if_state) ,"left")),1,1,curr_pos+2) + blinsert(ifs, bl_statein, 2,1,curr_pos) + blinsert(ifs, bl_pinsin, 1+1+ db.state_bitsize*2,1,curr_pos) + + i=i+1 + end + end + end + blinsert(c,thens,1,1,1) + blinsert(c,ifs, 1+db.state_bitsize*2,1,1) + blinsert(c,bl_register(cumulative_state), 1, 1, (i-1)*3+1 ) + + blinsert(c,bl_bend_bundle_from_down_to_right_step2(db.state_bitsize),1,1,(i-1)*3+1 +2) + blinsert(c,bl_t_bundle_to_down_step2_and_connections(db.state_bitsize), + db.state_bitsize*2,1,(i-1)*3+1 ) + + + local posy = (i-1)*3+1 +2 + local posx = 2*2*db.state_bitsize + 2 + blinsert(c,bl_bundle_horisontal(db.state_bitsize,2*#db.inputs_used),posx,1,posy) + return c +end + + +function pins_to_value(lpins,defined_output_pins) + local hpins = list_to_hash(lpins) + local v = "" + for _,p in ipairs(defined_output_pins) do + if hpins[p] ~= nil then + if not is_negated(p) then + v = v .. "1" + else + v = v .. "0" + end + else + v=v.."0" + end + end + return v +end + + +function generate_output_ifstate_thenpins(db) + local c = new_circ() + local defined_pins = db.outputs_used + + -- computing output state + local cumulative_state = string.rep("0", #defined_pins) + for state,out_pins in pairs(db.outputs) do + local value = db.state_values[state] + if value ~= nil then + if is_all_zeros(value) then + cumulative_state = pins_to_value(out_pins,defined_pins ) + end + end + end + +-- generating + local ifs = new_circ() + local thens = new_circ() + local nots = new_circ() + local i = 1 + for state,out_pins in pairs(db.outputs) do + local value = db.state_values[state] + if value == nil then return new_circ() end --aborting all, no states + + local pinso = pins_to_value(out_pins,defined_pins) + + local if_state_state + if is_all_zeros(value) then + if_state = "off" + else + if_state = "on" + end + + local bl_state = bl_state_value_in(value,if_state) + local bl_stateout = bl_state_value_out(pinso,inverse_state(if_state), cumulative_state) + + -- putting all together + local curr_pos = (i-1)*3+1 + blinsert(ifs,bl_state,1,1,curr_pos) + blinsert(nots, gnode_to_circ(g_gate_not(inverse_state(if_state) ,"right")), + 1,1,curr_pos+2) + + blinsert(thens, bl_stateout, 1,1,curr_pos) + i=i+1 + + end + + blinsert(c,ifs,1,1,1) + blinsert(c,nots, db.state_bitsize*2+1,1,1) + blinsert(c,thens,db.state_bitsize*2+2,1,1) + if count_hash(db.outputs) ~= 0 then + blinsert(c,bl_t_bundle_to_down_step2_and_down_conn(db.state_bitsize), + 1,1,(i-1)*3+1 ) + end + + return c + +end + +----------------------------------------------------------------- + +function fill_with_air(c) + if c == nil then return nil end + local sx = c.nodes.sx + local sy = c.nodes.sy + local sz = c.nodes.sz + + for ix=1,sx do + for iy=1,sy do + for iz=1,sz do + if m3_get(c.nodes,ix,iy,iz) == nil then + m3_set(c.nodes,ix,iy,iz, {name="air",param2=0}) + end + end + end + end + -- do I have to fill meta too? +end + + + + +function fsmgenerate_raw(db) + local ifth = generate_ifthens(db) + local ifout = generate_output_ifstate_thenpins(db) + local c = new_circ() + + local hsize = ifth.nodes.sx + local vsize = ifth.nodes.sz + + local hsize2 = ifout.nodes.sx + local vsize2 = ifout.nodes.sz + + local max = math.max(vsize,vsize2) + + + blinsert(c,ifth,1,1,max+1-vsize) + blinsert(c,ifout,hsize+2,1,max-vsize2+1 ) + + blinsert(c,bl_bundle_horisontal(db.state_bitsize,1), + 1+ifth.nodes.sx,1, max+1-db.state_bitsize) + + fill_with_air(c) + return c +end + +function generate_circuit(bin,options) + return fsmgenerate_raw(bin) +end diff --git a/mods/mesecons_x/mesecons_autotools/fsm/lib.lua b/mods/mesecons_x/mesecons_autotools/fsm/lib.lua new file mode 100644 index 00000000..0959dbc7 --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/fsm/lib.lua @@ -0,0 +1,11 @@ +function DeepCopy(Src) + local Dest = {} + if type(Src) ~= "table" then return Src end + for Key, Val in pairs(Src) do + + Key = type(Key) == "table" and DeepCopy(Key) or Key + Val = type(Val) == "table" and DeepCopy(Val) or Val + Dest[Key] = Val + end + return Dest +end diff --git a/mods/mesecons_x/mesecons_autotools/fsm/priority.lua b/mods/mesecons_x/mesecons_autotools/fsm/priority.lua new file mode 100644 index 00000000..7c6f37e5 --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/fsm/priority.lua @@ -0,0 +1,113 @@ +function pins_to_area(pins,defined_pins) + -- pins : list + + local part = {} + for _,pin in pairs(pins) do + if is_negated(pin) then + part[drop_negation(pin)] = false + else + part[pin] = true + end + end + + local parts = {} + table.insert(parts,part) + + local area = {} + + area.vars = defined_pins + area.parts = parts + + return area +end + +function part_to_pins(part) + local list = {} + for k,v in pairs(part) do + if v == true then + table.insert(list, k) + else + table.insert(list, add_negation(k)) + end + end + return list +end + +function apply_priority_state(list_ifs,defined_pins) + if list_ifs == nil then return nil end + if #list_ifs == 0 then return {} end + local new_ifs = {} + local aggreg_area = pins_to_area(list_ifs[1].pins,defined_pins) + + table.insert(new_ifs,list_ifs[1]) + + for i=2,#list_ifs do + local curr_area = pins_to_area(list_ifs[i].pins,defined_pins) + local new_area = area_sub(curr_area,aggreg_area) + aggreg_area = area_add(aggreg_area,curr_area) + + for _,part in pairs(new_area.parts) do + table.insert(new_ifs, { pins = part_to_pins(part), state = list_ifs[i].state }) + end + end + return new_ifs +end + +function apply_priority_special_case_no_input_pins(db) + -- no inputs, adding one phantom input + table.insert(db.inputs_used, "x") + apply_priority(db) + db.inputs_used = {} + +end + +-- changes db.trans +function apply_priority(db) + if db.inputs_used == nil then return end + if #db.inputs_used == 0 then + if count_hash(db.trans) == 0 then + return + else + apply_priority_special_case_no_input_pins(db) + return + end + end + + + local new_trans = {} + for state, v in pairs(db.trans) do + new_trans[state] = apply_priority_state(v, db.inputs_used) + end + db.trans = new_trans +end + +------------------------------------------------------------------------ +-- other algorithms +------------------------------------------------------------------------ + +function clear_empty_transitions(db) + for state,ifs in pairs(db.trans) do + if #ifs == 0 then + db.trans[state] = nil + end + end +end + + +------------------------------------------------------------------------ +-- default behavior +------------------------------------------------------------------------ + + +function add_default_loops(db) + -- if no transition, stay in current state + local hreachables = db.reachables + for s,_ in pairs(hreachables) do + if db.trans[s] == nil then + db.trans[s] = {} + end + table.insert(db.trans[s], { pins = {} , state = s } ) + end +end + + diff --git a/mods/mesecons_x/mesecons_autotools/init.lua b/mods/mesecons_x/mesecons_autotools/init.lua new file mode 100644 index 00000000..d712357a --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/init.lua @@ -0,0 +1,323 @@ +dofile(minetest.get_modpath("mesecons_autotools").."/debug.lua"); + + +mesecons_autotools = {} +mesecons_autotools.users = {} +mesecons_autotools.actions = {} + + +-- Basic functions + +--[[ +mesecons_autotools = +{ + user_name = { + pos[1..2] = { x = number, y = number, z = number} + stack_direction = {x,y,z} + stack_counter = number + entities = + options = { + option1 = value1 + option2 = value2 + } + } + + user_name = ... +]]-- + +mesecons_autotools.set_pos = function(user,nr,pos) + if mesecons_autotools.users[user] == nil then + mesecons_autotools.users[user] = {} + end + if mesecons_autotools.users[user].pos == nil then + mesecons_autotools.users[user].pos = {} + end + if pos == nil then + mesecons_autotools.users[user].pos[nr] = nil + else + local p = vector.new(pos) + mesecons_autotools.users[user].pos[nr] = p + end +end + +mesecons_autotools.get_pos = function(user,nr) + if mesecons_autotools.users[user] == nil then + return nil + end + if mesecons_autotools.users[user].pos == nil then + return nil + end + if mesecons_autotools.users[user].pos[nr] == nil then + return nil + else + return vector.new(mesecons_autotools.users[user].pos[nr]) + end + + +end + +mesecons_autotools.get_stack_counter = function(user) + if mesecons_autotools.users[user] == nil then + mesecons_autotools.users[user] = {} + end + + if mesecons_autotools.users[user].stack_counter == nil then + mesecons_autotools.users[user].stack_counter = 0 + end + + return mesecons_autotools.users[user].stack_counter +end + +mesecons_autotools.inc_stack_counter = function(user) + -- get value and create structure if needed + local count = mesecons_autotools.get_stack_counter(user) + mesecons_autotools.users[user].stack_counter = count + 1 +end + +mesecons_autotools.dec_stack_counter = function(user) + -- get value and create structure if needed + local count = mesecons_autotools.get_stack_counter(user) + if count == 0 then return end + mesecons_autotools.users[user].stack_counter = count - 1 +end + +mesecons_autotools.zero_stack_counter = function(user) + -- get value and create structure if needed + local count = mesecons_autotools.get_stack_counter(user) + mesecons_autotools.users[user].stack_counter = 0 +end + +mesecons_autotools.zero_stack_direction = function(user) + if mesecons_autotools.users[user] == nil then + mesecons_autotools.users[user] = {} + end + mesecons_autotools.users[user].stack_direction = { x = 0, y = 0, z =0 } +end + +mesecons_autotools.set_stack_direction = function(user,direction) + -- get rid of nils + mesecons_autotools.zero_stack_direction(user) + mesecons_autotools.users[user].stack_direction = direction +end + +mesecons_autotools.get_stack_direction = function(user) + if mesecons_autotools.users[user] == nil then + mesecons_autotools.users[user] = {} + end + if mesecons_autotools.users[user].stack_direction == nil then + mesecons_autotools.users[user].stack_direction = { x = 0, y = 0, z =0 } + end + return mesecons_autotools.users[user].stack_direction +end + + +mesecons_autotools.set_option = function(user,field,value) + if mesecons_autotools.users[user] == nil then + mesecons_autotools.users[user] = {} + end + if mesecons_autotools.users[user].options == nil then + mesecons_autotools.users[user].options = {} + end + mesecons_autotools.users[user].options[field] = value +end + +mesecons_autotools.get_option = function(user,field) + if mesecons_autotools.users[user] == nil then + return nil + end + if mesecons_autotools.users[user].options == nil then + return nil + end + return mesecons_autotools.users[user].options[field] +end + +mesecons_autotools.is_full_selection = function(user) + if mesecons_autotools.get_pos(user,1) == nil then return false end + if mesecons_autotools.get_pos(user,2) == nil then return false end + return true +end + + +-- Actions/Callbacks ('user' clicked 'button' on 'pos' using 'tool') + +-- button = "left" | "right" +-- pos = { x = number, y = number, z = number } +-- tool = "black" | "red" | ... +-- type = "air" | "block" + +mesecons_autotools.execute_action = function(tool,button,type,user,pos,rad,under) +-- if user == nil then return end +-- if pos == nil then return end + if tool == nil then return end + if button == nil then return end + if type == nil then return end + if rad == nil then return end + -- under == nil can be nil + + if mesecons_autotools.actions[tool] == nil then return end + if mesecons_autotools.actions[tool][button] == nil then return end + if mesecons_autotools.actions[tool][button][type] == nil then return end + + + mesecons_autotools.actions[tool][button][type](user,pos,rad,under) + +end + + + +mesecons_autotools.register_action = function(tool,button,type,action) + if mesecons_autotools.actions[tool] == nil then + mesecons_autotools.actions[tool] = {} + end + if mesecons_autotools.actions[tool][button] == nil then + mesecons_autotools.actions[tool][button] = {} + end + if mesecons_autotools.actions[tool][button][type] == nil then + mesecons_autotools.actions[tool][button][type] = {} + end + mesecons_autotools.actions[tool][button][type] = action +end + + +function is_in_list(list,value) + + for _,v in ipairs(list) do + if v == value then return true end + + end + return false + +end + + + function ref_place(pos,node) + if minetest.get_item_group(node.name, "mesecon_needs_receiver") == 1 then + mesecon.receiver_place(pos) + end + end + + function ref_remove(pos,node) + if minetest.get_item_group(node.name, "mesecon_needs_receiver") == 1 then + mesecon.receiver_remove(pos) + end + end + + + + +mesecons_autotools.set_node = function(pos,node,why) + + if why == nil then + minetest.set_node(pos,node) + else + + if is_in_list({"start_node","place+refresh"},why) then + local n = minetest.get_node(pos) + mesecon.on_dignode(pos,n) + ref_remove(pos,n) + + + minetest.set_node(pos,node) + mesecon.on_placenode(pos,node) + ref_place(pos,node) + end + + + if is_in_list({"start_node","middle_node"},why) then + minetest.set_node(pos,node) + mesecon.on_placenode(pos,node) + ref_place(pos,node) + end + + + + + + if is_in_list({"delete"},why) then + local n = minetest.get_node(pos) + mesecon.on_dignode(pos,n) + ref_remove(pos,n) + + minetest.set_node(pos,node) + mesecon.on_placenode(pos,node) + ref_place(pos,node) + + end + + + if is_in_list({"delete_crossover","delete_end"},why) then -- + local n = minetest.get_node(pos) + mesecon.on_dignode(pos,n) + ref_remove(pos,n) + + minetest.set_node(pos,node) + mesecon.on_placenode(pos,node) + ref_place(pos,node) + + + + end + + if is_in_list({"paste_circuit"},why) then + minetest.set_node(pos,node) + end + + if is_in_list({"add_wire"},why) then + minetest.set_node(pos,node) + end + + if is_in_list({"red"},why) then + local n = minetest.get_node(pos) + mesecon.on_dignode(pos,n) + ref_remove(pos,n) + + minetest.set_node(pos,node) + mesecon.on_placenode(pos,node) + ref_place(pos,node) + + end + + if is_in_list({"put_tail_wires"},why) then + minetest.set_node(pos,node) + end + + if is_in_list({"copy"},why) then + minetest.set_node(pos,node) + end + + if is_in_list({"paste_from_buffor"},why) then + minetest.set_node(pos,node) + end + + + end + +end + + +-- Register Tools + +dofile(minetest.get_modpath("mesecons_autotools").."/tools.lua"); + + +-- Register Rendering + +dofile(minetest.get_modpath("mesecons_autotools").."/render.lua"); + +-- Regiser Circuit + +dofile(minetest.get_modpath("mesecons_autotools").."/book/circuit.lua"); +--dofile(minetest.get_modpath("mesecons_autotools").."/book/library.lua"); +dofile(minetest.get_modpath("mesecons_autotools").."/book/file.lua"); + +-- Register FSM generator +dofile(minetest.get_modpath("mesecons_autotools").."/fsm/fsm.lua"); + +-- Register Formula generator +--dofile(minetest.get_modpath("mesecons_autotools").."/formula/formula.lua"); + + +-- Register chatcommands + +dofile(minetest.get_modpath("mesecons_autotools").."/commands/all_commands.lua"); + diff --git a/mods/mesecons_x/mesecons_autotools/render.lua b/mods/mesecons_x/mesecons_autotools/render.lua new file mode 100644 index 00000000..56026dd9 --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/render.lua @@ -0,0 +1,156 @@ +-- Remove entities +local function clear_selection(user) + if mesecons_autotools.users[user] == nil then + mesecons_autotools.users[user] = {} + end + if mesecons_autotools.users[user].entities == nil then + mesecons_autotools.users[user].entities = {} + end + + + + for _,v in pairs(mesecons_autotools.users[user].entities) do + v:remove() + end + mesecons_autotools.users[user].entities = {} + + +end + + +-- Register entities +minetest.register_entity(":mesecons_autotools:pos1", { + initial_properties = { + visual = "cube", + visual_size = {x=1.11, y=1.11, }, + textures = {"pos1.png", "pos1.png", + "pos1.png", "pos1.png", + "pos1.png", "pos1.png"}, + collisionbox = {-0.55, -0.55, -0.55, 0.55, 0.55, 0.55}, + physical = false, + static_save = false, + }, + on_activate = function(self, staticdata, dtime_s) + end, + + on_punch = function(self,hitter) + end, + on_blast = function(self, damage) + return false, false, {} -- don't damage or knockback + end, +}) +minetest.register_entity(":mesecons_autotools:pos2", { + initial_properties = { + visual = "cube", + visual_size = {x=1.1, y=1.1}, + textures = {"pos2.png", "pos2.png", + "pos2.png", "pos2.png", + "pos2.png", "pos2.png"}, + collisionbox = {-0.55, -0.55, -0.55, 0.55, 0.55, 0.55}, + physical = false, + static_save = false, + }, + on_activate = function(self, staticdata, dtime_s) + end, + + on_punch = function(self,hitter) + end, + + on_blast = function(self, damage) + return false, false, {} -- don't damage or knockback + end, +}) +minetest.register_entity(":mesecons_autotools:wall", { + initial_properties = { + visual = "upright_sprite", + textures = {"wall.png"}, + visual_size = {x=10, y=10}, + physical = false, + static_save = false, + }, + on_activate = function(self, staticdata, dtime_s) + end, + + on_punch = function(self,hitter) + end, + + on_blast = function(self, damage) + return false, false, {} -- don't damage or knockback + end, +}) + +minetest.register_entity(":mesecons_autotools:pos", { + initial_properties = { + visual = "cube", + visual_size = {x=1.1, y=1.1}, + textures = {"pos.png", "pos.png", + "pos.png", "pos.png", + "pos.png", "pos.png"}, + collisionbox = {-0.55, -0.55, -0.55, 0.55, 0.55, 0.55}, + physical = false, + static_save = false, + }, + on_activate = function(self, staticdata, dtime_s) + end, + + on_punch = function(self,hitter) + end, + + on_blast = function(self, damage) + return false, false, {} -- don't damage or knockback + end, +}) + +--[[ not used: TODO remove +local function generate_corners(user) + local pos = {} + pos[1] = mesecons_autotools.get_pos(user,1) + pos[2] = mesecons_autotools.get_pos(user,2) + + if pos[1] == nil then return end + if pos[2] == nil then return end + + + local list = {} + for xi = 1,2 do + for yi = 1,2 do + for zi = 1,2 do + local p = { x = pos[xi].x , y = pos[yi].y , z = pos[zi].z } + if not vector.equals(p,pos[1]) then + table.insert(list,p) + end + end + end + end + return list +end +]]-- + + +local function show_selection(user) + local pos1 = mesecons_autotools.get_pos(user,1) + local pos2 = mesecons_autotools.get_pos(user,2) + + if pos1 ~= nil then + local e1 = minetest.add_entity(pos1,"mesecons_autotools:pos1") + table.insert(mesecons_autotools.users[user].entities, e1) + end + + if pos2 ~= nil then + local e2 = minetest.add_entity(pos2,"mesecons_autotools:pos2") + table.insert(mesecons_autotools.users[user].entities, e2) + end + + + +end + + + +mesecons_autotools.render = function(user) + clear_selection(user) + show_selection(user) +end + + + diff --git a/mods/mesecons_x/mesecons_autotools/textures/and0.png b/mods/mesecons_x/mesecons_autotools/textures/and0.png new file mode 100644 index 00000000..fa450f72 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/and0.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/and1.png b/mods/mesecons_x/mesecons_autotools/textures/and1.png new file mode 100644 index 00000000..2f1139d4 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/and1.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/and2.png b/mods/mesecons_x/mesecons_autotools/textures/and2.png new file mode 100644 index 00000000..28e8adb4 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/and2.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/and3.png b/mods/mesecons_x/mesecons_autotools/textures/and3.png new file mode 100644 index 00000000..4c7cadd3 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/and3.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/black.png b/mods/mesecons_x/mesecons_autotools/textures/black.png new file mode 100644 index 00000000..2f1ee627 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/black.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/black_x.png b/mods/mesecons_x/mesecons_autotools/textures/black_x.png new file mode 100644 index 00000000..5fe7941b Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/black_x.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/blue.png b/mods/mesecons_x/mesecons_autotools/textures/blue.png new file mode 100644 index 00000000..6869edf5 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/blue.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/cancel.png b/mods/mesecons_x/mesecons_autotools/textures/cancel.png new file mode 100644 index 00000000..e0cdebed Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/cancel.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/circuit_empty.png b/mods/mesecons_x/mesecons_autotools/textures/circuit_empty.png new file mode 100644 index 00000000..1623d00b Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/circuit_empty.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/circuit_full.png b/mods/mesecons_x/mesecons_autotools/textures/circuit_full.png new file mode 100644 index 00000000..dd737597 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/circuit_full.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/circuit_test.png b/mods/mesecons_x/mesecons_autotools/textures/circuit_test.png new file mode 100644 index 00000000..1b243d3e Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/circuit_test.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/corner0.png b/mods/mesecons_x/mesecons_autotools/textures/corner0.png new file mode 100644 index 00000000..1272d0ce Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/corner0.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/corner1.png b/mods/mesecons_x/mesecons_autotools/textures/corner1.png new file mode 100644 index 00000000..d0e64d47 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/corner1.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/corner2.png b/mods/mesecons_x/mesecons_autotools/textures/corner2.png new file mode 100644 index 00000000..37e1d445 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/corner2.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/corner3.png b/mods/mesecons_x/mesecons_autotools/textures/corner3.png new file mode 100644 index 00000000..550e5c2c Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/corner3.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/corssover.png b/mods/mesecons_x/mesecons_autotools/textures/corssover.png new file mode 100644 index 00000000..ef7e8710 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/corssover.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/diode0.png b/mods/mesecons_x/mesecons_autotools/textures/diode0.png new file mode 100644 index 00000000..309ff3fa Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/diode0.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/diode1.png b/mods/mesecons_x/mesecons_autotools/textures/diode1.png new file mode 100644 index 00000000..eed69eb5 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/diode1.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/diode2.png b/mods/mesecons_x/mesecons_autotools/textures/diode2.png new file mode 100644 index 00000000..6c052c36 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/diode2.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/diode3.png b/mods/mesecons_x/mesecons_autotools/textures/diode3.png new file mode 100644 index 00000000..69b3639f Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/diode3.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/drop_btn.png b/mods/mesecons_x/mesecons_autotools/textures/drop_btn.png new file mode 100644 index 00000000..c79b396a Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/drop_btn.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/empty.png b/mods/mesecons_x/mesecons_autotools/textures/empty.png new file mode 100644 index 00000000..f0d00bc9 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/empty.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/ff0.png b/mods/mesecons_x/mesecons_autotools/textures/ff0.png new file mode 100644 index 00000000..66f2ae7a Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/ff0.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/ff1.png b/mods/mesecons_x/mesecons_autotools/textures/ff1.png new file mode 100644 index 00000000..fd8e005e Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/ff1.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/ff2.png b/mods/mesecons_x/mesecons_autotools/textures/ff2.png new file mode 100644 index 00000000..c5fb7749 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/ff2.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/ff3.png b/mods/mesecons_x/mesecons_autotools/textures/ff3.png new file mode 100644 index 00000000..92914aa2 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/ff3.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/empty.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/empty.png new file mode 100644 index 00000000..f0d00bc9 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/empty.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/and0.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/and0.png new file mode 100644 index 00000000..fa450f72 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/and0.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/and1.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/and1.png new file mode 100644 index 00000000..2f1139d4 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/and1.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/and2.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/and2.png new file mode 100644 index 00000000..28e8adb4 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/and2.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/and3.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/and3.png new file mode 100644 index 00000000..4c7cadd3 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/and3.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/diode0.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/diode0.png new file mode 100644 index 00000000..309ff3fa Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/diode0.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/diode1.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/diode1.png new file mode 100644 index 00000000..eed69eb5 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/diode1.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/diode2.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/diode2.png new file mode 100644 index 00000000..6c052c36 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/diode2.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/diode3.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/diode3.png new file mode 100644 index 00000000..69b3639f Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/diode3.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/nand0.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/nand0.png new file mode 100644 index 00000000..88b2ba8c Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/nand0.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/nand1.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/nand1.png new file mode 100644 index 00000000..0c659eed Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/nand1.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/nand2.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/nand2.png new file mode 100644 index 00000000..da3a2802 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/nand2.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/nand3.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/nand3.png new file mode 100644 index 00000000..cfc7f3e6 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/nand3.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/nor0.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/nor0.png new file mode 100644 index 00000000..e5866909 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/nor0.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/nor1.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/nor1.png new file mode 100644 index 00000000..86aec63e Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/nor1.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/nor2.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/nor2.png new file mode 100644 index 00000000..d6a9784e Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/nor2.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/nor3.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/nor3.png new file mode 100644 index 00000000..c7de7437 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/nor3.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/not0.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/not0.png new file mode 100644 index 00000000..9ba61fec Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/not0.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/not1.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/not1.png new file mode 100644 index 00000000..7a259562 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/not1.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/not2.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/not2.png new file mode 100644 index 00000000..e2ae188d Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/not2.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/not3.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/not3.png new file mode 100644 index 00000000..6f65e955 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/not3.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/or0.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/or0.png new file mode 100644 index 00000000..87cd8279 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/or0.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/or1.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/or1.png new file mode 100644 index 00000000..c008c925 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/or1.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/or2.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/or2.png new file mode 100644 index 00000000..895a46fe Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/or2.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/or3.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/or3.png new file mode 100644 index 00000000..676c6d55 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/or3.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/xor0.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/xor0.png new file mode 100644 index 00000000..3f783e98 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/xor0.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/xor1.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/xor1.png new file mode 100644 index 00000000..224e98b1 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/xor1.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/xor2.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/xor2.png new file mode 100644 index 00000000..b3e36c44 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/xor2.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/xor3.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/xor3.png new file mode 100644 index 00000000..44059d03 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate/xor3.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/and3/jeija_gate3_and3r0.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/and3/jeija_gate3_and3r0.png new file mode 100644 index 00000000..d5027737 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/and3/jeija_gate3_and3r0.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/and3/jeija_gate3_and3r1.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/and3/jeija_gate3_and3r1.png new file mode 100644 index 00000000..617150e3 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/and3/jeija_gate3_and3r1.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/and3/jeija_gate3_and3r2.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/and3/jeija_gate3_and3r2.png new file mode 100644 index 00000000..665e1218 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/and3/jeija_gate3_and3r2.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/and3/jeija_gate3_and3r3.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/and3/jeija_gate3_and3r3.png new file mode 100644 index 00000000..04c6a488 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/and3/jeija_gate3_and3r3.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/nand3/jeija_gate3_nand3r0.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/nand3/jeija_gate3_nand3r0.png new file mode 100644 index 00000000..30e4c8a0 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/nand3/jeija_gate3_nand3r0.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/nand3/jeija_gate3_nand3r1.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/nand3/jeija_gate3_nand3r1.png new file mode 100644 index 00000000..623870dd Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/nand3/jeija_gate3_nand3r1.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/nand3/jeija_gate3_nand3r2.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/nand3/jeija_gate3_nand3r2.png new file mode 100644 index 00000000..3ac0fa65 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/nand3/jeija_gate3_nand3r2.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/nand3/jeija_gate3_nand3r3.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/nand3/jeija_gate3_nand3r3.png new file mode 100644 index 00000000..77951be0 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/nand3/jeija_gate3_nand3r3.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/nor3/jeija_gate3_nor3r0.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/nor3/jeija_gate3_nor3r0.png new file mode 100644 index 00000000..a3a0c3a0 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/nor3/jeija_gate3_nor3r0.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/nor3/jeija_gate3_nor3r1.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/nor3/jeija_gate3_nor3r1.png new file mode 100644 index 00000000..b73a7ccf Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/nor3/jeija_gate3_nor3r1.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/nor3/jeija_gate3_nor3r2.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/nor3/jeija_gate3_nor3r2.png new file mode 100644 index 00000000..17f13d95 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/nor3/jeija_gate3_nor3r2.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/nor3/jeija_gate3_nor3r3.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/nor3/jeija_gate3_nor3r3.png new file mode 100644 index 00000000..9a9dac0e Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/nor3/jeija_gate3_nor3r3.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/nor3/jeija_gate_nor3.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/nor3/jeija_gate_nor3.png new file mode 100644 index 00000000..774fa234 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/nor3/jeija_gate_nor3.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/or3/jeija_gate3_or3r0.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/or3/jeija_gate3_or3r0.png new file mode 100644 index 00000000..e68caa68 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/or3/jeija_gate3_or3r0.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/or3/jeija_gate3_or3r1.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/or3/jeija_gate3_or3r1.png new file mode 100644 index 00000000..8303af94 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/or3/jeija_gate3_or3r1.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/or3/jeija_gate3_or3r2.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/or3/jeija_gate3_or3r2.png new file mode 100644 index 00000000..61974530 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/or3/jeija_gate3_or3r2.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/or3/jeija_gate3_or3r3.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/or3/jeija_gate3_or3r3.png new file mode 100644 index 00000000..c788f2a9 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/gate3/or3/jeija_gate3_or3r3.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/pink.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/pink.png new file mode 100644 index 00000000..e03b52b8 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/pink.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/regs/ff0.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/regs/ff0.png new file mode 100644 index 00000000..66f2ae7a Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/regs/ff0.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/regs/ff1.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/regs/ff1.png new file mode 100644 index 00000000..fd8e005e Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/regs/ff1.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/regs/ff2.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/regs/ff2.png new file mode 100644 index 00000000..c5fb7749 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/regs/ff2.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/regs/ff3.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/regs/ff3.png new file mode 100644 index 00000000..92914aa2 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/regs/ff3.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/regs/latch0.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/regs/latch0.png new file mode 100644 index 00000000..089b64ba Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/regs/latch0.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/regs/latch1.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/regs/latch1.png new file mode 100644 index 00000000..f545b81c Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/regs/latch1.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/regs/latch2.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/regs/latch2.png new file mode 100644 index 00000000..f2ed0483 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/regs/latch2.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/regs/latch3.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/regs/latch3.png new file mode 100644 index 00000000..16f1ffea Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/regs/latch3.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/unknown.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/unknown.png new file mode 100644 index 00000000..f91b9eac Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/unknown.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/corner0.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/corner0.png new file mode 100644 index 00000000..1272d0ce Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/corner0.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/corner1.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/corner1.png new file mode 100644 index 00000000..d0e64d47 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/corner1.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/corner2.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/corner2.png new file mode 100644 index 00000000..37e1d445 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/corner2.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/corner3.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/corner3.png new file mode 100644 index 00000000..550e5c2c Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/corner3.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/corssover.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/corssover.png new file mode 100644 index 00000000..ef7e8710 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/corssover.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/tjunction0.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/tjunction0.png new file mode 100644 index 00000000..5c5fa7b6 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/tjunction0.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/tjunction1.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/tjunction1.png new file mode 100644 index 00000000..344126be Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/tjunction1.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/tjunction2.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/tjunction2.png new file mode 100644 index 00000000..9cb62015 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/tjunction2.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/tjunction3.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/tjunction3.png new file mode 100644 index 00000000..77ea4151 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/tjunction3.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/wireh.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/wireh.png new file mode 100644 index 00000000..8a5d8956 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/wireh.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/wirev.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/wirev.png new file mode 100644 index 00000000..c0fce224 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/wirev.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/xjunction.png b/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/xjunction.png new file mode 100644 index 00000000..f123fa51 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formspec/wires/xjunction.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/formula_book.png b/mods/mesecons_x/mesecons_autotools/textures/formula_book.png new file mode 100644 index 00000000..0108e996 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/formula_book.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/fsm_book.png b/mods/mesecons_x/mesecons_autotools/textures/fsm_book.png new file mode 100644 index 00000000..ff366102 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/fsm_book.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/fsm_book_empty.png b/mods/mesecons_x/mesecons_autotools/textures/fsm_book_empty.png new file mode 100644 index 00000000..3cfc8cb5 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/fsm_book_empty.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/grey.png b/mods/mesecons_x/mesecons_autotools/textures/grey.png new file mode 100644 index 00000000..fe32c335 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/grey.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_and3r0.png b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_and3r0.png new file mode 100644 index 00000000..d5027737 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_and3r0.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_and3r1.png b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_and3r1.png new file mode 100644 index 00000000..617150e3 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_and3r1.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_and3r2.png b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_and3r2.png new file mode 100644 index 00000000..665e1218 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_and3r2.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_and3r3.png b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_and3r3.png new file mode 100644 index 00000000..04c6a488 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_and3r3.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_nand3r0.png b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_nand3r0.png new file mode 100644 index 00000000..30e4c8a0 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_nand3r0.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_nand3r1.png b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_nand3r1.png new file mode 100644 index 00000000..623870dd Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_nand3r1.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_nand3r2.png b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_nand3r2.png new file mode 100644 index 00000000..3ac0fa65 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_nand3r2.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_nand3r3.png b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_nand3r3.png new file mode 100644 index 00000000..77951be0 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_nand3r3.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_nor3r0.png b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_nor3r0.png new file mode 100644 index 00000000..a3a0c3a0 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_nor3r0.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_nor3r1.png b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_nor3r1.png new file mode 100644 index 00000000..b73a7ccf Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_nor3r1.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_nor3r2.png b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_nor3r2.png new file mode 100644 index 00000000..17f13d95 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_nor3r2.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_nor3r3.png b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_nor3r3.png new file mode 100644 index 00000000..9a9dac0e Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_nor3r3.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_or3r0.png b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_or3r0.png new file mode 100644 index 00000000..e68caa68 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_or3r0.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_or3r1.png b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_or3r1.png new file mode 100644 index 00000000..8303af94 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_or3r1.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_or3r2.png b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_or3r2.png new file mode 100644 index 00000000..61974530 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_or3r2.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_or3r3.png b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_or3r3.png new file mode 100644 index 00000000..c788f2a9 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate3_or3r3.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/jeija_gate_nor3.png b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate_nor3.png new file mode 100644 index 00000000..774fa234 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/jeija_gate_nor3.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/latch0.png b/mods/mesecons_x/mesecons_autotools/textures/latch0.png new file mode 100644 index 00000000..089b64ba Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/latch0.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/latch1.png b/mods/mesecons_x/mesecons_autotools/textures/latch1.png new file mode 100644 index 00000000..f545b81c Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/latch1.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/latch2.png b/mods/mesecons_x/mesecons_autotools/textures/latch2.png new file mode 100644 index 00000000..f2ed0483 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/latch2.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/latch3.png b/mods/mesecons_x/mesecons_autotools/textures/latch3.png new file mode 100644 index 00000000..16f1ffea Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/latch3.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/library.png b/mods/mesecons_x/mesecons_autotools/textures/library.png new file mode 100644 index 00000000..4f7508db Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/library.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/nand0.png b/mods/mesecons_x/mesecons_autotools/textures/nand0.png new file mode 100644 index 00000000..88b2ba8c Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/nand0.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/nand1.png b/mods/mesecons_x/mesecons_autotools/textures/nand1.png new file mode 100644 index 00000000..0c659eed Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/nand1.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/nand2.png b/mods/mesecons_x/mesecons_autotools/textures/nand2.png new file mode 100644 index 00000000..da3a2802 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/nand2.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/nand3.png b/mods/mesecons_x/mesecons_autotools/textures/nand3.png new file mode 100644 index 00000000..cfc7f3e6 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/nand3.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/nor0.png b/mods/mesecons_x/mesecons_autotools/textures/nor0.png new file mode 100644 index 00000000..e5866909 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/nor0.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/nor1.png b/mods/mesecons_x/mesecons_autotools/textures/nor1.png new file mode 100644 index 00000000..86aec63e Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/nor1.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/nor2.png b/mods/mesecons_x/mesecons_autotools/textures/nor2.png new file mode 100644 index 00000000..d6a9784e Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/nor2.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/nor3.png b/mods/mesecons_x/mesecons_autotools/textures/nor3.png new file mode 100644 index 00000000..c7de7437 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/nor3.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/not0.png b/mods/mesecons_x/mesecons_autotools/textures/not0.png new file mode 100644 index 00000000..9ba61fec Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/not0.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/not1.png b/mods/mesecons_x/mesecons_autotools/textures/not1.png new file mode 100644 index 00000000..7a259562 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/not1.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/not2.png b/mods/mesecons_x/mesecons_autotools/textures/not2.png new file mode 100644 index 00000000..e2ae188d Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/not2.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/not3.png b/mods/mesecons_x/mesecons_autotools/textures/not3.png new file mode 100644 index 00000000..6f65e955 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/not3.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/or0.png b/mods/mesecons_x/mesecons_autotools/textures/or0.png new file mode 100644 index 00000000..87cd8279 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/or0.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/or1.png b/mods/mesecons_x/mesecons_autotools/textures/or1.png new file mode 100644 index 00000000..c008c925 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/or1.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/or2.png b/mods/mesecons_x/mesecons_autotools/textures/or2.png new file mode 100644 index 00000000..895a46fe Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/or2.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/or3.png b/mods/mesecons_x/mesecons_autotools/textures/or3.png new file mode 100644 index 00000000..676c6d55 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/or3.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/orange.png b/mods/mesecons_x/mesecons_autotools/textures/orange.png new file mode 100644 index 00000000..e0195bdf Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/orange.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/orange_up.png b/mods/mesecons_x/mesecons_autotools/textures/orange_up.png new file mode 100644 index 00000000..56ff087f Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/orange_up.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/pink.png b/mods/mesecons_x/mesecons_autotools/textures/pink.png new file mode 100644 index 00000000..e03b52b8 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/pink.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/pos.png b/mods/mesecons_x/mesecons_autotools/textures/pos.png new file mode 100644 index 00000000..8dcf687a Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/pos.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/pos1.png b/mods/mesecons_x/mesecons_autotools/textures/pos1.png new file mode 100644 index 00000000..4c304aa8 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/pos1.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/pos2.png b/mods/mesecons_x/mesecons_autotools/textures/pos2.png new file mode 100644 index 00000000..1502f165 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/pos2.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/question.png b/mods/mesecons_x/mesecons_autotools/textures/question.png new file mode 100644 index 00000000..4e577e64 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/question.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/question_hovered.png b/mods/mesecons_x/mesecons_autotools/textures/question_hovered.png new file mode 100644 index 00000000..d032445e Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/question_hovered.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/red.png b/mods/mesecons_x/mesecons_autotools/textures/red.png new file mode 100644 index 00000000..43cf848b Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/red.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/refresh.png b/mods/mesecons_x/mesecons_autotools/textures/refresh.png new file mode 100644 index 00000000..ac12fa1f Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/refresh.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/selection/pos1.png b/mods/mesecons_x/mesecons_autotools/textures/selection/pos1.png new file mode 100644 index 00000000..4c304aa8 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/selection/pos1.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/selection/pos2.png b/mods/mesecons_x/mesecons_autotools/textures/selection/pos2.png new file mode 100644 index 00000000..1502f165 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/selection/pos2.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/test.png b/mods/mesecons_x/mesecons_autotools/textures/test.png new file mode 100644 index 00000000..961ecb92 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/test.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/tjunction0.png b/mods/mesecons_x/mesecons_autotools/textures/tjunction0.png new file mode 100644 index 00000000..5c5fa7b6 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/tjunction0.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/tjunction1.png b/mods/mesecons_x/mesecons_autotools/textures/tjunction1.png new file mode 100644 index 00000000..344126be Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/tjunction1.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/tjunction2.png b/mods/mesecons_x/mesecons_autotools/textures/tjunction2.png new file mode 100644 index 00000000..9cb62015 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/tjunction2.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/tjunction3.png b/mods/mesecons_x/mesecons_autotools/textures/tjunction3.png new file mode 100644 index 00000000..77ea4151 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/tjunction3.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/tools/black.png b/mods/mesecons_x/mesecons_autotools/textures/tools/black.png new file mode 100644 index 00000000..2f1ee627 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/tools/black.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/tools/blue.png b/mods/mesecons_x/mesecons_autotools/textures/tools/blue.png new file mode 100644 index 00000000..6869edf5 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/tools/blue.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/tools/orange.png b/mods/mesecons_x/mesecons_autotools/textures/tools/orange.png new file mode 100644 index 00000000..e0195bdf Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/tools/orange.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/tools/orange_up.png b/mods/mesecons_x/mesecons_autotools/textures/tools/orange_up.png new file mode 100644 index 00000000..56ff087f Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/tools/orange_up.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/tools/red.png b/mods/mesecons_x/mesecons_autotools/textures/tools/red.png new file mode 100644 index 00000000..43cf848b Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/tools/red.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/tools/refresh.png b/mods/mesecons_x/mesecons_autotools/textures/tools/refresh.png new file mode 100644 index 00000000..ac12fa1f Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/tools/refresh.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/tools/white.png b/mods/mesecons_x/mesecons_autotools/textures/tools/white.png new file mode 100644 index 00000000..e4bc23e0 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/tools/white.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/tools/white_down (copy).png b/mods/mesecons_x/mesecons_autotools/textures/tools/white_down (copy).png new file mode 100644 index 00000000..ac3ea7d0 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/tools/white_down (copy).png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/tools/white_down.png b/mods/mesecons_x/mesecons_autotools/textures/tools/white_down.png new file mode 100644 index 00000000..a1b1f6e9 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/tools/white_down.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/tools/white_up.png b/mods/mesecons_x/mesecons_autotools/textures/tools/white_up.png new file mode 100644 index 00000000..f1660a67 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/tools/white_up.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/tools/yellow.png b/mods/mesecons_x/mesecons_autotools/textures/tools/yellow.png new file mode 100644 index 00000000..0ea65241 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/tools/yellow.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/tools/yellow_updown.png b/mods/mesecons_x/mesecons_autotools/textures/tools/yellow_updown.png new file mode 100644 index 00000000..62f51cda Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/tools/yellow_updown.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/unknown.png b/mods/mesecons_x/mesecons_autotools/textures/unknown.png new file mode 100644 index 00000000..f91b9eac Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/unknown.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/wall.png b/mods/mesecons_x/mesecons_autotools/textures/wall.png new file mode 100644 index 00000000..fde36a87 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/wall.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/white.png b/mods/mesecons_x/mesecons_autotools/textures/white.png new file mode 100644 index 00000000..e4bc23e0 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/white.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/white_down (copy).png b/mods/mesecons_x/mesecons_autotools/textures/white_down (copy).png new file mode 100644 index 00000000..ac3ea7d0 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/white_down (copy).png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/white_down.png b/mods/mesecons_x/mesecons_autotools/textures/white_down.png new file mode 100644 index 00000000..a1b1f6e9 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/white_down.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/white_up.png b/mods/mesecons_x/mesecons_autotools/textures/white_up.png new file mode 100644 index 00000000..f1660a67 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/white_up.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/wireh.png b/mods/mesecons_x/mesecons_autotools/textures/wireh.png new file mode 100644 index 00000000..8a5d8956 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/wireh.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/wirev.png b/mods/mesecons_x/mesecons_autotools/textures/wirev.png new file mode 100644 index 00000000..c0fce224 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/wirev.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/xjunction.png b/mods/mesecons_x/mesecons_autotools/textures/xjunction.png new file mode 100644 index 00000000..f123fa51 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/xjunction.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/xor0.png b/mods/mesecons_x/mesecons_autotools/textures/xor0.png new file mode 100644 index 00000000..3f783e98 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/xor0.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/xor1.png b/mods/mesecons_x/mesecons_autotools/textures/xor1.png new file mode 100644 index 00000000..224e98b1 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/xor1.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/xor2.png b/mods/mesecons_x/mesecons_autotools/textures/xor2.png new file mode 100644 index 00000000..b3e36c44 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/xor2.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/xor3.png b/mods/mesecons_x/mesecons_autotools/textures/xor3.png new file mode 100644 index 00000000..44059d03 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/xor3.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/yellow.png b/mods/mesecons_x/mesecons_autotools/textures/yellow.png new file mode 100644 index 00000000..0ea65241 Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/yellow.png differ diff --git a/mods/mesecons_x/mesecons_autotools/textures/yellow_updown.png b/mods/mesecons_x/mesecons_autotools/textures/yellow_updown.png new file mode 100644 index 00000000..62f51cda Binary files /dev/null and b/mods/mesecons_x/mesecons_autotools/textures/yellow_updown.png differ diff --git a/mods/mesecons_x/mesecons_autotools/tools.lua b/mods/mesecons_x/mesecons_autotools/tools.lua new file mode 100644 index 00000000..70148a6d --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/tools.lua @@ -0,0 +1,137 @@ +-- Common functions +-- a bit of a weld (TODO: fix that) +function is_circuit_element(pos) + local node = minetest.get_node(pos) + local name = node.name + + local m = string.match(name,"^mesecons_") + if m ~= nil then + return true + end + + m = string.match(name,"^mesecons:") + if m ~= nil then + return true + end + + if name == "default:mese" then + return true + end + + + return false +end + + + + +-- Register all tools and callbacks + + +dofile(minetest.get_modpath("mesecons_autotools").."/tools/selection.lua"); +dofile(minetest.get_modpath("mesecons_autotools").."/tools/direction.lua"); +dofile(minetest.get_modpath("mesecons_autotools").."/tools/wire.lua"); +dofile(minetest.get_modpath("mesecons_autotools").."/tools/bundle.lua"); + + + + + +local tool_list = { + {"black", "Auto Wire Tool"}, + {"grey", "Auto crossing Tool"}, + {"blue", "Selection Tool"}, + {"white_up", "Selection Top Edge Tool"}, + {"white_down", "Selection Bottom Edge Tool"}, + {"white", "Selection Right Edge Tool"}, + {"orange", "Stack Right Tool"}, + {"orange_up", "Stack Up Tool"}, + {"red", "Delete Tool"}, + {"yellow", "Move Horizontal Tool"}, + {"yellow_updown", "Move Vertical Tool"}, + {"refresh", "Refresh Tool"}, + + } +for _,t in pairs(tool_list) do + local tool = t[1] + local description = t[2] + + minetest.register_tool("mesecons_autotools:" .. tool , { + description = description, + inventory_image = tool .. ".png", + stack_max = 1, + groups = { tool =1 }, + + on_use = function(itemstack, player, pointed_thing) + local pos = pointed_thing.under + local player_pos = vector.round(player:get_pos()) + local player_name = player:get_player_name() + local rad = player:get_look_horizontal() + + if pointed_thing.type == "node" then + if (is_circuit_element(pos)) then + pos = pointed_thing.under + mesecons_autotools.execute_action(tool,"left","block", player_name, pos, rad, pointed_thing.under); + else + pos = pointed_thing.above + mesecons_autotools.execute_action(tool,"left","block", player_name, pos, rad, pointed_thing.under); + end + + elseif pointed_thing.type == "nothing" then + if (is_circuit_element(player_pos)) then + pos = pointed_thing.under + mesecons_autotools.execute_action(tool,"left","air", player_name, player_pos, rad); + else + pos = pointed_thing.above + mesecons_autotools.execute_action(tool,"left","air", player_name, player_pos, rad); + end + end + + end, + + on_place = function(itemstack, player, pointed_thing) + local pos = pointed_thing.under + local player_pos = vector.round(player:get_pos()) + local player_name = player:get_player_name() + local rad = player:get_look_horizontal() + + if pointed_thing.type == "node" then + if (is_circuit_element(pos)) then + pos = pointed_thing.under + mesecons_autotools.execute_action(tool,"right","block", player_name, pos, rad, pointed_thing.under); + else + pos = pointed_thing.above + mesecons_autotools.execute_action(tool,"right","block", player_name, pos, rad, pointed_thing.under); + end + end + + + end, + on_secondary_use = function(itemstack, player, pointed_thing) + local pos = pointed_thing.under + local player_pos = vector.round(player:get_pos()) + local player_name = player:get_player_name() + local rad = player:get_look_horizontal() + + if pointed_thing.type == "nothing" then + if (is_circuit_element(player_pos)) then + pos = pointed_thing.under + mesecons_autotools.execute_action(tool,"right","air", player_name, player_pos, rad); + else + pos = pointed_thing.above + mesecons_autotools.execute_action(tool,"right","air", player_name, player_pos, rad); + end + + end + + end + + + }) + + + + -- Implementations + dofile(minetest.get_modpath("mesecons_autotools").."/tools/" .. tool .. "/".. tool .. ".lua"); + +end diff --git a/mods/mesecons_x/mesecons_autotools/tools/black/black.lua b/mods/mesecons_x/mesecons_autotools/tools/black/black.lua new file mode 100644 index 00000000..3223e03c --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/tools/black/black.lua @@ -0,0 +1,67 @@ + + + + +mesecons_autotools.register_action("black","left","air", function(user,pos,rad) + -- Unselect pos + mesecons_autotools.set_pos(user,1,nil); + mesecons_autotools.set_pos(user,2,nil); + + -- Update + mesecons_autotools.render(user) + mesecons_autotools.zero_stack_counter(user) + mesecons_autotools.zero_stack_direction(user) + +end) +mesecons_autotools.register_action("black","left","block", function(user,pos,rad) + mesecons_autotools.set_pos(user,1,pos) + mesecons_autotools.set_pos(user,2,pos) + + -- Update + mesecons_autotools.render(user) + mesecons_autotools.zero_stack_counter(user) + mesecons_autotools.zero_stack_direction(user) +end) + +mesecons_autotools.register_action("black","right","block", function(user,pos,rad) + local pos1 = mesecons_autotools.get_pos(user,1) + local pos2 = mesecons_autotools.get_pos(user,2) + local user_direction = radians_to_direction_looking_forward(rad) + local sel = {} + sel.pos1 = pos1 + sel.pos2 = pos2 + + if not mesecons_autotools.is_full_selection(user) then return end + + local done = false + done = create_bundle_straight_wire(sel ,pos) + if done == true then + local direction = tunel_direction(sel,pos) + local distance = distance_to_selection(sel,pos,direction) -1 + + -- set new selection + local front_wall = tunel_front_wall(sel,pos) + mesecons_autotools.set_pos(user,1,front_wall.pos1) + mesecons_autotools.set_pos(user,2,front_wall.pos2) + shift_selection(user, vector.multiply(direction,distance)) + + -- Update + mesecons_autotools.render(user) + mesecons_autotools.zero_stack_counter(user) + mesecons_autotools.zero_stack_direction(user) + elseif create_bundle_bended_wire(user,sel,pos,user_direction) then + -- nothing to do here so far + -- update of new selection if inside the function + end + + + +end) + +mesecons_autotools.register_action("black","right","air", function(user,pos,rad) + +end) + + + + \ No newline at end of file diff --git a/mods/mesecons_x/mesecons_autotools/tools/blue/blue.lua b/mods/mesecons_x/mesecons_autotools/tools/blue/blue.lua new file mode 100644 index 00000000..5d093c46 --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/tools/blue/blue.lua @@ -0,0 +1,30 @@ + + +local function select_pos(user,pos,nr) + mesecons_autotools.set_pos(user,nr,pos); + + + -- Update + mesecons_autotools.render(user) + mesecons_autotools.zero_stack_counter(user) +end + + + + +mesecons_autotools.register_action("blue","left","air", function(user,pos,rad) + select_pos(user,pos,1) +end) +mesecons_autotools.register_action("blue","left","block", function(user,pos,rad) + select_pos(user,pos,1) +end) + +mesecons_autotools.register_action("blue","right","block", function(user,pos,rad) + select_pos(user,pos,2) +end) + +mesecons_autotools.register_action("blue","right","air", function(user,pos,rad) + select_pos(user,pos,2) +end) + + \ No newline at end of file diff --git a/mods/mesecons_x/mesecons_autotools/tools/bundle.lua b/mods/mesecons_x/mesecons_autotools/tools/bundle.lua new file mode 100644 index 00000000..5de380b7 --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/tools/bundle.lua @@ -0,0 +1,890 @@ + +function is_in_selection(sel,p) + local pos = {} + pos[1] = sel.pos1 + pos[2] = sel.pos2 + + if pos[1] == nil then return false end + if pos[2] == nil then return false end + + local xmax = math.max(pos[1].x, pos[2].x) + local xmin = math.min(pos[1].x, pos[2].x) + + local ymax = math.max(pos[1].y, pos[2].y) + local ymin = math.min(pos[1].y, pos[2].y) + + local zmax = math.max(pos[1].z, pos[2].z) + local zmin = math.min(pos[1].z, pos[2].z) + + local x = p.x + local y = p.y + local z = p.z + + if (xmin<=p.x) and (p.x<=xmax) and + (ymin<=p.y) and (p.y<=ymax) and + (zmin<=p.z) and (p.z<=zmax) then + return true + end + return false +end + +function is_in_layer(sel,p) + local pos = {} + pos[1] = sel.pos1 + pos[2] = sel.pos2 + + local ymax = math.max(pos[1].y, pos[2].y) + local ymin = math.min(pos[1].y, pos[2].y) + + if (p.y > ymax) or (p.y< ymin) then return false end + return true + +end + +function is_in_tube(sel,p) + if is_in_selection(sel,p) then return false end + if not is_in_layer(sel,p) then return false end + local pos = {} + pos[1] = sel.pos1 + pos[2] = sel.pos2 + + local xmax = math.max(pos[1].x, pos[2].x) + local xmin = math.min(pos[1].x, pos[2].x) + + local ymax = math.max(pos[1].y, pos[2].y) + local ymin = math.min(pos[1].y, pos[2].y) + + local zmax = math.max(pos[1].z, pos[2].z) + local zmin = math.min(pos[1].z, pos[2].z) + + local x = p.x + local y = p.y + local z = p.z + + if (xmin <=x ) and (x<=xmax) then return true end + if (zmin <=z) and (z<=zmax) then return true end + return false + +end + +function is_in_wings(sel,p) + if is_in_selection(sel,p) then return false end + if not is_in_layer(sel,p) then return false end + if is_in_tube(sel,p) then return false end + return true +end + + + +function front_wall_tube(sel,p) + local pos = {} + pos[1] = sel.pos1 + pos[2] = sel.pos2 + + local xmax = math.max(pos[1].x, pos[2].x) + local xmin = math.min(pos[1].x, pos[2].x) + + local ymax = math.max(pos[1].y, pos[2].y) + local ymin = math.min(pos[1].y, pos[2].y) + + local zmax = math.max(pos[1].z, pos[2].z) + local zmin = math.min(pos[1].z, pos[2].z) + + local x = p.x + local y = p.y + local z = p.z + + local new_sel = {} + local new_pos1 = vector.new(pos[1]) + local new_pos2 = vector.new(pos[2]) + local direction = {} + + + if (xmin<=x) and (x<=xmax) then + if (z > zmax) then + direction.x = 0 + direction.y = 0 + direction.z = 1 + + new_pos1.z = zmax + new_pos2.z = zmax + else + direction.x = 0 + direction.y = 0 + direction.z = -1 + + new_pos1.z = zmin + new_pos2.z = zmin + end + end + if (zmin<=z) and (z<=zmax) then + if( x > xmax) then + direction.x = 1 + direction.y = 0 + direction.z = 0 + + new_pos1.x = xmax + new_pos2.x = xmax + else + direction.x = -1 + direction.y = 0 + direction.z = 0 + + new_pos1.x = xmin + new_pos2.x = xmin + + end + + end + + + new_sel.pos1 = new_pos1 + new_sel.pos2 = new_pos2 + + return new_sel,direction +end + +function tunel_direction(sel,pos) + local wall,dir = front_wall_tube(sel,pos) + return dir +end + +function tunel_front_wall(sel,pos) + local wall,dir = front_wall_tube(sel,pos) + return wall +end + + + + +function is_dir_vertical(direction) + if direction.z ~= 0 then return true end + return false +end + +function is_look_vertical(rad) + local dir = radians_to_direction_looking_forward(rad) + return is_dir_vertical(dir) +end + +--[[ +function is_dir_horizontal(direction) + if direction.x ~= then return true end + return false +end +]]-- + +function front_wall_by_direction(sel,direction) + local pos = {} + pos[1] = sel.pos1 + pos[2] = sel.pos2 + + local xmax = math.max(pos[1].x, pos[2].x) + local xmin = math.min(pos[1].x, pos[2].x) + + local ymax = math.max(pos[1].y, pos[2].y) + local ymin = math.min(pos[1].y, pos[2].y) + + local zmax = math.max(pos[1].z, pos[2].z) + local zmin = math.min(pos[1].z, pos[2].z) + + + local new_sel = {} + local new_pos1 = vector.new(pos[1]) + local new_pos2 = vector.new(pos[2]) + + if direction.x == 1 then + new_pos1.x = xmax + new_pos2.x = xmax + end + if direction.x == -1 then + new_pos1.x = xmin + new_pos2.x = xmin + end + if direction.z == 1 then + new_pos1.z = zmax + new_pos2.z = zmax + end + if direction.z == -1 then + new_pos1.z = zmin + new_pos2.z = zmin + end + if direction.y == 1 then + new_pos1.y = ymax + new_pos2.y = ymax + end + if direction.y == -1 then + new_pos1.y = ymin + new_pos2.y = ymin + end + + new_sel.pos1 = new_pos1 + new_sel.pos2 = new_pos2 + + return new_sel +end +--[[ +function get_wing_cords(sel,p) + local zero = {x =0,z=0} + local cord + if is_in_selection(sel,p) then return zero end + if not is_in_layer(sel,p) then return zero end + + local pos = {} + pos[1] = sel.pos1 + pos[2] = sel.pos2 + + local xmax = math.max(pos[1].x, pos[2].x) + local xmin = math.min(pos[1].x, pos[2].x) + + local ymax = math.max(pos[1].y, pos[2].y) + local ymin = math.min(pos[1].y, pos[2].y) + + local zmax = math.max(pos[1].z, pos[2].z) + local zmin = math.min(pos[1].z, pos[2].z) + + local x = p.x + local y = p.y + local z = p.z + + if (x>xmax) and (z>zmax) then + cord = { x = 1, z = 1} + end + if (xzmax) then + cord = {x = -1 , z = 1} + end + if (zxmax) then + cord = { x = 1 , z = -1 } + end + if (z < zmin) and (x < xmin) then + cord = { x -1 ,z = -1 } + end + + return cord +end +]]-- +--[[ +function front_wall_wing(sel,p,rad) + local cord = get_wing_cords(sel,p) + + local wall_dir + wall_dir.y = 0 + + if cord.x == 1 and cord.z == 1 then + if is_look_vertical(rad) then + wall_dir = {x=1,z=0} + else + wall_dir = {x=0,z=1} + end + end + + if cord.x == -1 and cord.z == 1 then + if is_look_vertical(rad) then + wall_dir = {x=-1,z=0} + else + wall_dir = {x=0,z=1} + end + end + + if cord.x == 1 and cord.z == -1 then + if is_look_vertical(rad) then + wall_dir = {x=1,z=0} + else + wall_dir = {x=0,z=-1} + end + end + + if cord.x == -1 and cord.z == -1 then + if is_look_vertical(rad) then + wall_dir = {x=-1,z=0} + else + wall_dir = {x=0,z=-1} + end + end + + local wall = front_wall_by_direction(wall_dir) + + return wall,wall_dir +end + +]]-- +function distance_to_selection(sel,p,direction) + local dist = 0 + local pos = {} + pos[1] = sel.pos1 + pos[2] = sel.pos2 + + if not is_in_layer(sel,p) then return dist end + + --local direction = tunel_direction(sel,p) + + + local xmax = math.max(pos[1].x, pos[2].x) + local xmin = math.min(pos[1].x, pos[2].x) + + local ymax = math.max(pos[1].y, pos[2].y) + local ymin = math.min(pos[1].y, pos[2].y) + + local zmax = math.max(pos[1].z, pos[2].z) + local zmin = math.min(pos[1].z, pos[2].z) + + if direction.x ~= 0 then + if direction.x == 1 then + dist = math.abs(p.x - xmax) + elseif direction.x == -1 then + dist = math.abs(xmin-p.x) + end + + elseif direction.z ~= 0 then + if direction.z == 1 then + dist = math.abs(p.z - zmax) + elseif direction.z == -1 then + dist = math.abs(zmin - p.z) + end + + end + + return dist + 1 + +end + +--[[ +function direction_to_pins(direction) + local pin = {0,0,0,0} + if direction.x == -1 then + pin[1] = 1 + end + if direction.x == 1 then + pin[3] = 1 + end + if direction.z == 1 then + pin[2] = 1 + end + if direction.z == -1 then + pin[4] == 1 + end + return pin +end +]]-- +function direction_to_pin(direction) + if direction.x == -1 then + return 1 + end + if direction.x == 1 then + return 3 + end + if direction.z == 1 then + return 2 + end + if direction.z == -1 then + return 4 + end +end + + +function pos_to_connect(wall,direction) + local list = {} + iterate_selection(wall.pos1,wall.pos2, function(pos) + local pins = get_pins_from_pos(pos) + local dpin = direction_to_pin(direction) + if pins[dpin] == 1 then + table.insert(list,pos) + end + end) + return list +end + +function _is_block_type(pos,direction) + local node = minetest.get_node(pos) + local name = node.name + + if name == "air" then + return "buildable" + end + + if name == "mesecons_insulated:insulated_off" or + name == "mesecons_insulated:insulated_on" then + + local param2 = node.param2 + local pin = direction_to_pin(direction) + + if (param2==0 or param2==2) and (pin==2 or pin==4) then + return "buildable" + end + if (param2==1 or param2==3) and (pin==1 or pin==3) then + return "buildable" + end + return "last" + end + + + local pos_pins = get_pins_from_pos(pos) + local dir_pin = flip_pin(direction_to_pin(direction)) + if pos_pins[dir_pin] ==1 then + return "last" + end + return "cancel" +end + + +function is_block_type(pos,direction) + local res = _is_block_type(pos,direction) + local node = minetest.get_node(pos) + local name = node.name + + + return res +end + + +function is_block_cancel(pos,direction) + if is_block_type(pos,direction) == "cancel" then + return true + else + return false + end +end + +function is_block_last(pos,direction) + if is_block_type(pos,direction) == "last" then + return true + else + return false + end +end + +function is_block_buildable(pos,direction) + if is_block_type(pos,direction) == "buildable" then + return true + else + return false + end +end + + + +function _can_build_wire(pos,direction,size) + local current = { x=pos.x , y =pos.y, z=pos.z} + + local flag = false + for i=1,size,1 do + + if is_block_cancel(current,direction) then + return false + end + if is_block_last(current,direction) then + return true + end + + current = vector.add(current,direction) + end + return flag +end + +function can_build_wire(pos,direction,size) + return _can_build_wire(pos,direction,size) +end + + +function add_wire(pos,direction) + local node = minetest.get_node(pos) + local name = node.name + + if name == "air" then + local pins = get_pins_from_pos(pos) + local dpin = direction_to_pin(direction) + + pins[dpin] = 1 + pins[flip_pin(dpin)] = 1 + + local nnode = get_node_from_pins(pins) + + --minetest.set_node(pos,nnode) + mesecons_autotools.set_node(pos,nnode,"add_wire") + else + local nnode = { name = "mesecons_extrawires:crossover_off" } + --minetest.set_node(pos, nnode) + mesecons_autotools.set_node(pos,nnode,"add_wire") + + end + + + +end +--[[ not used +function add_last_wire(pos,direction) + local pins = get_pins_from_pos(pos) + local dpin = direction_to_pin(direction) + + pins[flip_pin(dpin)] = 1 + + local node = get_node_from_pins(pins) + + minetest.set_node(pos,node) + +end +]]-- + +function build_wire_inside(pos,direction,size) + local current = { x=pos.x , y =pos.y, z=pos.z} + + if not can_build_wire(pos,direction,size) then return end + + for i=1,size,1 do + if is_block_cancel(current,direction) then + return + elseif is_block_buildable(current,direction) then + add_wire(current,direction) + elseif is_block_last(current,direction) then + break + end + current = vector.add(current,direction) + end +end + + + +function create_wires_inside_selection(sel,wall,direction) + local size = size_by_direction(sel.pos1,sel.pos2,direction) + local back_direction = vector.multiply(direction,-1) + + + iterate_selection(wall.pos1,wall.pos2,function(pos) + build_wire_inside(pos,back_direction,size) + end) + +end + + +function create_bundle_straight_wire(sel,pos) + local pos1 = sel.pos1 + local pos2 = sel.pos2 + + if not is_in_tube(sel,pos) then return false end + + local wall,direction = front_wall_tube(sel,pos) + + local distance = distance_to_selection(sel,pos,direction) + + if is_one_block(pos1,pos2) or + is_empty_selection(pos1,pos2) or + is_tower_selection(pos1,pos2) then + + iterate_selection(sel.pos1, sel.pos2, function(pos) + create_straight_wire_n(pos,direction,distance) + end) + else + + create_wires_inside_selection(sel,wall,direction) + + + local wire_list = pos_to_connect(wall,direction) + iterate_list(wire_list,function(pos) + create_straight_wire_n(pos,direction,distance) + end) + + end + return true +end + + + +function is_flat_selection(sel) + local p1 = sel.pos1 + local p2 = sel.pos2 + + if( p1.x == p2.x and p1.z == p2.z ) then return false end + if (p1.x == p2.x ) then return true end + if( p1.z == p2.z ) then return true end + return false +end + +-- direction of selection (according to the shape (=flat edge) +function sel_directions_frontwall(sel) + local p1 = sel.pos1 + local p2 = sel.pos2 + + if( p1.x == p2.x ) then + return {x=1,y=0,z=0},{x=-1,y=0,z=0} + end + if( p1.z == p2.z ) then + return {x=0,y=0,z=1},{x=0,y=0,z=-1} + end + print "Error: sel_direction(sel) not a flat selection (use is_flat_selection(sel) to check!!!" + return {x=0,y=0,z=0} +end + + +function normalize(p) + local x,y,z + if( p.x > 0 ) then x = 1 end + if( p.x == 0 ) then x = 0 end + if( p.x < 0 ) then x = -1 end + + if( p.y > 0 ) then y = 1 end + if( p.y == 0 ) then y = 0 end + if( p.y < 0 ) then y = -1 end + + if( p.z > 0 ) then z = 1 end + if( p.z == 0 ) then z = 0 end + if( p.z < 0 ) then z = -1 end + return {x=x,y=y,z=z} +end +-- vectors directing from p1 to p2 +function toward_direction(p1,p2) + local d1 = {x=p2.x-p1.x,y=0,z=0 } + local d2 = {x=0,y=0,z=p2.z-p1.z} + return normalize(d1),normalize(d2) +end + +-- comparing two points/vectors +function cmp(p1,p2) + if (p1.x==p2.x) and (p1.y==p2.y) and (p1.z==p2.z) then return true else return false end +end + +-- {p1,p2} cup {p3,p4} // only one can be common, so I dont check other possibilietes +function cup(p1,p2,p3,p4) + if cmp(p1,p3) then return p1 end + if cmp(p1,p4) then return p1 end + if cmp(p2,p3) then return p2 end + if cmp(p2,p4) then return p2 end +--print("DEGUG.CRITICAL ERROR: cup, p1,p2,p3,p4 =" ..dump(p1)..dump(p2)..dump(p3)..dump(p4)) + return nil +end + +-- checks if vectors have the same parallerism +function same_line(d1,d2) + if math.abs(d1.x) == math.abs(d2.x) and math.abs(d1.z) == math.abs(d2.z) then return true end + return false +end + +-- returns direction from selection toward point, and direction from poin towards selection +function compute_directions(sel,pos) + local s1,s2 + local sp1,sp2 + + s1,s2 = sel_directions_frontwall(sel) +--print("sel,pos="..dump(sel).."," .. dump(pos)) + sp1,sp2 = toward_direction(sel.pos1,pos) -- no matter if sel.pos1 or sel.pos2 +--print("toward="..dump(sp1)..","..dump(sp2)) + local sel_direction = cup(s1,s2,sp1,sp2) + + local p1,p2 + p1,p2 = toward_direction(pos,sel.pos1) -- no matter if sel.pos1 or sel.pos2 + local pos_direction + if same_line(sel_direction,p1) then + pos_direction = p2 + else + pos_direction = p1 + end + return sel_direction, pos_direction +end + + +-- computing point A +function compute_A(sel,sel_dir, pos, pos_dir) + local s1 = sel.pos1 + local s2 = sel.pos2 + + local dist1x = math.abs(pos.x-s1.x) + local dist2x = math.abs(pos.x-s2.x) + local dist1z = math.abs(pos.z-s1.z) + local dist2z = math.abs(pos.z-s2.z) + + local mx = math.min(dist1x,dist2x) + local mz = math.min(dist1z,dist2z) + + local sihfta + if pos_dir.x ~= 0 then + shifta = vector.multiply(pos_dir,mx) + else + shifta = vector.multiply(pos_dir,mz) + end + local a = vector.add(shifta,pos) + return a +end + +--[[ + +function compute_X(sel,sel_dir,pos,pos_dir,A) + local d = vector.multiply(sel_dir,-1) + return vector.add(A,d) +end + +]]-- +--[[ +function selection_len(sel) + local p1=sel.pos1 + local p2=sel.pos2 + if( p1.x == p2.x ) then return math.abs(p2.z-p1.z)+1 end + if( p1.z == p2.z ) then return math.abs(p2.x-p1.x)+1 end + +-- print("CRITICAL ERRROR ERROR ERROR: selection_len(sel): "..dump(sel)) +end +]]-- +--[[ +function compute_D(sel,sel_dir,pos,pos_dir,A) + local l = selection_len(sel) + return vector.add(A, vector.multiply(pos_dir,l-1)) +end +]]-- +--[[ +function crossing_point(p1,p1_dir,p2) + local len + local cross + if(p1_dir.x ~= 0 ) then + len = math.abs(p2.x-p1.x) + else + len = math.abs(p2.z-p1.z) + end + cross = vector.add(p1,vector.multiply(p1_dir,len)) + return cross +end +]]-- + +function create_wire_bended(p1,dir1, p2, dir2) + local len + if(dir1.x ~= 0 ) then + len = math.abs(p2.x-p1.x) + else + len = math.abs(p2.z-p1.z) + end + create_straight_wire_n(p1,dir1,len+1) + + local cross = vector.add(p1,vector.multiply(dir1,len)) + if(dir2.x ~= 0 ) then + len = math.abs(p2.x-p1.x) + else + len = math.abs(p2.z-p1.z) + end + create_straight_wire_n(cross,dir2,len+1) +end +--[[ +function create_bundle_twist_wire(sel,in_dir,_X,_Y,xm, out_dir, _A,am) + local max_size = 0 +--print("debug|sel.in_dir,X,Y,xm,out_dir,A,am=" .. dump(sel) .. dump(in_dir)..dump(X)..dump(Y)..dump(xm)..dump(out_dir)..dump(A).. dump(am)) + + local usize = hight_of_selection(sel) + local X = _X + local A = _A + local Y = _Y + + for k=1,usize do + --move all point up to next layer + + local shifts_in = get_shifts(X,xm,in_dir,sel) + local ssize = #shifts_in + max_size = math.max(max_size,ssize) + +print("shifts="..dump(shifts_in)) + for i=1,ssize do + local start_pos = vector.add(X,vector.multiply(xm,shifts_in[i])) + local end_pos = vector.add(A,vector.multiply(am,i-1)) + create_wire_bended(start_pos,in_dir,end_pos,vector.multiply(out_dir,1)) + end + + local up = {x=0,y=1,z=0} + X = vector.add(X,up) + Y = vector.add(Y,up) + A = vector.add(A,up) + + + end + return max_size + +end +]]-- +function compute_S1(sel,sel_dir,pos,pos_dir) + local s1 = sel.pos1 + local s2 = sel.pos2 + local p = pos + + local sx1 = math.abs(p.x-s1.x) + local sx2 = math.abs(p.x-s2.x) + local sz1 = math.abs(p.z-s1.z) + local sz2 = math.abs(p.z-s2.z) + + local mx = math.min(sx1,sx2) + local mz = math.min(sz1,sz2) + + local A = compute_A(sel,sel_dir, pos,pos_dir) + local len + if( sel_dir.x ~= 0 ) then + len = mx + else + len = mz + end + local S1 = vector.add(A, vector.multiply( vector.multiply(sel_dir,len) , -1)) + return S1 + +end + +function get_virtual_shifts(pos,move_direction,look_direction,sel) + local curr = pos + local shift = 0 + local shifts = {} + while( is_in_selection(sel,curr) ) do + table.insert(shifts,shift) + shift = shift + 1 + curr = vector.add(curr,move_direction) + end + return shifts +end + +function create_bundle_bended_wire(user,sel,pos,user_dir) + local sel_direction, pos_direction + local pos1 = sel.pos1 + local pos2 = sel.pos2 + + if not is_in_wings(sel,pos) then return false end + if not is_flat_selection(sel) then return false end + + sel_direction,pos_direction = compute_directions(sel,pos) + + local usize = hight_of_selection(sel) + local S1_original = compute_S1(sel,sel_direction,pos,pos_direction) + local max_wires = 0 + + + if is_empty_selection(pos1,pos2) then + local S1 = S1_original + for k=1,usize do + local shifts = get_virtual_shifts(S1,pos_direction,sel_direction,sel) + local ssize = #shifts + max_wires = math.max(max_wires,ssize) + for i=1,ssize do + local start_pos = vector.add(S1,vector.multiply(pos_direction,shifts[i])) + local end_pos = vector.add(pos, vector.multiply(sel_direction,i-1)) + create_wire_bended(start_pos,sel_direction,end_pos, vector.multiply(pos_direction,-1)) + end + S1 = vector.add(S1,{x=0,y=1,z=0}) + end + else + local S1 = S1_original + for k=1,usize do + local shifts = get_shifts(S1,pos_direction,sel_direction,sel) + local ssize = #shifts + max_wires=math.max(max_wires,ssize) + for i=1,ssize do + local start_pos = vector.add(S1,vector.multiply(pos_direction,shifts[i])) + local end_pos = vector.add(pos, vector.multiply(sel_direction,i-1)) + create_wire_bended(start_pos,sel_direction,end_pos, vector.multiply(pos_direction,-1)) + end + S1 = vector.add(S1,{x=0,y=1,z=0}) + end + end + + -- computing selection + local new_sel = {} + new_sel.pos1 = pos + new_sel.pos2 = vector.add(vector.add(pos, vector.multiply(sel_direction,max_wires-1)),{x=0,y=usize-1,z=0}) + + mesecons_autotools.set_pos(user,1,new_sel.pos1) + mesecons_autotools.set_pos(user,2,new_sel.pos2) + mesecons_autotools.render(user) + + mesecons_autotools.zero_stack_counter(user) + mesecons_autotools.zero_stack_direction(user) + + return true +end diff --git a/mods/mesecons_x/mesecons_autotools/tools/direction.lua b/mods/mesecons_x/mesecons_autotools/tools/direction.lua new file mode 100644 index 00000000..86e10a16 --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/tools/direction.lua @@ -0,0 +1,28 @@ +function radians_to_vectors(rad) + local pi = math.pi + if (rad>=0) and (rad<=pi/4) or (rad<=2*pi) and (rad>=(3/2+1/4)*pi) then + return {left = {x=-1,z=0,y=0},right = { x=1, z = 0,y=0 } } + elseif (rad >= 1/4*pi) and (rad <= (1/2+1/4)*pi) then + return { left = {x = 0 ,z=-1,y=0}, right = { x = 0, z = 1 ,y=0} } + elseif (rad >= (1-1/4)*pi ) and (rad <= (3/2-1/4)*pi ) then + return { left = { x = 1, z =0 ,y=0}, right = { x = -1, z = 0 ,y=0} } + else + return { left = { z =1, x = 0 ,y=0} , right = { z = -1 , x = 0,y=0 }} + end +end + + +function radians_to_direction_looking_forward(rad) + if rad == nil then return {x=1,z=0,y=0} end + local pi = math.pi + if (rad>=0) and (rad<=pi/4) or (rad<=2*pi) and (rad>=(3/2+1/4)*pi) then + return {x=0, z =1 ,y=0} + elseif (rad >= 1/4*pi) and (rad <= (1/2+1/4)*pi) then + return {x=-1,z=0,y=0} + elseif (rad >= (1-1/4)*pi ) and (rad <= (3/2-1/4)*pi ) then + return {x=0,z=-1,y=0} + else + return {x=1,z=0,y=0} + end +end + diff --git a/mods/mesecons_x/mesecons_autotools/tools/grey/grey.lua b/mods/mesecons_x/mesecons_autotools/tools/grey/grey.lua new file mode 100644 index 00000000..045a2f66 --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/tools/grey/grey.lua @@ -0,0 +1,156 @@ + + +function has_wire_sticking_out(pos,direction) + local pins = get_pins_from_pos(pos,"any") + local dir_pin = dir_to_inx(direction) + + if( pins[dir_pin] == 1 ) then + return true + else + return false + end +end + + +function get_shifts(p00,move_direction, look_direction,sel) + local curr = p00 + local shift = 0 + local shifts = {} + + while ( is_in_selection(sel,curr) ) do + if( has_wire_sticking_out(curr,look_direction) ) then + table.insert(shifts,shift) + end + shift = shift + 1 + curr = vector.add(curr,move_direction) + end + return shifts +end + + +function hight_of_selection(sel) + local pos1 = sel.pos1 + local pos2 = sel.pos2 + return math.abs(pos1.y-pos2.y)+1 +end + +function replace(sel,direction,new_node) + local p00 = get_corner00(sel,direction) + local v_move = direction + local h_move = rotate_direction_right(direction) + local v_look = rotate_direction_left(direction) + local h_look = rotate_direction_right(h_move) + + local usize = hight_of_selection(sel) + local u_move = { x=0,y=1,z=0} + + + +for k=1,usize do + + local hshifts = get_shifts(p00,h_move,h_look,sel) + local vshifts = get_shifts(p00,v_move,v_look,sel) + + local hsize = #hshifts + local vsize = #vshifts + local m = math.min(hsize,vsize) + + for i=1,m do + local hs = vector.multiply(h_move,hshifts[i]) + local vs = vector.multiply(v_move,vshifts[i]) + local hvs = vector.add(hs,vs) + local pos = vector.add(p00,hvs) + + --local node = minetest.get_node(pos) + --print("debug.node="..dump(node)) + --minetest.set_node(pos,new_node) + + -- remove metadata TODO + mesecons_autotools.set_node(pos,new_node,"place+refresh") + end + + p00 = vector.add(p00,u_move) +end + +end + + + +function unconnect(sel,direction) + local nover = "mesecons_extrawires:crossover_off" + + replace(sel,direction,{name=nover}) + +end + +function connect(sel,direction) + local ncross = "mesecons_morewires:xjunction_off" + replace(sel,direction,{name=ncross}) +end + + + + + +mesecons_autotools.register_action("grey","left","air", function(user,pos,rad) + local pos1 = mesecons_autotools.get_pos(user,1) + local pos2 = mesecons_autotools.get_pos(user,2) + + local direction = radians_to_direction_looking_forward(rad) + + if pos1 == nil then return end + if pos2 == nil then return end + + local sel = {pos1=pos1, pos2=pos2} + + unconnect(sel,direction) +end) +mesecons_autotools.register_action("grey","left","block", function(user,pos,rad) + local pos1 = mesecons_autotools.get_pos(user,1) + local pos2 = mesecons_autotools.get_pos(user,2) + + local direction = radians_to_direction_looking_forward(rad) + + if pos1 == nil then return end + if pos2 == nil then return end + + local sel = {pos1=pos1, pos2=pos2} + + unconnect(sel,direction) + +end) + +mesecons_autotools.register_action("grey","right","block", function(user,pos,rad) + local pos1 = mesecons_autotools.get_pos(user,1) + local pos2 = mesecons_autotools.get_pos(user,2) + + local direction = radians_to_direction_looking_forward(rad) + + if pos1 == nil then return end + if pos2 == nil then return end + + local sel = {pos1=pos1, pos2=pos2} + + connect(sel,direction) + + +end) + +mesecons_autotools.register_action("grey","right","air", function(user,pos,rad) + local pos1 = mesecons_autotools.get_pos(user,1) + local pos2 = mesecons_autotools.get_pos(user,2) + + local direction = radians_to_direction_looking_forward(rad) + + if pos1 == nil then return end + if pos2 == nil then return end + + local sel = {pos1=pos1, pos2=pos2} + + connect(sel,direction) + +end) + + + + \ No newline at end of file diff --git a/mods/mesecons_x/mesecons_autotools/tools/orange/orange.lua b/mods/mesecons_x/mesecons_autotools/tools/orange/orange.lua new file mode 100644 index 00000000..1c1f4494 --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/tools/orange/orange.lua @@ -0,0 +1,106 @@ +local function stack_right(user,rad) + local dir = radians_to_vectors(rad) + local left = dir.left + local right = dir.right + + local pos = {} + pos[1] = mesecons_autotools.get_pos(user,1) + pos[2] = mesecons_autotools.get_pos(user,2) + + + if pos[1] == nil then return end + if pos[2] == nil then return end + + + -- compute shift vector + + local shift_vector = {} + if right.x ~= 0 then + shift_vector.x = right.x * (math.abs(pos[2].x - pos[1].x)+1) + shift_vector.z = 0 + shift_vector.y = 0 + elseif right.z ~= 0 then + shift_vector.x = 0 + shift_vector.y = 0 + shift_vector.z = right.z * (math.abs(pos[2].z - pos[1].z)+1) + end + + copy(pos[1],pos[2],shift_vector) + shift_selection(user,shift_vector) + + -- Update + mesecons_autotools.render(user) + + + local old_stack_direction = mesecons_autotools.get_stack_direction(user) + if not vector.equals(old_stack_direction,right) then + mesecons_autotools.set_stack_direction(user,right) + mesecons_autotools.zero_stack_counter(user) + end + mesecons_autotools.inc_stack_counter(user) + + +end + + +local function stack_remove(user,rad) + local dir = radians_to_vectors(rad) + local left = dir.left + local right = dir.right + + local pos = {} + pos[1] = mesecons_autotools.get_pos(user,1) + pos[2] = mesecons_autotools.get_pos(user,2) + + + if pos[1] == nil then return end + if pos[2] == nil then return end + + if not vector.equals(mesecons_autotools.get_stack_direction(user),right) then return end + if mesecons_autotools.get_stack_counter(user) == 0 then return end + + -- compute shift vector + local shift_vector = {} + if right.x ~= 0 then + shift_vector.x = - right.x * (math.abs(pos[2].x - pos[1].x)+1) + shift_vector.z = 0 + shift_vector.y = 0 + elseif right.z ~= 0 then + shift_vector.x = 0 + shift_vector.y = 0 + shift_vector.z = - right.z * (math.abs(pos[2].z - pos[1].z)+1) + end + + delete(pos[1],pos[2]) + shift_selection(user,shift_vector) + + mesecons_autotools.dec_stack_counter(user) + + + -- Update + mesecons_autotools.render(user) + + +end + + + + + +mesecons_autotools.register_action("orange","left","air", function(user,pos,rad) + stack_remove(user,rad) +end) +mesecons_autotools.register_action("orange","left","block", function(user,pos,rad) + stack_remove(user,rad) +end) + +mesecons_autotools.register_action("orange","right","block", function(user,pos,rad) + stack_right(user,rad) +end) + +mesecons_autotools.register_action("orange","right","air", function(user,pos,rad) + stack_right(user,rad) +end) + + + \ No newline at end of file diff --git a/mods/mesecons_x/mesecons_autotools/tools/orange_up/orange_up.lua b/mods/mesecons_x/mesecons_autotools/tools/orange_up/orange_up.lua new file mode 100644 index 00000000..8731e250 --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/tools/orange_up/orange_up.lua @@ -0,0 +1,92 @@ + + + + + +local function stack_up(user) + if not mesecons_autotools.is_full_selection(user) then return end + + + local pos = {} + pos[1] = mesecons_autotools.get_pos(user,1) + pos[2] = mesecons_autotools.get_pos(user,2) + + + + local ymax = math.max(pos[1].y,pos[2].y) + local ymin = math.min(pos[1].y,pos[2].y) + local shift_up = ymax - ymin + 1 + local shift_vector = { x= 0, y = shift_up , z= 0 } + copy(pos[1],pos[2],shift_vector) + shift_selection(user,shift_vector) + + + if not vector.equals(mesecons_autotools.get_stack_direction(user),{x=0,y=1,z=0}) then + mesecons_autotools.zero_stack_counter(user); + end + + + mesecons_autotools.inc_stack_counter(user) + mesecons_autotools.set_stack_direction(user, { x=0,y=1,z=0 } ) + + + -- Update + mesecons_autotools.render(user) + + + +end + + +local function stack_remove(user) + if not mesecons_autotools.is_full_selection(user) then return end + + + local pos = {} + pos[1] = mesecons_autotools.get_pos(user,1) + pos[2] = mesecons_autotools.get_pos(user,2) + + + + local ymax = math.max(pos[1].y,pos[2].y) + local ymin = math.min(pos[1].y,pos[2].y) + local shift_down = ymax - ymin + 1 + local shift_vector = { x= 0, y = -shift_down , z= 0 } + + if mesecons_autotools.get_stack_counter(user) == 0 then + return + end + + if not vector.equals(mesecons_autotools.get_stack_direction(user),{x=0,y=1,z=0}) then return end + + delete(pos[1],pos[2]) + shift_selection(user,shift_vector) + + mesecons_autotools.dec_stack_counter(user) + + + + -- Update + mesecons_autotools.render(user) +end + + + + +mesecons_autotools.register_action("orange_up","left","air", function(user,pos,rad) + stack_remove(user) +end) +mesecons_autotools.register_action("orange_up","left","block", function(user,pos,rad) + stack_remove(user) +end) + +mesecons_autotools.register_action("orange_up","right","block", function(user,pos,rad) + stack_up(user) +end) + +mesecons_autotools.register_action("orange_up","right","air", function(user,pos,rad) + stack_up(user) +end) + + + \ No newline at end of file diff --git a/mods/mesecons_x/mesecons_autotools/tools/red/red.lua b/mods/mesecons_x/mesecons_autotools/tools/red/red.lua new file mode 100644 index 00000000..2f09826b --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/tools/red/red.lua @@ -0,0 +1,47 @@ + + + + +mesecons_autotools.register_action("red","left","air", function(user,pos,rad) + + +end) +mesecons_autotools.register_action("red","left","block", function(user,pos,rad,under) + --minetest.set_node(under,{name="air"}) + + if is_circuit_element(under) then + mesecons_autotools.set_node(under,{name="air"},"red") + end + +end) + +mesecons_autotools.register_action("red","right","block", function(user,pos,rad,under) + local sel = {} + sel.pos1 = mesecons_autotools.get_pos(user,1) + sel.pos2 = mesecons_autotools.get_pos(user,2) + if is_in_selection(sel,under) then + iterate_selection(sel.pos1,sel.pos2,function(p) + delete_node(p) + end) + else + if is_circuit_element(under) then + delete_node(under) + end + + end + + +end) + +mesecons_autotools.register_action("red","right","air", function(user,pos,rad) + if not mesecons_autotools.is_full_selection(user) then return end + + local pos = {} + pos[1] = mesecons_autotools.get_pos(user,1) + pos[2] = mesecons_autotools.get_pos(user,2) + + delete(pos[1],pos[2]) +end) + + + \ No newline at end of file diff --git a/mods/mesecons_x/mesecons_autotools/tools/refresh/refresh.lua b/mods/mesecons_x/mesecons_autotools/tools/refresh/refresh.lua new file mode 100644 index 00000000..b0bef77c --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/tools/refresh/refresh.lua @@ -0,0 +1,105 @@ + + +function is_mese(node) + if node.name == "default:mese" or + node.name == "mesecons_extrawires:mese_powered" then + return true + else + return false + end + +end + +function mese_off(node) + local n = {} + if is_mese(node) then + n.name = "default:mese" + n.param2 = node.param2 + return n + else + return node + end +end + + + + +function wire_off(node) + local n = {} + local name = node.name + n.param2 = node.param2 + + if is_wire_node(node) then + if string.match(name, "^mesecons_extrawires:crossover_") ~= nil then + n.name = "mesecons_extrawires:crossover_off" + return n + else + local base,state = string.match(name, "^(.*)_([^_]+)$") + base = base or "" + state = state or "" + + local name_off = base .. "_" .. "off" + n.name = name_off + return n + end + + else + return node + end +end + + + +local function refresh_selection(pos1,pos2) + iterate_selection(pos1,pos2, function(pos) + -- mesecon.on_placenode(pos,minetest.get_node(pos)) + + local node = minetest.get_node(pos) + local new_node = wire_off(node) + + + + local cur_node = minetest.get_node(pos) + mesecon.on_dignode(pos,cur_node) + ref_remove(pos,cur_node) + + minetest.set_node(pos,new_node) + mesecon.on_placenode(pos,new_node) + ref_place(pos,new_node) + + end) + +end + + + +mesecons_autotools.register_action("refresh","left","air", function(user,pos,rad) + + +end) +mesecons_autotools.register_action("refresh","left","block", function(user,pos,rad) + --mesecon.on_placenode(pos, minetest.get_node(pos)) + refresh_selection(pos,pos) +end) + +mesecons_autotools.register_action("refresh","right","block", function(user,pos,rad) + if not mesecons_autotools.is_full_selection(user) then return end + + local pos1 = mesecons_autotools.get_pos(user,1) + local pos2 = mesecons_autotools.get_pos(user,2) + refresh_selection(pos1,pos2) + +end) + +mesecons_autotools.register_action("refresh","right","air", function(user,pos,rad) + if not mesecons_autotools.is_full_selection(user) then return end + + local pos1 = mesecons_autotools.get_pos(user,1) + local pos2 = mesecons_autotools.get_pos(user,2) + refresh_selection(pos1,pos2) +end) + + + + + \ No newline at end of file diff --git a/mods/mesecons_x/mesecons_autotools/tools/selection.lua b/mods/mesecons_x/mesecons_autotools/tools/selection.lua new file mode 100644 index 00000000..3694a39d --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/tools/selection.lua @@ -0,0 +1,173 @@ +function iterate_selection(pos1,pos2,action) + local xmin = math.min(pos1.x,pos2.x) + local ymin = math.min(pos1.y,pos2.y) + local zmin = math.min(pos1.z,pos2.z) + + local xmax = math.max(pos1.x,pos2.x) + local ymax = math.max(pos1.y,pos2.y) + local zmax = math.max(pos1.z,pos2.z) + + + for ix = xmin,xmax,1 do + for iy = ymin,ymax,1 do + for iz = zmin,zmax,1 do + action({x=ix,y=iy,z=iz}) + end + end + end + +end + +function iterate_list(list,action) + for _,v in ipairs(list) do + action(v) + end +end + + +-- not tested, not used +function copy_safe(pos1,pos2,shift_vector) + local buffor = {} + copy_to_buffor(pos1,pos2,buffor) + paste_from_buffor(shift_vector,buffor) +end + + +function copy(pos1,pos2, shift_vector) + iterate_selection(pos1,pos2, function(pos) + local node = minetest.get_node(pos) + local meta = minetest.get_meta(pos):to_table() + + local new_pos = vector.add(pos,shift_vector) + --minetest.set_node(new_pos, node) + --mesecons_autotools.set_node(new_pos, node,"copy") + minetest.set_node(new_pos,node) + minetest.get_meta(new_pos):from_table(meta) + + end) +end + + +--[[ +function copy_to_buffor(pos1,pos2,buffor) + iterate_selection(pos1,pos2, function(pos) + local node = minetest.get_node(pos) + table.insert(buffor, { pos = pos, node = node } ) + end) + +end + +function paste_from_buffor(shift_vector,buffor) + for _,v in pairs(buffor) do + local pos = v.pos + local node = v.node + + local new_pos = vector.add(pos,shift_vector) + + --minetest.set_node(new_pos,node) + mesecons_autotools.set_node(new_pos,node,"paste_from_buffor") + end + +end +]]-- + + +function copy_to_buffor(pos1,pos2,buffor) + + iterate_selection(pos1,pos2, function(pos) + local node = minetest.get_node(pos) + local meta = minetest.get_meta(pos):to_table() + + table.insert(buffor, { node = { pos = pos, node = node }, meta = meta} ) + end) + +end + +function paste_from_buffor(shift_vector,buffor) + + for _,v in pairs(buffor) do + local pos = v.node.pos + local node = v.node.node + local meta = v.meta + + local new_pos = vector.add(pos,shift_vector) + + minetest.set_node(new_pos,node) + minetest.get_meta(new_pos):from_table(meta) + + --mesecons_autotools.set_node(new_pos,node,"paste_from_buffor") + end + +end + + + +function delete(pos1,pos2) + iterate_selection(pos1,pos2, function(pos) + minetest.set_node(pos,{ name = "air" } ) + minetest.get_meta(pos):from_table({}) + end) + +end + + + +function shift_selection(user,shift_vector) + if not mesecons_autotools.is_full_selection(user) then return end + + local pos = {} + pos[1] = mesecons_autotools.get_pos(user,1) + pos[2] = mesecons_autotools.get_pos(user,2) + + + mesecons_autotools.set_pos(user,1, vector.add(pos[1],shift_vector)) + mesecons_autotools.set_pos(user,2, vector.add(pos[2],shift_vector)) + + + +end + +function is_one_block(pos1,pos2) + if (pos1.x ~= pos2.x ) then return false end + if pos1.y ~= pos2.y then return false end + if pos1.z ~= pos2.z then return false end + return true +end + +function is_empty_selection(pos1,pos2) + local list = {} + iterate_selection(pos1,pos2, function(pos) + local node = minetest.get_node(pos) + local name = node.name + if name ~= "air" then + table.insert(list,1) + end + end) + for _,v in ipairs(list) do + if v == 1 then + return false + end + end + return true + +end + +function is_tower_selection(pos1,pos2) + if pos1.x == pos2.x and pos1.z == pos2.z then return true end + return false +end + + +function size_by_direction(pos1,pos2,direction) + local dx = math.abs(pos1.x - pos2.x) +1 + local dy = math.abs(pos1.y - pos2.y) +1 + local dz = math.abs(pos1.z - pos2.z) +1 + + if direction.x ~= 0 then return dx end + if direction.y ~= 0 then return dy end + if direction.z ~= 0 then return dz end + + return 0 +end + + diff --git a/mods/mesecons_x/mesecons_autotools/tools/test/test.lua b/mods/mesecons_x/mesecons_autotools/tools/test/test.lua new file mode 100644 index 00000000..bcb2a3d8 --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/tools/test/test.lua @@ -0,0 +1,24 @@ + +mesecons_autotools.register_action("test","left","air", function(user,pos,rad) + + end) +mesecons_autotools.register_action("test","left","block", function(user,pos,rad) + local node = minetest.get_node(pos) + -- print ("rules[" .. dump(mesecon.get_any_rules(node)) .. "]" ) + print("node=" .. dump(minetest.get_node(pos) )) + print("meta=" ..dump(minetest.get_meta(pos):to_table() ) ) + end) + + mesecons_autotools.register_action("test","right","block", function(user,pos,rad) + + end) + + mesecons_autotools.register_action("test","right","air", function(user,pos,rad) + local pos1 = mesecons_autotools.get_pos(user,1) + local pos2 = mesecons_autotools.get_pos(user,2) + + print ("D=pos1="..dump(pos1) .. ", pos2="..dump(pos2)) + end) + + + diff --git a/mods/mesecons_x/mesecons_autotools/tools/white/white.lua b/mods/mesecons_x/mesecons_autotools/tools/white/white.lua new file mode 100644 index 00000000..2813b9a7 --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/tools/white/white.lua @@ -0,0 +1,151 @@ + +local function get_right_nr(user,rad) + local dir = radians_to_vectors(rad) + local left = dir.left + local right = dir.right + + local lpos = {} + lpos[1] = mesecons_autotools.get_pos(user,1) + lpos[2] = mesecons_autotools.get_pos(user,2) + local posrigth_number + + if lpos[1] == nil then return end + if lpos[2] == nil then return end + + + + + if right.x == 1 then + if lpos[1].x > lpos[2].x then + posrigth_number = 1 + else + posrigth_number = 2 + end + elseif right.x == -1 then + if lpos[1].x > lpos[2].x then + posrigth_number = 2 + else + posrigth_number = 1 + end + elseif right.z == 1 then + if lpos[1].z > lpos[2].z then + posrigth_number = 1 + else + posrigth_number =2 + end + elseif right.z == -1 then + if lpos[1].z > lpos[2].z then + posrigth_number = 2 + else + posrigth_number = 1 + end + + end + + return posrigth_number + +end + + +local function move_right(user,rad) + local dir = radians_to_vectors(rad) + local left = dir.left + local right = dir.right + + local right_nr = get_right_nr(user,rad) + local lpos = {} + lpos[1] = mesecons_autotools.get_pos(user,1) + lpos[2] = mesecons_autotools.get_pos(user,2) + + + if right == nil then return end + if right_nr == nil then return end + if lpos[1] == nil then return end + if lpos[2] == nil then return end + + + local new_pos = vector.add(lpos[right_nr], right) + mesecons_autotools.set_pos(user,right_nr, new_pos) + + -- Update + mesecons_autotools.render(user) + mesecons_autotools.zero_stack_counter(user) +end + +local function can_shrink(user,right) + local lpos = {} + lpos[1] = mesecons_autotools.get_pos(user,1) + lpos[2] = mesecons_autotools.get_pos(user,2) + + if right == nil then return end + if lpos[1] == nil then return end + if lpos[2] == nil then return end + + if right.x ~= 0 then + if lpos[1].x == lpos[2].x then + return false + else + return true + end + end + + if right.z ~= 0 then + if lpos[1].z == lpos[2].z then + return false + else + return true + end + end +end + + +local function move_left(user,rad) + local dir = radians_to_vectors(rad) + local left = dir.left + local right = dir.right + + + if can_shrink(user,right) == false then return end + + + local right_nr = get_right_nr(user,rad) + local lpos = {} + lpos[1] = mesecons_autotools.get_pos(user,1) + lpos[2] = mesecons_autotools.get_pos(user,2) + + + if left == nil then return end + if lpos[1] == nil then return end + if lpos[2] == nil then return end + + + + local new_pos = vector.add(lpos[right_nr], left) + mesecons_autotools.set_pos(user,right_nr, new_pos) + + -- Update + mesecons_autotools.render(user) + mesecons_autotools.zero_stack_counter(user) + +end + + +mesecons_autotools.register_action("white","left","air", function(user,pos,rad) + move_left(user,rad) + + +end) +mesecons_autotools.register_action("white","left","block", function(user,pos,rad) + move_left(user,rad) +end) + +mesecons_autotools.register_action("white","right","block", function(user,pos,rad) + move_right(user,rad) +end) + +mesecons_autotools.register_action("white","right","air", function(user,pos,rad) + move_right(user,rad) +end) + + + \ No newline at end of file diff --git a/mods/mesecons_x/mesecons_autotools/tools/white_down/white_down.lua b/mods/mesecons_x/mesecons_autotools/tools/white_down/white_down.lua new file mode 100644 index 00000000..9ee2f33e --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/tools/white_down/white_down.lua @@ -0,0 +1,72 @@ + +local function move_up(user) + local vector_up = vector.new(0,1,0) + + + local lpos = {} + lpos[1] = mesecons_autotools.get_pos(user,1) + lpos[2] = mesecons_autotools.get_pos(user,2) + local posdown_number + + if lpos[1] == nil then return end + if lpos[2] == nil then return end + + if lpos[1].y == lpos[2].y then return end + + if lpos[1].y < lpos[2].y then + posdown_number = 1 + else + posdown_number = 2 + end + + local new_pos = vector.add(lpos[posdown_number], vector_up) + mesecons_autotools.set_pos(user,posdown_number, new_pos) + + -- Update + mesecons_autotools.render(user) + mesecons_autotools.zero_stack_counter(user) + +end + +local function move_down(user) + local vector_up = vector.new(0,-1,0) + + + local lpos = {} + lpos[1] = mesecons_autotools.get_pos(user,1) + lpos[2] = mesecons_autotools.get_pos(user,2) + local posdown_number + + if lpos[1] == nil then return end + if lpos[2] == nil then return end + + + + if lpos[1].y < lpos[2].y then + posdown_number = 1 + else + posdown_number = 2 + end + + local new_pos = vector.add(lpos[posdown_number], vector_up) + mesecons_autotools.set_pos(user,posdown_number, new_pos) + + -- Update + mesecons_autotools.render(user) + mesecons_autotools.zero_stack_counter(user) +end + +mesecons_autotools.register_action("white_down","left","air", function(user,pos,rad) + move_down(user); +end) +mesecons_autotools.register_action("white_down","left","block", function(user,pos,rad) + move_down(user); +end) + +mesecons_autotools.register_action("white_down","right","block", function(user,pos,rad) + move_up(user); +end) + +mesecons_autotools.register_action("white_down","right","air", function(user,pos,rad) + move_up(user); +end) diff --git a/mods/mesecons_x/mesecons_autotools/tools/white_up/white_up.lua b/mods/mesecons_x/mesecons_autotools/tools/white_up/white_up.lua new file mode 100644 index 00000000..92cb15d5 --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/tools/white_up/white_up.lua @@ -0,0 +1,73 @@ + +local function move_up(user) + local vector_up = vector.new(0,1,0) + + + local lpos = {} + lpos[1] = mesecons_autotools.get_pos(user,1) + lpos[2] = mesecons_autotools.get_pos(user,2) + local posup_number + + + + + if lpos[1] == nil then return end + if lpos[2] == nil then return end + + if lpos[1].y > lpos[2].y then + posup_number = 1 + else + posup_number = 2 + end + + local new_pos = vector.add(lpos[posup_number], vector_up) + mesecons_autotools.set_pos(user,posup_number, new_pos) + + -- Update + mesecons_autotools.render(user) + mesecons_autotools.zero_stack_counter(user) + +end + +local function move_down(user) + local vector_up = vector.new(0,-1,0) + + + local lpos = {} + lpos[1] = mesecons_autotools.get_pos(user,1) + lpos[2] = mesecons_autotools.get_pos(user,2) + local posup_number + + if lpos[1] == nil then return end + if lpos[2] == nil then return end + + if lpos[1].y == lpos[2].y then return end + + if lpos[1].y > lpos[2].y then + posup_number = 1 + else + posup_number = 2 + end + + local new_pos = vector.add(lpos[posup_number], vector_up) + mesecons_autotools.set_pos(user,posup_number, new_pos) + + -- Update + mesecons_autotools.render(user) + mesecons_autotools.zero_stack_counter(user) +end + +mesecons_autotools.register_action("white_up","left","air", function(user,pos,rad) + move_down(user); +end) +mesecons_autotools.register_action("white_up","left","block", function(user,pos,rad) + move_down(user); +end) + +mesecons_autotools.register_action("white_up","right","block", function(user,pos,rad) + move_up(user); +end) + +mesecons_autotools.register_action("white_up","right","air", function(user,pos,rad) + move_up(user); +end) diff --git a/mods/mesecons_x/mesecons_autotools/tools/wire.lua b/mods/mesecons_x/mesecons_autotools/tools/wire.lua new file mode 100644 index 00000000..8fff2791 --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/tools/wire.lua @@ -0,0 +1,445 @@ + + +function get_node_from_pins(pins) + local t = "mesecons_extrawires:tjunction_off" + local c = "mesecons_extrawires:corner_off" + local w = "mesecons_insulated:insulated_off" + local a = "air" + local x = "mesecons_morewires:xjunction_off" + + -- {left,up,right,down node_name, rotation} + local list = { + -- empty + {0,0,0,0,a,0}, + + -- wire + {1,0,1,0,w,0}, + {0,1,0,1,w,1}, + + -- corner + {1,0,0,1,c,0}, + {1,1,0,0,c,1}, + {0,1,1,0,c,2}, + {0,0,1,1,c,3}, + + -- tjunction + {1,0,1,1,t,0}, + {1,1,0,1,t,1}, + {1,1,1,0,t,2}, + {0,1,1,1,t,3}, + + -- xjunction + {1,1,1,1,x,0}, + + -- starting wire + {1,0,0,0,w,0}, + {0,1,0,0,w,1}, + {0,0,1,0,w,0}, + {0,0,0,1,w,1}, + } + + local node_name = "air" + local rotate = 0 + for _,v in ipairs(list) do + if (pins[1] == v[1]) and + (pins[2] == v[2]) and + (pins[3] == v[3]) and + (pins[4] == v[4]) then + + node_name = v[5] + rotate = v[6] + + end + + end + + return { name = node_name, param2 = rotate } + + +end + +function get_pins_from_pos(pos,type) + local node = minetest.get_node(pos) + + local rs = {} + if type == "input" then + rs = mesecon.get_any_inputrules(node) + elseif type == "output" then + rs = mesecon.get_any_outputrules(node) + else + rs = mesecon.get_any_rules(node) + end + if rs == nil then + rs = {} + else + rs = mesecon.flattenrules (rs) + end + + + -- Filter only y=0 + local list = {} + for _,v in pairs(rs) do + if v.y == 0 then + if v.x ~= 0 and v.z == 0 then + table.insert(list,v) + end + if v.z ~= 0 and v.x == 0 then + table.insert(list,v) + end + + end + end + + -- constructiong pin structure + + local pins = {0,0,0,0} + for _,v in pairs(list) do + if v.x == 1 then pins[3] = 1 end + if v.x == -1 then pins[1] = 1 end + if v.z == 1 then pins[2] = 1 end + if v.z == -1 then pins[4] = 1 end + end + return pins +end + + + +function dir_to_inx(d) + if d.x == 1 then return 3 end + if d.x == -1 then return 1 end + if d.z == 1 then return 2 end + if d.z == -1 then return 4 end + return 1 +end + +function get_pin_from_direction(direction) + return dir_to_inx(direction) +end + + + +local function neighbours_pins(pos) + local npins = {0,0,0,0} + for _,ix in ipairs({1,-1}) do + + local shift = { x=ix,y=0,z=0 } + local neigh = vector.add(pos,shift) + + local pins = get_pins_from_pos(neigh) + npins[ dir_to_inx( shift) ] = pins [ dir_to_inx( vector.multiply(shift,-1) ) ] + end + for _,iz in ipairs({1,-1}) do + + local shift = { x=0,y=0,z=iz } + local neigh = vector.add(pos,shift) + + local pins = get_pins_from_pos(neigh) + npins[ dir_to_inx( shift) ] = pins [ dir_to_inx( vector.multiply(shift,-1) ) ] + end + return npins +end + + +local function pins_and(pins1,pins2) + local pout = {} + for i=1,4,1 do + pout[i] = pins1[i] * pins2[i] + end + return pout + +end + + +local function start_node(pos,direction) + + local node = minetest.get_node(pos) + local name = node.name + + -- Only wires changed + local list = { + "mesecons_insulated:insulated_off","mesecons_insulated:insulated_on", + "mesecons_extrawires:corner_off","mesecons_extrawires:corner_on", + "mesecons_extrawires:tjunction_off", "mesecons_extrawires:tjunction_on", + "air" + } + + if not is_in_list(list,name) then return end + + + local npins = neighbours_pins(pos) + local mypins = get_pins_from_pos(pos) + local compins = pins_and(npins,mypins) + + -- adding wire + + if direction.x == 1 then + compins[3] = 1 + end + if direction.x == -1 then + compins[1] = 1 + end + + if direction.z == 1 then + compins[2] = 1 + end + if direction.z == -1 then + compins[4] = 1 + end + + --merge_wire(pos,direction) + local new_node = get_node_from_pins(compins) + + --minetest.set_node(pos,new_node) + mesecons_autotools.set_node(pos,new_node,"start_node") +end + +local function end_node(pos,direction) + --merge_wire(pos, vector.multiply(direction, -1)) + start_node(pos, vector.multiply(direction,-1)) +end + + +local function middle_node(pos, direction) + local node = minetest.get_node(pos) + local name = node.name + local param2 = node.param2 + + --minetest.set_node(pos,{name = "default:dirt"}) + --if true then return end + + if name ~= "mesecons_insulated:insulated_off" and + name ~= "mesecons_insulated:insulated_on" and + name ~= "air" then + return + end + + -- do crossing + if name == "air" then + local prm2 = 0 + if direction.z ~= 0 then + prm2 = 1 + end + if direction.x ~= 0 then + prm2 = 0 + end + --minetest.set_node(pos, { name ="mesecons_insulated:insulated_off", param2= 1 } ) + mesecons_autotools.set_node(pos, + {name ="mesecons_insulated:insulated_off", param2= prm2 }, + "middle_node") + + else + -- if nothing to do + if (direction.x ~= 0 ) and + ( param2 == 0 or param2 == 2 ) then + return + end + if (direction.z ~= 0 ) and + (param2 == 1 or param2 == 3 ) then + return + end + + --minetest.set_node(pos,{ name ="mesecons_extrawires:crossover_off" } ) + mesecons_autotools.set_node(pos, + { name ="mesecons_extrawires:crossover_off" }, + "middle_node") + + end +end + + +function create_straight_wire_n(pos,direction,size) + local current = pos + + -- first + start_node(current,direction) + current = vector.add(current,direction) + + -- middle + for i = 2, size-1, 1 do + middle_node(current,direction) + current = vector.add(current,direction) + + end + + -- last + end_node(current,direction) +end + +local function distance_taxi_metric(pos1,pos2) + local x1 = pos1.x + local x2 = pos2.x + + local dx = math.abs(x2-x1) + + local z1 = pos1.z + local z2 = pos2.z + + local dz = math.abs(z2-z1) + + return dz+dx+1 +end + + +function create_straight_wire(pos1,pos2) + + -- Check if straight line + if pos1.y ~= pos2.y then return end + if (pos1.x ~= pos2.x ) and (pos1.z ~= pos2.z) then return end + + + + -- Compute direction + local direction = { x =0,y=0,z=0} + if pos1.x == pos2.x then + if pos1.z < pos2.z then + direction.z = 1 + else + direction.z = -1 + end + end + if pos1.z == pos2.z then + if pos1.x < pos2.x then + direction.x = 1 + else + direction.x = -1 + end + end + + + -- Compute size + local size = distance_taxi_metric(pos1,pos2) + + + create_straight_wire_n(pos1,direction,size) + return true +end + +function hop_pos(pos,pin) + local new_pos = { x = pos.x, y = pos.y, z = pos.z } + + if pin == 1 then + new_pos.x = pos.x - 1 + end + if pin == 2 then + new_pos.z = pos.z + 1 + end + if pin == 3 then + new_pos.x = pos.x + 1 + end + if pin == 4 then + new_pos.z = pos.z -1 + end + + return new_pos +end + +function flip_pin(pin) + if pin == 1 then return 3 end + if pin == 2 then return 4 end + if pin == 3 then return 1 end + if pin == 4 then return 2 end +end + +-- TODO: refactor +function hop_pin(pin) + if pin == 1 then return 3 end + if pin == 2 then return 4 end + if pin == 3 then return 1 end + if pin == 4 then return 2 end +end + + + +local function delete(p,pin) + local node = minetest.get_node(p) + local name = node.name + + if name == "mesecons_insulated:insulated_off" or + name == "mesecons_insulated:insulated_on" or + name == "mesecons_extrawires:corner_off" or + name == "mesecons_extrawires:corner_on" + then + + -- continue deleting + local node_pins = get_pins_from_pos(p) + + -- not connected to anything + if node_pins[pin] == 0 then return end + + node_pins[pin] = 0 + for i=1,4,1 do + if node_pins[i] == 1 then + --minetest.set_node(p,{name="air"}) + mesecons_autotools.set_node(p,{name="air"},"delete") + delete(hop_pos(p,i),hop_pin(i)) + end + end + + + + elseif name == "mesecons_extrawires:crossover_off" or + name == "mesecons_extrawires:crossover_on" or + name == "mesecons_extrawires:crossover_10" or + name == "mesecons_extrawires:crossover_01" then + + -- continue deleting + + local node_pins = get_pins_from_pos(p) + node_pins[pin] = 0 + node_pins[hop_pin(pin)] = 0 + + local new_node = get_node_from_pins(node_pins) + -- minetest.set_node(p,new_node) + mesecons_autotools.set_node(p,new_node,"delete_crossover") + delete(hop_pos(p,hop_pin(pin)),pin) + + + + elseif name == "mesecons_extrawires:tjunction_off" or + name == "mesecons_extrawires:tjunction_on" or + name == "mesecons_morewires:xjunction_off" or + name == "mesecons_morewires:xjunction_on" then + + -- end of wire + + local node_pins = get_pins_from_pos(p) + + -- not connected to anything + if node_pins[pin] == 0 then return end + + node_pins[pin] = 0 + local new_node = get_node_from_pins(node_pins) + --minetest.set_node(p,new_node) + mesecons_autotools.set_node(p,new_node,"delete_end") + + + + else + -- do nothing (other blocks) + end +end + + +function delete_node(pos) + local node = minetest.get_node(pos) + + local pins = get_pins_from_pos(pos) + + --minetest.set_node(pos,{name="air"}) + mesecons_autotools.set_node(pos,{name="air"},"delete") + + for i=1,4,1 do + if pins[i] == 1 then + delete(hop_pos(pos,i),hop_pin(i)) + end + end + + +end + + + + + + + diff --git a/mods/mesecons_x/mesecons_autotools/tools/yellow/yellow.lua b/mods/mesecons_x/mesecons_autotools/tools/yellow/yellow.lua new file mode 100644 index 00000000..edb4a33c --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/tools/yellow/yellow.lua @@ -0,0 +1,218 @@ + +function can_move_into(sel,direction) + local front_wall = front_wall_by_direction(sel,direction) + + local pos1 = vector.new(front_wall.pos1) + local pos2 = vector.new(front_wall.pos2) + + pos1 = vector.add(pos1,direction) + pos2 = vector.add(pos2,direction) + + local shifted ={pos1=pos1,pos2=pos2} + + local result = {} + iterate_selection(pos1,pos2, function(pos) + local node = minetest.get_node(pos) + local name = node.name + + if name == "air" then + return + end + if + name == "mesecons_insulated:insulated_off" or + name == "mesecons_insulated:insulated_on" then + + local pins = get_pins_from_pos(pos) + local dpin = get_pin_from_direction(direction) + if pins[dpin] == 1 then + return + else + table.insert(result,false) + return + end + + + end + return table.insert(result,false) + end) + + for _,v in pairs(result) do + if v == false then + return false + end + end + + return true +end + + +function is_pos_connected(pos,direction) + local node = minetest.get_node(pos) + + local pins = get_pins_from_pos(pos) + local dpin = get_pin_from_direction(direction) + + -- no sticking out + if pins[dpin] == 0 then return false end + + + local neigh_pos + local neigh_pins + local connect_pin + + -- checking pos[out] <-> neigh[in] + + pins = get_pins_from_pos(pos,"output") + dpin = get_pin_from_direction(direction) + neigh_pos = hop_pos(pos,dpin) + neigh_pins = get_pins_from_pos(neigh_pos,"input") + connect_pin = neigh_pins[ hop_pin(dpin) ] + + if connect_pin == 1 then + return true + end + + -- checking pos[in] <-> neidth[out] + + pins = get_pins_from_pos(pos,"input") + dpin = get_pin_from_direction(direction) + neigh_pos = hop_pos(pos,dpin) + neigh_pins = get_pins_from_pos(neigh_pos,"output") + connect_pin = neigh_pins[ hop_pin(dpin) ] + + if connect_pin == 1 then + return true + end + + + + return false + + + +--[[ + local neigh_pos = hop_pos(pos,dpin) + local neigh_pins = get_pins_from_pos(neigh_pos) + local connect_pin = neigh_pins[ hop_pin(dpin) ] + + if connect_pin == 1 then + return true + else + return false + end +]]-- +end + + +function generate_tail_wires(back_wall,direction) + local pos1 = back_wall.pos1 + local pos2 = back_wall.pos2 + + local back_direction = vector.multiply(direction,-1) + local bd_pin = get_pin_from_direction(back_direction) + + + local list_pos = {} + iterate_selection(pos1,pos2, function(pos) + if is_pos_connected(pos,back_direction) then + table.insert(list_pos,pos) + end + end) + return list_pos +end + +function put_tail_wires(list,direction) + local node = {} + node.name = "mesecons_insulated:insulated_off" + node.param2 = 0 + for _,pos in ipairs(list) do + if direction.x ~= 0 then + node.param2 = 0 + else + node.param2 = 1 + end + --minetest.set_node(pos,node) + mesecons_autotools.set_node(pos,node,"put_tail_wires") + + end + +end + + +function get_back_wall(sel,direction) + return front_wall_by_direction(sel, vector.multiply(direction,-1)) +end + + + + +local function move_selection(user,rad,click) + local dir = radians_to_vectors(rad) + local left = dir.left + local right = dir.right + + local pos = {} + pos[1] = mesecons_autotools.get_pos(user,1) + pos[2] = mesecons_autotools.get_pos(user,2) + + + if pos[1] == nil then return end + if pos[2] == nil then return end + + + -- compute shift vector + + local direction = {} + if click == "left" then + direction = left + else + direction = right + end + + local buffor = {} + local tail = {} + local sel = { pos1=pos[1], pos2=pos[2]} + local back_wall = get_back_wall(sel,direction) + + if not can_move_into(sel,direction) then return end + + copy_to_buffor(pos[1],pos[2],buffor) + tail = generate_tail_wires(back_wall,direction) + + + delete(pos[1],pos[2]) + paste_from_buffor(direction,buffor) + put_tail_wires(tail,direction) + + shift_selection(user,direction) + + + -- Update + mesecons_autotools.render(user) + mesecons_autotools.zero_stack_counter(user) + mesecons_autotools.zero_stack_direction(user) +end + + + + + + +mesecons_autotools.register_action("yellow","left","air", function(user,pos,rad) + move_selection(user,rad,"left") +end) +mesecons_autotools.register_action("yellow","left","block", function(user,pos,rad) + move_selection(user,rad,"left") +end) + +mesecons_autotools.register_action("yellow","right","block", function(user,pos,rad) + move_selection(user,rad,"right") +end) + +mesecons_autotools.register_action("yellow","right","air", function(user,pos,rad) + move_selection(user,rad,"right") +end) + + + + \ No newline at end of file diff --git a/mods/mesecons_x/mesecons_autotools/tools/yellow_updown/yellow_updown.lua b/mods/mesecons_x/mesecons_autotools/tools/yellow_updown/yellow_updown.lua new file mode 100644 index 00000000..67652744 --- /dev/null +++ b/mods/mesecons_x/mesecons_autotools/tools/yellow_updown/yellow_updown.lua @@ -0,0 +1,73 @@ + + + + +local function move_selection(user,rad,click) + local pos = {} + pos[1] = mesecons_autotools.get_pos(user,1) + pos[2] = mesecons_autotools.get_pos(user,2) + + + if pos[1] == nil then return end + if pos[2] == nil then return end + + + -- compute shift vector + + local shift_vector = {} + if click == "up" then + shift_vector = {x=0,y=1,z=0} + else + shift_vector = {x=0,y=-1,z=0} + end + + local new_pos1 = vector.add(pos[1],shift_vector) + local new_pos2 = vector.add(pos[2],shift_vector) + + + --[[ + if not is_empty_selection(new_pos1,new_pos2) then + return + end + ]]-- + local sel = { pos1=pos[1], pos2=pos[2]} + if not can_move_into(sel,shift_vector) then return end + + + local buffor = {} + copy_to_buffor(pos[1],pos[2],buffor) + delete(pos[1],pos[2]) + paste_from_buffor(shift_vector,buffor) + + shift_selection(user,shift_vector) + + + -- Update + mesecons_autotools.render(user) + mesecons_autotools.zero_stack_counter(user) + mesecons_autotools.zero_stack_direction(user) + + +end + + + + + + +mesecons_autotools.register_action("yellow_updown","left","air", function(user,pos,rad) + move_selection(user,rad,"down") +end) +mesecons_autotools.register_action("yellow_updown","left","block", function(user,pos,rad) + move_selection(user,rad,"down") +end) + +mesecons_autotools.register_action("yellow_updown","right","block", function(user,pos,rad) + move_selection(user,rad,"up") +end) + +mesecons_autotools.register_action("yellow_updown","right","air", function(user,pos,rad) + move_selection(user,rad,"up") +end) + + \ No newline at end of file diff --git a/mods/mesecons_x/mesecons_gates3/init.lua b/mods/mesecons_x/mesecons_gates3/init.lua new file mode 100644 index 00000000..530a020b --- /dev/null +++ b/mods/mesecons_x/mesecons_gates3/init.lua @@ -0,0 +1,154 @@ +local selection_box = { + type = "fixed", + fixed = { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 } +} + +local nodebox = { + type = "fixed", + fixed = { + { -8/16, -8/16, -8/16, 8/16, -7/16, 8/16 }, -- bottom slab + { -6/16, -7/16, -6/16, 6/16, -6/16, 6/16 } + }, +} + +local function gate_rotate_rules(node, rules) + for rotations = 0, node.param2 - 1 do + rules = mesecon.rotate_rules_left(rules) + end + return rules +end + +local function gate3_get_output_rules(node) + return gate_rotate_rules(node, {{x=1, y=0, z=0}}) +end + +local function gate3_get_input_rules(node) + return gate_rotate_rules(node, { + {x=0, y=0, z=1, name="input1"}, + {x=0, y=0, z=-1, name="input2"}, + {x=-1, y=0, z=0, name="input3"} + }) +end + +local function set_gate3(pos, node, state) + local gate = minetest.registered_nodes[node.name] + + if mesecon.do_overheat(pos) then + minetest.remove_node(pos) + mesecon.receptor_off(pos, gate3_get_output_rules(node)) + minetest.add_item(pos, gate.drop) + elseif state then + minetest.swap_node(pos, {name = gate.onstate, param2=node.param2}) + mesecon.receptor_on(pos, gate3_get_output_rules(node)) + else + minetest.swap_node(pos, {name = gate.offstate, param2=node.param2}) + mesecon.receptor_off(pos, gate3_get_output_rules(node)) + end +end + +local function update_gate3(pos, node, link, newstate) + local gate = minetest.registered_nodes[node.name] + + local meta = minetest.get_meta(pos) + + + meta:set_int(link.name, newstate == "on" and 1 or 0) + + local val1 = meta:get_int("input1") == 1 and 1 or 0 + local val2 = meta:get_int("input2") == 1 and 1 or 0 + local val3 = meta:get_int("input3") == 1 and 1 or 0 + + + set_gate3(pos, node, gate.assess(val1==1 and true or false, + val2==1 and true or false, + val3==1 and true or false)) + +end + +local function register_gate(name, assess, recipe, description) + local description = "Logic Gate: "..name + + local basename = "mesecons_gates3:"..name + mesecon.register_node(basename, { + description = description, + inventory_image = "jeija_gate_off.png^jeija_gate_"..name..".png", + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + drawtype = "nodebox", + drop = basename.."_off", + selection_box = selection_box, + node_box = nodebox, + walkable = true, + sounds = default.node_sound_stone_defaults(), + assess = assess, + onstate = basename.."_on", + offstate = basename.."_off", + after_dig_node = mesecon.do_cooldown, + },{ + tiles = { + "jeija_microcontroller_bottom.png^".."jeija_gate_off.png^".. + "jeija_gate_output_off.png^".."jeija_gate_"..name..".png", + "jeija_microcontroller_bottom.png^".."jeija_gate_output_off.png^".. + "[transformFY", + "jeija_gate_side.png^".."jeija_gate_side_output_off.png", + "jeija_gate_side.png", + "jeija_gate_side.png", + "jeija_gate_side.png" + }, + groups = {dig_immediate = 2, overheat = 1}, + mesecons = { receptor = { + state = "off", + rules = gate3_get_output_rules + }, effector = { + rules = gate3_get_input_rules, + action_change = update_gate3 + }} + },{ + tiles = { + "jeija_microcontroller_bottom.png^".."jeija_gate_on.png^".. + "jeija_gate_output_on.png^".."jeija_gate_"..name..".png", + "jeija_microcontroller_bottom.png^".."jeija_gate_output_on.png^".. + "[transformFY", + "jeija_gate_side.png^".."jeija_gate_side_output_on.png", + "jeija_gate_side.png", + "jeija_gate_side.png", + "jeija_gate_side.png" + }, + groups = {dig_immediate = 2, not_in_creative_inventory = 1, overheat = 1}, + mesecons = { receptor = { + state = "on", + rules = gate3_get_output_rules + }, effector = { + rules = gate3_get_input_rules, + action_change = update_gate3 + }} + }) + + minetest.register_craft({output = basename.."_off", recipe = recipe}) +end + +register_gate("and3", function (val1, val2, val3) return (val1 and val2 and val3) end, + {{"mesecons:mesecon", "mesecons:mesecon", ""}, + {"", "mesecons_materials:silicon", "mesecons:mesecon"}, + {"mesecons:mesecon", "", ""}}, + "AND Gate") + + +register_gate("nand3", function (val1, val2,val3) return not (val1 and val2 and val3) end, + {{"mesecons:mesecon", "mesecons:mesecon", ""}, + {"", "mesecons_materials:silicon", "mesecons_torch:mesecon_torch_on"}, + {"mesecons:mesecon", "", ""}}, + "NAND Gate") + +register_gate("nor3", function (val1, val2, val3) return not (val1 or val2 or val3) end, + {{"mesecons:mesecon", "mesecons:mesecon", ""}, + {"", "mesecons:mesecon", "mesecons_torch:mesecon_torch_on"}, + {"mesecons:mesecon", "", ""}}, + "NOR Gate") + +register_gate("or3", function (val1, val2, val3) return (val1 or val2 or val3) end, + {{"mesecons:mesecon", "mesecons:mesecon", ""}, + {"", "mesecons:mesecon", "mesecons:mesecon"}, + {"mesecons:mesecon", "", ""}}, + "OR Gate") diff --git a/mods/mesecons_x/mesecons_gates3/mod.conf b/mods/mesecons_x/mesecons_gates3/mod.conf new file mode 100644 index 00000000..437757cb --- /dev/null +++ b/mods/mesecons_x/mesecons_gates3/mod.conf @@ -0,0 +1,3 @@ +author = marek +name = mesecons_gates3 +depends = mesecons, mesecons_microcontroller, mesecons_delayer, mesecons_torch, mesecons_materials diff --git a/mods/mesecons_x/mesecons_gates3/textures/jeija_gate_and3.png b/mods/mesecons_x/mesecons_gates3/textures/jeija_gate_and3.png new file mode 100644 index 00000000..87fef0fd Binary files /dev/null and b/mods/mesecons_x/mesecons_gates3/textures/jeija_gate_and3.png differ diff --git a/mods/mesecons_x/mesecons_gates3/textures/jeija_gate_nand3.png b/mods/mesecons_x/mesecons_gates3/textures/jeija_gate_nand3.png new file mode 100644 index 00000000..61c6ef6e Binary files /dev/null and b/mods/mesecons_x/mesecons_gates3/textures/jeija_gate_nand3.png differ diff --git a/mods/mesecons_x/mesecons_gates3/textures/jeija_gate_nor3.png b/mods/mesecons_x/mesecons_gates3/textures/jeija_gate_nor3.png new file mode 100644 index 00000000..774fa234 Binary files /dev/null and b/mods/mesecons_x/mesecons_gates3/textures/jeija_gate_nor3.png differ diff --git a/mods/mesecons_x/mesecons_gates3/textures/jeija_gate_or3.png b/mods/mesecons_x/mesecons_gates3/textures/jeija_gate_or3.png new file mode 100644 index 00000000..5b36c43a Binary files /dev/null and b/mods/mesecons_x/mesecons_gates3/textures/jeija_gate_or3.png differ diff --git a/mods/mesecons_x/mesecons_morewires/init.lua b/mods/mesecons_x/mesecons_morewires/init.lua new file mode 100644 index 00000000..5f270247 --- /dev/null +++ b/mods/mesecons_x/mesecons_morewires/init.lua @@ -0,0 +1,2 @@ +dofile(minetest.get_modpath("mesecons_morewires").."/xjunction.lua"); +dofile(minetest.get_modpath("mesecons_morewires").."/nopower_plant.lua"); diff --git a/mods/mesecons_x/mesecons_morewires/mod.conf b/mods/mesecons_x/mesecons_morewires/mod.conf new file mode 100644 index 00000000..15683d88 --- /dev/null +++ b/mods/mesecons_x/mesecons_morewires/mod.conf @@ -0,0 +1,3 @@ +author = marek +name = mesecons_morewires +depends = mesecons diff --git a/mods/mesecons_x/mesecons_morewires/nopower_plant.lua b/mods/mesecons_x/mesecons_morewires/nopower_plant.lua new file mode 100644 index 00000000..66918ff8 --- /dev/null +++ b/mods/mesecons_x/mesecons_morewires/nopower_plant.lua @@ -0,0 +1,33 @@ +-- Just emits no power, always. + + +minetest.register_node("mesecons_morewires:nopower_plant", { + drawtype = "plantlike", + visual_scale = 1, + tiles = {"jeija_nopower_plant.png"}, + inventory_image = "jeija_nopower_plant.png", + paramtype = "light", + is_ground_content = false, + walkable = false, + groups = {dig_immediate=3, mesecon = 2}, + light_source = minetest.LIGHT_MAX-9, + description="No Power Plant", + selection_box = { + type = "fixed", + fixed = {-0.3, -0.5, -0.3, 0.3, -0.5+0.7, 0.3}, + }, + sounds = default.node_sound_leaves_defaults(), + mesecons = {receptor = { + state = mesecon.state.off + }}, + on_blast = mesecon.on_blastnode, +}) + +minetest.register_craft({ + output = "mesecons_morewires:nopower_plant 1", + recipe = { + {"group:mesecon_conductor_craftable"}, + {"group:mesecon_conductor_craftable"}, + {"wool:black"}, + } +}) diff --git a/mods/mesecons_x/mesecons_morewires/textures/jeija_insulated_wire_x_top_off.png b/mods/mesecons_x/mesecons_morewires/textures/jeija_insulated_wire_x_top_off.png new file mode 100644 index 00000000..e6969e05 Binary files /dev/null and b/mods/mesecons_x/mesecons_morewires/textures/jeija_insulated_wire_x_top_off.png differ diff --git a/mods/mesecons_x/mesecons_morewires/textures/jeija_insulated_wire_x_top_on.png b/mods/mesecons_x/mesecons_morewires/textures/jeija_insulated_wire_x_top_on.png new file mode 100644 index 00000000..15e90da1 Binary files /dev/null and b/mods/mesecons_x/mesecons_morewires/textures/jeija_insulated_wire_x_top_on.png differ diff --git a/mods/mesecons_x/mesecons_morewires/textures/jeija_nopower_plant.png b/mods/mesecons_x/mesecons_morewires/textures/jeija_nopower_plant.png new file mode 100644 index 00000000..3c7be6c3 Binary files /dev/null and b/mods/mesecons_x/mesecons_morewires/textures/jeija_nopower_plant.png differ diff --git a/mods/mesecons_x/mesecons_morewires/xjunction.lua b/mods/mesecons_x/mesecons_morewires/xjunction.lua new file mode 100644 index 00000000..a400317b --- /dev/null +++ b/mods/mesecons_x/mesecons_morewires/xjunction.lua @@ -0,0 +1,97 @@ + +local xjunction_nodebox = { + type = "fixed", + -- ±0.001 is to prevent z-fighting + fixed = { + { -3/32, -17/32, -16/32+0.001, 3/32, -13/32, -3/32}, + { -3/32, -17/32, 16/32+0.001, 3/32, -13/32, 3/32}, + { -16/32-0.001, -17/32, -3/32, -3/32, -13/32, 3/32 }, + { 16/32+0.001, -17/32, -3/32, 3/32, -13/32, 3/32 }, + + { -6/32, -17/32, -6/32, 6/32, -12/32, 6/32 }, + } +} + +local xjunction_selectionbox = { + type = "fixed", + fixed = { -16/32, -16/32, -16/32, 16/32, -13/32, 16/32 }, +} +local xjunction_rules = +{ + {x = 1, y = 0, z = 0}, + {x =-1, y = 0, z = 0}, + {x = 0, y = 0, z = 1}, + {x = 0, y = 0, z =-1}, +} + + + +minetest.register_node("mesecons_morewires:xjunction_on", { + drawtype = "nodebox", + tiles = { + "jeija_insulated_wire_x_top_on.png", + "jeija_insulated_wire_sides_on.png", + "jeija_insulated_wire_ends_on.png", + "jeija_insulated_wire_ends_on.png", + "jeija_insulated_wire_ends_on.png", + "jeija_insulated_wire_ends_on.png" + }, + + paramtype = "light", +-- paramtype2 = "facedir", + is_ground_content = false, + walkable = false, + sunlight_propagates = true, + selection_box = xjunction_selectionbox, + node_box = xjunction_nodebox, + groups = {dig_immediate = 3, not_in_creative_inventory = 1}, + drop = "mesecons_morewires:xjunction_off", + sounds = default.node_sound_defaults(), + mesecons = {conductor = + { + state = mesecon.state.on, + rules = xjunction_rules, + offstate = "mesecons_morewires:xjunction_off" + }}, + on_blast = mesecon.on_blastnode, + on_rotate = nil +}) + +minetest.register_node("mesecons_morewires:xjunction_off", { + drawtype = "nodebox", + description = "Insulated Mesecon X-junction", + tiles = { + "jeija_insulated_wire_x_top_off.png", + "jeija_insulated_wire_sides_off.png", + "jeija_insulated_wire_ends_off.png", + "jeija_insulated_wire_ends_off.png", + "jeija_insulated_wire_ends_off.png", + "jeija_insulated_wire_ends_off.png" + }, + paramtype = "light", +-- paramtype2 = "facedir", + is_ground_content = false, + walkable = false, + sunlight_propagates = true, + selection_box = xjunction_selectionbox, + node_box = xjunction_nodebox, + groups = {dig_immediate = 3}, + sounds = default.node_sound_defaults(), + mesecons = {conductor = + { + state = mesecon.state.off, + rules = xjunction_rules, + onstate = "mesecons_morewires:xjunction_on" + }}, + on_blast = mesecon.on_blastnode, + on_rotate = nil +}) + +minetest.register_craft({ + output = "mesecons_morewires:xjunction_off 2", + recipe = { + {"","mesecons_insulated:insulated_off", ""}, + {"mesecons_insulated:insulated_off","mesecons_insulated:insulated_off" , "mesecons_insulated:insulated_off"}, + {"","mesecons_insulated:insulated_off", ""}, + } +}) diff --git a/mods/mesecons_x/mesecons_regs/depends.txt b/mods/mesecons_x/mesecons_regs/depends.txt new file mode 100644 index 00000000..f3e0392f --- /dev/null +++ b/mods/mesecons_x/mesecons_regs/depends.txt @@ -0,0 +1,6 @@ +mesecons +mesecons_microcontroller +mesecons_delayer + +mesecons_torch +mesecons_materials diff --git a/mods/mesecons_x/mesecons_regs/init.lua b/mods/mesecons_x/mesecons_regs/init.lua new file mode 100644 index 00000000..61999e9e --- /dev/null +++ b/mods/mesecons_x/mesecons_regs/init.lua @@ -0,0 +1,232 @@ +local nodebox = { + type = "fixed", + fixed = {{-8/16, -8/16, -8/16, 8/16, -7/16, 8/16 }}, +} + +local function gate_rotate_rules(node, rules) + for rotations = 0, node.param2 - 1 do + rules = mesecon.rotate_rules_left(rules) + end + return rules +end + + +local function latch_get_input_rules(node) + return gate_rotate_rules(node, + { + {x=-1, y=0, z=0, name="data"}, + {x=0, y=0, z=-1, name="enable"} + }) +end + +local function latch_get_output_rules(node) + return gate_rotate_rules(node, + { {x=1,y=0,z=0 }} + ) +end + + + +local function set_latch(pos,node,state) + local latch = minetest.registered_nodes[node.name] + if state then + minetest.swap_node(pos, {name = latch.onstate, param2=node.param2}) + mesecon.receptor_on(pos, latch_get_output_rules(node)) + else + minetest.swap_node(pos, {name = latch.offstate, param2=node.param2}) + mesecon.receptor_off(pos, latch_get_output_rules(node)) + end +end + + +local function update_latch(pos, node, link, newstate) + local latch = minetest.registered_nodes[node.name] + local meta = minetest.get_meta(pos) + + local data= meta:get_int("data") == 1 and 1 or 0 + local enable = meta:get_int("enable") == 1 and 1 or 0 + + + if link.name == "enable" then + if newstate == "off" and enable == 1 then + if data == 0 then + set_latch(pos,node,false) + else + set_latch(pos,node,true) + end + meta:set_int("enable",0) + end + if newstate == "on" then + if data == 0 then + set_latch(pos,node,false) + else + set_latch(pos,node,true) + end + meta:set_int("enable",1) + end + + end + + if link.name == "data" then + if enable == 1 then + local nv = newstate == "on" and 1 or 0 + set_latch(pos,node, nv == 1 and true or false) + meta:set_int("data",nv) + else + meta:set_int("data", newstate == "on" and 1 or 0 ) + end + end + +end + + + +local function register_latch() + local name = "latch" + local description = "Logic Memory Circuit: "..name + + local basename = "mesecons_regs:"..name + mesecon.register_node(basename, + { + description = description, + inventory_image = "jeija_gate_off.png^jeija_gate_"..name..".png", + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + drawtype = "nodebox", + drop = basename.."_off", + selection_box = nodebox, + node_box = nodebox, + walkable = true, + sounds = default.node_sound_stone_defaults(), + onstate = basename.."_on", + offstate = basename.."_off", + after_dig_node = mesecon.do_cooldown, + },{ + tiles = {"jeija_microcontroller_bottom.png^".."jeija_gate_off.png^".. + "jeija_gate_"..name..".png"}, + groups = {dig_immediate = 2, overheat = 1}, + mesecons = { receptor = { + state = "off", + rules = latch_get_output_rules + }, effector = { + rules = latch_get_input_rules, + action_change = update_latch + }} + },{ + tiles = {"jeija_microcontroller_bottom.png^".."jeija_gate_on.png^".. + "jeija_gate_"..name..".png"}, + groups = {dig_immediate = 2, not_in_creative_inventory = 1, overheat = 1}, + mesecons = { receptor = { + state = "on", + rules = latch_get_output_rules + }, effector = { + rules = latch_get_input_rules, + action_change = update_latch + }} + }) + + + minetest.register_craft({output = basename.."_off", recipe = { + { "mesecons_gates:and_off", "mesecons_gates:and_off", "mesecons_gates:not_off"}, + { "mesecons_gates:nor_off", "mesecons_gates:nor_off", "mesecons_insulated:insulated_off"}, + { "mesecons_insulated:insulated_off", "mesecons_insulated:insulated_off", "mesecons_insulated:insulated_off"} + }}) + +end + + +register_latch() + + + + + +local function update_flipflop(pos, node, link, newstate) + local latch = minetest.registered_nodes[node.name] + local meta = minetest.get_meta(pos) + + local data= meta:get_int("data") == 1 and 1 or 0 + local enable = meta:get_int("enable") == 1 and 1 or 0 + + + + if link.name == "enable" then + if newstate == "off" then + meta:set_int("enable",0) + end + if newstate == "on" and enable == 0 then + if data == 0 then + set_latch(pos,node,false) + else + set_latch(pos,node,true) + end + meta:set_int("enable",1) + end + + end + + if link.name == "data" then + meta:set_int("data", newstate == "on" and 1 or 0 ) + end + +end + + + +local function register_flipflop() + local name = "flipflop" + local description = "Logic Memory Circuit: "..name + + local basename = "mesecons_regs:"..name + mesecon.register_node(basename, + { + description = description, + inventory_image = "jeija_gate_off.png^jeija_gate_"..name..".png", + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + drawtype = "nodebox", + drop = basename.."_off", + selection_box = nodebox, + node_box = nodebox, + walkable = true, + sounds = default.node_sound_stone_defaults(), + onstate = basename.."_on", + offstate = basename.."_off", + after_dig_node = mesecon.do_cooldown, + },{ + tiles = {"jeija_microcontroller_bottom.png^".."jeija_gate_off.png^".. + "jeija_gate_"..name..".png"}, + groups = {dig_immediate = 2, overheat = 1}, + mesecons = { receptor = { + state = "off", + rules = latch_get_output_rules + }, effector = { + rules = latch_get_input_rules, + action_change = update_flipflop + }} + },{ + tiles = {"jeija_microcontroller_bottom.png^".."jeija_gate_on.png^".. + "jeija_gate_"..name..".png"}, + groups = {dig_immediate = 2, not_in_creative_inventory = 1, overheat = 1}, + mesecons = { receptor = { + state = "on", + rules = latch_get_output_rules + }, effector = { + rules = latch_get_input_rules, + action_change = update_flipflop + }} + }) + + minetest.register_craft({output = basename.."_off", + recipe = { + { "mesecons_regs:latch_off", "mesecons_regs:latch_off", }, + { "mesecons_gates:not_off", "mesecons_insulated:insulated_off",}, + { "mesecons_extrawires:tjunction_off", "mesecons_extrawires:corner_off", } + }}) + +end + + +register_flipflop() diff --git a/mods/mesecons_x/mesecons_regs/mod.conf b/mods/mesecons_x/mesecons_regs/mod.conf new file mode 100644 index 00000000..50814724 --- /dev/null +++ b/mods/mesecons_x/mesecons_regs/mod.conf @@ -0,0 +1,5 @@ +author = marek +description = Adds Latch and Filipflops circuits. +title = Mesecon Register Circuits +name = mesecons_regs +depends = mesecons diff --git a/mods/mesecons_x/mesecons_regs/textures/jeija_gate_flipflop.png b/mods/mesecons_x/mesecons_regs/textures/jeija_gate_flipflop.png new file mode 100644 index 00000000..d07e9258 Binary files /dev/null and b/mods/mesecons_x/mesecons_regs/textures/jeija_gate_flipflop.png differ diff --git a/mods/mesecons_x/mesecons_regs/textures/jeija_gate_latch.png b/mods/mesecons_x/mesecons_regs/textures/jeija_gate_latch.png new file mode 100644 index 00000000..dcad2f94 Binary files /dev/null and b/mods/mesecons_x/mesecons_regs/textures/jeija_gate_latch.png differ diff --git a/mods/mesecons_x/mesecons_regs/textures/jeija_gate_off.png b/mods/mesecons_x/mesecons_regs/textures/jeija_gate_off.png new file mode 100644 index 00000000..2f77aeb1 Binary files /dev/null and b/mods/mesecons_x/mesecons_regs/textures/jeija_gate_off.png differ diff --git a/mods/mesecons_x/mesecons_regs/textures/jeija_gate_on.png b/mods/mesecons_x/mesecons_regs/textures/jeija_gate_on.png new file mode 100644 index 00000000..406e4f6e Binary files /dev/null and b/mods/mesecons_x/mesecons_regs/textures/jeija_gate_on.png differ diff --git a/mods/mesecons_x/modpack.conf b/mods/mesecons_x/modpack.conf new file mode 100644 index 00000000..575b188a --- /dev/null +++ b/mods/mesecons_x/modpack.conf @@ -0,0 +1,6 @@ +name = mesecons_x +title = Mesecons Extended +author = marek +description = Adds Latch, Flipflop, tools for automatic wireing, 3-input gates etc. +release = 11016 + diff --git a/mods/mesecons_x/picture.png b/mods/mesecons_x/picture.png new file mode 100644 index 00000000..702d63b0 Binary files /dev/null and b/mods/mesecons_x/picture.png differ diff --git a/mods/mesecons_x/picture_4bit_incrementer.png b/mods/mesecons_x/picture_4bit_incrementer.png new file mode 100644 index 00000000..78d447d7 Binary files /dev/null and b/mods/mesecons_x/picture_4bit_incrementer.png differ diff --git a/mods/mesecons_x/screenshot.png b/mods/mesecons_x/screenshot.png new file mode 100644 index 00000000..702d63b0 Binary files /dev/null and b/mods/mesecons_x/screenshot.png differ diff --git a/mods/moremesecons/.github/workflows/luacheck.yml b/mods/moremesecons/.github/workflows/luacheck.yml new file mode 100644 index 00000000..3c99a991 --- /dev/null +++ b/mods/moremesecons/.github/workflows/luacheck.yml @@ -0,0 +1,10 @@ +name: luacheck +on: [push, pull_request] +jobs: + luacheck: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@master + - name: Luacheck + uses: lunarmodules/luacheck@master diff --git a/mods/moremesecons/.gitignore b/mods/moremesecons/.gitignore new file mode 100644 index 00000000..c8d945c1 --- /dev/null +++ b/mods/moremesecons/.gitignore @@ -0,0 +1,7 @@ +## Generic ignorable patterns and files +*~ +debug.txt + +## Eclipse project files & directories +.project +.settings diff --git a/mods/moremesecons/.luacheckrc b/mods/moremesecons/.luacheckrc new file mode 100644 index 00000000..aa5d02ea --- /dev/null +++ b/mods/moremesecons/.luacheckrc @@ -0,0 +1,9 @@ +read_globals = { + -- Defined by Minetest + "minetest", "vector", "PseudoRandom", "VoxelArea", "table", + + -- Mods + "digiline", "default", "creative", +} +globals = {"moremesecons", "mesecon"} +ignore = {"212", "631", "422", "432"} diff --git a/mods/moremesecons/LICENSE.txt b/mods/moremesecons/LICENSE.txt new file mode 100644 index 00000000..52d13511 --- /dev/null +++ b/mods/moremesecons/LICENSE.txt @@ -0,0 +1,374 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. + diff --git a/mods/moremesecons/README.md b/mods/moremesecons/README.md new file mode 100644 index 00000000..f58e8171 --- /dev/null +++ b/mods/moremesecons/README.md @@ -0,0 +1,50 @@ +# MoreMesecons + +Based on Mesecons by Jeija
+By @paly2 and @HybridDog
+With the participation of @LeMagnesium (bugfix), @Ataron (textures), @JAPP (texture). + +Dependencies: [Mesecons](https://github.com/Jeija/minetest-mod-mesecons/)
+Optional dependencies: [digilines](https://github.com/minetest-mods/digilines) + +MoreMesecons is a mod for minetest which adds some mesecons items. + +[Here](http://github.com/minetest-mods/MoreMesecons/wiki)'s the wiki ! + +## New items + +* `Adjustable Blinky plant` : Like a mesecons blinky plant, but... adjustable. Right-click to change the interval. +* `Adjustable Player Detector` : Like a mesecons player detector, but you can change its detection radius by right-click. +* `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). +* `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". +* `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. +* `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")). +* `Igniter` : This node is a lighter that ignites its adjacent flammable nodes (including TNT). +* `Injector Controller` : This node is useful to activate/deactivate a pipeworks filter injector : it sends a blinky signal. +* `Jammer` : If turned on, this node stops mesecons in a radius of 10 nodes. +* `LuaBlock`: This block allows its owner to execute any Lua code in the global environment when turned on. Using it requires the server privilege. +* `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. +* `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. +* `Sayer` : This node sends a message to every players inside a radius of 8 nodes. +* `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. +* `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. +* `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. +* `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. +* `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. +* `Wireless Jammer` : If it receives a mesecons signal, it deactivates all wireless (receptors) in a radius of 15 nodes. + +## Settings + +You can set the settings by using the Minetest GUI ("Settings" tab -> Advanced settings -> Mods -> MoreMesecons). + +## The Sayer and the Speech Dispatcher + +[Speech Dispatcher project](http://freecode.com/projects/speech-dispatcher) + +The Sayer item is able to speak on your speakers using the speech dispatcher, under these conditions: +1. The moremesecons_sayer mod is present in your trusted_mods setting +2. You are playing in singleplayer. +3. You are using a POSIX-compliant system and a sh-compatible shell (such as bash, dash, zsh...). Microsoft Windows is NOT POSIX-compliant. +4. The speech dispatcher is installed on your system. + +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). diff --git a/mods/moremesecons/description.txt b/mods/moremesecons/description.txt new file mode 100644 index 00000000..4172a16d --- /dev/null +++ b/mods/moremesecons/description.txt @@ -0,0 +1 @@ +Adds more Mesecons items. diff --git a/mods/moremesecons/modpack.conf b/mods/moremesecons/modpack.conf new file mode 100644 index 00000000..189af181 --- /dev/null +++ b/mods/moremesecons/modpack.conf @@ -0,0 +1,6 @@ +name = moremesecons +author = Palige +release = 25228 +title = MoreMesecons +description = Adds more Mesecons items. + diff --git a/mods/moremesecons/modpack.txt b/mods/moremesecons/modpack.txt new file mode 100644 index 00000000..33d91f57 --- /dev/null +++ b/mods/moremesecons/modpack.txt @@ -0,0 +1 @@ +The presence of this file indicates that the current folder is a modpack. \ No newline at end of file diff --git a/mods/moremesecons/moremesecons_adjustable_blinkyplant/init.lua b/mods/moremesecons/moremesecons_adjustable_blinkyplant/init.lua new file mode 100644 index 00000000..66c5e9d8 --- /dev/null +++ b/mods/moremesecons/moremesecons_adjustable_blinkyplant/init.lua @@ -0,0 +1,66 @@ +local toggle_timer = function (pos, restart) + local timer = minetest.get_node_timer(pos) + if timer:is_started() + and not restart then + timer:stop() + else + local interval = tonumber(minetest.get_meta(pos):get_string("interval")) or 1 + if interval < moremesecons.setting("adjustable_blinky_plant", "min_interval", 0.5) then + interval = moremesecons.setting("adjustable_blinky_plant", "min_interval", 0.5) + end + timer:start(interval) + end +end + +local on_timer = function(pos) + if mesecon.flipstate(pos, minetest.get_node(pos)) == "on" then + mesecon.receptor_on(pos) + else + mesecon.receptor_off(pos) + end + toggle_timer(pos, false) +end + +mesecon.register_node("moremesecons_adjustable_blinkyplant:adjustable_blinky_plant", { + description="Adjustable Blinky Plant", + drawtype = "plantlike", + inventory_image = "moremesecons_blinky_plant_off.png", + paramtype = "light", + walkable = false, + sounds = default.node_sound_leaves_defaults(), + selection_box = { + type = "fixed", + fixed = {-0.3, -0.5, -0.3, 0.3, -0.5+0.7, 0.3}, + }, + on_timer = on_timer, + on_construct = function(pos) + local meta = minetest.get_meta(pos) + meta:set_string("interval", "1") + meta:set_string("formspec", "field[interval;interval;${interval}]") + toggle_timer(pos, true) + end, + on_receive_fields = function(pos, _, fields, player) + local interval = tonumber(fields.interval) + if interval + and not minetest.is_protected(pos, player:get_player_name()) then + minetest.get_meta(pos):set_string("interval", interval) + toggle_timer(pos, true) + end + end, +},{ + tiles = {"moremesecons_blinky_plant_off.png"}, + groups = {dig_immediate=3}, + mesecons = {receptor = { state = mesecon.state.off }} +},{ + tiles = {"moremesecons_blinky_plant_off.png^moremesecons_blinky_plant_on.png"}, + groups = {dig_immediate=3, not_in_creative_inventory=1}, + sunlight_propagates = true, + mesecons = {receptor = { state = mesecon.state.on }}, +}) + + +minetest.register_craft({ + output = "moremesecons_adjustable_blinkyplant:adjustable_blinky_plant_off 1", + recipe = { {"mesecons_blinkyplant:blinky_plant_off"}, + {"default:mese_crystal_fragment"},} +}) diff --git a/mods/moremesecons/moremesecons_adjustable_blinkyplant/mod.conf b/mods/moremesecons/moremesecons_adjustable_blinkyplant/mod.conf new file mode 100644 index 00000000..e6eca3ac --- /dev/null +++ b/mods/moremesecons/moremesecons_adjustable_blinkyplant/mod.conf @@ -0,0 +1,3 @@ +name = moremesecons_adjustable_blinkyplant +depends = mesecons,moremesecons_utils +optional_depends = craft_guide diff --git a/mods/moremesecons/moremesecons_adjustable_blinkyplant/textures/moremesecons_blinky_plant_off.png b/mods/moremesecons/moremesecons_adjustable_blinkyplant/textures/moremesecons_blinky_plant_off.png new file mode 100644 index 00000000..e36f3a10 Binary files /dev/null and b/mods/moremesecons/moremesecons_adjustable_blinkyplant/textures/moremesecons_blinky_plant_off.png differ diff --git a/mods/moremesecons/moremesecons_adjustable_blinkyplant/textures/moremesecons_blinky_plant_on.png b/mods/moremesecons/moremesecons_adjustable_blinkyplant/textures/moremesecons_blinky_plant_on.png new file mode 100644 index 00000000..8f157d1f Binary files /dev/null and b/mods/moremesecons/moremesecons_adjustable_blinkyplant/textures/moremesecons_blinky_plant_on.png differ diff --git a/mods/moremesecons/moremesecons_adjustable_player_detector/init.lua b/mods/moremesecons/moremesecons_adjustable_player_detector/init.lua new file mode 100644 index 00000000..672f87e0 --- /dev/null +++ b/mods/moremesecons/moremesecons_adjustable_player_detector/init.lua @@ -0,0 +1,158 @@ +-- Adjustable Player Detector +-- Detects players in a certain radius +-- The radius can be changes by right-click (by default 6) + +local function make_formspec(meta) + meta:set_string("formspec", "size[9,5]" .. + "field[0.3, 0;9,2;scanname;Comma-separated list of the names of players to scan for (empty for any):;${scanname}]".. + "field[0.3,1.5;4,2;digiline_channel;Digiline Channel (optional):;${digiline_channel}]".. + "field[0.3,3;4,2;radius;Detection radius:;${radius}]".. + "button_exit[3.5,3.5;2,3;;Save]") +end + +local function object_detector_make_formspec(pos) + make_formspec(minetest.get_meta(pos)) +end + +local function object_detector_on_receive_fields(pos, _, fields, player) + if not fields.scanname + or not fields.digiline_channel + or minetest.is_protected(pos, player:get_player_name()) then + return + end + + local meta = minetest.get_meta(pos) + meta:set_string("scanname", fields.scanname) + meta:set_string("digiline_channel", fields.digiline_channel) + local r = tonumber(fields.radius) + if r then + meta:set_int("radius", r) + end +end + +-- returns true if player was found, false if not +local object_detector_scan = function (pos) + local meta = minetest.get_meta(pos) + local scanname = meta:get_string("scanname") + local scan_all = scanname == "" + local scan_names = scanname:split(',') + local radius = meta:get_int("radius") + if radius <= 0 then + radius = 6 + end + for _,obj in pairs(minetest.get_objects_inside_radius(pos, radius)) do + local isname = obj:get_player_name() -- "" is returned if it is not a player; "" ~= nil! + if isname ~= "" then + if scan_all then + return true, isname + end + for _, name in ipairs(scan_names) do + if isname == name then + return true, isname + end + end + end + end + return false +end + +-- set player name when receiving a digiline signal on a specific channel +local object_detector_digiline = { + effector = { + action = function (pos, node, channel, msg) + local meta = minetest.get_meta(pos) + local active_channel = meta:get_string("digiline_channel") + if channel ~= active_channel then + return + end + if type(msg) == "string" then + meta:set_string("scanname", msg) + make_formspec(meta) + elseif type(msg) == "table" then + if msg.radius then + local r = tonumber(msg.radius) + if r then + meta:set_int("radius", tonumber(msg.radius)) + make_formspec(meta) + end + end + if msg.scanname then + meta:set_string("scanname", msg.scanname) + make_formspec(meta) + end + if msg.command and msg.command == "get" then + local found, name = object_detector_scan(pos) + if not found then + name = "" + end + digiline:receptor_send(pos, digiline.rules.default, channel, name) + end + end + end, + }, + receptor = {} +} + +minetest.register_node("moremesecons_adjustable_player_detector:player_detector_off", { + tiles = {"default_steel_block.png", "default_steel_block.png", "moremesecons_player_detector_off.png"}, + paramtype = "light", + walkable = true, + groups = {cracky=3}, + description="Adjustable Player Detector", + mesecons = {receptor = { + state = mesecon.state.off, + rules = mesecon.rules.pplate + }}, + on_construct = object_detector_make_formspec, + on_receive_fields = object_detector_on_receive_fields, + sounds = default.node_sound_stone_defaults(), + digiline = object_detector_digiline +}) + +minetest.register_node("moremesecons_adjustable_player_detector:player_detector_on", { + tiles = {"default_steel_block.png", "default_steel_block.png", "moremesecons_player_detector_on.png"}, + paramtype = "light", + walkable = true, + groups = {cracky=3,not_in_creative_inventory=1}, + drop = 'moremesecons_adjustable_player_detector:player_detector_off', + mesecons = {receptor = { + state = mesecon.state.on, + rules = mesecon.rules.pplate + }}, + on_construct = object_detector_make_formspec, + on_receive_fields = object_detector_on_receive_fields, + sounds = default.node_sound_stone_defaults(), + digiline = object_detector_digiline +}) + +minetest.register_craft({ + output = 'moremesecons_adjustable_player_detector:player_detector_off', + recipe = { + {"mesecons_detector:object_detector_off"}, + {"default:mese_crystal_fragment"} + } +}) + +minetest.register_abm({ + nodenames = {"moremesecons_adjustable_player_detector:player_detector_off"}, + interval = 1.0, + chance = 1, + action = function(pos) + if object_detector_scan(pos) then + minetest.swap_node(pos, {name = "moremesecons_adjustable_player_detector:player_detector_on"}) + mesecon.receptor_on(pos, mesecon.rules.pplate) + end + end, +}) + +minetest.register_abm({ + nodenames = {"moremesecons_adjustable_player_detector:player_detector_on"}, + interval = 1.0, + chance = 1, + action = function(pos) + if not object_detector_scan(pos) then + minetest.swap_node(pos, {name = "moremesecons_adjustable_player_detector:player_detector_off"}) + mesecon.receptor_off(pos, mesecon.rules.pplate) + end + end, +}) diff --git a/mods/moremesecons/moremesecons_adjustable_player_detector/mod.conf b/mods/moremesecons/moremesecons_adjustable_player_detector/mod.conf new file mode 100644 index 00000000..07723e47 --- /dev/null +++ b/mods/moremesecons/moremesecons_adjustable_player_detector/mod.conf @@ -0,0 +1,3 @@ +name = moremesecons_adjustable_player_detector +depends = mesecons +optional_depends = craft_guide diff --git a/mods/moremesecons/moremesecons_adjustable_player_detector/textures/moremesecons_player_detector_off.png b/mods/moremesecons/moremesecons_adjustable_player_detector/textures/moremesecons_player_detector_off.png new file mode 100644 index 00000000..47bb37b1 Binary files /dev/null and b/mods/moremesecons/moremesecons_adjustable_player_detector/textures/moremesecons_player_detector_off.png differ diff --git a/mods/moremesecons/moremesecons_adjustable_player_detector/textures/moremesecons_player_detector_on.png b/mods/moremesecons/moremesecons_adjustable_player_detector/textures/moremesecons_player_detector_on.png new file mode 100644 index 00000000..a73a43dc Binary files /dev/null and b/mods/moremesecons/moremesecons_adjustable_player_detector/textures/moremesecons_player_detector_on.png differ diff --git a/mods/moremesecons/moremesecons_commandblock/init.lua b/mods/moremesecons/moremesecons_commandblock/init.lua new file mode 100644 index 00000000..f9d63ee5 --- /dev/null +++ b/mods/moremesecons/moremesecons_commandblock/init.lua @@ -0,0 +1,180 @@ +local strip_color_codes = minetest.settings:get_bool("strip_color_codes", false) + +local function initialize_data(meta) + local NEAREST_MAX_DISTANCE = moremesecons.setting("commandblock", "nearest_max_distance", 8, 1) + + local commands = meta:get_string("commands") + meta:set_string("formspec", + "invsize[9,5;]" .. + "textarea[0.5,0.5;8.5,4;commands;Commands;"..minetest.formspec_escape(commands).."]" .. + "label[1,3.8;@nearest is replaced by the nearest player name ("..tostring(NEAREST_MAX_DISTANCE).." nodes max for the nearest distance)".."]" .. + "button_exit[3.3,4.5;2,1;submit;Submit]") + local owner = meta:get_string("owner") + if owner == "" then + owner = "not owned" + else + owner = "owned by " .. owner + end + meta:set_string("infotext", "Command Block\n" .. + "(" .. owner .. ")\n" .. + "Commands: "..commands) +end + +local function construct(pos) + local meta = minetest.get_meta(pos) + + meta:set_string("commands", "tell @nearest Commandblock unconfigured") + + meta:set_string("owner", "") + + initialize_data(meta) +end + +local function after_place(pos, placer) + if placer then + local meta = minetest.get_meta(pos) + meta:set_string("owner", placer:get_player_name()) + initialize_data(meta) + end +end + +local function receive_fields(pos, _, fields, player) + if not fields.submit then + return + end + local meta = minetest.get_meta(pos) + local owner = meta:get_string("owner") + if owner ~= "" + and player:get_player_name() ~= owner then + return + end + if strip_color_codes then + meta:set_string("commands", minetest.strip_colors(fields.commands)) + else + meta:set_string("commands", fields.commands) + end + + initialize_data(meta) +end + +local function resolve_commands(commands, pos) + local nearest = "" + local min_distance = math.huge + local players = minetest.get_connected_players() + for _, player in pairs(players) do + local distance = vector.distance(pos, player:get_pos()) + if distance < min_distance then + min_distance = distance + nearest = player:get_player_name() + end + end + local new_commands = commands:gsub("@nearest", nearest) + return new_commands, min_distance, new_commands ~= commands +end + +local function commandblock_action_on(pos, node) + local NEAREST_MAX_DISTANCE = moremesecons.setting("commandblock", "nearest_max_distance", 8, 1) + + local accepted_commands = {} + do + local commands_str = moremesecons.setting("commandblock", "authorized_commands", "tell") + for command in string.gmatch(commands_str, "([^ ]+)") do + accepted_commands[command] = true + end + end + + if node.name ~= "moremesecons_commandblock:commandblock_off" then + return + end + + minetest.swap_node(pos, {name = "moremesecons_commandblock:commandblock_on"}) + + local meta = minetest.get_meta(pos) + local owner = meta:get_string("owner") + if owner == "" then + return + end + + local commands, distance, nearest_in_commands = resolve_commands(meta:get_string("commands"), pos) + if distance > NEAREST_MAX_DISTANCE and nearest_in_commands then + minetest.chat_send_player(owner, "The nearest player is too far to use his name in the commands of a craftable command block.") + return + end + for _, command in pairs(commands:split("\n")) do + local pos = command:find(" ") + local cmd, param = command, "" + if pos then + cmd = command:sub(1, pos - 1) + param = command:sub(pos + 1) + end + local cmddef = minetest.chatcommands[cmd] + if not accepted_commands[cmd] and next(accepted_commands) then + minetest.chat_send_player(owner, "You can not execute the command "..cmd.." with a craftable command block ! This event will be reported.") + minetest.log("action", "Player "..owner.." tryed to execute an unauthorized command with a craftable command block.") + return + end + if not cmddef then + minetest.chat_send_player(owner, "The command "..cmd.." does not exist") + return + end + local has_privs, missing_privs = minetest.check_player_privs(owner, cmddef.privs) + if not has_privs then + minetest.chat_send_player(owner, "You don't have permission " + .."to run "..cmd + .." (missing privileges: " + ..table.concat(missing_privs, ", ")..")") + return + end + cmddef.func(owner, param) + end +end + +local function commandblock_action_off(pos, node) + if node.name == "moremesecons_commandblock:commandblock_on" then + minetest.swap_node(pos, {name = "moremesecons_commandblock:commandblock_off"}) + end +end + +local function can_dig(pos, player) + local meta = minetest.get_meta(pos) + local owner = meta:get_string("owner") + return owner == "" or owner == player:get_player_name() +end + +minetest.register_node("moremesecons_commandblock:commandblock_off", { + description = "Craftable Command Block", + tiles = {"moremesecons_commandblock_off.png"}, + groups = {cracky=2, mesecon_effector_off=1}, + on_construct = construct, + after_place_node = after_place, + on_receive_fields = receive_fields, + can_dig = can_dig, + sounds = default.node_sound_stone_defaults(), + mesecons = {effector = { + action_on = commandblock_action_on + }} +}) + +minetest.register_node("moremesecons_commandblock:commandblock_on", { + tiles = {"moremesecons_commandblock_on.png"}, + groups = {cracky=2, mesecon_effector_on=1, not_in_creative_inventory=1}, + light_source = 10, + drop = "moremesecons_commandblock:commandblock_off", + on_construct = construct, + after_place_node = after_place, + on_receive_fields = receive_fields, + can_dig = can_dig, + sounds = default.node_sound_stone_defaults(), + mesecons = {effector = { + action_off = commandblock_action_off + }} +}) + +minetest.register_craft({ + output = "moremesecons_commandblock:commandblock_off", + recipe = { + {"group:mesecon_conductor_craftable","default:mese_crystal","group:mesecon_conductor_craftable"}, + {"default:mese_crystal","group:mesecon_conductor_craftable","default:mese_crystal"}, + {"group:mesecon_conductor_craftable","default:mese_crystal","group:mesecon_conductor_craftable"} + } +}) diff --git a/mods/moremesecons/moremesecons_commandblock/mod.conf b/mods/moremesecons/moremesecons_commandblock/mod.conf new file mode 100644 index 00000000..30f8b633 --- /dev/null +++ b/mods/moremesecons/moremesecons_commandblock/mod.conf @@ -0,0 +1,3 @@ +name = moremesecons_commandblock +depends = mesecons,moremesecons_utils +optional_depends = craft_guide diff --git a/mods/moremesecons/moremesecons_commandblock/textures/moremesecons_commandblock_off.png b/mods/moremesecons/moremesecons_commandblock/textures/moremesecons_commandblock_off.png new file mode 100644 index 00000000..dd8ed9dd Binary files /dev/null and b/mods/moremesecons/moremesecons_commandblock/textures/moremesecons_commandblock_off.png differ diff --git a/mods/moremesecons/moremesecons_commandblock/textures/moremesecons_commandblock_on.png b/mods/moremesecons/moremesecons_commandblock/textures/moremesecons_commandblock_on.png new file mode 100644 index 00000000..05095ab6 Binary files /dev/null and b/mods/moremesecons/moremesecons_commandblock/textures/moremesecons_commandblock_on.png differ diff --git a/mods/moremesecons/moremesecons_conductor_signalchanger/init.lua b/mods/moremesecons/moremesecons_conductor_signalchanger/init.lua new file mode 100644 index 00000000..fc47e51a --- /dev/null +++ b/mods/moremesecons/moremesecons_conductor_signalchanger/init.lua @@ -0,0 +1,81 @@ +local nodebox = { + type = "fixed", + fixed = {{-8/16, -8/16, -8/16, 8/16, -7/16, 8/16 }}, +} + +local function signalchanger_get_output_rules(node) + local rules = {{x=-1, y=0, z=0}} + for _ = 0, node.param2 do + rules = mesecon.rotate_rules_left(rules) + end + return rules +end + +local function signalchanger_get_input_rules(node) + 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"}} + for _ = 0, node.param2 do + rules = mesecon.rotate_rules_left(rules) + end + return rules +end + +local update = function(pos, node, link, newstate) + local meta = minetest.get_meta(pos) + meta:set_int(link.name, newstate == "on" and 1 or 0) + local input_on = meta:get_int("input_on") == 1 + local input_off = meta:get_int("input_off") == 1 + local input_signal = meta:get_int("input_signal") == 1 + + if input_on then + minetest.swap_node(pos, {name = "moremesecons_conductor_signalchanger:conductor_signalchanger_on", param2 = node.param2}) + elseif input_off then + mesecon.receptor_off(pos, signalchanger_get_output_rules(node)) + minetest.swap_node(pos, {name = "moremesecons_conductor_signalchanger:conductor_signalchanger_off", param2 = node.param2}) + end + + 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 + mesecon.receptor_on(pos, signalchanger_get_output_rules(node)) + else + mesecon.receptor_off(pos, signalchanger_get_output_rules(node)) + end +end + +mesecon.register_node("moremesecons_conductor_signalchanger:conductor_signalchanger", { + description = "Conductor Signal Changer", + inventory_image = "moremesecons_conductor_signalchanger_off.png", + groups = {dig_immediate = 2}, + paramtype = "light", + paramtype2 = "facedir", + drawtype = "nodebox", + selection_box = nodebox, + node_box = nodebox, +},{ + groups = {dig_immediate = 2}, + mesecons = { + receptor = { + rules = signalchanger_get_output_rules + }, + effector = { + rules = signalchanger_get_input_rules, + action_change = update + }, + }, + tiles = {"moremesecons_conductor_signalchanger_off.png"}, +},{ + groups = {dig_immediate = 2, not_in_creative_inventory = 1}, + mesecons = { + receptor = { + rules = signalchanger_get_output_rules, + }, + effector = { + rules = signalchanger_get_input_rules, + action_change = update, + }, + }, + tiles = {"moremesecons_conductor_signalchanger_on.png"}, +}) + +minetest.register_craft({ + output = "moremesecons_conductor_signalchanger:conductor_signalchanger_off", + recipe = {{"group:mesecon_conductor_craftable","moremesecons_signalchanger:signalchanger_off"}} +}) diff --git a/mods/moremesecons/moremesecons_conductor_signalchanger/mod.conf b/mods/moremesecons/moremesecons_conductor_signalchanger/mod.conf new file mode 100644 index 00000000..975942a2 --- /dev/null +++ b/mods/moremesecons/moremesecons_conductor_signalchanger/mod.conf @@ -0,0 +1,3 @@ +name = moremesecons_conductor_signalchanger +depends = mesecons +optional_depends = craft_guide diff --git a/mods/moremesecons/moremesecons_conductor_signalchanger/textures/moremesecons_conductor_signalchanger_off.png b/mods/moremesecons/moremesecons_conductor_signalchanger/textures/moremesecons_conductor_signalchanger_off.png new file mode 100644 index 00000000..02232192 Binary files /dev/null and b/mods/moremesecons/moremesecons_conductor_signalchanger/textures/moremesecons_conductor_signalchanger_off.png differ diff --git a/mods/moremesecons/moremesecons_conductor_signalchanger/textures/moremesecons_conductor_signalchanger_on.png b/mods/moremesecons/moremesecons_conductor_signalchanger/textures/moremesecons_conductor_signalchanger_on.png new file mode 100644 index 00000000..58279361 Binary files /dev/null and b/mods/moremesecons/moremesecons_conductor_signalchanger/textures/moremesecons_conductor_signalchanger_on.png differ diff --git a/mods/moremesecons/moremesecons_dual_delayer/init.lua b/mods/moremesecons/moremesecons_dual_delayer/init.lua new file mode 100644 index 00000000..6cfb9d42 --- /dev/null +++ b/mods/moremesecons/moremesecons_dual_delayer/init.lua @@ -0,0 +1,100 @@ +local function dual_delayer_get_input_rules(node) + local rules = {{x=1, y=0, z=0}} + for _ = 0, node.param2 do + rules = mesecon.rotate_rules_left(rules) + end + return rules +end + +local function dual_delayer_get_output_rules(node) + local rules = {{x=0, y=0, z=1}, {x=0, y=0, z=-1}} + for _ = 0, node.param2 do + rules = mesecon.rotate_rules_left(rules) + end + return rules +end + +local dual_delayer_activate = function(pos, node) + mesecon.receptor_on(pos, {dual_delayer_get_output_rules(node)[1]}) -- Turn on the port 1 + minetest.swap_node(pos, {name = "moremesecons_dual_delayer:dual_delayer_10", param2 = node.param2}) + minetest.after(0.4, function() + mesecon.receptor_on(pos, {dual_delayer_get_output_rules(node)[2]}) -- Turn on the port 2 + minetest.swap_node(pos, {name = "moremesecons_dual_delayer:dual_delayer_11", param2 = node.param2}) + end) +end + +local dual_delayer_deactivate = function(pos, node, link) + mesecon.receptor_off(pos, {dual_delayer_get_output_rules(node)[2]}) -- Turn off the port 2 + minetest.swap_node(pos, {name = "moremesecons_dual_delayer:dual_delayer_10", param2 = node.param2}) + minetest.after(0.4, function() + mesecon.receptor_off(pos, {dual_delayer_get_output_rules(node)[1]}) -- Turn off the port 1 + minetest.swap_node(pos, {name = "moremesecons_dual_delayer:dual_delayer_00", param2 = node.param2}) + end) +end + + +for n,i in pairs({{0,0},{1,0},{1,1}}) do + local i1,i2 = unpack(i) + + local groups = {dig_immediate = 2} + if n ~= 1 then + groups.not_in_creative_inventory = 1 + end + + local top_texture = "^moremesecons_dual_delayer_overlay.png^[makealpha:255,126,126" + if i1 == i2 then + if i1 == 0 then + top_texture = "mesecons_wire_off.png"..top_texture + else + top_texture = "mesecons_wire_on.png"..top_texture + end + else + local pre = "mesecons_wire_off.png^[lowpart:50:mesecons_wire_on.png^[transformR" + if i1 == 0 then + pre = pre.. 90 + else + pre = pre.. 270 + end + top_texture = pre..top_texture + end + + local use_texture_alpha + if minetest.features.use_texture_alpha_string_modes then + use_texture_alpha = "opaque" + end + minetest.register_node("moremesecons_dual_delayer:dual_delayer_"..i1 ..i2, { + description = "Dual Delayer", + drop = "moremesecons_dual_delayer:dual_delayer_00", + inventory_image = top_texture, + wield_image = top_texture, + paramtype = "light", + paramtype2 = "facedir", + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = {{-6/16, -8/16, -8/16, 6/16, -7/16, 1/16 }, + {-8/16, -8/16, 1/16, -6/16, -7/16, -1/16}, + {8/16, -8/16, -1/16, 6/16, -7/16, 1/16}} + }, + groups = groups, + 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"}, + use_texture_alpha = use_texture_alpha, + mesecons = { + receptor = { + state = mesecon.state.off, + rules = dual_delayer_get_output_rules + }, + effector = { + rules = dual_delayer_get_input_rules, + action_on = dual_delayer_activate, + action_off = dual_delayer_deactivate + } + } + }) +end + +minetest.register_craft({ + type = "shapeless", + output = "moremesecons_dual_delayer:dual_delayer_00 2", + recipe = {"mesecons_delayer:delayer_off_1", "mesecons_delayer:delayer_off_1"} +}) diff --git a/mods/moremesecons/moremesecons_dual_delayer/mod.conf b/mods/moremesecons/moremesecons_dual_delayer/mod.conf new file mode 100644 index 00000000..3926831d --- /dev/null +++ b/mods/moremesecons/moremesecons_dual_delayer/mod.conf @@ -0,0 +1,3 @@ +name = moremesecons_dual_delayer +depends = mesecons +optional_depends = craft_guide diff --git a/mods/moremesecons/moremesecons_dual_delayer/textures/moremesecons_dual_delayer_bottom.png b/mods/moremesecons/moremesecons_dual_delayer/textures/moremesecons_dual_delayer_bottom.png new file mode 100644 index 00000000..4cdb641e Binary files /dev/null and b/mods/moremesecons/moremesecons_dual_delayer/textures/moremesecons_dual_delayer_bottom.png differ diff --git a/mods/moremesecons/moremesecons_dual_delayer/textures/moremesecons_dual_delayer_ends.png b/mods/moremesecons/moremesecons_dual_delayer/textures/moremesecons_dual_delayer_ends.png new file mode 100644 index 00000000..c1f47d3f Binary files /dev/null and b/mods/moremesecons/moremesecons_dual_delayer/textures/moremesecons_dual_delayer_ends.png differ diff --git a/mods/moremesecons/moremesecons_dual_delayer/textures/moremesecons_dual_delayer_overlay.png b/mods/moremesecons/moremesecons_dual_delayer/textures/moremesecons_dual_delayer_overlay.png new file mode 100644 index 00000000..97423891 Binary files /dev/null and b/mods/moremesecons/moremesecons_dual_delayer/textures/moremesecons_dual_delayer_overlay.png differ diff --git a/mods/moremesecons/moremesecons_dual_delayer/textures/moremesecons_dual_delayer_side_left.png b/mods/moremesecons/moremesecons_dual_delayer/textures/moremesecons_dual_delayer_side_left.png new file mode 100644 index 00000000..46bb7939 Binary files /dev/null and b/mods/moremesecons/moremesecons_dual_delayer/textures/moremesecons_dual_delayer_side_left.png differ diff --git a/mods/moremesecons/moremesecons_dual_delayer/textures/moremesecons_dual_delayer_side_right.png b/mods/moremesecons/moremesecons_dual_delayer/textures/moremesecons_dual_delayer_side_right.png new file mode 100644 index 00000000..5e9cc8db Binary files /dev/null and b/mods/moremesecons/moremesecons_dual_delayer/textures/moremesecons_dual_delayer_side_right.png differ diff --git a/mods/moremesecons/moremesecons_entity_detector/init.lua b/mods/moremesecons/moremesecons_entity_detector/init.lua new file mode 100644 index 00000000..165e3996 --- /dev/null +++ b/mods/moremesecons/moremesecons_entity_detector/init.lua @@ -0,0 +1,138 @@ +-- Entity detector +-- Detects entitys in a certain radius +-- The radius can be changes by right-click (by default 6) + +local function make_formspec(meta) + meta:set_string("formspec", "size[9,5]" .. + "field[0.3, 0;9,2;scanname;Comma-separated list of the names (itemstring) of entities to scan for (empty for any):;${scanname}]".. + "field[0.3,1.5;4,2;digiline_channel;Digiline Channel (optional):;${digiline_channel}]".. + "field[0.3,3;2,2;radius;Detection radius:;${radius}]".. + "button_exit[3.5,3.5;2,3;;Save]") +end + +local function object_detector_make_formspec(pos) + make_formspec(minetest.get_meta(pos)) +end + +local function object_detector_on_receive_fields(pos, _, fields, player) + if not fields.scanname + or not fields.digiline_channel + or minetest.is_protected(pos, player:get_player_name()) then + return + end + + local meta = minetest.get_meta(pos) + meta:set_string("scanname", fields.scanname) + meta:set_string("digiline_channel", fields.digiline_channel) + local r = tonumber(fields.radius) + if r then + local max_radius = moremesecons.setting("entity_detector", "max_radius", 16, 0) + meta:set_int("radius", math.min(r, max_radius)) + end +end + +-- returns true if entity was found, false if not +local object_detector_scan = function (pos) + local meta = minetest.get_meta(pos) + local scanname = meta:get_string("scanname") + local scan_all = scanname == "" + local scan_names = scanname:split(',') + local max_radius = moremesecons.setting("entity_detector", "max_radius", 16, 0) + local radius = math.min(tonumber(meta:get("radius")) or 6, max_radius) + for _,obj in pairs(minetest.get_objects_inside_radius(pos, radius)) do + local luaentity = obj:get_luaentity() + if luaentity then + if scan_all then + return true + end + local isname = luaentity.name + for _, name in ipairs(scan_names) do + if isname == name or (isname == "__builtin:item" and luaentity.itemstring == name) then + return true + end + end + end + end + return false +end + +-- set entity name when receiving a digiline signal on a specific channel +local object_detector_digiline = { + effector = { + action = function (pos, node, channel, msg) + local meta = minetest.get_meta(pos) + local active_channel = meta:get_string("digiline_channel") + if channel ~= active_channel then + return + end + meta:set_string("scanname", msg) + if meta:get_string("formspec") ~= "" then + make_formspec(meta) + end + end, + } +} + +minetest.register_node("moremesecons_entity_detector:entity_detector_off", { + tiles = {"default_steel_block.png", "default_steel_block.png", "moremesecons_entity_detector_off.png"}, + paramtype = "light", + walkable = true, + groups = {cracky=3}, + description="Entity Detector", + mesecons = {receptor = { + state = mesecon.state.off, + rules = mesecon.rules.pplate + }}, + on_construct = object_detector_make_formspec, + on_receive_fields = object_detector_on_receive_fields, + sounds = default.node_sound_stone_defaults(), + digiline = object_detector_digiline +}) + +minetest.register_node("moremesecons_entity_detector:entity_detector_on", { + tiles = {"default_steel_block.png", "default_steel_block.png", "moremesecons_entity_detector_on.png"}, + paramtype = "light", + walkable = true, + groups = {cracky=3,not_in_creative_inventory=1}, + drop = 'moremesecons_entity_detector:entity_detector_off', + mesecons = {receptor = { + state = mesecon.state.on, + rules = mesecon.rules.pplate + }}, + on_construct = object_detector_make_formspec, + on_receive_fields = object_detector_on_receive_fields, + sounds = default.node_sound_stone_defaults(), + digiline = object_detector_digiline +}) + +minetest.register_craft({ + output = 'moremesecons_entity_detector:entity_detector_off', + recipe = { + {"default:mese_crystal_fragment"}, + {"mesecons_detector:object_detector_off"} + } +}) + +minetest.register_abm({ + nodenames = {"moremesecons_entity_detector:entity_detector_off"}, + interval = 1.0, + chance = 1, + action = function(pos) + if object_detector_scan(pos) then + minetest.swap_node(pos, {name = "moremesecons_entity_detector:entity_detector_on"}) + mesecon.receptor_on(pos, mesecon.rules.pplate) + end + end, +}) + +minetest.register_abm({ + nodenames = {"moremesecons_entity_detector:entity_detector_on"}, + interval = 1.0, + chance = 1, + action = function(pos) + if not object_detector_scan(pos) then + minetest.swap_node(pos, {name = "moremesecons_entity_detector:entity_detector_off"}) + mesecon.receptor_off(pos, mesecon.rules.pplate) + end + end, +}) diff --git a/mods/moremesecons/moremesecons_entity_detector/mod.conf b/mods/moremesecons/moremesecons_entity_detector/mod.conf new file mode 100644 index 00000000..b47d9242 --- /dev/null +++ b/mods/moremesecons/moremesecons_entity_detector/mod.conf @@ -0,0 +1,3 @@ +name = moremesecons_entity_detector +depends = mesecons +optional_depends = craft_guide diff --git a/mods/moremesecons/moremesecons_entity_detector/textures/moremesecons_entity_detector_off.png b/mods/moremesecons/moremesecons_entity_detector/textures/moremesecons_entity_detector_off.png new file mode 100644 index 00000000..0e96bc5e Binary files /dev/null and b/mods/moremesecons/moremesecons_entity_detector/textures/moremesecons_entity_detector_off.png differ diff --git a/mods/moremesecons/moremesecons_entity_detector/textures/moremesecons_entity_detector_on.png b/mods/moremesecons/moremesecons_entity_detector/textures/moremesecons_entity_detector_on.png new file mode 100644 index 00000000..fa4aceb8 Binary files /dev/null and b/mods/moremesecons/moremesecons_entity_detector/textures/moremesecons_entity_detector_on.png differ diff --git a/mods/moremesecons/moremesecons_igniter/init.lua b/mods/moremesecons/moremesecons_igniter/init.lua new file mode 100644 index 00000000..82cbbdf7 --- /dev/null +++ b/mods/moremesecons/moremesecons_igniter/init.lua @@ -0,0 +1,48 @@ +local function add_back_igniter(pos) + local name = minetest.get_node(pos).name + + if name == "moremesecons_igniter:igniter" then + -- this should not happen + minetest.log("error", "[moremesecons_igniter] igniter is already back") + return + end + + if name == "ignore" then + -- in case of unloaded chunk + minetest.get_voxel_manip():read_from_map(pos, pos) + name = minetest.get_node(pos).name + end + + if name == "air" + or name == "fire:basic_flame" then + minetest.set_node(pos, {name="moremesecons_igniter:igniter"}) + else + -- drop it as item if something took place there in the 0.8 seconds + pos.y = pos.y+1 + minetest.add_item(pos, "moremesecons_igniter:igniter") + pos.y = pos.y-1 + end +end + +local function igniter_on(pos) + minetest.set_node(pos, {name="fire:basic_flame"}) + minetest.after(0.8, add_back_igniter, pos) +end + +minetest.register_node("moremesecons_igniter:igniter", { + description = "Igniter", + paramtype = "light", + tiles = {"moremesecons_igniter.png"}, + groups = {cracky=3}, + mesecons = { + effector = { + action_on = igniter_on + }} +}) + + +minetest.register_craft({ + output = "moremesecons_igniter:igniter", + recipe = { {"default:torch"}, + {"default:mese_crystal_fragment"},} +}) diff --git a/mods/moremesecons/moremesecons_igniter/mod.conf b/mods/moremesecons/moremesecons_igniter/mod.conf new file mode 100644 index 00000000..3245b92e --- /dev/null +++ b/mods/moremesecons/moremesecons_igniter/mod.conf @@ -0,0 +1,3 @@ +name = moremesecons_igniter +depends = mesecons,fire +optional_depends = craft_guide diff --git a/mods/moremesecons/moremesecons_igniter/textures/moremesecons_igniter.png b/mods/moremesecons/moremesecons_igniter/textures/moremesecons_igniter.png new file mode 100644 index 00000000..b3fce67c Binary files /dev/null and b/mods/moremesecons/moremesecons_igniter/textures/moremesecons_igniter.png differ diff --git a/mods/moremesecons/moremesecons_induction_transmitter/init.lua b/mods/moremesecons/moremesecons_induction_transmitter/init.lua new file mode 100644 index 00000000..cca1e4c2 --- /dev/null +++ b/mods/moremesecons/moremesecons_induction_transmitter/init.lua @@ -0,0 +1,100 @@ +local function induction_transmitter_get_input_rules(node) + -- All horizontal rules, except the output + local rules = { + {x=-1,y=0,z=0}, + {x=1,y=0,z=0}, + {x=0,y=0,z=-1}, + {x=0,y=0,z=1} + } + for i, r in ipairs(rules) do + if vector.equals(r, minetest.facedir_to_dir(node.param2)) then + table.remove(rules, i) + end + end + return rules +end + +local function induction_transmitter_get_output_rules(node) + return {vector.multiply(minetest.facedir_to_dir(node.param2), 2)} +end + +local function act(pos, node, state) + minetest.swap_node(pos, {name = "moremesecons_induction_transmitter:induction_transmitter_"..state, param2 = node.param2}) + + local dir = minetest.facedir_to_dir(node.param2) + local target_pos = vector.add(pos, vector.multiply(dir, 2)) + local target_node = minetest.get_node(target_pos) + if mesecon.is_effector(target_node.name) then + -- Switch on an aside node, so it sends a signal to the target node + local aside_rule = mesecon.effector_get_rules(target_node)[1] + if not aside_rule then + return + end + mesecon["receptor_"..state](vector.add(target_pos, aside_rule), {vector.multiply(aside_rule, -1)}) + elseif mesecon.is_conductor(target_node.name) then + -- Switch on the conductor itself + mesecon["receptor_"..state](target_pos, mesecon.conductor_get_rules(target_node)) + end +end + +mesecon.register_node("moremesecons_induction_transmitter:induction_transmitter", { + description = "Induction Transmitter", + drawtype = "nodebox", + paramtype = "light", + paramtype2 = "facedir", + node_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, 0.125, 0.5, 0.5, 0.5}, + {-0.375, -0.375, -0.1875, 0.375, 0.375, 0.125}, + {-0.25, -0.25, -0.5, 0.25, 0.25, -0.1875}, + } + }, + selection_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, 0.125, 0.5, 0.5, 0.5}, + {-0.375, -0.375, -0.1875, 0.375, 0.375, 0.125}, + {-0.25, -0.25, -0.5, 0.25, 0.25, -0.1875}, + }, + }, +}, { + tiles = {"default_mese_block.png"}, + groups = {cracky = 3}, + mesecons = { + receptor = { + state = mesecon.state.off, + rules = induction_transmitter_get_output_rules + }, + effector = { + rules = induction_transmitter_get_input_rules, + action_on = function(pos, node) + act(pos, node, "on") + end + } + } +}, { + light_source = 5, + tiles = {"default_mese_block.png^[brighten"}, + groups = {cracky = 3, not_in_creative_inventory = 1}, + mesecons = { + receptor = { + state = mesecon.state.on, + rules = induction_transmitter_get_output_rules + }, + effector = { + rules = induction_transmitter_get_input_rules, + action_off = function(pos, node) + act(pos, node, "off") + end + } + } +}) + +minetest.register_craft({ + output = "moremesecons_induction_transmitter:induction_transmitter_off", + recipe = { + {"default:mese_crystal_fragment", "mesecons_torch:mesecon_torch_on", "default:mese_crystal_fragment"}, + {"", "default:mese_crystal_fragment", ""} + } +}) diff --git a/mods/moremesecons/moremesecons_induction_transmitter/mod.conf b/mods/moremesecons/moremesecons_induction_transmitter/mod.conf new file mode 100644 index 00000000..fb6bef5b --- /dev/null +++ b/mods/moremesecons/moremesecons_induction_transmitter/mod.conf @@ -0,0 +1,2 @@ +name = moremesecons_induction_transmitter +depends = mesecons,mesecons_torch,default diff --git a/mods/moremesecons/moremesecons_injector_controller/init.lua b/mods/moremesecons/moremesecons_injector_controller/init.lua new file mode 100644 index 00000000..5be9f07d --- /dev/null +++ b/mods/moremesecons/moremesecons_injector_controller/init.lua @@ -0,0 +1,84 @@ +local injector_controller_get_output_rules = function(node) + local rules = {{x = 0, y = 0, z = 1}} + for _ = 0, node.param2 do + rules = mesecon.rotate_rules_left(rules) + end + return rules +end + +local injector_controller_get_input_rules = function(node) + local rules = {{x = 0, y = 0, z = -1}, + {x = 1, y = 0, z = 0}, + {x = -1, y = 0, z = 0}} + for _ = 0, node.param2 do + rules = mesecon.rotate_rules_left(rules) + end + return rules +end + +local start_timer = function(pos) + local timer = minetest.get_node_timer(pos) + timer:start(1) +end +local stop_timer = function(pos, node) + local timer = minetest.get_node_timer(pos) + timer:stop() + mesecon.receptor_off(pos, injector_controller_get_output_rules(node)) + minetest.swap_node(pos, {name="moremesecons_injector_controller:injector_controller_off", param2=node.param2}) +end + +local on_timer = function(pos) + local node = minetest.get_node(pos) + if(mesecon.flipstate(pos, node) == "on") then + mesecon.receptor_on(pos, injector_controller_get_output_rules(node)) + else + mesecon.receptor_off(pos, injector_controller_get_output_rules(node)) + end + start_timer(pos) +end + +mesecon.register_node("moremesecons_injector_controller:injector_controller", { + description="Injector Controller", + drawtype = "nodebox", + inventory_image = "moremesecons_injector_controller_off.png", + paramtype = "light", + paramtype2 = "facedir", + node_box = { + type = "fixed", + fixed = {{-8/16, -8/16, -8/16, 8/16, -7/16, 8/16 }}, + }, + on_timer = on_timer, +},{ + tiles = {"moremesecons_injector_controller_off.png", "moremesecons_injector_controller_side.png", "moremesecons_injector_controller_side.png"}, + groups = {dig_immediate=2}, + mesecons = { + receptor = { + state = mesecon.state.off, + rules = injector_controller_get_output_rules + }, + effector = { + rules = injector_controller_get_input_rules, + action_on = start_timer, + action_off = stop_timer, + } + } +},{ + tiles = {"moremesecons_injector_controller_on.png", "moremesecons_injector_controller_side.png", "moremesecons_injector_controller_side.png"}, + groups = {dig_immediate=2, not_in_creative_inventory=1}, + mesecons = { + receptor = { + state = mesecon.state.on, + rules = injector_controller_get_output_rules + }, + effector = { + rules = injector_controller_get_input_rules, + action_off = stop_timer, + action_on = start_timer, + } + } +}) + +minetest.register_craft({ + output = "moremesecons_injector_controller:injector_controller_off", + recipe = {{"mesecons_blinkyplant:blinky_plant_off","mesecons_gates:and_off"}} +}) diff --git a/mods/moremesecons/moremesecons_injector_controller/mod.conf b/mods/moremesecons/moremesecons_injector_controller/mod.conf new file mode 100644 index 00000000..d396545c --- /dev/null +++ b/mods/moremesecons/moremesecons_injector_controller/mod.conf @@ -0,0 +1,3 @@ +name = moremesecons_injector_controller +depends = mesecons +optional_depends = craft_guide diff --git a/mods/moremesecons/moremesecons_injector_controller/textures/moremesecons_injector_controller_off.png b/mods/moremesecons/moremesecons_injector_controller/textures/moremesecons_injector_controller_off.png new file mode 100644 index 00000000..ecc5d59b Binary files /dev/null and b/mods/moremesecons/moremesecons_injector_controller/textures/moremesecons_injector_controller_off.png differ diff --git a/mods/moremesecons/moremesecons_injector_controller/textures/moremesecons_injector_controller_on.png b/mods/moremesecons/moremesecons_injector_controller/textures/moremesecons_injector_controller_on.png new file mode 100644 index 00000000..820e6afc Binary files /dev/null and b/mods/moremesecons/moremesecons_injector_controller/textures/moremesecons_injector_controller_on.png differ diff --git a/mods/moremesecons/moremesecons_injector_controller/textures/moremesecons_injector_controller_side.png b/mods/moremesecons/moremesecons_injector_controller/textures/moremesecons_injector_controller_side.png new file mode 100644 index 00000000..6f7bbc6e Binary files /dev/null and b/mods/moremesecons/moremesecons_injector_controller/textures/moremesecons_injector_controller_side.png differ diff --git a/mods/moremesecons/moremesecons_jammer/init.lua b/mods/moremesecons/moremesecons_jammer/init.lua new file mode 100644 index 00000000..1e4e3f16 --- /dev/null +++ b/mods/moremesecons/moremesecons_jammer/init.lua @@ -0,0 +1,133 @@ +-- see wireless jammer +local storage = minetest.get_mod_storage() + +local jammers = moremesecons.load_MapDataStorage_legacy(storage, "jammers_v2", + "jammers") + +local function update_mod_storage() + storage:set_string("jammers_v2", jammers:serialize()) +end + +local function add_jammer(pos) + if jammers:getAt(pos) then + return + end + jammers:setAt(pos, true) + update_mod_storage() +end + +local function remove_jammer(pos) + jammers:removeAt(pos) + update_mod_storage() +end + +local function is_jammed(pos) + local JAMMER_MAX_DISTANCE = moremesecons.setting("jammer", "max_distance", 10, 1) + + local minp = vector.subtract(pos, JAMMER_MAX_DISTANCE) + local maxp = vector.add(pos, JAMMER_MAX_DISTANCE) + for p in jammers:iter(minp, maxp) do + local d = vector.subtract(pos, p) + if d.x ^ 2 + d.y ^ 2 + d.z ^ 2 <= JAMMER_MAX_DISTANCE^2 then + return true + end + end + return false +end + +minetest.after(0, function() -- After loading all mods, override some functions + local jammed + + local actual_node_get = mesecon.get_node_force + local function temp_node_get(pos, ...) + local node = actual_node_get(pos, ...) + if jammed == nil + and node then + jammed = is_jammed(pos) + end + return node + end + + local actual_is_conductor_off = mesecon.is_conductor_off + local function temp_is_conductor_off(...) + if jammed then + -- go to the next elseif, there's is_effector + return + end + local v = actual_is_conductor_off(...) + if v then + -- it continues to the next frontier + jammed = nil + end + return v + end + + local actual_is_effector = mesecon.is_effector + local function temp_is_effector(...) + local abort_here = jammed + -- the last elseif before continuing, jammed needs to be nil then + jammed = nil + if abort_here then + return + end + return actual_is_effector(...) + end + + local actual_turnon = mesecon.turnon + function mesecon.turnon(...) + --set those to the temporary functions + mesecon.get_node_force = temp_node_get + mesecon.is_conductor_off = temp_is_conductor_off + mesecon.is_effector = temp_is_effector + + actual_turnon(...) + + mesecon.get_node_force = actual_node_get + mesecon.is_conductor_off = actual_is_conductor_off + mesecon.is_effector = actual_is_effector + + -- safety + jammed = nil + end +end) + +mesecon.register_node("moremesecons_jammer:jammer", { + description = "Mesecons Jammer", + paramtype = "light", +},{ + tiles = {"moremesecons_jammer_off.png"}, + groups = {dig_immediate=2}, + mesecons = {effector = { + action_on = function(pos) + add_jammer(pos) + minetest.sound_play("moremesecons_jammer", {pos = pos}) + minetest.swap_node(pos, {name="moremesecons_jammer:jammer_on"}) + end + }}, +},{ + tiles = {"moremesecons_jammer_on.png"}, + groups = {dig_immediate=2, not_in_creative_inventory=1}, + mesecons = {effector = { + action_off = function(pos) + remove_jammer(pos) + minetest.swap_node(pos, {name="moremesecons_jammer:jammer_off"}) + end + }}, + on_destruct = remove_jammer, + on_construct = add_jammer, +}) + +minetest.register_craft({ + output = "moremesecons_jammer:jammer_off", + recipe = {{"group:mesecon_conductor_craftable", "default:mese", "group:mesecon_conductor_craftable"}, + {"", "moremesecons_wireless:jammer_off", ""}} +}) + +if moremesecons.setting("jammer", "enable_lbm", false) then + minetest.register_lbm({ + name = "moremesecons_jammer:add_jammer", + nodenames = {"moremesecons_jammer:jammer_on"}, + run_at_every_load = true, + action = add_jammer + }) +end diff --git a/mods/moremesecons/moremesecons_jammer/mod.conf b/mods/moremesecons/moremesecons_jammer/mod.conf new file mode 100644 index 00000000..01cabddb --- /dev/null +++ b/mods/moremesecons/moremesecons_jammer/mod.conf @@ -0,0 +1,3 @@ +name = moremesecons_jammer +depends = mesecons,moremesecons_utils +optional_depends = craft_guide diff --git a/mods/moremesecons/moremesecons_jammer/sounds/moremesecons_jammer.ogg b/mods/moremesecons/moremesecons_jammer/sounds/moremesecons_jammer.ogg new file mode 100644 index 00000000..930b0b40 Binary files /dev/null and b/mods/moremesecons/moremesecons_jammer/sounds/moremesecons_jammer.ogg differ diff --git a/mods/moremesecons/moremesecons_jammer/textures/moremesecons_jammer_off.png b/mods/moremesecons/moremesecons_jammer/textures/moremesecons_jammer_off.png new file mode 100644 index 00000000..77e8205d Binary files /dev/null and b/mods/moremesecons/moremesecons_jammer/textures/moremesecons_jammer_off.png differ diff --git a/mods/moremesecons/moremesecons_jammer/textures/moremesecons_jammer_on.png b/mods/moremesecons/moremesecons_jammer/textures/moremesecons_jammer_on.png new file mode 100644 index 00000000..cafccdea Binary files /dev/null and b/mods/moremesecons/moremesecons_jammer/textures/moremesecons_jammer_on.png differ diff --git a/mods/moremesecons/moremesecons_luablock/init.lua b/mods/moremesecons/moremesecons_luablock/init.lua new file mode 100644 index 00000000..24bc7eed --- /dev/null +++ b/mods/moremesecons/moremesecons_luablock/init.lua @@ -0,0 +1,160 @@ +local storage = minetest.get_mod_storage() +local pos_data = moremesecons.get_storage_data(storage, "pos_data") + +local function set_data(pos, code, owner) + local data = { + code = code, + owner = owner + } + moremesecons.set_data_to_pos(pos_data, pos, data) +end + +local function check_data(pos, code, owner) + local stored_data = moremesecons.get_data_from_pos(pos_data, pos) + if not stored_data then + return false + end + if code ~= stored_data.code + or owner ~= stored_data.owner then + return false + end + return true +end + + +local function make_formspec(meta, pos) + local code = minetest.formspec_escape(meta:get_string("code")) + local errmsg = minetest.formspec_escape(meta:get_string("errmsg")) + meta:set_string("formspec", + "size[10,8;]" .. + "textarea[0.5,0.5;9.5,7;code;Code;"..code.."]" .. + "label[0.1,7;"..errmsg.."]" .. + "button_exit[4,7.5;2,1;submit;Submit]") +end + +minetest.register_node("moremesecons_luablock:luablock", { + description = "Lua Block", + tiles = {"moremesecons_luablock.png"}, + groups = {cracky = 2}, + on_place = function(itemstack, placer, pointed_thing) + local under = pointed_thing.under + local node = minetest.get_node(under) + local udef = minetest.registered_nodes[node.name] + if udef and udef.on_rightclick and + not (placer and placer:get_player_control().sneak) then + return udef.on_rightclick(under, node, placer, itemstack, + pointed_thing) or itemstack + end + + local pos + if minetest.registered_items[minetest.get_node(under).name].buildable_to then + pos = under + else + pos = pointed_thing.above + end + + local name = placer:get_player_name() + if minetest.is_protected(pos, name) and + not minetest.check_player_privs(name, {protection_bypass = true}) then + minetest.record_protection_violation(pos, name) + return itemstack + end + if not minetest.check_player_privs(name, {server = true}) then + minetest.chat_send_player(name, "You can't use a LuaBlock without the server privilege.") + return itemstack + end + + local node_def = minetest.registered_nodes[minetest.get_node(pos).name] + if not node_def or not node_def.buildable_to then + return itemstack + end + + minetest.set_node(pos, {name = "moremesecons_luablock:luablock"}) + + local meta = minetest.get_meta(pos) + meta:set_string("owner", name) + meta:set_string("infotext", "LuaBlock owned by " .. name) + make_formspec(meta, pos) + + if not (creative and creative.is_enabled_for + and creative.is_enabled_for(placer:get_player_name())) then + itemstack:take_item() + end + return itemstack + end, + on_receive_fields = function(pos, form_name, fields, sender) + if not fields.submit then + return + end + local name = sender:get_player_name() + local meta = minetest.get_meta(pos) + if name ~= meta:get_string("owner") then + minetest.chat_send_player(name, "You don't own this LuaBlock.") + return + end + if not minetest.check_player_privs(name, {server = true}) then + minetest.chat_send_player(name, "You can't use a LuaBlock without the server privilege.") + return + end + + meta:set_string("code", fields.code) + set_data(pos, fields.code, name) + make_formspec(meta, pos) + end, + can_dig = function(pos, player) + local meta = minetest.get_meta(pos) + return meta:get_string("owner") == player:get_player_name() + end, + on_destruct = function(pos) + moremesecons.remove_data_from_pos(pos_data, pos) + end, + mesecons = {effector = { + action_on = function(npos, node) + local meta = minetest.get_meta(npos) + local code = meta:get_string("code") + local owner = meta:get_string("owner") + if code == "" then + return + end + if not check_data(npos, code, owner) then + minetest.log("warning", "[moremesecons_luablock] Metadata of LuaBlock at pos "..minetest.pos_to_string(npos).." does not match its mod storage data!") + return + end + + local env = {} + for k, v in pairs(_G) do + env[k] = v + end + env.pos = table.copy(npos) + env.mem = minetest.deserialize(meta:get_string("mem")) or {} + + local func, err_syntax + if _VERSION == "Lua 5.1" then + func, err_syntax = loadstring(code) + if func then + setfenv(func, env) + end + else + func, err_syntax = load(code, nil, "t", env) + end + if not func then + meta:set_string("errmsg", err_syntax) + make_formspec(meta, npos) + return + end + + local good, err_runtime = pcall(func) + + if not good then + meta:set_string("errmsg", err_runtime) + make_formspec(meta, npos) + return + end + + meta:set_string("mem", minetest.serialize(env.mem)) + + meta:set_string("errmsg", "") + make_formspec(meta, npos) + end + }} +}) diff --git a/mods/moremesecons/moremesecons_luablock/mod.conf b/mods/moremesecons/moremesecons_luablock/mod.conf new file mode 100644 index 00000000..3f553948 --- /dev/null +++ b/mods/moremesecons/moremesecons_luablock/mod.conf @@ -0,0 +1,2 @@ +name = moremesecons_luablock +depends = mesecons,moremesecons_utils diff --git a/mods/moremesecons/moremesecons_luablock/textures/moremesecons_luablock.png b/mods/moremesecons/moremesecons_luablock/textures/moremesecons_luablock.png new file mode 100644 index 00000000..4dafb12f Binary files /dev/null and b/mods/moremesecons/moremesecons_luablock/textures/moremesecons_luablock.png differ diff --git a/mods/moremesecons/moremesecons_luacontroller_tool/init.lua b/mods/moremesecons/moremesecons_luacontroller_tool/init.lua new file mode 100644 index 00000000..54b6cb01 --- /dev/null +++ b/mods/moremesecons/moremesecons_luacontroller_tool/init.lua @@ -0,0 +1,357 @@ +local templates = {MoreMesecons = { + logic = [[-- AND +port.a = pin.b and pin.c +-- OR +port.a = pin.b or pin.c +-- NOT +port.a = not pin.b +-- NAND +port.a = not (pin.b and pin.c) +-- NOR +port.a = not (pin.b or pin.c) +-- XOR +port.a = pin.b ~= pin.c +-- XNOR / NXOR +port.a = pin.b == pin.c]], + + digilinesth = [[digiline_send(channel, msg) +if event.type == "digiline" then + print(event.channel) + print(event.msg) +end]], + + clock = [[number_of_oscillations = 0 -- 0 for infinity +interval = 1 +input_port = "A" +output_port = "C" + +if event.type == "on" and event.pin.name == input_port and not mem.running then + if not mem.counter then + mem.counter = 0 + end + mem.running = true + port[string.lower(output_port)] = true + interrupt(interval) + mem.counter = mem.counter + 1 +elseif event.type == "off" and event.pin.name == input_port and mem.running and number_of_oscillations == 0 then + mem.running = false + mem.counter = 0 +elseif event.type == "interrupt" then + if not port[string.lower(output_port)] and mem.running then + port[string.lower(output_port)] = true + interrupt(interval) + mem.counter = mem.counter + 1 + else + port[string.lower(output_port)] = false + if mem.counter < number_of_oscillations or number_of_oscillations == 0 and mem.running then + interrupt(interval) + else + mem.running = false + mem.counter = 0 + end + end +end]], + + counter = [[counter_limit = 5 +output_time = 0.5 +input_port = "A" +output_port = "C" + +if event.type == "on" and event.pin.name == input_port then + if not mem.counter then + mem.counter = 0 + end + mem.counter = mem.counter + 1 + if mem.counter >= counter_limit then + port[string.lower(output_port)] = true + interrupt(output_time) + mem.counter = 0 + end +elseif event.type == "interrupt" then + port[string.lower(output_port)] = false +end]] +}} + + +local file_path = minetest.get_worldpath().."/MoreMesecons_lctt" + +-- load templates from a compressed file +do + local templates_file = io.open(file_path, "rb") + if templates_file then + local templates_raw = templates_file:read("*all") + io.close(templates_file) + if templates_raw + and templates_raw ~= "" then + local data = minetest.deserialize(minetest.decompress(templates_raw)) + for name,t in pairs(data) do + templates[name] = t + end + end + end +end + +-- the save function +local function save_to_file() + local templates_file = io.open(file_path, "w") + if not templates_file then + minetest.log("error", "[MoreMesecons] Could not open file for saving!") + return + end + local player_templates = table.copy(templates) + player_templates.MoreMesecons = nil + templates_file:write(minetest.compress(minetest.serialize(player_templates))) + io.close(templates_file) +end + +-- save doesn't save more than every 10s to disallow spamming +local saving +local function save() + if saving then + return + end + saving = true + minetest.after(16, function() + save_to_file() + saving = false + end) +end + +minetest.register_on_shutdown(function() + if saving then + save_to_file() + end +end) + + +-- used for the dropdown formspec element +local function fill_formspec_dropdown_list(t, selected) + local it,num = {},1 + for i in pairs(t) do + it[num] = i + num = num+1 + end + num = num-1 + table.sort(it) + local txt = "" + local selected_id + for i = 1,num do + local t = it[i] + if not selected_id + and t == selected then + selected_id = i + end + txt = txt..t -- add available indices + if i ~= num then + txt = txt.."," + end + end + return txt..";"..(selected_id or 1).."]" + --spec = string.sub(spec, 1, -2) +end + +local pdata = {} + +local function get_selection_formspec(pname, selected_template) + -- templates might be removed by someone while changing sth in formspec + local pl_templates = templates[pname] + if not pl_templates then + pname = next(templates) + pl_templates = templates[pname] + end + + local template_code = pl_templates[selected_template] + if not template_code then + selected_template = next(pl_templates) + template_code = pl_templates[selected_template] + end + + local spec = "size[10,10]".. + + -- show available players, field player_name, current player name is the selected one + "dropdown[0,0;5;player_name;".. + fill_formspec_dropdown_list(templates, pname).. + + -- show templates of pname + "dropdown[5,0;5;template_name;".. + fill_formspec_dropdown_list(pl_templates, selected_template).. + + -- show selected template + "textarea[0,1;10.5,8.5;template_code;template code:;"..minetest.formspec_escape(template_code).."]".. + + -- save name + "field[5,9.5;5,0;save_name;savename;"..selected_template.."]".. + + "button[0,10;2,0;button;set]".. + + "button[2,10;2,0;button;add]".. + + "button[5,10;2,0;button;save]" + + return spec +end + +-- tests if the node is a luacontroller +local function is_luacontroller(pos) + if not pos then + return false + end + return string.match(minetest.get_node(pos).name, "mesecons_luacontroller:luacontroller%d%d%d%d") +end + +-- do not localize the function directly here to support possible overwritten luacontrollers +local luac_def = minetest.registered_nodes["mesecons_luacontroller:luacontroller0000"] +local function set_luacontroller_code(pos, code, sender) + luac_def.on_receive_fields(pos, nil, {code=code, program=""}, sender) +end + +minetest.register_tool("moremesecons_luacontroller_tool:lctt", { + description = "luacontroller template tool", + inventory_image = "moremesecons_luacontroller_tool.png", + + on_use = function(_, player, pt) + if not player + or not pt then + return + end + + local pname = player:get_player_name() + local pos = pt.under + if not is_luacontroller(pos) then + minetest.chat_send_player(pname, "You can use the luacontroller template tool only on luacontroller nodes.") + return + end + + pdata[pname] = { + pos = pos, + player_name = pname, + template_name = pdata[pname] and pdata[pname].template_name or next(templates[pname] or templates[next(templates)]), + } + minetest.show_formspec(pname, "moremesecons:luacontroller_tool", get_selection_formspec(pdata[pname].player_name, pdata[pname].template_name)) + end, +}) + +--[[ Luacontroller reset_meta function, by Jeija +local function reset_meta(pos, code, errmsg) + local meta = minetest.get_meta(pos) + meta:set_string("code", code) + code = minetest.formspec_escape(code or "") + errmsg = minetest.formspec_escape(errmsg or "") + meta:set_string("formspec", "size[10,8]".. + "background[-0.2,-0.25;10.4,8.75;jeija_luac_background.png]".. + "textarea[0.2,0.6;10.2,5;code;;"..code.."]".. + "image_button[3.75,6;2.5,1;jeija_luac_runbutton.png;program;]".. + "image_button_exit[9.72,-0.25;0.425,0.4;jeija_close_window.png;exit;]".. + "label[0.1,5;"..errmsg.."]") + meta:set_int("heat", 0) + meta:set_int("luac_id", math.random(1, 65535)) +end--]] + +-- used to avoid possibly crashes +local function get_code_or_nil(pname, player_name, template_name) + local player_templates = templates[player_name] + if not player_templates then + minetest.chat_send_player(pname, "error: "..player_name.." doesn't have templates now") + return + end + local code = player_templates[template_name] + if not code then + minetest.chat_send_player(pname, "error: "..template_name.." doesn't exist now") + return + end + return code +end + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname ~= "moremesecons:luacontroller_tool" + or fields.quit + or not player then + return + end + + --minetest.chat_send_all(dump(fields)) + + local pname = player:get_player_name() + + if fields.player_name + and fields.player_name ~= pdata[pname].player_name then + -- show available templates of that player + minetest.show_formspec(pname, "moremesecons:luacontroller_tool", + get_selection_formspec(fields.player_name, pdata[pname].template_name) + ) + pdata[pname].player_name = fields.player_name + return + end + + if fields.template_name + and fields.template_name ~= pdata[pname].template_name then + -- show selected template of that player + minetest.show_formspec(pname, "moremesecons:luacontroller_tool", + get_selection_formspec(pdata[pname].player_name, fields.template_name) + ) + pdata[pname].template_name = fields.template_name + return + end + + local pos = pdata[pname].pos + if not is_luacontroller(pos) then + -- this can happen + return + end + + local meta = minetest.get_meta(pos) + + if fields.button == "set" then + -- replace the code of the luacontroller with the template + local code = get_code_or_nil(pname, fields.player_name, fields.template_name) + if code then + set_luacontroller_code(pos, code, player) + minetest.chat_send_player(pname, "code set to template at "..minetest.pos_to_string(pos)) + end + return + end + + if fields.button == "add" then + -- add the template to the end of the code of the luacontroller + local code = get_code_or_nil(pname, fields.player_name, fields.template_name) + if code then + set_luacontroller_code(pos, meta:get_string("code").."\r"..code, player) + minetest.chat_send_player(pname, "code added to luacontroller at "..minetest.pos_to_string(pos)) + end + return + end + + if fields.button == "save" then + -- save the template, when you try to change others' templates, yours become changed + local savename = fields.template_name + if fields.save_name + and fields.save_name ~= "" + and fields.save_name ~= savename then + savename = minetest.formspec_escape(fields.save_name) + end + local code = fields.template_code + if not code then + minetest.chat_send_player(pname, "error: template code missing") + return + end + templates[pname] = templates[pname] or {} + if code == "" then + templates[pname][savename] = nil + if not next(templates[pname]) then + templates[pname] = nil + end + minetest.chat_send_player(pname, "template removed") + save() + return + end + code = minetest.formspec_escape(code) + if templates[pname][savename] == code then + minetest.chat_send_player(pname, "template not saved because it didn't change") + return + end + templates[pname][savename] = code + save() + minetest.chat_send_player(pname, "template "..pname.."/"..savename.." saved") + return + end +end) diff --git a/mods/moremesecons/moremesecons_luacontroller_tool/mod.conf b/mods/moremesecons/moremesecons_luacontroller_tool/mod.conf new file mode 100644 index 00000000..3cac5a52 --- /dev/null +++ b/mods/moremesecons/moremesecons_luacontroller_tool/mod.conf @@ -0,0 +1,2 @@ +name = moremesecons_luacontroller_tool +depends = mesecons,mesecons_luacontroller,moremesecons_utils diff --git a/mods/moremesecons/moremesecons_luacontroller_tool/textures/moremesecons_luacontroller_tool.png b/mods/moremesecons/moremesecons_luacontroller_tool/textures/moremesecons_luacontroller_tool.png new file mode 100644 index 00000000..ec0154db Binary files /dev/null and b/mods/moremesecons/moremesecons_luacontroller_tool/textures/moremesecons_luacontroller_tool.png differ diff --git a/mods/moremesecons/moremesecons_mesechest/init.lua b/mods/moremesecons/moremesecons_mesechest/init.lua new file mode 100644 index 00000000..2fe26cda --- /dev/null +++ b/mods/moremesecons/moremesecons_mesechest/init.lua @@ -0,0 +1,120 @@ +local function mesechest_get_output_rules(node) + local rules = {{x=-1, y=0, z=0}, + {x=0, y=0, z=-1}, + {x=0, y=0, z=1}} + for _ = 0, node.param2 do + rules = mesecon.rotate_rules_left(rules) + end + return rules +end + +-- default.chest.register_chest() doesn't allow to register most of the callbacks we need +-- we have to override the chest node we registered again +default.chest.register_chest("moremesecons_mesechest:mesechest", { + description = "Mese Chest", + tiles = { + "default_chest_top.png^[colorize:#d8e002:70", + "default_chest_top.png^[colorize:#d8e002:70", + "default_chest_side.png^[colorize:#d8e002:70", + "default_chest_side.png^[colorize:#d8e002:70", + "default_chest_front.png^[colorize:#d8e002:70", + "default_chest_inside.png^[colorize:#d8e002:70" + }, + sounds = default.node_sound_wood_defaults(), + sound_open = "default_chest_open", + sound_close = "default_chest_close", + groups = {choppy = 2, oddly_breakable_by_hand = 2}, + mesecons = { + receptor = { + rules = mesechest_get_output_rules + } + } +}) + +default.chest.register_chest("moremesecons_mesechest:mesechest_locked", { + description = "Locked Mese Chest", + tiles = { + "default_chest_top.png^[colorize:#d8e002:70", + "default_chest_top.png^[colorize:#d8e002:70", + "default_chest_side.png^[colorize:#d8e002:70", + "default_chest_side.png^[colorize:#d8e002:70", + "default_chest_lock.png^[colorize:#d8e002:70", + "default_chest_inside.png^[colorize:#d8e002:70" + }, + sounds = default.node_sound_wood_defaults(), + sound_open = "default_chest_open", + sound_close = "default_chest_close", + groups = {choppy = 2, oddly_breakable_by_hand = 2}, + protected = true, + mesecons = { + receptor = { + rules = mesechest_get_output_rules + } + } +}) + +local moremesecons_chests = {} + +for _, chest in ipairs({"moremesecons_mesechest:mesechest", "moremesecons_mesechest:mesechest_locked", + "moremesecons_mesechest:mesechest_open", "moremesecons_mesechest:mesechest_locked_open"}) do + local old_def = minetest.registered_nodes[chest] + + local old_on_metadata_inventory_put = old_def.on_metadata_inventory_put + local old_on_metadata_inventory_take = old_def.on_metadata_inventory_take + local old_on_rightclick = old_def.on_rightclick + + local override = {} + override.on_metadata_inventory_put = function(pos, ...) + old_on_metadata_inventory_put(pos, ...) + mesecon.receptor_on(pos, {mesechest_get_output_rules(minetest.get_node(pos))[2]}) + minetest.after(1, function(pos) + mesecon.receptor_off(pos, {mesechest_get_output_rules(minetest.get_node(pos))[2]}) + end, pos) + end + override.on_metadata_inventory_take = function(pos, ...) + old_on_metadata_inventory_take(pos, ...) + mesecon.receptor_on(pos, {mesechest_get_output_rules(minetest.get_node(pos))[3]}) + minetest.after(1, function(pos) + mesecon.receptor_off(pos, {mesechest_get_output_rules(minetest.get_node(pos))[3]}) + end, pos) + end + override.on_rightclick = function(pos, node, clicker, ...) + if old_on_rightclick(pos, node, clicker, ...) == nil then + mesecon.receptor_on(pos, {mesechest_get_output_rules(node)[1]}) + end + end + + minetest.override_item(chest, override) + moremesecons_chests[chest] = true +end + +-- if the chest is getting closed, turn the signal off +-- luacheck: ignore 122 +local old_lid_close = default.chest.chest_lid_close +function default.chest.chest_lid_close(pn) + local pos = default.chest.open_chests[pn].pos + -- old_lid_close will return true if the chest won't be closed + if old_lid_close(pn) then + return true + end + local node = minetest.get_node(pos) + if moremesecons_chests[node.name] then + mesecon.receptor_off(pos, {mesechest_get_output_rules(node)[1]}) + end +end + +minetest.register_craft({ + output = "moremesecons_mesechest:mesechest", + recipe = {{"group:mesecon_conductor_craftable", "default:chest", "group:mesecon_conductor_craftable"}} +}) + +minetest.register_craft({ + output = "moremesecons_mesechest:mesechest_locked", + recipe = {{"group:mesecon_conductor_craftable", "default:chest_locked", "group:mesecon_conductor_craftable"}} +}) + +-- Legacy +minetest.register_alias("default:mesechest", "moremesecons_mesechest:mesechest") +minetest.register_alias("mesechest", "moremesecons_mesechest:mesechest") +minetest.register_alias("default:mesechest_locked", "moremesecons_mesechest:mesechest") +minetest.register_alias("mesechest_locked", "moremesecons_mesechest:mesechest_locked") diff --git a/mods/moremesecons/moremesecons_mesechest/mod.conf b/mods/moremesecons/moremesecons_mesechest/mod.conf new file mode 100644 index 00000000..fdb396f4 --- /dev/null +++ b/mods/moremesecons/moremesecons_mesechest/mod.conf @@ -0,0 +1,2 @@ +name = moremesecons_mesechest +depends = default,mesecons diff --git a/mods/moremesecons/moremesecons_playerkiller/init.lua b/mods/moremesecons/moremesecons_playerkiller/init.lua new file mode 100644 index 00000000..dea28daa --- /dev/null +++ b/mods/moremesecons/moremesecons_playerkiller/init.lua @@ -0,0 +1,62 @@ +local kill_nearest_player = function(pos) + local MAX_DISTANCE = moremesecons.setting("playerkiller", "max_distance", 8, 1) + + -- Search the nearest player + local nearest + local min_distance = MAX_DISTANCE + for _, player in pairs(minetest.get_connected_players()) do + local distance = vector.distance(pos, player:getpos()) + if distance < min_distance then + min_distance = distance + nearest = player + end + end + + if not nearest then + -- no nearby player + return + end + + local owner = minetest.get_meta(pos):get_string("owner") + if not owner then + -- maybe some mod placed it + return + end + + if owner == nearest:get_player_name() then + -- don't kill the owner ! + return + end + + -- And kill him + nearest:set_hp(0) + minetest.log("action", "Player "..owner.." kills player "..nearest:get_player_name().." using a MoreMesecons Player Killer.") +end + +minetest.register_craft({ + output = "moremesecons_playerkiller:playerkiller", + recipe = { {"","default:mese",""}, + {"default:apple","mesecons_detector:object_detector_off","default:apple"}, + {"","default:apple",""}} +}) + +minetest.register_node("moremesecons_playerkiller:playerkiller", { + description = "Player Killer", + tiles = {"moremesecons_playerkiller_top.png", "moremesecons_playerkiller_top.png", "moremesecons_playerkiller_side.png"}, + paramtype = "light", + walkable = true, + groups = {cracky=3}, + mesecons = {effector = { + state = mesecon.state.off, + action_on = kill_nearest_player + }}, + after_place_node = function(pos, placer) + if not placer then + return + end + local meta = minetest.get_meta(pos) + meta:set_string("owner", placer:get_player_name()) + meta:set_string("infotext", "PlayerKiller owned by " .. meta:get_string("owner")) + end, + sounds = default.node_sound_stone_defaults(), +}) diff --git a/mods/moremesecons/moremesecons_playerkiller/mod.conf b/mods/moremesecons/moremesecons_playerkiller/mod.conf new file mode 100644 index 00000000..e6acdf58 --- /dev/null +++ b/mods/moremesecons/moremesecons_playerkiller/mod.conf @@ -0,0 +1,3 @@ +name = moremesecons_playerkiller +depends = mesecons,mesecons_materials,moremesecons_utils +optional_depends = craft_guide diff --git a/mods/moremesecons/moremesecons_playerkiller/textures/moremesecons_playerkiller_side.png b/mods/moremesecons/moremesecons_playerkiller/textures/moremesecons_playerkiller_side.png new file mode 100644 index 00000000..77f28720 Binary files /dev/null and b/mods/moremesecons/moremesecons_playerkiller/textures/moremesecons_playerkiller_side.png differ diff --git a/mods/moremesecons/moremesecons_playerkiller/textures/moremesecons_playerkiller_top.png b/mods/moremesecons/moremesecons_playerkiller/textures/moremesecons_playerkiller_top.png new file mode 100644 index 00000000..a61d3445 Binary files /dev/null and b/mods/moremesecons/moremesecons_playerkiller/textures/moremesecons_playerkiller_top.png differ diff --git a/mods/moremesecons/moremesecons_sayer/init.lua b/mods/moremesecons/moremesecons_sayer/init.lua new file mode 100644 index 00000000..f5d0bad8 --- /dev/null +++ b/mods/moremesecons/moremesecons_sayer/init.lua @@ -0,0 +1,123 @@ +local use_speech_dispatcher = moremesecons.setting("sayer", "use_speech_dispatcher", true) + +local popen, execute = io.popen, os.execute +if use_speech_dispatcher then + if not minetest.is_singleplayer() then + minetest.log("warning", "[moremesecons_sayer] use_speech_dispatcher = true, but the speech dispatcher can only be used in singleplayer") + use_speech_dispatcher = false + else + local ie = {} + if minetest.request_insecure_environment then + ie = minetest.request_insecure_environment() + end + if not ie then + 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.") + use_speech_dispatcher = false + else + popen = ie.io.popen + execute = ie.os.execute + end + end + + if use_speech_dispatcher then + if popen("if hash spd-say 2>/dev/null; then printf yes; fi"):read("*all") ~= "yes" then + minetest.log("warning", "[moremesecons_sayer] use_speech_dispatcher = true, but it seems the speech dispatcher isn't installed on your system") + use_speech_dispatcher = false + end + end +end + +local sayer_activate +if use_speech_dispatcher then + minetest.log("info", "[moremesecons_sayer] using speech dispatcher") + local tab = { + "spd-say", + nil, + "" + } + local language = minetest.settings:get("language") or "en" + if language ~= "en" then + tab[3] = "-l "..language + end + + function sayer_activate(pos) + local MAX_DISTANCE = moremesecons.setting("sayer", "max_distance", 8, 1) ^ 2 + + local text = minetest.get_meta(pos):get_string("text") + if text == "" then + -- nothing to say + return + end + if string.find(text, '"') then + text = "So, singleplayer, you want to use me to execute commands? Writing quotes is not allowed!" + end + tab[2] = '"'..text..'"' + local ppos = minetest.get_player_by_name("singleplayer"):getpos() + ppos.y = ppos.y+1.625 -- camera position (without bobbing) + -- that here's just 1 volume means that it's mono + local volume = math.floor(-100*( + 1-MAX_DISTANCE/vector.distance(pos, ppos)^2 + +0.5)) + if volume <= -100 then + -- nothing to hear + return + end + if volume > 0 then + --volume = "+"..math.min(100, volume) + -- volume bigger 0 somehow isn't louder, it rather tries to scream + volume = "+"..math.min(100, math.floor(volume/(MAX_DISTANCE-1)+0.5)) + end + if volume == 0 then + tab[4] = nil + else + tab[4] = "-i "..volume + end + execute(table.concat(tab, " ")) + end +else + function sayer_activate(pos) + local MAX_DISTANCE = moremesecons.setting("sayer", "max_distance", 8, 1) + + local tab = { + "Sayer at pos", + nil, + "says : "..minetest.get_meta(pos):get_string("text") + } + for _,player in pairs(minetest.get_connected_players()) do + if vector.distance(pos, player:getpos()) <= MAX_DISTANCE then + tab[2] = minetest.pos_to_string(pos) + minetest.chat_send_player(player:get_player_name(), table.concat(tab, " ")) + end + end + end +end + +minetest.register_node("moremesecons_sayer:sayer", { + description = "sayer", + tiles = {"mesecons_noteblock.png", "default_wood.png"}, + drawtype = "nodebox", + paramtype = "light", + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5}, + }, + groups = {dig_immediate = 2}, + on_construct = function(pos) + minetest.get_meta(pos):set_string("formspec", "field[text;text;${text}]") + end, + on_receive_fields = function(pos, _, fields, player) + if fields.text + and not minetest.is_protected(pos, player:get_player_name()) then + minetest.get_meta(pos):set_string("text", fields.text) + end + end, + mesecons = {effector = { + action_on = sayer_activate + }} +}) + +minetest.register_craft({ + output = "moremesecons_sayer:sayer 2", + recipe = {{"mesecons_luacontroller:luacontroller0000", "mesecons_noteblock:noteblock"}, + {"group:wood", "group:wood"}} +}) diff --git a/mods/moremesecons/moremesecons_sayer/mod.conf b/mods/moremesecons/moremesecons_sayer/mod.conf new file mode 100644 index 00000000..7e7fdc1d --- /dev/null +++ b/mods/moremesecons/moremesecons_sayer/mod.conf @@ -0,0 +1,3 @@ +name = moremesecons_sayer +depends = mesecons,mesecons_noteblock,moremesecons_utils,default +optional_depends = craft_guide diff --git a/mods/moremesecons/moremesecons_signalchanger/init.lua b/mods/moremesecons/moremesecons_signalchanger/init.lua new file mode 100644 index 00000000..0de35264 --- /dev/null +++ b/mods/moremesecons/moremesecons_signalchanger/init.lua @@ -0,0 +1,81 @@ +local nodebox = { + type = "fixed", + fixed = {{-8/16, -8/16, -8/16, 8/16, -7/16, 8/16 }}, +} + +local function signalchanger_get_output_rules(node) + local rules = {{x=-1, y=0, z=0}, + {x=1, y=0, z=0}} + for _ = 0, node.param2 do + rules = mesecon.rotate_rules_left(rules) + end + return rules +end + +local function signalchanger_get_input_rules(node) + local rules = {{x=0, y=0, z=-1, name="input_on"}, {x=0, y=0, z=1, name="input_off"}} + for _ = 0, node.param2 do + rules = mesecon.rotate_rules_left(rules) + end + return rules +end + +local update = function(pos, node, link, newstate) + local meta = minetest.get_meta(pos) + meta:set_int(link.name, newstate == "on" and 1 or 0) + local input_on = meta:get_int("input_on") == 1 + local input_off = meta:get_int("input_off") == 1 + if input_on then + mesecon.receptor_on(pos, {signalchanger_get_output_rules(node)[1]}) + mesecon.receptor_off(pos, {signalchanger_get_output_rules(node)[2]}) + minetest.swap_node(pos, {name = "moremesecons_signalchanger:signalchanger_on", param2 = node.param2}) + elseif input_off then + mesecon.receptor_off(pos, {signalchanger_get_output_rules(node)[1]}) + mesecon.receptor_on(pos, {signalchanger_get_output_rules(node)[2]}) + minetest.swap_node(pos, {name = "moremesecons_signalchanger:signalchanger_off", param2 = node.param2}) + end +end + +mesecon.register_node("moremesecons_signalchanger:signalchanger", { + description = "Signal Changer", + inventory_image = "moremesecons_signalchanger_off.png", + groups = {dig_immediate = 2}, + paramtype = "light", + paramtype2 = "facedir", + drawtype = "nodebox", + selection_box = nodebox, + node_box = nodebox, +},{ + groups = {dig_immediate = 2}, + mesecons = { + receptor = { + rules = signalchanger_get_output_rules + }, + effector = { + rules = signalchanger_get_input_rules, + action_change = update + }, + }, + tiles = {"moremesecons_signalchanger_off.png"}, + on_construct = function(pos) + local node = minetest.get_node(pos) + mesecon.receptor_on(pos, {signalchanger_get_output_rules(node)[2]}) + end +},{ + groups = {dig_immediate = 2, not_in_creative_inventory = 1}, + mesecons = { + receptor = { + rules = signalchanger_get_output_rules, + }, + effector = { + rules = signalchanger_get_input_rules, + action_change = update, + }, + }, + tiles = {"moremesecons_signalchanger_on.png"}, +}) + +minetest.register_craft({ + output = "moremesecons_signalchanger:signalchanger_off", + recipe = {{"group:mesecon_conductor_craftable","moremesecons_switchtorch:switchtorch_off","group:mesecon_conductor_craftable"}} +}) diff --git a/mods/moremesecons/moremesecons_signalchanger/mod.conf b/mods/moremesecons/moremesecons_signalchanger/mod.conf new file mode 100644 index 00000000..852e30f0 --- /dev/null +++ b/mods/moremesecons/moremesecons_signalchanger/mod.conf @@ -0,0 +1,3 @@ +name = moremesecons_signalchanger +depends = mesecons +optional_depends = craft_guide diff --git a/mods/moremesecons/moremesecons_signalchanger/textures/moremesecons_signalchanger_off.png b/mods/moremesecons/moremesecons_signalchanger/textures/moremesecons_signalchanger_off.png new file mode 100644 index 00000000..df7a8cdd Binary files /dev/null and b/mods/moremesecons/moremesecons_signalchanger/textures/moremesecons_signalchanger_off.png differ diff --git a/mods/moremesecons/moremesecons_signalchanger/textures/moremesecons_signalchanger_on.png b/mods/moremesecons/moremesecons_signalchanger/textures/moremesecons_signalchanger_on.png new file mode 100644 index 00000000..5b94536f Binary files /dev/null and b/mods/moremesecons/moremesecons_signalchanger/textures/moremesecons_signalchanger_on.png differ diff --git a/mods/moremesecons/moremesecons_switchtorch/init.lua b/mods/moremesecons/moremesecons_switchtorch/init.lua new file mode 100644 index 00000000..2001f037 --- /dev/null +++ b/mods/moremesecons/moremesecons_switchtorch/init.lua @@ -0,0 +1,129 @@ +local rotate_torch_rules = function (rules, param2) + if param2 == 5 then + return mesecon.rotate_rules_right(rules) + elseif param2 == 2 then + return mesecon.rotate_rules_right(mesecon.rotate_rules_right(rules)) --180 degrees + elseif param2 == 4 then + return mesecon.rotate_rules_left(rules) + elseif param2 == 1 then + return mesecon.rotate_rules_down(rules) + elseif param2 == 0 then + return mesecon.rotate_rules_up(rules) + else + return rules + end +end + +local output_rules = { + {x = 1, y = 0, z = 0}, + {x = 0, y = 0, z = 1}, + {x = 0, y = 0, z =-1}, + {x = 0, y = 1, z = 0}, + {x = 0, y =-1, z = 0} +} +local torch_get_output_rules = function(node) + return rotate_torch_rules(output_rules, node.param2) +end + +local input_rules = { + {x = -2, y = 0, z = 0}, + {x = -1, y = 1, z = 0} +} +local torch_get_input_rules = function(node) + return rotate_torch_rules(input_rules, node.param2) +end + +minetest.register_craft({ + output = "moremesecons_switchtorch:switchtorch_off 4", + recipe = { + {"default:stick"}, + {"group:mesecon_conductor_craftable"}, + } +}) + +local torch_selectionbox = +{ + type = "wallmounted", + wall_top = {-0.1, 0.5-0.6, -0.1, 0.1, 0.5, 0.1}, + wall_bottom = {-0.1, -0.5, -0.1, 0.1, -0.5+0.6, 0.1}, + wall_side = {-0.5, -0.1, -0.1, -0.5+0.6, 0.1, 0.1}, +} + +minetest.register_node("moremesecons_switchtorch:switchtorch_off", { + description = "Switch Torch", + inventory_image = "moremesecons_switchtorch_on.png", + wield_image = "moremesecons_switchtorch_on.png", + drawtype = "torchlike", + tiles = {"moremesecons_switchtorch_off.png", "moremesecons_switchtorch_off_ceiling.png", "moremesecons_switchtorch_off_side.png"}, + paramtype = "light", + walkable = false, + paramtype2 = "wallmounted", + selection_box = torch_selectionbox, + groups = {dig_immediate = 3}, + mesecons = {receptor = { + state = mesecon.state.off, + rules = torch_get_output_rules + }}, + + on_construct = function(pos)-- For EndPower + minetest.get_meta(pos):set_int("EndPower", 1) -- 1 for true, 0 for false + end +}) + +minetest.register_node("moremesecons_switchtorch:switchtorch_on", { + drawtype = "torchlike", + tiles = {"moremesecons_switchtorch_on.png", "moremesecons_switchtorch_on_ceiling.png", "moremesecons_switchtorch_on_side.png"}, + paramtype = "light", + sunlight_propagates = true, + walkable = false, + paramtype2 = "wallmounted", + selection_box = torch_selectionbox, + groups = {dig_immediate=3, not_in_creative_inventory = 1}, + drop = "moremesecons_switchtorch:switchtorch_off", + light_source = 9, + mesecons = {receptor = { + state = mesecon.state.on, + rules = torch_get_output_rules + }}, +}) + +minetest.register_abm({ + nodenames = {"moremesecons_switchtorch:switchtorch_off","moremesecons_switchtorch:switchtorch_on"}, + interval = 1, + chance = 1, + action = function(pos, node) + local is_powered = false + for _, rule in ipairs(torch_get_input_rules(node)) do + local src = vector.add(pos, rule) + if mesecon.is_power_on(src) then + is_powered = true + break + end + end + + local meta = minetest.get_meta(pos) + if meta:get_int("EndPower") == 0 == is_powered then + return + end + if not is_powered then + meta:set_int("EndPower", 1) + return + end + if node.name == "moremesecons_switchtorch:switchtorch_on" then + minetest.swap_node(pos, {name = "moremesecons_switchtorch:switchtorch_off", param2 = node.param2}) + mesecon.receptor_off(pos, torch_get_output_rules(node)) + elseif node.name == "moremesecons_switchtorch:switchtorch_off" then + minetest.swap_node(pos, {name = "moremesecons_switchtorch:switchtorch_on", param2 = node.param2}) + mesecon.receptor_on(pos, torch_get_output_rules(node)) + end + meta:set_int("EndPower", 0) + end +}) + +-- Param2 Table (Block Attached To) +-- 5 = z-1 +-- 3 = x-1 +-- 4 = z+1 +-- 2 = x+1 +-- 0 = y+1 +-- 1 = y-1 diff --git a/mods/moremesecons/moremesecons_switchtorch/mod.conf b/mods/moremesecons/moremesecons_switchtorch/mod.conf new file mode 100644 index 00000000..f13be84c --- /dev/null +++ b/mods/moremesecons/moremesecons_switchtorch/mod.conf @@ -0,0 +1,3 @@ +name = moremesecons_switchtorch +depends = mesecons +optional_depends = craft_guide diff --git a/mods/moremesecons/moremesecons_switchtorch/textures/moremesecons_switchtorch_off.png b/mods/moremesecons/moremesecons_switchtorch/textures/moremesecons_switchtorch_off.png new file mode 100644 index 00000000..c37a6767 Binary files /dev/null and b/mods/moremesecons/moremesecons_switchtorch/textures/moremesecons_switchtorch_off.png differ diff --git a/mods/moremesecons/moremesecons_switchtorch/textures/moremesecons_switchtorch_off_ceiling.png b/mods/moremesecons/moremesecons_switchtorch/textures/moremesecons_switchtorch_off_ceiling.png new file mode 100644 index 00000000..d768644b Binary files /dev/null and b/mods/moremesecons/moremesecons_switchtorch/textures/moremesecons_switchtorch_off_ceiling.png differ diff --git a/mods/moremesecons/moremesecons_switchtorch/textures/moremesecons_switchtorch_off_side.png b/mods/moremesecons/moremesecons_switchtorch/textures/moremesecons_switchtorch_off_side.png new file mode 100644 index 00000000..1d7effee Binary files /dev/null and b/mods/moremesecons/moremesecons_switchtorch/textures/moremesecons_switchtorch_off_side.png differ diff --git a/mods/moremesecons/moremesecons_switchtorch/textures/moremesecons_switchtorch_on.png b/mods/moremesecons/moremesecons_switchtorch/textures/moremesecons_switchtorch_on.png new file mode 100644 index 00000000..a8a21f24 Binary files /dev/null and b/mods/moremesecons/moremesecons_switchtorch/textures/moremesecons_switchtorch_on.png differ diff --git a/mods/moremesecons/moremesecons_switchtorch/textures/moremesecons_switchtorch_on_ceiling.png b/mods/moremesecons/moremesecons_switchtorch/textures/moremesecons_switchtorch_on_ceiling.png new file mode 100644 index 00000000..6501c624 Binary files /dev/null and b/mods/moremesecons/moremesecons_switchtorch/textures/moremesecons_switchtorch_on_ceiling.png differ diff --git a/mods/moremesecons/moremesecons_switchtorch/textures/moremesecons_switchtorch_on_side.png b/mods/moremesecons/moremesecons_switchtorch/textures/moremesecons_switchtorch_on_side.png new file mode 100644 index 00000000..ddf6936a Binary files /dev/null and b/mods/moremesecons/moremesecons_switchtorch/textures/moremesecons_switchtorch_on_side.png differ diff --git a/mods/moremesecons/moremesecons_teleporter/init.lua b/mods/moremesecons/moremesecons_teleporter/init.lua new file mode 100644 index 00000000..df1d03ca --- /dev/null +++ b/mods/moremesecons/moremesecons_teleporter/init.lua @@ -0,0 +1,108 @@ +local storage = minetest.get_mod_storage() + +local teleporters = minetest.deserialize(storage:get_string("teleporters")) or {} +local teleporters_rids = moremesecons.load_MapDataStorage_legacy(storage, + "teleporters_rids_v2", "teleporters_rids") + +local function update_mod_storage() + storage:set_string("teleporters", minetest.serialize(teleporters)) + storage:set_string("teleporters_rids_v2", teleporters_rids:serialize()) +end + + +local function register(pos) + if not teleporters_rids:getAt(pos) then + table.insert(teleporters, pos) + teleporters_rids:setAt(pos, #teleporters) + update_mod_storage() + end +end + +local function teleport_nearest(pos) + local MAX_TELEPORTATION_DISTANCE = moremesecons.setting("teleporter", "max_t2t_distance", 50, 1) + local MAX_PLAYER_DISTANCE = moremesecons.setting("teleporter", "max_p2t_distance", 25, 1) + + -- Search for the nearest player + local nearest = nil + local min_distance_player = MAX_PLAYER_DISTANCE + local players = minetest.get_connected_players() + for _, player in pairs(players) do + local distance = vector.distance(pos, player:getpos()) + if distance <= min_distance_player then + min_distance_player = distance + nearest = player + end + end + + if not nearest then + -- If there is no nearest player (maybe too far away...) + return + end + + -- Search for the corresponding teleporter and teleport + if not minetest.registered_nodes["moremesecons_teleporter:teleporter"] then return end + + local newpos = {} + local min_distance = MAX_TELEPORTATION_DISTANCE + for i = 1, #teleporters do + if minetest.get_node(teleporters[i]).name == "moremesecons_teleporter:teleporter" then + local tel_pos + if teleporters[i].y == pos.y and teleporters[i].x == pos.x and teleporters[i].z ~= pos.z then + tel_pos = {x=teleporters[i].x, y=teleporters[i].y+1, z=teleporters[i].z} + elseif teleporters[i].z == pos.z and teleporters[i].x == pos.x and teleporters[i].y ~= pos.y then + tel_pos = {x=teleporters[i].x, y=teleporters[i].y+1, z=teleporters[i].z} + elseif teleporters[i].z == pos.z and teleporters[i].y == pos.y and teleporters[i].x ~= pos.x then + tel_pos = {x=teleporters[i].x, y=teleporters[i].y+1, z=teleporters[i].z} + end + + if tel_pos then + local distance = vector.distance(tel_pos, pos) + if distance <= min_distance then + min_distance = distance + newpos = tel_pos + end + end + end + end + if not newpos.x then + newpos = {x=pos.x, y=pos.y+1, z=pos.z} -- If newpos doesn't exist, teleport on the current teleporter + end + + nearest:moveto(newpos) + minetest.log("action", "Player "..nearest:get_player_name().." was teleported using a MoreMesecons Teleporter.") +end + +minetest.register_craft({ + output = "moremesecons_teleporter:teleporter 2", + recipe = {{"default:diamond","default:stick","default:mese"}} +}) +minetest.register_node("moremesecons_teleporter:teleporter", { + tiles = {"moremesecons_teleporter.png"}, + paramtype = "light", + walkable = true, + groups = {cracky=3}, + description="Teleporter", + mesecons = {effector = { + state = mesecon.state.off, + action_on = teleport_nearest + }}, + sounds = default.node_sound_stone_defaults(), + on_construct = register, + on_destruct = function(pos) + local RID = teleporters_rids:getAt(pos) + if RID then + table.remove(teleporters, RID) + teleporters_rids:removeAt(pos) + update_mod_storage() + end + end, +}) + +if moremesecons.setting("teleporter", "enable_lbm", false) then + minetest.register_lbm({ + name = "moremesecons_teleporter:add_teleporter", + nodenames = {"moremesecons_teleporter:teleporter"}, + run_at_every_load = true, + action = register + }) +end diff --git a/mods/moremesecons/moremesecons_teleporter/mod.conf b/mods/moremesecons/moremesecons_teleporter/mod.conf new file mode 100644 index 00000000..b0ea1265 --- /dev/null +++ b/mods/moremesecons/moremesecons_teleporter/mod.conf @@ -0,0 +1,3 @@ +name = moremesecons_teleporter +depends = mesecons,moremesecons_utils +optional_depends = craft_guide diff --git a/mods/moremesecons/moremesecons_teleporter/textures/moremesecons_teleporter.png b/mods/moremesecons/moremesecons_teleporter/textures/moremesecons_teleporter.png new file mode 100644 index 00000000..cd9140a3 Binary files /dev/null and b/mods/moremesecons/moremesecons_teleporter/textures/moremesecons_teleporter.png differ diff --git a/mods/moremesecons/moremesecons_timegate/init.lua b/mods/moremesecons/moremesecons_timegate/init.lua new file mode 100644 index 00000000..2920a90d --- /dev/null +++ b/mods/moremesecons/moremesecons_timegate/init.lua @@ -0,0 +1,136 @@ +local timegate_get_output_rules = function(node) + local rules = {{x = 0, y = 0, z = 1}} + for _ = 0, node.param2 do + rules = mesecon.rotate_rules_left(rules) + end + return rules +end + +local timegate_get_input_rules = function(node) + local rules = {{x = 0, y = 0, z = -1}} + for _ = 0, node.param2 do + rules = mesecon.rotate_rules_left(rules) + end + return rules +end + +-- Functions that are called after the delay time + +local function timegate_activate(pos, node) + -- using a meta string allows writing the time in hexadecimals + local time = tonumber(minetest.get_meta(pos):get_string("time")) + if not time then + return + end + node.name = "moremesecons_timegate:timegate_on" + minetest.swap_node(pos, node) + mesecon.receptor_on(pos) + minetest.after(time, function() + local node = minetest.get_node(pos) + if node.name == "moremesecons_timegate:timegate_on" then + mesecon.receptor_off(pos) + node.name = "moremesecons_timegate:timegate_off" + minetest.swap_node(pos, node) + end + end) +end + +local boxes = {{ -6/16, -8/16, -6/16, 6/16, -7/16, 6/16 }, -- the main slab + + { -2/16, -7/16, -4/16, 2/16, -26/64, -3/16 }, -- the jeweled "on" indicator + { -3/16, -7/16, -3/16, 3/16, -26/64, -2/16 }, + { -4/16, -7/16, -2/16, 4/16, -26/64, 2/16 }, + { -3/16, -7/16, 2/16, 3/16, -26/64, 3/16 }, + { -2/16, -7/16, 3/16, 2/16, -26/64, 4/16 }, + + { -6/16, -7/16, -6/16, -4/16, -27/64, -4/16 }, -- the timer indicator + { -8/16, -8/16, -1/16, -6/16, -7/16, 1/16 }, -- the two wire stubs + { 6/16, -8/16, -1/16, 8/16, -7/16, 1/16 }} + +local use_texture_alpha +if minetest.features.use_texture_alpha_string_modes then + use_texture_alpha = "opaque" +end +mesecon.register_node("moremesecons_timegate:timegate", { + description = "Time Gate", + drawtype = "nodebox", + inventory_image = "moremesecons_timegate_off.png", + wield_image = "moremesecons_timegate_off.png", + walkable = true, + selection_box = { + type = "fixed", + fixed = { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 }, + }, + node_box = { + type = "fixed", + fixed = boxes + }, + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + is_ground_content = true, + sounds = default.node_sound_stone_defaults(), + on_construct = function(pos) + minetest.get_meta(pos):set_string("formspec", "field[time;time;${time}]") + end, + on_receive_fields = function(pos, _, fields, player) + if fields.time + and not minetest.is_protected(pos, player:get_player_name()) then + minetest.get_meta(pos):set_string("time", fields.time) + end + end +},{ + tiles = { + "moremesecons_timegate_off.png", + "moremesecons_timegate_bottom.png", + "moremesecons_timegate_ends_off.png", + "moremesecons_timegate_ends_off.png", + "moremesecons_timegate_sides_off.png", + "moremesecons_timegate_sides_off.png" + }, + use_texture_alpha = use_texture_alpha, + groups = {bendy=2,snappy=1,dig_immediate=2}, + mesecons = { + receptor = + { + state = mesecon.state.off, + rules = timegate_get_output_rules + }, + effector = + { + rules = timegate_get_input_rules, + action_on = timegate_activate + } + }, +},{ + tiles = { + "moremesecons_timegate_on.png", + "moremesecons_timegate_bottom.png", + "moremesecons_timegate_ends_on.png", + "moremesecons_timegate_ends_on.png", + "moremesecons_timegate_sides_on.png", + "moremesecons_timegate_sides_on.png" + }, + use_texture_alpha = use_texture_alpha, + groups = {bendy=2,snappy=1,dig_immediate=2, not_in_creative_inventory=1}, + mesecons = { + receptor = { + state = mesecon.state.on, + rules = timegate_get_output_rules + }, + effector = { + rules = timegate_get_input_rules, + } + }, +}) + +minetest.register_craft({ + output = "moremesecons_timegate:timegate_off 2", + recipe = { + {"group:mesecon_conductor_craftable", "mesecons_delayer:delayer_off_1", "group:mesecon_conductor_craftable"}, + {"default:wood","default:wood", "default:wood"}, + } +}) + +minetest.register_alias("moremesecons_temporarygate:temporarygate_off", "moremesecons_timegate:timegate_off") +minetest.register_alias("moremesecons_temporarygate:temporarygate_on", "moremesecons_timegate:timegate_on") diff --git a/mods/moremesecons/moremesecons_timegate/mod.conf b/mods/moremesecons/moremesecons_timegate/mod.conf new file mode 100644 index 00000000..a2c07b3d --- /dev/null +++ b/mods/moremesecons/moremesecons_timegate/mod.conf @@ -0,0 +1,3 @@ +name = moremesecons_timegate +depends = mesecons +optional_depends = craft_guide diff --git a/mods/moremesecons/moremesecons_timegate/textures/moremesecons_timegate_bottom.png b/mods/moremesecons/moremesecons_timegate/textures/moremesecons_timegate_bottom.png new file mode 100644 index 00000000..5f2b67a0 Binary files /dev/null and b/mods/moremesecons/moremesecons_timegate/textures/moremesecons_timegate_bottom.png differ diff --git a/mods/moremesecons/moremesecons_timegate/textures/moremesecons_timegate_ends_off.png b/mods/moremesecons/moremesecons_timegate/textures/moremesecons_timegate_ends_off.png new file mode 100644 index 00000000..f8c8b1c2 Binary files /dev/null and b/mods/moremesecons/moremesecons_timegate/textures/moremesecons_timegate_ends_off.png differ diff --git a/mods/moremesecons/moremesecons_timegate/textures/moremesecons_timegate_ends_on.png b/mods/moremesecons/moremesecons_timegate/textures/moremesecons_timegate_ends_on.png new file mode 100644 index 00000000..953fde3f Binary files /dev/null and b/mods/moremesecons/moremesecons_timegate/textures/moremesecons_timegate_ends_on.png differ diff --git a/mods/moremesecons/moremesecons_timegate/textures/moremesecons_timegate_off.png b/mods/moremesecons/moremesecons_timegate/textures/moremesecons_timegate_off.png new file mode 100644 index 00000000..d0f1ebde Binary files /dev/null and b/mods/moremesecons/moremesecons_timegate/textures/moremesecons_timegate_off.png differ diff --git a/mods/moremesecons/moremesecons_timegate/textures/moremesecons_timegate_on.png b/mods/moremesecons/moremesecons_timegate/textures/moremesecons_timegate_on.png new file mode 100644 index 00000000..7c019352 Binary files /dev/null and b/mods/moremesecons/moremesecons_timegate/textures/moremesecons_timegate_on.png differ diff --git a/mods/moremesecons/moremesecons_timegate/textures/moremesecons_timegate_sides_off.png b/mods/moremesecons/moremesecons_timegate/textures/moremesecons_timegate_sides_off.png new file mode 100644 index 00000000..cae207cd Binary files /dev/null and b/mods/moremesecons/moremesecons_timegate/textures/moremesecons_timegate_sides_off.png differ diff --git a/mods/moremesecons/moremesecons_timegate/textures/moremesecons_timegate_sides_on.png b/mods/moremesecons/moremesecons_timegate/textures/moremesecons_timegate_sides_on.png new file mode 100644 index 00000000..9647a019 Binary files /dev/null and b/mods/moremesecons/moremesecons_timegate/textures/moremesecons_timegate_sides_on.png differ diff --git a/mods/moremesecons/moremesecons_utils/init.lua b/mods/moremesecons/moremesecons_utils/init.lua new file mode 100644 index 00000000..a6cbcc2b --- /dev/null +++ b/mods/moremesecons/moremesecons_utils/init.lua @@ -0,0 +1,381 @@ +moremesecons = {} + +function moremesecons.setting(modname, settingname, default, min) + local setting = "moremesecons_" .. modname .. "." .. settingname + + if type(default) == "boolean" then + local ret = minetest.settings:get_bool(setting) + if ret == nil then + ret = default + end + return ret + elseif type(default) == "string" then + return minetest.settings:get(setting) or default + elseif type(default) == "number" then + local ret = tonumber(minetest.settings:get(setting)) or default + if not ret then + minetest.log("warning", "[moremesecons_"..modname.."]: setting '"..setting.."' must be a number. Set to default value ("..tostring(default)..").") + ret = default + elseif ret ~= ret then -- NaN + minetest.log("warning", "[moremesecons_"..modname.."]: setting '"..setting.."' is NaN. Set to default value ("..tostring(default)..").") + ret = default + end + if min and ret < min then + minetest.log("warning", "[moremesecons_"..modname.."]: setting '"..setting.."' is under minimum value "..tostring(min)..". Set to minimum value ("..tostring(min)..").") + ret = min + end + return ret + end +end + +-- Storage helpers + +function moremesecons.get_storage_data(storage, name) + return { + tab = minetest.deserialize(storage:get_string(name)) or {}, + name = name, + storage = storage + } +end + +function moremesecons.set_data_to_pos(sto, pos, data) + sto.tab[minetest.hash_node_position(pos)] = data + sto.storage:set_string(sto.name, minetest.serialize(sto.tab)) +end + +function moremesecons.get_data_from_pos(sto, pos) + return sto.tab[minetest.hash_node_position(pos)] +end + +function moremesecons.remove_data_from_pos(sto, pos) + sto.tab[minetest.hash_node_position(pos)] = nil + sto.storage:set_string(sto.name, minetest.serialize(sto.tab)) +end + +-- Some additional vector helpers + +-- The same as minetest.hash_node_position; I copied it to ensure backwards +-- compatibility and used hexadecimal number notation +local function node_position_key(pos) + return (pos.z + 0x8000) * 0x10000 * 0x10000 + + (pos.y + 0x8000) * 0x10000 + + pos.x + 0x8000 +end + +local MapDataStorage = {} +setmetatable(MapDataStorage, {__call = function() + local obj = {} + setmetatable(obj, MapDataStorage) + return obj +end}) +MapDataStorage.__index = { + getAt = function(self, pos) + return self[node_position_key(pos)] + end, + setAt = function(self, pos, data) + -- If x, y or z is omitted, the key corresponds to a position outside + -- of the map (hopefully), so it can be used to skip lines and planes + local vi_z = (pos.z + 0x8000) * 0x10000 * 0x10000 + local vi_zy = vi_z + (pos.y + 0x8000) * 0x10000 + local vi = vi_zy + pos.x + 0x8000 + local is_new = self[vi] == nil + self[vi] = data + if is_new then + self[vi_z] = (self[vi_z] or 0) + 1 + self[vi_zy] = (self[vi_zy] or 0) + 1 + end + end, + setAtI = function(self, vi, data) + local vi_zy = vi - vi % 0x10000 + local vi_z = vi - vi % (0x10000 * 0x10000) + local is_new = self[vi] == nil + self[vi] = data + if is_new then + self[vi_z] = (self[vi_z] or 0) + 1 + self[vi_zy] = (self[vi_zy] or 0) + 1 + end + end, + removeAt = function(self, pos) + local vi_z = (pos.z + 0x8000) * 0x10000 * 0x10000 + local vi_zy = vi_z + (pos.y + 0x8000) * 0x10000 + local vi = vi_zy + pos.x + 0x8000 + if self[vi] == nil then + -- Nothing to remove + return + end + self[vi] = nil + -- Update existence information for the xy plane and x line + self[vi_z] = self[vi_z] - 1 + if self[vi_z] == 0 then + self[vi_z] = nil + self[vi_zy] = nil + return + end + self[vi_zy] = self[vi_zy] - 1 + if self[vi_zy] == 0 then + self[vi_zy] = nil + end + end, + iter = function(self, pos1, pos2) + local ystride = 0x10000 + local zstride = 0x10000 * 0x10000 + + -- Skip z values where no data can be found + pos1 = vector.new(pos1) + local vi_z = (pos1.z + 0x8000) * 0x10000 * 0x10000 + while not self[vi_z] do + pos1.z = pos1.z + 1 + vi_z = vi_z + zstride + if pos1.z > pos2.z then + -- There are no values to iterate through + return function() return end + end + end + -- Skipping y values is not yet implemented and may require much code + + local xrange = pos2.x - pos1.x + 1 + local yrange = pos2.y - pos1.y + 1 + local zrange = pos2.z - pos1.z + 1 + + -- x-only and y-only parts of the vector index of pos1 + local vi_y = (pos1.y + 0x8000) * 0x10000 + local vi_x = pos1.x + 0x8000 + + local y = 0 + local z = 0 + + local vi = node_position_key(pos1) + local pos = vector.new(pos1) + local nextaction = vi + xrange + pos.x = pos.x - 1 + vi = vi - 1 + local function iterfunc() + -- continue along x until it needs to jump + vi = vi + 1 + pos.x = pos.x + 1 + if vi ~= nextaction then + local v = self[vi] + if v == nil then + -- No data here + return iterfunc() + end + -- The returned position must not be changed + return pos, v + end + + -- Reset x position + vi = vi - xrange + -- Go along y until pos2.y is exceeded + while true do + y = y + 1 + pos.y = pos.y + 1 + -- Set vi to index(pos1.x, pos1.y + y, pos1.z + z) + vi = vi + ystride + if y == yrange then + break + end + if self[vi - vi_x] then + nextaction = vi + xrange + + vi = vi - 1 + pos.x = pos1.x - 1 + return iterfunc() + end + -- Nothing along this x line, so increase y again + end + + -- Go back along y + vi = vi - yrange * ystride + y = 0 + pos.y = pos1.y + -- Go along z until pos2.z is exceeded + while true do + z = z + 1 + pos.z = pos.z + 1 + vi = vi + zstride + if z == zrange then + -- Cuboid finished, return nil + return + end + if self[vi - vi_x - vi_y] then + y = 0 + nextaction = vi + xrange + + vi = vi - 1 + pos.x = pos1.x - 1 + return iterfunc() + end + -- Nothing in this xy plane, so increase z again + end + end + return iterfunc + end, + iterAll = function(self) + local previous_vi = nil + local function iterfunc() + local vi, v = next(self, previous_vi) + previous_vi = vi + if not vi then + return + end + local z = math.floor(vi / (0x10000 * 0x10000)) + vi = vi - z * 0x10000 * 0x10000 + local y = math.floor(vi / 0x10000) + if y == 0 or z == 0 then + -- The index does not refer to a position inside the map + return iterfunc() + end + local x = vi - y * 0x10000 - 0x8000 + y = y - 0x8000 + z = z - 0x8000 + return {x=x, y=y, z=z}, v + end + return iterfunc + end, + serialize = function(self) + local indices = {} + local values = {} + local i = 1 + for pos, v in self:iterAll() do + local vi = node_position_key(pos) + -- Convert the double reversible to a string; + -- minetest.serialize does not (yet) do this + indices[i] = ("%.17g"):format(vi) + values[i] = v + end + return minetest.serialize({ + version = "MapDataStorage_v1", + indices = "return {" .. table.concat(indices, ",") .. "}", + values = minetest.serialize(values), + }) + end, +} +MapDataStorage.deserialize = function(txtdata) + local data = minetest.deserialize(txtdata) + if data.version ~= "MapDataStorage_v1" then + minetest.log("error", "Unknown MapDataStorage version: " .. + data.version) + end + -- I assume that minetest.deserialize correctly deserializes the indices, + -- which are in the %a format + local indices = minetest.deserialize(data.indices) + local values = minetest.deserialize(data.values) + if not indices or not values then + return MapDataStorage() + end + data = MapDataStorage() + for i = 1,#indices do + local vi = indices[i] + local v = values[i] + data:setAtI(vi, v) + end + return data +end +moremesecons.MapDataStorage = MapDataStorage + + +-- Legacy + +-- vector_extras there: https://github.com/HybridDog/vector_extras +-- Creates a MapDataStorage object from old vector_extras generated table +function moremesecons.load_old_data_from_pos(t) + local data = MapDataStorage() + for z, yxv in pairs(t) do + for y, xv in pairs(yxv) do + for x, v in pairs(xv) do + data:setAt({x=x, y=y, z=z}, v) + end + end + end + return data +end + +function moremesecons.load_old_dfp_storage(modstorage, name) + local data = minetest.deserialize(modstorage:get_string(name)) + if not data then + return + end + return moremesecons.load_old_data_from_pos(data) +end + +function moremesecons.load_MapDataStorage_legacy(modstorage, name, oldname) + local t_old = moremesecons.load_old_dfp_storage(modstorage, oldname) + local t + if t_old and t_old ~= "" then + t = t_old + modstorage:set_string(name, t:serialize()) + modstorage:set_string(oldname, nil) + return t + end + t = modstorage:get_string(name) + if t and t ~= "" then + return MapDataStorage.deserialize(t) + end + return MapDataStorage() +end + + + +--[[ +-- This testing code shows an example usage of the MapDataStorage code +local function do_test() + print("Test if iter returns correct positions when a lot is set") + local data = MapDataStorage() + local k = 0 + for x = -5, 3 do + for y = -5, 3 do + for z = -5, 3 do + k = k + 1 + data:setAt({x=x, y=y, z=z}, k) + end + end + end + local expected_positions = {} + for z = -4, 2 do + for y = -4, 2 do + for x = -4, 2 do + expected_positions[#expected_positions+1] = {x=x, y=y, z=z} + end + end + end + local i = 0 + for pos in data:iter({x=-4, y=-4, z=-4}, {x=2, y=2, z=2}) do + i = i + 1 + assert(vector.equals(pos, expected_positions[i])) + end + + print("Test if iter works correctly on a corner") + local found = false + for pos in data:iter({x=-8, y=-7, z=-80}, {x=-5, y=-5, z=-5}) do + assert(not found) + found = true + assert(vector.equals(pos, {x=-5, y=-5, z=-5})) + end + assert(found) + + print("Test if iter finds all corners") + local expected_positions = {} + local k = 1 + for _, z in ipairs({-9, -6}) do + for _, y in ipairs({-9, -6}) do + for _, x in ipairs({-8, -6}) do + local pos = {x=x, y=y, z=z} + expected_positions[#expected_positions+1] = pos + data:setAt(pos, k) + k = k + 1 + end + end + end + local i = 1 + for pos, v in data:iter({x=-8, y=-9, z=-9}, {x=-6, y=-6, z=-6}) do + assert(v == i) + assert(vector.equals(pos, expected_positions[i])) + i = i + 1 + --~ print("found " .. minetest.pos_to_string(pos)) + end + assert(i == 8 + 1, "Not enough or too many corners found") + + --~ data:iterAll() +end +do_test() +--]] diff --git a/mods/moremesecons/moremesecons_utils/mod.conf b/mods/moremesecons/moremesecons_utils/mod.conf new file mode 100644 index 00000000..d317b408 --- /dev/null +++ b/mods/moremesecons/moremesecons_utils/mod.conf @@ -0,0 +1,2 @@ +name = moremesecons_utils +description = Various helping functions for moremesecons diff --git a/mods/moremesecons/moremesecons_wireless/init.lua b/mods/moremesecons/moremesecons_wireless/init.lua new file mode 100644 index 00000000..9c887dfa --- /dev/null +++ b/mods/moremesecons/moremesecons_wireless/init.lua @@ -0,0 +1,500 @@ +local storage = minetest.get_mod_storage() + +-- Names wireless_meta, and jammers were used in old versions of this mod. +-- There is legacy code at the end of this file to migrate the mod storage. +local wireless = minetest.deserialize(storage:get_string("networks")) or {} +local wireless_meta = moremesecons.get_storage_data(storage, "wireless_meta_2") +local jammers = moremesecons.get_storage_data(storage, "jammers_2") + +local function update_mod_storage() + storage:set_string("networks", minetest.serialize(wireless)) +end + +local wireless_effector_off +local function remove_wireless(pos) + local wls = moremesecons.get_data_from_pos(wireless_meta, pos) + if not wls then + return + end + + if not wls.owner or wls.owner == "" then + moremesecons.remove_data_from_pos(wireless_meta, pos) + return + end + + if not wireless[wls.owner] or not next(wireless[wls.owner]) then + wireless[wls.owner] = nil + moremesecons.remove_data_from_pos(wireless_meta, pos) + return + end + + if not wls.channel or wls.channel == "" then + moremesecons.remove_data_from_pos(wireless_meta, pos) + return + end + + local network = wireless[wls.owner][wls.channel] + + if network.sources[wls.id] then + wireless_effector_off(pos) + end + + moremesecons.remove_data_from_pos(wireless_meta, pos) + + network.members[wls.id] = nil + if not next(network.members) then + wireless[wls.owner][wls.channel] = nil + if not next(wireless[wls.owner]) then + wireless[wls.owner] = nil + end + end + update_mod_storage() +end + +local function set_owner(pos, owner) + if not owner or owner == "" then + return + end + + remove_wireless(pos) + + local meta = minetest.get_meta(pos) + if meta then + meta:set_string("owner", owner) + end + + local wls = moremesecons.get_data_from_pos(wireless_meta, pos) or {} + wls.owner = owner + moremesecons.set_data_to_pos(wireless_meta, pos, wls) + + if not wireless[owner] then + wireless[owner] = {} + end + + if meta then + meta:set_string("infotext", "Wireless owned by " .. owner .. " on " .. ((wls.channel and wls.channel ~= "") and "channel " .. wls.channel or "undefined channel")) + end +end + +local wireless_receptor_on +local wireless_receptor_off +local wireless_effector_on +local function set_channel(pos, channel) + if not channel or channel == "" then + return + end + + local meta = minetest.get_meta(pos) + + local wls = moremesecons.get_data_from_pos(wireless_meta, pos) + if not wls or wls.owner == "" then + return + end + + if wls.id then + remove_wireless(pos) + end + + if meta then + meta:set_string("channel", channel) + end + wls.channel = channel + moremesecons.set_data_to_pos(wireless_meta, pos, wls) + + if not wireless[wls.owner] then + wireless[wls.owner] = {} + end + if not wireless[wls.owner][channel] then + wireless[wls.owner][channel] = { + members = {}, + sources = {} + } + end + + -- Find the first free ID + local id = 1 + while wireless[wls.owner][channel].members[id] do + id = id + 1 + end + wls.id = id + moremesecons.set_data_to_pos(wireless_meta, pos, wls) + + local network = wireless[wls.owner][channel] + + network.members[id] = pos + + if meta then + meta:set_int("id", id) + end + + update_mod_storage() + + if meta then + meta:set_string("infotext", "Wireless owned by " .. wls.owner .. " on channel " .. channel) + end + + if wls.effector then + wireless_effector_on(pos) + elseif next(network.sources) then + wireless_receptor_on(pos, id, network, false) + else + wireless_receptor_off(pos, id, network, false) + end +end + +local function register_wireless(pos) + local meta = minetest.get_meta(pos) + local owner = meta:get_string("owner") + if owner == "" then + return + end + remove_wireless(pos) + + set_owner(pos, owner) + + local channel = meta:get_string("channel") + if channel ~= "" then + set_channel(pos, channel) + end +end + +local function check_wireless_exists(pos) + local nn = minetest.get_node(pos).name + if nn:sub(1, 30) == "moremesecons_wireless:wireless" then + return true + elseif nn ~= "ignore" then + -- Defer the remove_wireless() call so it doesn't interfere + -- with pairs(). + minetest.after(0, remove_wireless, pos) + return false + end +end + +function wireless_receptor_on(pos, id, network, check) + if check == false or check_wireless_exists(pos) then + minetest.swap_node(pos, {name = "moremesecons_wireless:wireless_on"}) + if not network.sources[id] then + mesecon.receptor_on(pos) + end + end +end + +function wireless_receptor_off(pos, id, network, check) + if check == false or check_wireless_exists(pos) then + minetest.swap_node(pos, {name = "moremesecons_wireless:wireless_off"}) + mesecon.receptor_off(pos) + end +end + +local function activate_network(owner, channel) + local network = wireless[owner][channel] + for i, wl_pos in pairs(network.members) do + wireless_receptor_on(wl_pos, i, network) + end +end + +local function deactivate_network(owner, channel) + local network = wireless[owner][channel] + for i, wl_pos in pairs(network.members) do + wireless_receptor_off(wl_pos, i, network) + end +end + +local is_jammed +function wireless_effector_on(pos) + if is_jammed(pos) then + -- jamming doesn't disallow receiving signals, only sending them + return + end + + local wls = moremesecons.get_data_from_pos(wireless_meta, pos) + if not wls then + return + end + + wls.effector = true + + moremesecons.set_data_to_pos(wireless_meta, pos, wls) + + if wls.owner == "" or not wireless[wls.owner] or wls.channel == "" or not wireless[wls.owner][wls.channel] then + return + end + + local network = wireless[wls.owner][wls.channel] + network.sources[wls.id] = true + activate_network(wls.owner, wls.channel) + + update_mod_storage() +end + +function wireless_effector_off(pos) + local wls = moremesecons.get_data_from_pos(wireless_meta, pos) + if not wls then + return + end + + wls.effector = nil + moremesecons.set_data_to_pos(wireless_meta, pos, wls) + + if wls.owner == "" or not wireless[wls.owner] or wls.channel == "" or not wireless[wls.owner][wls.channel] then + return + end + + local network = wireless[wls.owner][wls.channel] + network.sources[wls.id] = nil + if not next(network.sources) then + deactivate_network(wls.owner, wls.channel) + else + -- There is another source in the network. Turn this wireless into + -- a receptor. + mesecon.receptor_on(pos) + end + + update_mod_storage() +end + +-- This table is required to prevent a message from being sent in loop between wireless nodes +local sending_digilines = {} + +local function on_digiline_receive(pos, node, channel, msg) + if is_jammed(pos) then + return + end + + local wls = moremesecons.get_data_from_pos(wireless_meta, pos) + if not wls then + return + end + + if wls.owner == "" or not wireless[wls.owner] or channel == "" or not wireless[wls.owner][wls.channel] then + return + end + + local pos_hash = minetest.hash_node_position(pos) + if sending_digilines[pos_hash] then + return + end + + sending_digilines[pos_hash] = true + for i, wl_pos in pairs(wireless[wls.owner][wls.channel].members) do + if i ~= wls.id then + digiline:receptor_send(wl_pos, digiline.rules.default, channel, msg) + end + end + sending_digilines[pos_hash] = nil +end + +mesecon.register_node("moremesecons_wireless:wireless", { + paramtype = "light", + paramtype2 = "facedir", + description = "Wireless", + digiline = { + receptor = {}, + effector = { + action = on_digiline_receive + }, + }, + sounds = default.node_sound_stone_defaults(), + on_construct = function(pos) + minetest.get_meta(pos):set_string("formspec", "field[channel;channel;${channel}]") + end, + on_destruct = function(pos) + remove_wireless(pos) + mesecon.receptor_off(pos) + end, + after_place_node = function(pos, placer) + set_owner(pos, placer:get_player_name()) + end, + on_receive_fields = function(pos, _, fields, player) + local meta = minetest.get_meta(pos) + local playername = player:get_player_name() + + local owner = meta:get_string("owner") + if not owner or owner == "" then + -- Old wireless + if not minetest.is_protected(pos, playername) then + set_owner(pos, playername) + else + return + end + end + + if playername == owner then + set_channel(pos, fields.channel) + end + end, +}, { + tiles = {"moremesecons_wireless_off.png"}, + groups = {cracky=3}, + mesecons = {effector = { + action_on = wireless_effector_on + }}, +}, { + tiles = {"moremesecons_wireless_on.png"}, + groups = {cracky=3, not_in_creative_inventory=1}, + mesecons = {effector = { + action_off = wireless_effector_off + }}, +}) + +minetest.register_alias("moremesecons_wireless:wireless", "moremesecons_wireless:wireless_off") + +minetest.register_craft({ + output = "moremesecons_wireless:wireless_off 2", + recipe = { + {"group:mesecon_conductor_craftable", "", "group:mesecon_conductor_craftable"}, + {"", "mesecons_torch:mesecon_torch_on", ""}, + {"group:mesecon_conductor_craftable", "", "group:mesecon_conductor_craftable"}, + } +}) + +local function remove_jammer(pos) + moremesecons.remove_data_from_pos(jammers, pos) +end + +local function add_jammer(pos) + remove_jammer(pos) + moremesecons.set_data_to_pos(jammers, pos, true) +end + +function is_jammed(pos) + local JAMMER_MAX_DISTANCE = moremesecons.setting("wireless", "jammer_max_distance", 15, 1) + local JAMMER_MAX_DISTANCE_SQUARE = JAMMER_MAX_DISTANCE^2 -- Cache this result + + for pos_hash, _ in pairs(jammers.tab) do + local j_pos = minetest.get_position_from_hash(pos_hash) + -- Fast comparisons first + if math.abs(pos.x - j_pos.x) <= JAMMER_MAX_DISTANCE and + math.abs(pos.y - j_pos.y) <= JAMMER_MAX_DISTANCE and + math.abs(pos.z - j_pos.z) <= JAMMER_MAX_DISTANCE and + (pos.x - j_pos.x)^2 + (pos.y - j_pos.y)^2 + (pos.z - j_pos.z)^2 <= JAMMER_MAX_DISTANCE_SQUARE then + return true + end + end + + return false +end + +if moremesecons.setting("wireless", "enable_jammer", true) then + mesecon.register_node("moremesecons_wireless:jammer", { + description = "Wireless Jammer", + paramtype = "light", + drawtype = "nodebox", + },{ + tiles = {"mesecons_wire_off.png^moremesecons_jammer_top.png", "moremesecons_jammer_bottom.png", "mesecons_wire_off.png^moremesecons_jammer_side_off.png"}, + node_box = { + type = "fixed", + fixed = { + -- connection + {-1/16, -0.5, -0.5, 1/16, -7/16, 0.5}, + {-0.5, -0.5, -1/16, 0.5, -7/16, 1/16}, + + --stabilization + {-1/16, -7/16, -1/16, 1/16, -6/16, 1/16}, + + -- fields + {-7/16, -6/16, -7/16, 7/16, -4/16, 7/16}, + {-5/16, -4/16, -5/16, 5/16, -3/16, 5/16}, + {-3/16, -3/16, -3/16, 3/16, -2/16, 3/16}, + {-1/16, -2/16, -1/16, 1/16, -1/16, 1/16}, + }, + }, + groups = {dig_immediate=2}, + mesecons = {effector = { + rules = mesecon.rules.flat, + action_on = function(pos) + add_jammer(pos) + minetest.swap_node(pos, {name="moremesecons_wireless:jammer_on"}) + end + }} + },{ + tiles = {"mesecons_wire_on.png^moremesecons_jammer_top.png", "moremesecons_jammer_bottom.png", "mesecons_wire_on.png^moremesecons_jammer_side_on.png"}, + node_box = { + type = "fixed", + fixed = { + -- connection + {-1/16, -0.5, -0.5, 1/16, -7/16, 0.5}, + {-0.5, -0.5, -1/16, 0.5, -7/16, 1/16}, + + --stabilization + {-1/16, -7/16, -1/16, 1/16, 5/16, 1/16}, + + -- fields + {-7/16, -6/16, -7/16, 7/16, -4/16, 7/16}, + {-5/16, -3/16, -5/16, 5/16, -1/16, 5/16}, + {-3/16, 0, -3/16, 3/16, 2/16, 3/16}, + {-1/16, 3/16, -1/16, 1/16, 5/16, 1/16}, + }, + }, + groups = {dig_immediate=2, not_in_creative_inventory=1}, + mesecons = {effector = { + rules = mesecon.rules.flat, + action_off = function(pos) + remove_jammer(pos) + minetest.swap_node(pos, {name="moremesecons_wireless:jammer_off"}) + end + }}, + on_destruct = remove_jammer, + on_construct = add_jammer, + }) + + minetest.register_craft({ + output = "moremesecons_wireless:jammer_off", + recipe = { + {"moremesecons_wireless:wireless", "mesecons_torch:mesecon_torch_on", "moremesecons_wireless:wireless"} + } + }) +end + +if moremesecons.setting("wireless", "enable_lbm", false) then + minetest.register_lbm({ + name = "moremesecons_wireless:add_jammer", + nodenames = {"moremesecons_wireless:jammer_on"}, + run_at_every_load = true, + action = add_jammer + }) + + minetest.register_lbm({ + name = "moremesecons_wireless:add_wireless", + nodenames = {"moremesecons_wireless:wireless"}, + run_at_every_load = true, + action = register_wireless + }) +end + +-- Legacy +if storage:get_string("wireless_meta_2") == "" then + local wireless_meta_1 = minetest.deserialize(storage:get_string("wireless_meta")) + if not wireless_meta_1 then + return + end + + minetest.log("action", "[moremesecons_wireless] Migrating mod storage data...") + local jammers_1 = minetest.deserialize(storage:get_string("jammers")) + + local get = function(t, pos) + -- FIXME: this does not test explicitly for false, + -- but channel is never false + return t[pos.z] and t[pos.z][pos.y] and t[pos.z][pos.y][pos.x] + end + + for z, data_z in pairs(wireless_meta_1.owners) do + for y, data_y in pairs(data_z) do + for x, owner in pairs(data_y) do + local pos = {x = x, y = y, z = z} + set_owner(pos, owner) + set_channel(pos, get(wireless_meta_1.channels, pos)) + end + end + end + + for z, data_z in pairs(jammers_1) do + for y, data_y in pairs(data_z) do + for x, jammer in pairs(data_y) do + local pos = {x = x, y = y, z = z} + moremesecons.set_data_to_pos(jammers, pos, jammer) + end + end + end + minetest.log("action", "[moremesecons_wireless] Done!") +end diff --git a/mods/moremesecons/moremesecons_wireless/mod.conf b/mods/moremesecons/moremesecons_wireless/mod.conf new file mode 100644 index 00000000..b8ea551e --- /dev/null +++ b/mods/moremesecons/moremesecons_wireless/mod.conf @@ -0,0 +1,3 @@ +name = moremesecons_wireless +depends = mesecons,moremesecons_utils +optional_depends = digilines,craft_guide diff --git a/mods/moremesecons/moremesecons_wireless/textures/moremesecons_jammer_bottom.png b/mods/moremesecons/moremesecons_wireless/textures/moremesecons_jammer_bottom.png new file mode 100644 index 00000000..8df74806 Binary files /dev/null and b/mods/moremesecons/moremesecons_wireless/textures/moremesecons_jammer_bottom.png differ diff --git a/mods/moremesecons/moremesecons_wireless/textures/moremesecons_jammer_side_off.png b/mods/moremesecons/moremesecons_wireless/textures/moremesecons_jammer_side_off.png new file mode 100644 index 00000000..0c1fe1d3 Binary files /dev/null and b/mods/moremesecons/moremesecons_wireless/textures/moremesecons_jammer_side_off.png differ diff --git a/mods/moremesecons/moremesecons_wireless/textures/moremesecons_jammer_side_on.png b/mods/moremesecons/moremesecons_wireless/textures/moremesecons_jammer_side_on.png new file mode 100644 index 00000000..4d54e2ce Binary files /dev/null and b/mods/moremesecons/moremesecons_wireless/textures/moremesecons_jammer_side_on.png differ diff --git a/mods/moremesecons/moremesecons_wireless/textures/moremesecons_jammer_top.png b/mods/moremesecons/moremesecons_wireless/textures/moremesecons_jammer_top.png new file mode 100644 index 00000000..0adf8024 Binary files /dev/null and b/mods/moremesecons/moremesecons_wireless/textures/moremesecons_jammer_top.png differ diff --git a/mods/moremesecons/moremesecons_wireless/textures/moremesecons_wireless_off.png b/mods/moremesecons/moremesecons_wireless/textures/moremesecons_wireless_off.png new file mode 100644 index 00000000..fe639716 Binary files /dev/null and b/mods/moremesecons/moremesecons_wireless/textures/moremesecons_wireless_off.png differ diff --git a/mods/moremesecons/moremesecons_wireless/textures/moremesecons_wireless_on.png b/mods/moremesecons/moremesecons_wireless/textures/moremesecons_wireless_on.png new file mode 100644 index 00000000..27f8f9ce Binary files /dev/null and b/mods/moremesecons/moremesecons_wireless/textures/moremesecons_wireless_on.png differ diff --git a/mods/moremesecons/settingtypes.txt b/mods/moremesecons/settingtypes.txt new file mode 100644 index 00000000..c54c8c2b --- /dev/null +++ b/mods/moremesecons/settingtypes.txt @@ -0,0 +1,81 @@ +[Adjustable Blinky Plant] + +# Minimal interval authorized. Any lower will be set to it. +moremesecons_adjustable_blinky_plant.min_interval (Minimum Interval) float 0.5 + +[Craftable Commandblock] + +# Space-separated list of authorized commands +# Empty to authorize all +moremesecons_commandblock.authorized_commands (Authorized commands) string tell + +# Maximum distance of the @nearest player +# Any value less than or equal to 0 will be changed to 1 and a NaN value will be changed to the default value +moremesecons_commandblock.nearest_max_distance (Nearest player maximum distance) float 8 + +[Entity Detector] + +moremesecons_entity_detector.max_radius (Maximum entity detector radius) float 16 0 + +[Signal Jammer] + +# Jammer action range +# Any value less than or equal to 0 will be changed to 1 and a NaN value will be changed to the default value +moremesecons_jammer.max_distance (Jammer action range) float 10 + +# Whether to enable the registration LBM. +# The registration LBM will recover the jammer database if the moremesecons_jammer +# mod storage has been removed, and will create that mod storage after an update +# from an older version which did not use it. +moremesecons_jammer.enable_lbm (Enable Registration LBM) bool false + +[Player Killer] + +# Player Killer action range +# Any value less than or equal to 0 will be changed to 1 and a NaN value will be changed to the default value +moremesecons_playerkiller.max_distance (Player Killer action range) float 8 + +[Sayer] + +# Whether to use the Speech Dispatcher +# It will work only if: +# * moremesecons_sayer is present in your trusted_mods setting +# * you are playing in singleplayer +# * the speech-dispatcher is installed on your system +# * you are using a POSIX-compliant system and a sh-compatible shell (such as bash, dash, zsh...) +moremesecons_sayer.use_speech_dispatcher (Use the Speech Dispatcher) bool true + +# Sayer range +# Any value less than or equal to 0 will be changed to 1 and a NaN value will be changed to the default value +moremesecons_sayer.max_distance (Range) float 8 + +[Teleporter] + +# Maximum Teleporter To Teleporter distance +# Any value less than or equal to 0 will be changed to 1 and a NaN value will be changed to the default value +moremesecons_teleporter.max_t2t_distance (Maximum Teleporter To Teleporter distance) float 50 + +# Maximum Player To Teleporter distance +# Any value less than or equal to 0 will be set to 1 +moremesecons_teleporter.max_p2t_distance (Maximum Player To Teleporter distance) float 25 + +# Whether to enable the registration LBM. +# The registration LBM will recover a teleporter network if the moremesecons_teleporter +# mod storage has been removed, and will create that mod storage after an update +# from an older version which did not use it. +moremesecons_teleporter.enable_lbm (Enable Registration LBM) bool false + +[Wireless] + +# Whether to enable the wireless jammer node +moremesecons_wireless.enable_jammer (Enable wireless jammer) bool true + +# Wireless Jammer action range +# Any value less than or equal to 0 will be changed to 1 and a NaN value will be changed to the default value +moremesecons_wireless.jammer_max_distance (Wireless Jammer action range) float 15 + +# Whether to enable the registration LBM. +# The registration LBM will recover a wireless network if the moremesecons_wireless +# mod storage has been removed, and will create that mod storage after an update +# from an older version which did not use it. +moremesecons_wireless.enable_lbm (Enable Registration LBM) bool false diff --git a/world.mt b/world.mt index 2478f4c3..d7bb1a45 100644 --- a/world.mt +++ b/world.mt @@ -134,6 +134,7 @@ load_mod_markers = true load_mod_mercurio = true load_mod_mesecons = true load_mod_mesecons_alias = true +load_mod_mesecons_autotools = true load_mod_mesecons_blinkyplant = true load_mod_mesecons_button = true load_mod_mesecons_commandblock = true @@ -144,6 +145,7 @@ load_mod_mesecons_extrawires = true load_mod_mesecons_fpga = true load_mod_mesecons_gamecompat = true load_mod_mesecons_gates = true +load_mod_mesecons_gates3 = true load_mod_mesecons_hydroturbine = true load_mod_mesecons_insulated = true load_mod_mesecons_lamp = true @@ -151,6 +153,7 @@ load_mod_mesecons_lightstone = true load_mod_mesecons_luacontroller = true load_mod_mesecons_materials = true load_mod_mesecons_microcontroller = true +load_mod_mesecons_morewires = true load_mod_mesecons_movestones = true load_mod_mesecons_mvps = true load_mod_mesecons_noteblock = true @@ -159,6 +162,7 @@ load_mod_mesecons_powerplant = true load_mod_mesecons_pressureplates = true load_mod_mesecons_random = true load_mod_mesecons_receiver = true +load_mod_mesecons_regs = true load_mod_mesecons_solarpanel = true load_mod_mesecons_stickyblocks = true load_mod_mesecons_switch = true @@ -182,6 +186,28 @@ load_mod_morelights_dim_morelights_vintage = true load_mod_morelights_extras = true load_mod_morelights_modern = true load_mod_morelights_vintage = true +load_mod_moremesecons = true +load_mod_moremesecons_adjustable_blinkyplant = true +load_mod_moremesecons_adjustable_player_detector = true +load_mod_moremesecons_commandblock = true +load_mod_moremesecons_conductor_signalchanger = true +load_mod_moremesecons_dual_delayer = true +load_mod_moremesecons_entity_detector = true +load_mod_moremesecons_igniter = true +load_mod_moremesecons_induction_transmitter = true +load_mod_moremesecons_injector_controller = true +load_mod_moremesecons_jammer = true +load_mod_moremesecons_luablock = true +load_mod_moremesecons_luacontroller_tool = true +load_mod_moremesecons_mesechest = false +load_mod_moremesecons_playerkiller = false +load_mod_moremesecons_sayer = true +load_mod_moremesecons_signalchanger = true +load_mod_moremesecons_switchtorch = true +load_mod_moremesecons_teleporter = true +load_mod_moremesecons_timegate = true +load_mod_moremesecons_utils = true +load_mod_moremesecons_wireless = true load_mod_moreores = true load_mod_moreswords = true load_mod_motorboat = true