From 616da88d1a0eafca3511874090c95166aa3ec804 Mon Sep 17 00:00:00 2001 From: luk3yx Date: Sun, 9 Dec 2018 13:26:26 +1300 Subject: [PATCH] Initial commit --- API.md | 81 ++++++ LICENSE.md | 21 ++ README.md | 72 +++++ blueprint-types.png | Bin 0 -> 1120 bytes core.lua | 253 ++++++++++++++++++ crafting.png | Bin 0 -> 2574 bytes depends.txt | 7 + init.lua | 44 +++ mesecons.lua | 24 ++ pipeworks.lua | 75 ++++++ register.lua | 220 +++++++++++++++ textures/blueprints_blank.png | Bin 0 -> 288 bytes textures/blueprints_microcontroller.png | Bin 0 -> 222 bytes textures/blueprints_pipeworks_autocrafter.png | Bin 0 -> 211 bytes textures/blueprints_pipeworks_filter.png | Bin 0 -> 207 bytes textures/blueprints_pipeworks_tube.png | Bin 0 -> 258 bytes textures/blueprints_print.png | Bin 0 -> 193 bytes 17 files changed, 797 insertions(+) create mode 100644 API.md create mode 100644 LICENSE.md create mode 100644 README.md create mode 100644 blueprint-types.png create mode 100644 core.lua create mode 100644 crafting.png create mode 100644 depends.txt create mode 100644 init.lua create mode 100644 mesecons.lua create mode 100644 pipeworks.lua create mode 100644 register.lua create mode 100644 textures/blueprints_blank.png create mode 100644 textures/blueprints_microcontroller.png create mode 100644 textures/blueprints_pipeworks_autocrafter.png create mode 100644 textures/blueprints_pipeworks_filter.png create mode 100644 textures/blueprints_pipeworks_tube.png create mode 100644 textures/blueprints_print.png diff --git a/API.md b/API.md new file mode 100644 index 0000000..37f2562 --- /dev/null +++ b/API.md @@ -0,0 +1,81 @@ +
+

Blueprints API

+  +
+ +## Blueprint rules + +Blueprint rules define how nodes can be blueprinted. They are just a table with +the following parameters: + + - `allowed`: Specifies whether the item is allowed to be blueprinted + (`true`, `false` or `'default'`). If this is `'default'`, the item will be + blueprinted if it is visible in the creative inventory (does not have the + `not_in_creative_inventory` group). + - `param2`: Allows the node's param2 to be saved in the blueprint. Defaults to + `true`. + - `meta`: Allows the node's metadata to be copied. Can either be `true` to + allow everything to be copied, or a table with a list of metadata strings + to copy. + - `pvmeta`: A table containing a list of metadata strings to mark as private + when restoring from the blueprint. + - `inv_lists`: A table containing the inventory lists to be copied. + - `item`: A custom blueprint item to give the player when blueprinting the + object. Made with `blueprints.register_blueprint()`. + +*All parameters are optional, and will default to the ones specified in +`core.lua`.* + +To modify these rules for your node, you can add a `_blueprints` field to your +node's definition with a table containing any of the above parameters. Unknown +rules will be silently ignored. + +## Functions + +The following API functions exist, where the `node` parameter is normally a +`string`: + +### Node rules and aliases + + - `blueprints.get_rules(node)`: Gets a rules table for the node specified. + You should not modify this table, as you may inadvertently modify the + default rules. The `allowed` parameter will always be returned with either + `true` or `false`, the value for `'default'` will be calculated when this + is called. + - `blueprints.register_alias(old_node, new_node)`: This will make blueprints + treat `old_node` as the same as `new_node` internally. Blueprints made with + `new_node` can be applied to `old_node`s, and the blueprint rules of + `new_node` will be used for `old_node` as well. + - `blueprints.check_alias(node)`: Checks for node aliases, will return `node` + if no alias exists. Nodes registered with `mesecon.register_node` will be + auto-aliased (`_on` to `_off`), however this can be overridden by adding + a new alias. Aliases are not recursive. + +### Creating/applying blueprint strings/tables. + + - `blueprints.get_blueprint(pos, raw = false)`: Returns a blueprint string + (or table if raw is true) for the object. If the node cannot be blueprinted, + this will return `nil`. + - `blueprints.apply_blueprint(pos, blueprint, only_if_exists = false)`: Applies + the blueprint `blueprint` at `pos`, the blueprint specified may be a string + or table. Returns `true` on success or `nil` on faliure. + +### Other possibly useful function(s). + - `blueprints.check_protection(pos, name)`: Checks the protection at `pos` for + `name`, automatically recording a violation if one exists. Returns `true` + and records a violation if `name` has no access to `pos`, otherwise returns + `false`. + +### Registering blueprints. + - `blueprints.register_blueprint(name, def)`: Registers a non-blank blueprint. + `def` is optional, and if left out, sensible defaults will be used. Any + parameters valid with craftitems should work here, however `on_use`, + `on_place`, `stack_max` and a few others may be overridden. If + `inventory_image` is not specified, one will be generated based on the node + name (for example `blueprints:test_blueprint` would become + `blueprints_test_blueprint.png`) and are overlayed on top of the empty + blueprint texture. If you want to use a custom blank blueprint, you can + specify the `blank` parameter in the table. + - `bluepritns.register_blank_blueprint(name, def)`: The same as + `reigster_blueprint`, except for blank blueprints. `blank` should not be + specified here, and a `def` containing `description` is mandatory. diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..1ba4a63 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +# The MIT License (MIT) + +*Copyright © 2018 by luk3yx* + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..278d03f --- /dev/null +++ b/README.md @@ -0,0 +1,72 @@ +
+

Minetest blueprints mod

+  +
+ +A Minetest mod that allows items to be copied. + +## What is/isn't it? + +Blueprints is a way to copy complex node settings with two clicks. One blueprint +can only store one node, if you want to bulk save/load/copy/move nodes, see +[WorldEdit](https://github.com/Uberi/Minetest-WorldEdit). + +## Items + +Blueprints introduces two types of items: Blank blueprints, and... well... +non-blank blueprints. + +Blank blueprint crafting: + +![1 paper surrounded by 8 basic_materials plastic strips](crafting.png) + +Requires: + - 8 `basic_materials` plastic strips + - 1 paper sheet + +To erase data off a blueprint, provided it isn't already blank, put it in the +crafting grid. + +## Usage instructions + +Blueprints are relatively intuitive to use. To take a blueprint of something, +simply left-click it while holding a blank blueprint. To apply the blueprint +to other nodes, you can left-click the node. **Do not apply blueprints to chests +or other nodes with items in, you will lose your items.** To place a new node +down with the blueprint applied, just right-click while holding the blueprint. +Note that with pipeworks and mesecons placing a node with a blueprint will not +link up wires/pipes to the node. + +## What can/can't be blueprinted? + +By default, item metadata (such as node settings) is saved, however, of course, +node inventories aren't. This can be overridden on a per-item basis (for more +information, see the [API] page). Unless overridden by mods, nodes not in the +creative inventory cannot be blueprinted. + +Because of the way pipeworks teleportation tubes work, they cannot be +blueprinted. + +## Dependencies + +Blueprints has no mandatory dependencies, however blueprints will be uncraftable +without `basic_materials` and `default`. + +The following dependencies are so blueprint rules can be added onto items for +better compatibility: + - `mesecons` + - `mesecons_fpga` + - `mesecons_microcontroller` + - `mesecons_luacontroller` + - `pipeworks` + +## License + +The whole mod, including textures, are licensed under the [MIT license]. + +## API + +Mod developers can restrict what can/can't be blueprinted with the [API]. + +[API]: API.md +[MIT license]: LICENSE.md diff --git a/blueprint-types.png b/blueprint-types.png new file mode 100644 index 0000000000000000000000000000000000000000..d2e333c582d29c2beed2b80df5ca5d237772b6bf GIT binary patch literal 1120 zcmeAS@N?(olHy`uVBq!ia0y~yV7vijJ9DrBNqc^gwLpq3$=lt9;Xep2*t>i(P=vF< zBeIx*fm;}a85w5HkpK#^mw5WRvOnVC5Vz309pSQ+fr0t0r;B4q#jUq@4TEkwh_EGC zK2}`W%speFLg}tKD(NRwEtsdDkSv;1vT|WUTbrkRmxZg8PIkqusbLjc?_Y1s<@~Gs zb7R!|&uQg#8{fa!weIyg``Fx~xbph%3eJ+J0@{qGJZ#LpUV8WP+2qfTZ}Rlj_r?Lm z7V@NO9G)(@@3TD{!x{fZRt8ovhF2S8e?7f<{{8xWFMgihzUX{>lKkK2=Y1inZ+9t0{{KDh+0XxvS9tr)`aNH)^dZh$$kUs^xWEAD0FelW6^B>E9r3=u zUjEYl|8uimCVSnD-?HqL&hvba+CQJKuQGn~t-jj+ef)pR$N3S}ZRda%7VHD-2YCRj zf7=na#Xm32G4;7PYsps6xx$jC49@(#-e20f&GJwE$DfBQZ&g|tyf3~|U-DMc?YR6I zYu>oie|vrvNB5>yl)QabGd=V1^F-bE?a01WTrFOh(zkEo%HJJxqTZi<^7!;j`58ZF zWS=*fQ_Op9uj$OhEpmp>t6kO4m2R!jJzu-dY-Zwraqbk9fDn7>Dsy)Fvo)E%bFbU} zwA(c?V_!moU(&nE*|&^&K1E>!v{B@PXmB~#&=t_Oz7UnT3Azd7wdcx$<+{lecX=ur&t}H=wvYJ8S99`cD2kOS+_XU%z(e*NY!UvsS5_ zJFc)f{N$LFvXtDGX%8o^Sm@|?xcLRMR`%%)N5s#t-;VkHJMmSi<&=X$*Eb33Fo*yn z8e~}MjHNgKUs2=m*6CWecW0@|bA`h^j>=q;WwZY37wY!^sBt|vCpq}~r_O64$`K42 z4zOfb+dWtB;*Nb)e@k-@UOulfZO+3xpQChBEWX;vZasT!{nLZ5t&?Tym-0VeL_@{^I>b>fw)%-6~}zbZO&=S98u zg=ULg#wJay4NS1GTwEpS{(aVByP2D7{wFrp>UcsEei&-P-)z1AhW%X|Gx;O$zHQq5 zuVm}V%C~>-HUsk$IQ6qjN*!c!U_aE9yPiT}lZhxrgAKlh16 Qz_NhB)78&qol`;+0OwKu_W%F@ literal 0 HcmV?d00001 diff --git a/core.lua b/core.lua new file mode 100644 index 0000000..60ad5d7 --- /dev/null +++ b/core.lua @@ -0,0 +1,253 @@ +-- +-- Minetest blueprints mod: Core functions +-- + +blueprints = {} + +-- Default rules +-- These may be overriden on a per-node basis using '_blueprints' in the node's +-- definition. +blueprints.default_rules = { + -- allowed - Allows the node to be blueprint-ified. If this is 'default', + -- it will only allow nodes that are in the creative inventory, and will + -- be set to either true or false when blueprints.get_rules() is called. + allowed = 'default', + + -- param2 - Allows param2 to be saved in the blueprint. + param2 = true, + + -- meta - Specifies which meta strings to save. This can be 'true' to save + -- everything. + -- meta = {'formspec', 'infotext'}, + meta = true, + + -- pvmeta - Specifies which meta strings to mark as private. + pvmeta = {}, + + -- inv_lists - A list of inventory lists to be copied. + inv_lists = {}, + + -- item - The blueprint item to use. + item = 'blueprints:print' +} + +-- Aliases - Allow multiple nodes to be treated internally as one. +local aliases = {} +blueprints.register_alias = function(old_node, new_node) + aliases[old_node] = new_node +end + +blueprints.check_alias = function(node) + if aliases[node] then return aliases[node] end + local def = minetest.registered_nodes[node] + -- Mesecons integration + if def and def.__mesecon_state and def.__mesecon_basename then + node = def.__mesecon_basename .. '_off' + end + return node +end + +blueprints.check_reverse_alias = function(new_node, old_node) + return blueprints.check_alias(old_node) == new_node +end + +-- Get a list of rules for a node. +blueprints.get_rules = function(node) + if node and type(node) ~= 'string' then node = node.name end + + -- Check aliases + node = blueprints.check_alias(node) + + -- Unknown nodes cannot be blueprinted. + local def = false + if node and node ~= 'ignore' then + def = minetest.registered_nodes[node] + end + if not def then + return { + allowed = false, + param2 = false, + meta = {}, + pvmeta = {}, + inv_lists = {}, + item = 'blueprints:blank' + } + end + + -- Use the default rules + local node_rules = def._blueprints + if not node_rules then + if def.groups and def.groups.not_in_creative_inventory then + node_rules = {} + else + return blueprints.default_rules + end + end + + -- Replace any omitted values with the defaults. + local rules = {} + for k, v in pairs(blueprints.default_rules) do + if node_rules[k] ~= nil then + rules[k] = node_rules[k] + else + rules[k] = v + end + end + + -- Check for 'You hacker you!' + if rules.allowed == 'default' then + if def.groups and def.groups.not_in_creative_inventory then + rules.allowed = false + else + rules.allowed = true + end + end + + return rules +end + +-- Get a nicer inv_lists +local function get_inv_lists(rules) + local inv_lists = {} + if rules.inv_lists then + for _, list in ipairs(rules.inv_lists) do + inv_lists[list] = true + end + end + return inv_lists +end + +-- Get a blueprint string for a node. +blueprints.get_blueprint = function(pos, raw) + -- Check aliases + local node = minetest.get_node(pos) + node.name = blueprints.check_alias(node.name) + + -- Get the rules list + local rules = blueprints.get_rules(node) + if not rules.allowed then return end + + -- Using a meta table allows ints/floats/etc to be copied nicely. + local blueprint = {name = node.name, pattern = rules.pattern} + local metatable = minetest.get_meta(pos):to_table() + + -- Copy across allowed metadata fields + if (rules.meta == true or #rules.meta > 0) and metatable.fields then + if rules.meta == true then + blueprint.meta = metatable.fields + else + blueprint.meta = {} + for _, name in ipairs(rules.meta) do + blueprint.meta[name] = metatable.fields[name] + end + end + end + + -- Get a nicer inv_lists + local inv_lists = get_inv_lists(rules) + + -- Copy allowed inventories + if metatable.inventory then + blueprint.inv = {} + for listname, list in pairs(metatable.inventory) do + blueprint.inv[listname] = {} + for id, itemstack in ipairs(list) do + if inv_lists[listname] then + blueprint.inv[listname][id] = itemstack:to_table() or '' + else + blueprint.inv[listname][id] = '' + end + end + end + end + + -- Copy across param2 + if rules.param2 then + blueprint.param2 = node.param2 + end + + -- Return the blueprint + if not raw then + blueprint = minetest.serialize(blueprint) + end + return blueprint +end + +-- Apply blueprints (and double-check the allowed fields) +blueprints.apply_blueprint = function(pos, blueprint, only_if_exists) + -- Deserialize if required and get the rules + if type(blueprint) == 'string' then + blueprint = minetest.deserialize(blueprint) + end + if not blueprint then return end + + -- Make sure the node exists + if only_if_exists then + local node = minetest.get_node(pos) + if node.name ~= blueprint.name then + -- "Un-alias" the blueprint. + if blueprints.check_reverse_alias(blueprint.name, node.name) then + blueprint.name = node.name + else + return + end + end + end + + -- Get the rules + local rules = blueprints.get_rules(blueprint) + if not rules or not rules.allowed then return end + + -- Set the node (and param2) + local node = {name = blueprint.name} + if rules.param2 and blueprint.param2 then + node.param2 = blueprint.param2 + end + minetest.set_node(pos, node) + local metatable = {fields = {}, inventory = {}} + + -- Copy across allowed metadata fields + if blueprint.meta and rules.meta then + if rules.meta == true then + metatable.fields = blueprint.meta + else + for _, name in ipairs(rules.meta) do + metatable.fields[name] = blueprint.meta[name] + end + end + end + + -- Copy allowed inventories + if blueprint.inv then + local inv_lists = get_inv_lists(rules) + + for name, inv in pairs(blueprint.inv) do + metatable.inventory[name] = {} + for id, item in ipairs(inv) do + if not inv_lists[name] then item = '' end + metatable.inventory[name][id] = ItemStack(item) + end + end + end + + -- Update the node meta + local meta = minetest.get_meta(pos) + meta:from_table(metatable) + meta:mark_as_private(rules.pvmeta) + return true +end + +-- Protection check function +blueprints.check_protection = function(pos, name) + if type(name) ~= 'string' then + name = name:get_player_name() + end + + if minetest.is_protected(pos, name) and + not minetest.check_player_privs(name, {protection_bypass=true}) then + minetest.record_protection_violation(pos, name) + return true + end + + return false +end diff --git a/crafting.png b/crafting.png new file mode 100644 index 0000000000000000000000000000000000000000..5b8b8c70a9dd4b93a19bdb89ec68d33b8718c1e0 GIT binary patch literal 2574 zcmZXW3pmq#8^`}cOiW|m#LH7=DQ^e8$s#ea+JxmzL|jb=rdFXjG&9@73YF#%y@U=z zl0%Z5wx#u?gX1u2Mx{aydn#ID^ZaKXS8wmNYrpNf|M&m?eed6WU-##iGPI>wnslUlcVZ!&B!JV9fRaZa8o4H!l zBvY0o#Mv>=rKwLaMOCy6ZaXK6~QHG%HU|KPkaTt_>Z#- zi7fczjFKzS#GDW!&)~-y>wSFlF8H0Jc3R+DOgQBF&d9pi_vYy?RfM!BQU0)QcsLS( z>M8=ux{9;#(UR%m;k5_YO@qPqE42L~$8Vpzj(|8O0;{mVaDsOmw(?tE=Os2fe=2y( zc_EEP_Q>j{81$~i`NOoy=md|o=Z z?klfstb-IPtxB=MDS{wmpu}DpHsHIMrNY%*>h`3c61JF_;!x1*+OT8x21Uy4lwr|9 zAF}XisE+9Ezv0NVHl_cw(jV`D6L?u=B&3tyyk2BhpaZ!5STlv3I<= zh>1ard^)N?LTu{6^LPX`ra*JPL{p<(V11-9;oTAi@$t^GC&ElP#Ky`oRz7RUp@-QIyw*cG-O}GF&FieImgZPXpr$O* z!;tbR+h)9ff|qN;vv;*w)cuTqvdPKTLK_1nxH5>X}w{ z)iG!*our`NuZdOUp0ZLecHpVLny`t%o^m2v7}DR6BxJ9|OmtzOJ%{Y-)9Tt%_3aJz zKIPmO%8b11*I4N)O6*9s#Z^*+knISPIGXNR*m>-~EkS4Hj2yF(u*6Ex!*eMp6If~`G2WE*tvn-) zXxGMr4d0t){JAl;UFFm>XL|2QejlxvSze#E=bA%q+#zy8wsyJU^>taFf@1v%vH)bGpcq$i4hy zS`hy=Fn;pxHWKXh0GIwx;-=z(v4gx=@o;v%PVwWq1g)1fHx9qOW?;CL-b@SFyGF(S z9*1KR85#LlE|-sp(6(m2IUV}2kIPm%u;5O;VsY}eRCpXla+178Wea~cVR$=sIpY!f zZS@*V?Cjdv+Q_IVXDF|_a(R6q1c_y))u(c_mjI(!;)fYzdYPcjQwr4)mu-UX}Dd81G9M_0SMJnJ|;k3%wt_(7rWR>(W1T z)Lg}JDi`YbDwFdxiL%N`Eg*12RAHkb=zzPVq2@VpQc@c;LP71x+nyvG$-;?-Oh6qG zrj(VK*o#gDBVwG8URXI1;WhdBUk*hy5~RJ4pmyEO&(DvI@*E|u!~A(YnQ%<=3uZg5rv_eh) zgswy488XiL>uD;!VT8VMt|Aq#Y06r+-*Sp;vvZFtIPO8C$7+%9!o=QC`SYk< zB#Q!>MT8ctfYye?;pRay+8FR=sfV+*8kmLCJjgLs(dKCnq&bl>F~;+$_lrcM;w9G? z$p^wSFSy(7)^I;1TSi-iC#ZLF*AWtOggyix`9R~jO5uJ{R{;BMa4 z_p%cIm%kqQuR%)k)SaQ2(t&iRCBOZZIp_Yw}Xm*gP=`AB?$*V+Z+(lyp{gS>jx}zrr$Tdan%9#uKeJW zk_Bih@wf$lto+`oUu?ZuR;l16r-ZNr)Y2Z|$A24Is13Y7^!HT{XE z)7O>#5f2B4sOr;w+jM|JvY8S|xv6<2KrRD=b5UwyNotBhd1gt5g1e`0K#E=} zJ5YR@r;B5V#p$KNjzR|ncw*-AmHWS({7a_)gNpyly?RwE{ag%8#8WnHn(caUX^Z?u z#s)q)tBN&mL}R?HDvms!^JUTbvvRW=KSdbAE1aYF-JD%fR4Vl$uzQ znxasiS(2gP?&%wlqL<1J6nFA;aSX9Iotz-S+Vg@bN3i(+yRskN6HJ+}1F6*2U FngA@XKRN&a literal 0 HcmV?d00001 diff --git a/textures/blueprints_pipeworks_autocrafter.png b/textures/blueprints_pipeworks_autocrafter.png new file mode 100644 index 0000000000000000000000000000000000000000..e1dbfe1323a4a29d1760f667cafb55b7c2f0789d GIT binary patch literal 211 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmPd4~M9!+|~2moj@Vk%#er@=ltB<)VvZPmw~~#C^fMp zHASI3vm`^o-P1Q9MK6^dC~ofQ;uvCaIypgtwdVy>j$rZs$Cp23yBaCS2`92CNVoX* uWa%XwTF&8R{HWMUnDKp2i-Qa+4-Z3coZ55y9Z$VMW_!B&xvX{XE z)7O>#5f2B4oJjbT{JTIQ+02lL66gHf+|;}hAeVu`xhOTUBsE2$JhLQ2!QIn0AVn{g z9VqVV>Eak-aXL9cg0<%bQ;uNq|Hqdkd6< uTEsMwwO=MMEUnfx)>bHL)Z$ zMWH;iBtya7(>EYRFO?lAp62P|7-Dhy?Zn-@42nF?vL#7wRnHcsyGg}Q_IT*>fbBu( z!{p rn_DQ9?=G?TkxE?M{XE z)7O>#5f2B4nC=0O+`B*_+02lL66gHf+|;}hAeVu`xhOTUBsE2$JhLQ2!QIn0AVn{g z9Vl+@>Eak-aXL9cg0<%bQ;uNq|Hqd