Compare commits
	
		
			35 Commits
		
	
	
		
			eca7c55028
			...
			computers
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					59a217ceb9 | ||
| 
						 | 
					0dbc57cbbe | ||
| 
						 | 
					ee4cbef811 | ||
| 
						 | 
					fc7c0ff095 | ||
| 
						 | 
					1f28124569 | ||
| 
						 | 
					1ea698a1e1 | ||
| 
						 | 
					c46ec76c63 | ||
| 
						 | 
					aca2f138a8 | ||
| 
						 | 
					8267c4d71f | ||
| 
						 | 
					fa1f4894af | ||
| 
						 | 
					2593c55ee3 | ||
| 
						 | 
					3e4e65e01b | ||
| 
						 | 
					2060c59920 | ||
| 
						 | 
					4cfacb1abc | ||
| 
						 | 
					ef2ceed755 | ||
| 
						 | 
					d0a4ace94e | ||
| 
						 | 
					1397b08bcb | ||
| 
						 | 
					a844c7ec5e | ||
| 
						 | 
					f57b1642b9 | ||
| 
						 | 
					eacbe80fae | ||
| 
						 | 
					b3ca88e58d | ||
| 
						 | 
					b5ec85d037 | ||
| 
						 | 
					0af4ae2eb2 | ||
| 
						 | 
					2058c58738 | ||
| 
						 | 
					1ce0533672 | ||
| 
						 | 
					6f9a27ff05 | ||
| 
						 | 
					c350f40405 | ||
| 
						 | 
					35a3be337d | ||
| 
						 | 
					0664552799 | ||
| 
						 | 
					7043a7d15d | ||
| 
						 | 
					2e2d904261 | ||
| 
						 | 
					daf04bd400 | ||
| 
						 | 
					427b6b1f3f | ||
| 
						 | 
					92ee7e419e | ||
| 
						 | 
					0a43ffe46a | 
							
								
								
									
										18
									
								
								.github/workflows/luacheck.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,18 @@
 | 
			
		||||
 | 
			
		||||
name: luacheck
 | 
			
		||||
 | 
			
		||||
on: [push, pull_request]
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  build:
 | 
			
		||||
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
    - uses: actions/checkout@v1
 | 
			
		||||
    - name: apt
 | 
			
		||||
      run: sudo apt-get install -y luarocks
 | 
			
		||||
    - name: luacheck install
 | 
			
		||||
      run: luarocks install --local luacheck
 | 
			
		||||
    - name: luacheck run
 | 
			
		||||
      run: $HOME/.luarocks/bin/luacheck ./
 | 
			
		||||
							
								
								
									
										25
									
								
								.luacheckrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,25 @@
 | 
			
		||||
unused_args = false
 | 
			
		||||
allow_defined_top = true
 | 
			
		||||
 | 
			
		||||
exclude_files = {".luacheckrc"}
 | 
			
		||||
 | 
			
		||||
globals = {
 | 
			
		||||
    "minetest", "core",
 | 
			
		||||
 | 
			
		||||
    --mod provided
 | 
			
		||||
    "home_vending_machines", "computers",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
read_globals = {
 | 
			
		||||
    string = {fields = {"split"}},
 | 
			
		||||
    table = {fields = {"copy", "getn"}},
 | 
			
		||||
 | 
			
		||||
    --luac
 | 
			
		||||
    "math", "table",
 | 
			
		||||
 | 
			
		||||
    -- Builtin
 | 
			
		||||
    "vector", "ItemStack", "dump", "DIR_DELIM", "VoxelArea", "Settings", "PcgRandom", "VoxelManip", "PseudoRandom",
 | 
			
		||||
 | 
			
		||||
    --mod produced
 | 
			
		||||
    "default", "screwdriver", "unifieddyes", "formspec_ast", 
 | 
			
		||||
}
 | 
			
		||||
@@ -1,21 +0,0 @@
 | 
			
		||||
unused_args = false
 | 
			
		||||
allow_defined_top = true
 | 
			
		||||
max_comment_line_length = 999
 | 
			
		||||
 | 
			
		||||
read_globals = {
 | 
			
		||||
	"DIR_DELIM",
 | 
			
		||||
	"minetest", "core",
 | 
			
		||||
	"unpack",
 | 
			
		||||
	"dump",
 | 
			
		||||
	table = { fields = { "copy", "getn" } },
 | 
			
		||||
	"vector", "nodeupdate",
 | 
			
		||||
	"VoxelManip", "VoxelArea",
 | 
			
		||||
	"PseudoRandom", "ItemStack",
 | 
			
		||||
	"default",
 | 
			
		||||
	"unifieddyes",
 | 
			
		||||
	"screwdriver",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
globals = {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1,38 +0,0 @@
 | 
			
		||||
version 0.2.3:
 | 
			
		||||
  - Added animated router front
 | 
			
		||||
  - Added all crafts for new items
 | 
			
		||||
 | 
			
		||||
version 0.2.2:
 | 
			
		||||
  - Added printer
 | 
			
		||||
  - Added server
 | 
			
		||||
 | 
			
		||||
version 0.2.1:
 | 
			
		||||
  - Added modern tower pc
 | 
			
		||||
  - Added wifi router
 | 
			
		||||
  - Added flatscreen LCD and keyboard
 | 
			
		||||
 | 
			
		||||
Version 0.2.0:
 | 
			
		||||
  - Added recipes.
 | 
			
		||||
  - Partly re-written.
 | 
			
		||||
  - Removed original baby tower (seemed out of place).
 | 
			
		||||
  - You can now turn devices on and off by right-clicking.
 | 
			
		||||
  - Mod is now on github.
 | 
			
		||||
 | 
			
		||||
Version 0.1.4:
 | 
			
		||||
  - Added Admiral 64 & 128 (Commodore 64 & 128 lookalikes)
 | 
			
		||||
 | 
			
		||||
Version 0.1.3:
 | 
			
		||||
  - Added SX Spectre (Sinclair ZX Spectrum lookalike)
 | 
			
		||||
  - Added Pony SlayStation 2 (Sony PlayStation lookalike)
 | 
			
		||||
  - Minor fixes to textures.
 | 
			
		||||
 | 
			
		||||
Version 0.1.2:
 | 
			
		||||
  - Nodes now use the node box as selection box.
 | 
			
		||||
  - Added Pony SlayStation (Sony PlayStation lookalike)
 | 
			
		||||
  - Added Pony Vanio (Sony VAIO lookalike...err...just a generic laptop)
 | 
			
		||||
 | 
			
		||||
Version 0.1.1:
 | 
			
		||||
  - Added SheFriend SOO (Amiga 500 lookalike)
 | 
			
		||||
 | 
			
		||||
Version 0.1.0:
 | 
			
		||||
  - Initial Version only a baby tower.
 | 
			
		||||
							
								
								
									
										37
									
								
								computers/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,37 @@
 | 
			
		||||
 | 
			
		||||
# Minetest Computers Mod
 | 
			
		||||
 | 
			
		||||
By [Diego Martínez](kaeza@users.sf.net) and Contributors  
 | 
			
		||||
License: [MIT](https://spdx.org/licenses/MIT.html)
 | 
			
		||||
 | 
			
		||||
Adds interactive computers and networking to minetest
 | 
			
		||||
 | 
			
		||||
## Links
 | 
			
		||||
 | 
			
		||||
[Github](https://github.com/mt-mods/home_workshop_modpack)  
 | 
			
		||||
[Contentdb](https://content.minetest.net/packages/VanessaE/home_workshop_modpack/)  
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Setup
 | 
			
		||||
 | 
			
		||||
You should have recieved this mod as a part of the home workshop modpack. 
 | 
			
		||||
place the modpack in your /mods folder and enable the computer mod and its dependancies 
 | 
			
		||||
from the minetest GUI. For further information or help see: 
 | 
			
		||||
http://wiki.minetest.com/wiki/Installing_Mods
 | 
			
		||||
 | 
			
		||||
## Privs
 | 
			
		||||
 | 
			
		||||
This mod provides the computers_filesystem priv which is used to limit the access 
 | 
			
		||||
of players without it.
 | 
			
		||||
 | 
			
		||||
## Notes
 | 
			
		||||
 | 
			
		||||
Much thanks goes to the maintainers of the mod:
 | 
			
		||||
* Diego Martínez
 | 
			
		||||
* VannessaE
 | 
			
		||||
* mt-mods organization
 | 
			
		||||
 
 | 
			
		||||
Additional thanks goes to those who helped/advised with the core functionality of computers:
 | 
			
		||||
* Luk3yx
 | 
			
		||||
* BuckarooBanzai
 | 
			
		||||
* OgelGames
 | 
			
		||||
@@ -1,49 +0,0 @@
 | 
			
		||||
 | 
			
		||||
Decorative Computers Mod for Minetest
 | 
			
		||||
by Diego Martínez <kaeza@users.sf.net>
 | 
			
		||||
 | 
			
		||||
How to install:
 | 
			
		||||
Unzip the archive an place it in minetest-base-directory/mods/minetest/
 | 
			
		||||
if you have a windows client or a linux run-in-place client. If you have
 | 
			
		||||
a linux system-wide instalation place it in ~/.minetest/mods/minetest/.
 | 
			
		||||
If you want to install this mod only in one world create the folder
 | 
			
		||||
worldmods/ in your worlddirectory.
 | 
			
		||||
For further information or help see:
 | 
			
		||||
http://wiki.minetest.com/wiki/Installing_Mods
 | 
			
		||||
 | 
			
		||||
How to use the mod:
 | 
			
		||||
For now just use creative mode or the `/give' or `/giveme' chat commands
 | 
			
		||||
 to get the items.
 | 
			
		||||
 | 
			
		||||
These are the items currently defined by this mod:
 | 
			
		||||
 | 
			
		||||
"computers:shefriendSOO",
 | 
			
		||||
"computers:vanio",
 | 
			
		||||
"computers:vanio_off",
 | 
			
		||||
"computers:slaystation",
 | 
			
		||||
"computers:slaystation2",
 | 
			
		||||
"computers:specter",
 | 
			
		||||
"computers:wee",
 | 
			
		||||
"computers:piepad",
 | 
			
		||||
"computers:admiral64",
 | 
			
		||||
"computers:admiral128",
 | 
			
		||||
"computers:hueg_box",
 | 
			
		||||
"computers:monitor",
 | 
			
		||||
"computers:monitor_on",
 | 
			
		||||
"computers:router",
 | 
			
		||||
"computers:tower",
 | 
			
		||||
"computers:server",
 | 
			
		||||
"computers:server_on",
 | 
			
		||||
"computers:printer",
 | 
			
		||||
"computers:tetris_arcade",
 | 
			
		||||
 | 
			
		||||
There's also a `computers:computer' alias to `computers:babytower'.
 | 
			
		||||
 | 
			
		||||
Thanks to all the people in the forums and the #minetest IRC channel for
 | 
			
		||||
 their support and suggestions; in no particular order:
 | 
			
		||||
  OldCoder, Josh, tonyka, VanessaE, davidpace, Jordach, and all the other
 | 
			
		||||
  sirs/madammes that I forgot to mention (sorry, please remind me if it
 | 
			
		||||
  was you ;) ). 
 | 
			
		||||
 | 
			
		||||
See also:
 | 
			
		||||
http://minetest.net/
 | 
			
		||||
@@ -1,29 +0,0 @@
 | 
			
		||||
 | 
			
		||||
TO-DO List:
 | 
			
		||||
 | 
			
		||||
- New Nodes:
 | 
			
		||||
 | 
			
		||||
  - Computers:
 | 
			
		||||
    - Mainframe (well me have a rackserver now)
 | 
			
		||||
    - My Computer :P
 | 
			
		||||
 | 
			
		||||
  - Peripherals:
 | 
			
		||||
    - Scanner ( well we have a printer/scanner combo now)
 | 
			
		||||
 | 
			
		||||
  - Consoles:
 | 
			
		||||
    - NES
 | 
			
		||||
    - SNES
 | 
			
		||||
    - DC
 | 
			
		||||
 | 
			
		||||
  - Handhelds
 | 
			
		||||
    - GB/C
 | 
			
		||||
    - GBA
 | 
			
		||||
    - Calculator
 | 
			
		||||
    - Smartphone
 | 
			
		||||
 | 
			
		||||
- Animated screens
 | 
			
		||||
 | 
			
		||||
- Implement some kind of games (take code from `tetris' mod?). [It would be
 | 
			
		||||
   nice if Minetest provided a "canvas" GUI widget :)].
 | 
			
		||||
 | 
			
		||||
- Get more suggestions :)
 | 
			
		||||
							
								
								
									
										7
									
								
								computers/commands/cat/conf.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,7 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "cat",
 | 
			
		||||
    "license": "MIT",
 | 
			
		||||
    "version": 0.1,
 | 
			
		||||
    "engine": 0.44,
 | 
			
		||||
    "help": "output file to the terminal"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								computers/commands/cat/init.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,15 @@
 | 
			
		||||
function cat(pos, input, data)
 | 
			
		||||
    local path = computers.devicepath .. "/" .. minetest.hash_node_position(pos) .. data.element.pwd
 | 
			
		||||
    local files = computers.api.get_dir_keyed_list(path, false)
 | 
			
		||||
 | 
			
		||||
    if files[input] then
 | 
			
		||||
        local f = io.open(path .. "/" .. input)
 | 
			
		||||
        local fdata = f:read("*all")
 | 
			
		||||
        f:close()
 | 
			
		||||
        return fdata
 | 
			
		||||
    else
 | 
			
		||||
        return "file not found"
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return cat
 | 
			
		||||
							
								
								
									
										7
									
								
								computers/commands/cd/conf.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,7 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "cd",
 | 
			
		||||
    "license": "MIT",
 | 
			
		||||
    "version": 0.11,
 | 
			
		||||
    "engine": 0.41,
 | 
			
		||||
    "help": "move in and out of folders"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										28
									
								
								computers/commands/cd/init.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,28 @@
 | 
			
		||||
function cd(pos, input, data)
 | 
			
		||||
    if not minetest.check_player_privs(data.player, "computers_filesystem") then
 | 
			
		||||
        return "ERROR: permision denied"
 | 
			
		||||
    end
 | 
			
		||||
    local path = computers.devicepath .. "/" .. minetest.hash_node_position(pos) .. data.element.pwd
 | 
			
		||||
 | 
			
		||||
    if input and input ~= "" and not input:find("/") and not input:find("\\") then
 | 
			
		||||
        if input == ".." then
 | 
			
		||||
            local uri = data.element.pwd:split("/")
 | 
			
		||||
            uri[#uri] = nil
 | 
			
		||||
            data.element.pwd = "/" .. table.concat(uri, "/")
 | 
			
		||||
            if data.element.pwd == "/" then data.element.pwd = "" end
 | 
			
		||||
            return "sucess"
 | 
			
		||||
        else
 | 
			
		||||
            for _, folder in pairs(minetest.get_dir_list(path, true)) do
 | 
			
		||||
                if folder == input then
 | 
			
		||||
                    data.element.pwd = data.element.pwd .. "/" .. input
 | 
			
		||||
                    return "sucess"
 | 
			
		||||
                end
 | 
			
		||||
            end
 | 
			
		||||
            return "ERROR: path not found"
 | 
			
		||||
        end
 | 
			
		||||
    else
 | 
			
		||||
        return "invalid or missing input"
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return cd
 | 
			
		||||
							
								
								
									
										7
									
								
								computers/commands/echo/conf.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,7 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "echo",
 | 
			
		||||
    "license": "MIT",
 | 
			
		||||
    "version": 0.1,
 | 
			
		||||
    "engine": 0.3,
 | 
			
		||||
    "help": "prints out input to the terminal"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								computers/commands/echo/init.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,5 @@
 | 
			
		||||
function echo(pos, input, data)
 | 
			
		||||
    return input
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return echo
 | 
			
		||||
							
								
								
									
										7
									
								
								computers/commands/exit/conf.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,7 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "exit",
 | 
			
		||||
    "license": "MIT",
 | 
			
		||||
    "version": 0.1,
 | 
			
		||||
    "engine": 0.42,
 | 
			
		||||
    "help": "exits the computer"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								computers/commands/exit/init.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,7 @@
 | 
			
		||||
function exit(pos, input, data)
 | 
			
		||||
    minetest.close_formspec(data.player:get_player_name(), "")
 | 
			
		||||
 | 
			
		||||
    return "you shouldnt see this"
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return exit
 | 
			
		||||
							
								
								
									
										7
									
								
								computers/commands/expr/conf.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,7 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "expr",
 | 
			
		||||
    "license": "MIT",
 | 
			
		||||
    "version": 0.1,
 | 
			
		||||
    "engine": 0.42,
 | 
			
		||||
    "help": "exicutes mathmatical expresions"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										14
									
								
								computers/commands/expr/init.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,14 @@
 | 
			
		||||
function expr(pos, input, data)
 | 
			
		||||
    local output
 | 
			
		||||
    local func = computers.sandbox.loadstring("return " .. input, {env={}})
 | 
			
		||||
 | 
			
		||||
    if func then output = func() end
 | 
			
		||||
 | 
			
		||||
    if type(output) ~= "number" or output == nil then
 | 
			
		||||
        return "Error: invalid or missing input"
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    return tostring(output)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return expr
 | 
			
		||||
							
								
								
									
										7
									
								
								computers/commands/help/conf.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,7 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "help",
 | 
			
		||||
    "license": "MIT",
 | 
			
		||||
    "version": 0.1,
 | 
			
		||||
    "engine": 0.4,
 | 
			
		||||
    "help": "prints out help"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										9
									
								
								computers/commands/help/init.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,9 @@
 | 
			
		||||
function help(pos, input, data)
 | 
			
		||||
    local output = ""
 | 
			
		||||
    for command, def in pairs(computers.registered_confs) do
 | 
			
		||||
        output = output .. "\n" .. command .. ": " .. def.help
 | 
			
		||||
    end
 | 
			
		||||
    return output
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return help
 | 
			
		||||
							
								
								
									
										7
									
								
								computers/commands/ls/conf.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,7 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "ls",
 | 
			
		||||
    "license": "MIT",
 | 
			
		||||
    "version": 0.1,
 | 
			
		||||
    "engine": 0.4,
 | 
			
		||||
    "help": "lists out all files and folders in the current path"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										9
									
								
								computers/commands/ls/init.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,9 @@
 | 
			
		||||
function ls(pos, input, data)
 | 
			
		||||
    local path = computers.devicepath .. "/" .. minetest.hash_node_position(pos) .. data.element.pwd
 | 
			
		||||
    --make dir to be safe
 | 
			
		||||
    minetest.mkdir(path)
 | 
			
		||||
 | 
			
		||||
    return table.concat(minetest.get_dir_list(path), "  ")
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return ls
 | 
			
		||||
							
								
								
									
										7
									
								
								computers/commands/mkdir/conf.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,7 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "mkdir",
 | 
			
		||||
    "license": "MIT",
 | 
			
		||||
    "version": 0.11,
 | 
			
		||||
    "engine": 0.41,
 | 
			
		||||
    "help": "makes a dir in the current path"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								computers/commands/mkdir/init.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,15 @@
 | 
			
		||||
function mkdir(pos, input, data)
 | 
			
		||||
    if not minetest.check_player_privs(data.player, "computers_filesystem") then
 | 
			
		||||
        return "ERROR: permision denied"
 | 
			
		||||
    end
 | 
			
		||||
    local path = computers.devicepath .. "/" .. minetest.hash_node_position(pos) .. data.element.pwd
 | 
			
		||||
 | 
			
		||||
    if input and input ~= "" and not input:find("/") and not input:find("\\") then
 | 
			
		||||
        minetest.mkdir(path .. "/" .. input)
 | 
			
		||||
        return "folder " .. input .. " created"
 | 
			
		||||
    else
 | 
			
		||||
        return "invalid or missing input"
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return mkdir
 | 
			
		||||
							
								
								
									
										7
									
								
								computers/commands/nano/conf.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,7 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "nano",
 | 
			
		||||
    "license": "MIT",
 | 
			
		||||
    "version": 0.1,
 | 
			
		||||
    "engine": 0.42,
 | 
			
		||||
    "help": "allows editing of files"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										113
									
								
								computers/commands/nano/init.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,113 @@
 | 
			
		||||
function nano(pos, input, data)
 | 
			
		||||
    local path = computers.devicepath .. "/" .. minetest.hash_node_position(pos) .. data.element.pwd
 | 
			
		||||
    local files = computers.api.get_dir_keyed_list(path, false)
 | 
			
		||||
 | 
			
		||||
    if not input then return "no file designated" end
 | 
			
		||||
    if not files[input:split(" ")[1]] then return "file " .. input:split(" ")[1] .. " not found" end
 | 
			
		||||
    if computers.formspec.get_index_by_name(
 | 
			
		||||
        computers.formspec.registered_kast[data.player:get_player_name()],
 | 
			
		||||
        "nano_btn"
 | 
			
		||||
    ) then return "nano is already open, please close it" end
 | 
			
		||||
 | 
			
		||||
    local f = io.open(path .. "/" .. input:split(" ")[1])
 | 
			
		||||
    if not f then return "error reading file" end
 | 
			
		||||
    local file = f:read("*all")
 | 
			
		||||
    f:close()
 | 
			
		||||
 | 
			
		||||
    --clean up if there exists a legacy nano_ctn
 | 
			
		||||
    local nctn = computers.formspec.get_index_by_name(
 | 
			
		||||
        computers.formspec.registered_kast[data.player:get_player_name()],
 | 
			
		||||
        "nano_ctn"
 | 
			
		||||
    )
 | 
			
		||||
    if nctn then
 | 
			
		||||
        local fs = computers.formspec.registered_kast[data.player:get_player_name()]
 | 
			
		||||
        table.remove(fs, nctn)
 | 
			
		||||
        computers.formspec.registered_kast[data.player:get_player_name()] = fs
 | 
			
		||||
        minetest.chat_send_all(dump(fs))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    local form = computers.gui.add_tab(data.player, "Nano", {
 | 
			
		||||
        type = "container",
 | 
			
		||||
        name = "nano_ctn",
 | 
			
		||||
        state = 1,
 | 
			
		||||
        x = 0,
 | 
			
		||||
        y = 1,
 | 
			
		||||
        {
 | 
			
		||||
            type = "background",
 | 
			
		||||
            x = 0,
 | 
			
		||||
            y = 0,
 | 
			
		||||
            w = 10,
 | 
			
		||||
            h = 11,
 | 
			
		||||
            texture_name = "[combine:16x16^[noalpha"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            type = "textarea",
 | 
			
		||||
            x = 0,
 | 
			
		||||
            y = 0,
 | 
			
		||||
            w = 10,
 | 
			
		||||
            h = 10,
 | 
			
		||||
            name = "nano_editor",
 | 
			
		||||
            --read_only = 1,
 | 
			
		||||
            --label = "test",
 | 
			
		||||
            default = file,
 | 
			
		||||
            close_on_enter = false,
 | 
			
		||||
            --this breaks the scrollbar
 | 
			
		||||
            --[[ props = {
 | 
			
		||||
                border = false,
 | 
			
		||||
            } ]]
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            type = "box",
 | 
			
		||||
            x = 0,
 | 
			
		||||
            y = 10,
 | 
			
		||||
            w = 10,
 | 
			
		||||
            h = 1,
 | 
			
		||||
            color = "#ffffff"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            type = "field",
 | 
			
		||||
            x = 0,
 | 
			
		||||
            y = 10,
 | 
			
		||||
            w = 10,
 | 
			
		||||
            h = 1,
 | 
			
		||||
            name = "nano_commands",
 | 
			
		||||
            close_on_enter = false,
 | 
			
		||||
            pwd = "",
 | 
			
		||||
            props = {
 | 
			
		||||
                border = false,
 | 
			
		||||
            },
 | 
			
		||||
            on_event = function(form, player, element, value, fields)
 | 
			
		||||
                if value == "save" and fields.nano_editor then
 | 
			
		||||
                    --minetest.chat_send_all(fields.nano_editor)
 | 
			
		||||
                    if #fields.nano_editor < 12000 then --12000 is luacheck line length of 120 * 100 lines
 | 
			
		||||
                        minetest.safe_file_write(path .. "/" .. input:split(" ")[1], fields.nano_editor)
 | 
			
		||||
                    else
 | 
			
		||||
                        computers.api.chat_send_player(player, minetest.colorize("red", "[Nano]: file is to long"))
 | 
			
		||||
                    end
 | 
			
		||||
                elseif value == "exit" then
 | 
			
		||||
                    local btn = computers.formspec.get_index_by_name(form, "nano_btn")
 | 
			
		||||
                    local ctn = computers.formspec.get_index_by_name(form, "nano_ctn")
 | 
			
		||||
                    form[ctn].state = 1
 | 
			
		||||
                    table.remove(form, btn)
 | 
			
		||||
                    --table.remove(form, ctn) cant actually remove it from within itself, therefore we hide it
 | 
			
		||||
                    local tindex = 0
 | 
			
		||||
                    for index, tab in pairs(form.tabs) do
 | 
			
		||||
                        if tab == "nano" then tindex = index end
 | 
			
		||||
                    end
 | 
			
		||||
                    table.remove(form.tabs, tindex)
 | 
			
		||||
                    tindex = computers.formspec.get_index_by_name(form, "terminal_ctn")
 | 
			
		||||
 | 
			
		||||
                    form[tindex].state = 0
 | 
			
		||||
                else
 | 
			
		||||
                    computers.api.chat_send_player(player, minetest.colorize("red", "[Nano]: invalid command"))
 | 
			
		||||
                end
 | 
			
		||||
 | 
			
		||||
                return form
 | 
			
		||||
            end,
 | 
			
		||||
        },
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    return form
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return nano
 | 
			
		||||
							
								
								
									
										7
									
								
								computers/commands/net/conf.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,7 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "net",
 | 
			
		||||
    "license": "MIT",
 | 
			
		||||
    "version": 0.1,
 | 
			
		||||
    "engine": 0.43,
 | 
			
		||||
    "help": "configuration related to networking"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										64
									
								
								computers/commands/net/init.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,64 @@
 | 
			
		||||
function net(pos, input, data)
 | 
			
		||||
    input = input or ""
 | 
			
		||||
    local lookup = {
 | 
			
		||||
        list = function(param)
 | 
			
		||||
            if param == "-ids" then
 | 
			
		||||
                return table.concat(computers.networks.get_networks_in_area(pos), " ")
 | 
			
		||||
            elseif not param or param == "" then
 | 
			
		||||
                return table.concat(computers.networks.get_net_names_in_area(pos), " ")
 | 
			
		||||
            else
 | 
			
		||||
                return "invalid sub command"
 | 
			
		||||
            end
 | 
			
		||||
        end,
 | 
			
		||||
        join = function(param)
 | 
			
		||||
            local id = computers.networks.get_id_by_net_name(data.player, param)
 | 
			
		||||
            if not id then
 | 
			
		||||
                return "invalid network name"
 | 
			
		||||
            elseif minetest.get_meta(pos):get("net_id") then
 | 
			
		||||
                return "already joined to a network"
 | 
			
		||||
            else
 | 
			
		||||
                local _, networks = computers.networks.get_net_names_in_area(pos)
 | 
			
		||||
                if not networks[param] then return "network not in range" end
 | 
			
		||||
                minetest.get_meta(pos):set_string("net_id", id)
 | 
			
		||||
                local status = computers.networks.add_device(id, pos)
 | 
			
		||||
                if status then return "joined network " .. param else return "network join failed" end
 | 
			
		||||
            end
 | 
			
		||||
        end,
 | 
			
		||||
        leave = function(param)
 | 
			
		||||
            local id = minetest.get_meta(pos):get("net_id")
 | 
			
		||||
            if id then
 | 
			
		||||
                computers.networks.remove_device(id, pos)
 | 
			
		||||
                return "removed device from network " .. computers.networks.get_net_name(id)
 | 
			
		||||
            else
 | 
			
		||||
                return "not currently connected to any network"
 | 
			
		||||
            end
 | 
			
		||||
        end,
 | 
			
		||||
        status = function(param)
 | 
			
		||||
            local id = minetest.get_meta(pos):get("net_id")
 | 
			
		||||
            if id then
 | 
			
		||||
                return "connected to network " .. computers.networks.get_net_name(id)
 | 
			
		||||
            else
 | 
			
		||||
                return "not connected to any network"
 | 
			
		||||
            end
 | 
			
		||||
        end,
 | 
			
		||||
        dns = function(param)
 | 
			
		||||
            if minetest.get_item_group(minetest.get_node(pos).name, "computers_server") == 0 then
 | 
			
		||||
                return "command only available to servers"
 | 
			
		||||
            end
 | 
			
		||||
            if not param or param == "" then return "invalid or missing input" end
 | 
			
		||||
            if param:match("%W") then return "only alphanumerics allowed" end
 | 
			
		||||
            local id = minetest.get_meta(pos):get("net_id")
 | 
			
		||||
            if id then
 | 
			
		||||
                computers.networks.set_dns(id, pos, param)
 | 
			
		||||
                return "created dns record"
 | 
			
		||||
            else
 | 
			
		||||
                return "not connected to network"
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if not lookup[input:split(" ")[1]] then return "invalid sub command" end
 | 
			
		||||
    return lookup[input:split(" ")[1]](input:split(" ", 1)[2])
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return net
 | 
			
		||||
							
								
								
									
										7
									
								
								computers/commands/pwd/conf.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,7 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "pwd",
 | 
			
		||||
    "license": "MIT",
 | 
			
		||||
    "version": 0.1,
 | 
			
		||||
    "engine": 0.4,
 | 
			
		||||
    "help": "list the current path"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								computers/commands/pwd/init.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,7 @@
 | 
			
		||||
function pwd(pos, input, data)
 | 
			
		||||
    local output = data.element.pwd
 | 
			
		||||
    if output == "" then output = "/" end
 | 
			
		||||
    return output
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return pwd
 | 
			
		||||
							
								
								
									
										7
									
								
								computers/commands/test/conf.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,7 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "test",
 | 
			
		||||
    "license": "MIT",
 | 
			
		||||
    "version": 0.1,
 | 
			
		||||
    "engine": 100000000,
 | 
			
		||||
    "help": "literally worthless"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										6
									
								
								computers/commands/test/init.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,6 @@
 | 
			
		||||
function test(pos, input)
 | 
			
		||||
    --minetest.chat_send_all("test")
 | 
			
		||||
    return 0
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return test
 | 
			
		||||
							
								
								
									
										7
									
								
								computers/commands/touch/conf.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,7 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "touch",
 | 
			
		||||
    "license": "MIT",
 | 
			
		||||
    "version": 0.3,
 | 
			
		||||
    "engine": 0.42,
 | 
			
		||||
    "help": "creates a file in the current path"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								computers/commands/touch/init.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,22 @@
 | 
			
		||||
function touch(pos, input, data)
 | 
			
		||||
    local path = computers.devicepath .. "/" .. minetest.hash_node_position(pos) .. data.element.pwd
 | 
			
		||||
    --make dir to be safe
 | 
			
		||||
    minetest.mkdir(path)
 | 
			
		||||
 | 
			
		||||
    if #minetest.get_dir_list(path, false) > 10
 | 
			
		||||
    and not minetest.check_player_privs(data.player, "computers_filesystem") then
 | 
			
		||||
        return "ERROR: you have reached your max file limit"
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    if input and input ~= "" and not input:find("/") then
 | 
			
		||||
        if computers.api.get_dir_keyed_list(path, nil)[input] then
 | 
			
		||||
            return "ERROR: trying to create already existing file/folder"
 | 
			
		||||
        end
 | 
			
		||||
        minetest.safe_file_write(path .. "/" .. input, "")
 | 
			
		||||
        return "file " .. input .. " created"
 | 
			
		||||
    else
 | 
			
		||||
        return "invalid or missing input"
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return touch
 | 
			
		||||
							
								
								
									
										142
									
								
								computers/core/api.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,142 @@
 | 
			
		||||
--[[
 | 
			
		||||
    computers.sandbox code is from https://github.com/kikito/lua-sandbox
 | 
			
		||||
    License MIT 2013 Enrique García Cota
 | 
			
		||||
    additionally modified by wsor to work with lua 5.1/luajit
 | 
			
		||||
    modifications include:
 | 
			
		||||
        * additional protections
 | 
			
		||||
        * tweaking of structure
 | 
			
		||||
        * modifications to the default env
 | 
			
		||||
]]
 | 
			
		||||
computers.sandbox = {}
 | 
			
		||||
computers.api = {}
 | 
			
		||||
 | 
			
		||||
--default sandbox enviroment used if none is provided
 | 
			
		||||
computers.sandbox.default_env = {}
 | 
			
		||||
 | 
			
		||||
([[
 | 
			
		||||
    _VERSION assert   error    ipairs next pairs
 | 
			
		||||
    select   tonumber tostring type   unpack
 | 
			
		||||
 | 
			
		||||
    math.abs   math.acos math.asin  math.atan math.atan2 math.ceil
 | 
			
		||||
    math.cos   math.cosh math.deg   math.exp  math.fmod  math.floor
 | 
			
		||||
    math.frexp math.huge math.ldexp math.log  math.log10 math.max
 | 
			
		||||
    math.min   math.modf math.pi    math.pow  math.rad   math.random
 | 
			
		||||
    math.sin   math.sinh math.sqrt  math.tan  math.tanh
 | 
			
		||||
 | 
			
		||||
    os.clock os.difftime os.time
 | 
			
		||||
 | 
			
		||||
    string.byte string.char
 | 
			
		||||
    string.len  string.lower string.reverse
 | 
			
		||||
    string.sub  string.upper
 | 
			
		||||
 | 
			
		||||
    table.insert table.maxn table.remove table.sort table.concat
 | 
			
		||||
]]):gsub('%S+', function(id)
 | 
			
		||||
    local module, method = id:match('([^%.]+)%.([^%.]+)')
 | 
			
		||||
    if module then
 | 
			
		||||
        computers.sandbox.default_env[module] = computers.sandbox.default_env[module] or {}
 | 
			
		||||
        computers.sandbox.default_env[module][method] = _G[module][method]
 | 
			
		||||
    else
 | 
			
		||||
        computers.sandbox.default_env[id] = _G[id]
 | 
			
		||||
    end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
--takes a code string, returns a sandboxed function to exicute
 | 
			
		||||
function computers.sandbox.loadstring(code, options)
 | 
			
		||||
    local defaults = {
 | 
			
		||||
        env = table.copy(computers.sandbox.default_env),
 | 
			
		||||
        quota = 5000
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    options = options or {}
 | 
			
		||||
    for k, v in pairs(defaults) do
 | 
			
		||||
        if not options[k] then options[k] = v end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    assert(type(code) == "string", "[computers.sandbox]: passed is not a string")
 | 
			
		||||
 | 
			
		||||
    local env = options.env
 | 
			
		||||
    env._G = env
 | 
			
		||||
 | 
			
		||||
    if code:byte(1) == 27 then
 | 
			
		||||
        minetest.log("warning", "[computers.sandbox]: attempted bytecode execution termminated")
 | 
			
		||||
        return nil, "bytecode disallowed"
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    local f, err = loadstring(code)
 | 
			
		||||
    if not f then return nil, err end
 | 
			
		||||
    setfenv(f, env)
 | 
			
		||||
 | 
			
		||||
    if jit then jit.off(f, true) end
 | 
			
		||||
 | 
			
		||||
    local function timeout()
 | 
			
		||||
        debug.sethook()
 | 
			
		||||
        error("quota exceeded: " .. tostring(options.quota))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    return function(...)
 | 
			
		||||
        debug.sethook(timeout, "", options.quota)
 | 
			
		||||
        local string_metatable = getmetatable("")
 | 
			
		||||
        assert(string_metatable.__index == string, "[computers.sandbox]: error with the string metatable")
 | 
			
		||||
        string_metatable.__index = env.string
 | 
			
		||||
 | 
			
		||||
        local status, ret = pcall(f, ...)
 | 
			
		||||
 | 
			
		||||
        debug.sethook()
 | 
			
		||||
        string_metatable.__index = string
 | 
			
		||||
 | 
			
		||||
        if not status then error(ret) end
 | 
			
		||||
        return ret
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--supports string input or table env input with a default env of the base
 | 
			
		||||
function computers.sandbox.merge_env(nenv, denv)
 | 
			
		||||
    local base_env = table.copy(denv or computers.sandbox.default_env)
 | 
			
		||||
 | 
			
		||||
    if type(nenv) == "table" then
 | 
			
		||||
        for k, v in pairs(nenv) do
 | 
			
		||||
            base_env[k] = base_env[k] or {}
 | 
			
		||||
            for key, value in pairs(v) do
 | 
			
		||||
                base_env[k][key] = value
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
    elseif type(nenv) == "string" then
 | 
			
		||||
        nenv:gsub('%S+', function(id)
 | 
			
		||||
            local module, method = id:match('([^%.]+)%.([^%.]+)')
 | 
			
		||||
            if module then
 | 
			
		||||
                base_env[module] = base_env[module] or {}
 | 
			
		||||
                base_env[module][method] = _G[module][method]
 | 
			
		||||
            else
 | 
			
		||||
                base_env[id] = _G[id]
 | 
			
		||||
            end
 | 
			
		||||
        end)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    return base_env
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function computers.api.get_dir_keyed_list(path, is_dir)
 | 
			
		||||
    local files = minetest.get_dir_list(path, is_dir)
 | 
			
		||||
    local keyed = {}
 | 
			
		||||
    for _, file in pairs(files) do
 | 
			
		||||
        keyed[file] = true
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    return keyed
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function computers.api.chat_send_player(player, msg)
 | 
			
		||||
    local name = player
 | 
			
		||||
    if type(name) == "userdata" then name = player:get_player_name() end
 | 
			
		||||
    minetest.chat_send_player(name, msg)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--basically for dev usage only
 | 
			
		||||
function computers.api.benchmark(func, ...)
 | 
			
		||||
    local start_time = minetest.get_us_time()
 | 
			
		||||
    for i=1, 1000 do
 | 
			
		||||
        func(...)
 | 
			
		||||
    end
 | 
			
		||||
    minetest.chat_send_all(minetest.get_us_time()-start_time)
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										26
									
								
								computers/core/commands.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,26 @@
 | 
			
		||||
computers.registered_commands = {}
 | 
			
		||||
computers.registered_confs = {}
 | 
			
		||||
 | 
			
		||||
minetest.register_privilege("computers_filesystem", {
 | 
			
		||||
    description = "advanced use of computers filesystem",
 | 
			
		||||
    give_to_singleplayer = false,
 | 
			
		||||
    give_to_admin = false,
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
function computers.register_command(modpath)
 | 
			
		||||
    local func = dofile(modpath .. "/init.lua")
 | 
			
		||||
    local f = io.open(modpath .. "/conf.json")
 | 
			
		||||
    local conf = minetest.parse_json(f:read("*all"))
 | 
			
		||||
    f:close()
 | 
			
		||||
    if func and computers.os.version >= conf.engine then
 | 
			
		||||
        computers.registered_commands[conf.name] = func
 | 
			
		||||
        computers.registered_confs[conf.name] = conf
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--load default commands
 | 
			
		||||
local dirs = minetest.get_dir_list(computers.modpath .. "/commands", true)
 | 
			
		||||
 | 
			
		||||
for _, dir in pairs(dirs) do
 | 
			
		||||
    computers.register_command(computers.modpath .. "/commands/" .. dir)
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										173
									
								
								computers/core/formspec.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,173 @@
 | 
			
		||||
computers.formspec = {}
 | 
			
		||||
computers.formspec.registered_kast = {}
 | 
			
		||||
 | 
			
		||||
computers.formspec.get_element_by_name = formspec_ast.get_element_by_name
 | 
			
		||||
 | 
			
		||||
function computers.formspec.get_index_by_name(tree, name)
 | 
			
		||||
    --this doesnt support containers, use this to get container index and then pass container as tree
 | 
			
		||||
    if type(tree) ~= "table" then return end
 | 
			
		||||
 | 
			
		||||
    for key, element in pairs(tree) do
 | 
			
		||||
        if type(element) == "table" and element.name and element.name == name then
 | 
			
		||||
            return key
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--note this is terrible hard coded
 | 
			
		||||
local function insert_styles(form, styles)
 | 
			
		||||
    local headers = {size = true, position = true, anchor = true, no_prepend = true, real_cordinates = true}
 | 
			
		||||
    local cindex = 0
 | 
			
		||||
    local fs = {}
 | 
			
		||||
 | 
			
		||||
    for key, val in pairs(form) do
 | 
			
		||||
        if type(val) == "number" and not tonumber(key) then
 | 
			
		||||
            fs[key] = val
 | 
			
		||||
        elseif type(val) == "table" and val.type and headers[val.type] then
 | 
			
		||||
            table.insert(fs, val)
 | 
			
		||||
            cindex = key
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    for _, val in pairs(styles) do
 | 
			
		||||
        table.insert(fs, val)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    cindex = cindex+1
 | 
			
		||||
    for i=cindex, #form do
 | 
			
		||||
        table.insert(fs, form[i])
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    return fs
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function computers.formspec.convert_to_ast(form)
 | 
			
		||||
    local styles = {}
 | 
			
		||||
 | 
			
		||||
    local function rfind(fs)
 | 
			
		||||
        for key, val in pairs(fs) do
 | 
			
		||||
            if type(val) == "table" then
 | 
			
		||||
                if val.type and val.type:find("container") then
 | 
			
		||||
                    if val.state and val.state == 1 then
 | 
			
		||||
                        --cant use nil so swaping in thing that will never render
 | 
			
		||||
                        fs[key] = {type = "label",x = 100,y = 100,label = "nil",}
 | 
			
		||||
                    else
 | 
			
		||||
                        rfind(val)
 | 
			
		||||
                    end
 | 
			
		||||
                elseif val.props then
 | 
			
		||||
                    table.insert(styles, {type = "style", selectors = val.selectors or {val.name}, props = val.props})
 | 
			
		||||
                elseif val.read_only == 1 then
 | 
			
		||||
                    val.name = nil
 | 
			
		||||
                end
 | 
			
		||||
                if val.type == "field" then
 | 
			
		||||
                    table.insert(
 | 
			
		||||
                        styles,
 | 
			
		||||
                        {type = "field_close_on_enter", name = val.name, close_on_enter = val.close_on_enter}
 | 
			
		||||
                    )
 | 
			
		||||
                end
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    rfind(form)
 | 
			
		||||
 | 
			
		||||
    local fs = insert_styles(form, styles)
 | 
			
		||||
    return fs
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local forms = {}
 | 
			
		||||
 | 
			
		||||
function computers.formspec.show_formspec(player, formname, fs)
 | 
			
		||||
    local playername = player
 | 
			
		||||
    local formspec = fs
 | 
			
		||||
 | 
			
		||||
    if type(player) == "userdata" then
 | 
			
		||||
        playername = player:get_player_name()
 | 
			
		||||
    end
 | 
			
		||||
    if type(fs) == "table" then
 | 
			
		||||
        computers.formspec.registered_kast[playername] = table.copy(fs)
 | 
			
		||||
        formspec = formspec_ast.unparse(computers.formspec.convert_to_ast(fs))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    forms[formname] = true
 | 
			
		||||
 | 
			
		||||
    minetest.show_formspec(playername, formname, formspec)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function computers.formspec.close_formspec(player, formname)
 | 
			
		||||
    local name = player
 | 
			
		||||
    if type(name) == "userdata" then name = player:get_player_name() end
 | 
			
		||||
 | 
			
		||||
    minetest.close_formspec(name, formname or "")
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
 | 
			
		||||
    --if formname ~= "computers:gui" then return end
 | 
			
		||||
    if not forms[formname] then return end
 | 
			
		||||
    local pname = player:get_player_name()
 | 
			
		||||
 | 
			
		||||
    if fields.quit then computers.formspec.registered_kast[pname] = nil return end
 | 
			
		||||
 | 
			
		||||
    --[[
 | 
			
		||||
        trying to figure out what a player actually did can be a mess
 | 
			
		||||
        input can validly be nil for a text field sometimes, othertimes it can come in first
 | 
			
		||||
        when a user has actual selected a button. buttons only come in when selected,
 | 
			
		||||
        so we override whatever the first key is if there a button since we are sure it was pressed
 | 
			
		||||
        since we cant get types from fields, we rely on the button being named name_btn with _btn being a suffix
 | 
			
		||||
    ]]
 | 
			
		||||
 | 
			
		||||
    local keys = {}
 | 
			
		||||
    local btn_override
 | 
			
		||||
    for key, val in pairs(fields) do
 | 
			
		||||
        table.insert(keys, key)
 | 
			
		||||
        local split = key:split("_")
 | 
			
		||||
        if #split >= 2 and split[2] == "btn" then btn_override = key end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    local element = computers.formspec.get_element_by_name(
 | 
			
		||||
        computers.formspec.registered_kast[pname],
 | 
			
		||||
        btn_override or keys[1]
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    --minetest.chat_send_all(btn_override or keys[1])
 | 
			
		||||
    --minetest.chat_send_all(fields[keys[1]])
 | 
			
		||||
 | 
			
		||||
    if element and element.on_event then
 | 
			
		||||
        --on_event(form, player, element)
 | 
			
		||||
        local form = element.on_event(
 | 
			
		||||
            computers.formspec.registered_kast[pname],
 | 
			
		||||
            player,
 | 
			
		||||
            element,
 | 
			
		||||
            fields[btn_override or keys[1]],
 | 
			
		||||
            fields
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        if form then computers.formspec.show_formspec(player, formname, form) end
 | 
			
		||||
    end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
--[[
 | 
			
		||||
    yes, i know this isnt perfect
 | 
			
		||||
    requires a name field in the subtags
 | 
			
		||||
    returns a table keyed by the name field with sub tables containing the other sub tags
 | 
			
		||||
]]
 | 
			
		||||
function computers.formspec.get_hypertext_subtags(hypertext, tag)
 | 
			
		||||
    local adata = {}
 | 
			
		||||
    for a in string.gmatch(hypertext, "<"..tag..".->.-</"..tag..">") do
 | 
			
		||||
        local len = #tag+1
 | 
			
		||||
        local tags = string.split(string.sub(a:split(">")[1], len, -1), " ")
 | 
			
		||||
        local name
 | 
			
		||||
        local storage = {}
 | 
			
		||||
        for _, tag_string in pairs(tags) do
 | 
			
		||||
            local split = tag_string:split("=")
 | 
			
		||||
            if split[1] == "name" then
 | 
			
		||||
                name = split[2]
 | 
			
		||||
            else
 | 
			
		||||
                storage[split[1]] = split[2]
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
        adata[name] = storage
 | 
			
		||||
    end
 | 
			
		||||
    --minetest.chat_send_all(dump(adata))
 | 
			
		||||
    return adata
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										330
									
								
								computers/core/gui.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,330 @@
 | 
			
		||||
computers.gui = {}
 | 
			
		||||
 | 
			
		||||
local futil = computers.formspec
 | 
			
		||||
 | 
			
		||||
local f = io.open(computers.modpath .. "/default_page.page")
 | 
			
		||||
local default_page = f:read("*all")
 | 
			
		||||
f:close()
 | 
			
		||||
f = io.open(computers.modpath .. "/demo_page.page")
 | 
			
		||||
local demo_page = f:read("*all")
 | 
			
		||||
f:close()
 | 
			
		||||
 | 
			
		||||
local function select_btn(form, btn)
 | 
			
		||||
    --to hardcoded
 | 
			
		||||
    for _, obtn in pairs(form.tabs) do
 | 
			
		||||
        local cindex = futil.get_index_by_name(form, obtn .. "_btn")
 | 
			
		||||
        form[cindex].props.bgimg = "kuto_button.png^[combine:16x16^[noalpha^[colorize:#ffffff70"
 | 
			
		||||
        form[cindex].props.bgimg_hovered = "kuto_button.png^[combine:16x16^[noalpha^[colorize:#ffffff90"
 | 
			
		||||
 | 
			
		||||
        cindex = futil.get_index_by_name(form, obtn .. "_ctn")
 | 
			
		||||
        form[cindex].state = 1
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    local cindex = futil.get_index_by_name(form, btn .. "_btn")
 | 
			
		||||
    form[cindex].props.bgimg = "kuto_button.png^[combine:16x16^[noalpha^[colorize:#ffffff20"
 | 
			
		||||
    form[cindex].props.bgimg_hovered = "kuto_button.png^[combine:16x16^[noalpha^[colorize:#ffffff40"
 | 
			
		||||
 | 
			
		||||
    local aindex = futil.get_index_by_name(form, btn .. "_ctn")
 | 
			
		||||
    form[aindex].state = 0
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function computers.gui.load(pos, node, clicker)
 | 
			
		||||
 | 
			
		||||
    local formspec = {
 | 
			
		||||
        formspec_version = 4,
 | 
			
		||||
        tabs = {"terminal", "browser"},
 | 
			
		||||
        {
 | 
			
		||||
            type = "size",
 | 
			
		||||
            w = 10,
 | 
			
		||||
            h = 12,
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            type = "no_prepend"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            type = "bgcolor",
 | 
			
		||||
            bgcolor = "black",
 | 
			
		||||
            fullscreen = "neither"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            type = "button",
 | 
			
		||||
            x = 0,
 | 
			
		||||
            y = 0,
 | 
			
		||||
            w = 2,
 | 
			
		||||
            h = 1,
 | 
			
		||||
            name = "terminal_btn",
 | 
			
		||||
            label = "Terminal",
 | 
			
		||||
            on_event = function(form, player, element)
 | 
			
		||||
                select_btn(form, "terminal")
 | 
			
		||||
 | 
			
		||||
                return form
 | 
			
		||||
            end,
 | 
			
		||||
            props = {
 | 
			
		||||
                border = false,
 | 
			
		||||
                bgimg = "kuto_button.png^[combine:16x16^[noalpha^[colorize:#ffffff70",
 | 
			
		||||
                bgimg_hovered = "kuto_button.png^[combine:16x16^[noalpha^[colorize:#ffffff90",
 | 
			
		||||
                bgimg_middle = "4,4",
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            type = "button",
 | 
			
		||||
            x = 2,
 | 
			
		||||
            y = 0,
 | 
			
		||||
            w = 2,
 | 
			
		||||
            h = 1,
 | 
			
		||||
            name = "browser_btn",
 | 
			
		||||
            label = "Browser",
 | 
			
		||||
            on_event = function(form, player, element)
 | 
			
		||||
                select_btn(form, "browser")
 | 
			
		||||
 | 
			
		||||
                return form
 | 
			
		||||
            end,
 | 
			
		||||
            props = {
 | 
			
		||||
                border = false,
 | 
			
		||||
                bgimg = "kuto_button.png^[combine:16x16^[noalpha^[colorize:#ffffff70",
 | 
			
		||||
                bgimg_hovered = "kuto_button.png^[combine:16x16^[noalpha^[colorize:#ffffff90",
 | 
			
		||||
                bgimg_middle = "4,4",
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            type = "container",
 | 
			
		||||
            name = "terminal_ctn",
 | 
			
		||||
            state = 0,
 | 
			
		||||
            x = 0,
 | 
			
		||||
            y = 1,
 | 
			
		||||
            {
 | 
			
		||||
                type = "background",
 | 
			
		||||
                x = 0,
 | 
			
		||||
                y = 0,
 | 
			
		||||
                w = 10,
 | 
			
		||||
                h = 11,
 | 
			
		||||
                texture_name = "[combine:16x16^[noalpha"
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                type = "textarea",
 | 
			
		||||
                x = 0,
 | 
			
		||||
                y = 0,
 | 
			
		||||
                w = 10,
 | 
			
		||||
                h = 10,
 | 
			
		||||
                name = "terminal_output",
 | 
			
		||||
                read_only = 1,
 | 
			
		||||
                --label = "test",
 | 
			
		||||
                default = "welcome to kuto\nversion " .. computers.os.version .. "\n\nuser:~$ ",
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                type = "box",
 | 
			
		||||
                x = 0,
 | 
			
		||||
                y = 10,
 | 
			
		||||
                w = 10,
 | 
			
		||||
                h = 1,
 | 
			
		||||
                color = "#ffffff"
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                type = "field",
 | 
			
		||||
                x = 0,
 | 
			
		||||
                y = 10,
 | 
			
		||||
                w = 10,
 | 
			
		||||
                h = 1,
 | 
			
		||||
                name = "terminal_input",
 | 
			
		||||
                close_on_enter = false,
 | 
			
		||||
                pwd = "",
 | 
			
		||||
                props = {
 | 
			
		||||
                    border = false,
 | 
			
		||||
                },
 | 
			
		||||
                on_event = function(form, player, element, value)
 | 
			
		||||
                    local cindex = futil.get_index_by_name(form, "terminal_ctn")
 | 
			
		||||
                    local eindex = futil.get_index_by_name(form[cindex], "terminal_output")
 | 
			
		||||
                    local text = form[cindex][eindex].default
 | 
			
		||||
                    local pass_table = {
 | 
			
		||||
                        element = element,
 | 
			
		||||
                        player = player
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if value == "clear" then
 | 
			
		||||
                        form[cindex][eindex].default = "user:~" .. element.pwd .."$" .."\n"
 | 
			
		||||
                    end
 | 
			
		||||
 | 
			
		||||
                    local cdata = value:split(" ", false, 1)
 | 
			
		||||
 | 
			
		||||
                    if value == "clear" then
 | 
			
		||||
                        form[cindex][eindex].default = "user:~$ "
 | 
			
		||||
                    elseif value == "" then
 | 
			
		||||
                        form[cindex][eindex].default = text .. "user:~" .. element.pwd .."$" .. "\n"
 | 
			
		||||
                    elseif computers.registered_commands[cdata[1]] and cdata[2] == "-v" then
 | 
			
		||||
                        form[cindex][eindex].default = text .. value .. "\n" ..
 | 
			
		||||
                            computers.registered_confs[cdata[1]].version .. "\nuser:~" .. element.pwd .."$" .. "\n"
 | 
			
		||||
                    elseif computers.registered_commands[cdata[1]] then
 | 
			
		||||
                        form[cindex][eindex].default = text .. value .. "\n"
 | 
			
		||||
                        text = form[cindex][eindex].default
 | 
			
		||||
                        local output = computers.registered_commands[cdata[1]](pos, cdata[2], pass_table)
 | 
			
		||||
                        if output and type(output) == "string" then
 | 
			
		||||
                            form[cindex][eindex].default = text .. output .. "\n" .. "user:~" .. element.pwd .."$" .." "
 | 
			
		||||
                        elseif output and type(output) == "table" then
 | 
			
		||||
                            form = output
 | 
			
		||||
                        end
 | 
			
		||||
                    else
 | 
			
		||||
                        form[cindex][eindex].default = text .. value ..
 | 
			
		||||
                            "\nERROR: command not found\n" .. "user:~" .. element.pwd .."$" .. " "
 | 
			
		||||
                    end
 | 
			
		||||
 | 
			
		||||
                    return form
 | 
			
		||||
                end,
 | 
			
		||||
            },
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            type = "container",
 | 
			
		||||
            name = "browser_ctn",
 | 
			
		||||
            state = 1,
 | 
			
		||||
            x = 0,
 | 
			
		||||
            y = 1,
 | 
			
		||||
            --[[
 | 
			
		||||
                hardcoded background for now, need to build in custom element support
 | 
			
		||||
                into hypertext to map to formspec elements
 | 
			
		||||
                ]]
 | 
			
		||||
            {
 | 
			
		||||
                type = "background",
 | 
			
		||||
                x = 0,
 | 
			
		||||
                y = 0,
 | 
			
		||||
                w = 10,
 | 
			
		||||
                h = 10,
 | 
			
		||||
                texture_name = "[combine:16x16^[noalpha^[colorize:#ffffff70"
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                type = "hypertext",
 | 
			
		||||
                name = "browser_content",
 | 
			
		||||
                x = 0,
 | 
			
		||||
                y = 0,
 | 
			
		||||
                w = 10,
 | 
			
		||||
                h = 10,
 | 
			
		||||
                text = default_page,
 | 
			
		||||
                on_event = function(form, player, element, value, fields)
 | 
			
		||||
                    --minetest.chat_send_all("reached")
 | 
			
		||||
 | 
			
		||||
                    --hard coding some network stuff for now
 | 
			
		||||
                    local name = value:split(":")[2]
 | 
			
		||||
 | 
			
		||||
                    local tags = futil.get_hypertext_subtags(element.text, "action")
 | 
			
		||||
                    if tags[name] and tags[name]._href and tags[name]._href == "demo_page" then
 | 
			
		||||
                        --minetest.chat_send_all(tags[name]._href)
 | 
			
		||||
                        element.text = demo_page
 | 
			
		||||
                    elseif tags[name] and tags[name]._href and tags[name]._href == "default_page" then
 | 
			
		||||
                        element.text = default_page
 | 
			
		||||
                    end
 | 
			
		||||
 | 
			
		||||
                    return form
 | 
			
		||||
                end
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                type = "background",
 | 
			
		||||
                x = 0,
 | 
			
		||||
                y = 10,
 | 
			
		||||
                w = 10,
 | 
			
		||||
                h = 1,
 | 
			
		||||
                texture_name = "[combine:16x16^[noalpha"
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                type = "box",
 | 
			
		||||
                x = 0,
 | 
			
		||||
                y = 10,
 | 
			
		||||
                w = 10,
 | 
			
		||||
                h = 1,
 | 
			
		||||
                color = "#ffffff"
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                type = "field",
 | 
			
		||||
                x = 0,
 | 
			
		||||
                y = 10,
 | 
			
		||||
                w = 10,
 | 
			
		||||
                h = 1,
 | 
			
		||||
                name = "browser_url",
 | 
			
		||||
                close_on_enter = false,
 | 
			
		||||
                pwd = "",
 | 
			
		||||
                props = {
 | 
			
		||||
                    border = false,
 | 
			
		||||
                },
 | 
			
		||||
                on_event = function(form, player, element, value, fields)
 | 
			
		||||
                    local id = minetest.get_meta(pos):get("net_id")
 | 
			
		||||
                    if id then
 | 
			
		||||
                        local status, data = computers.networks.resolve_url(id, pos, value)
 | 
			
		||||
                        if status and data then
 | 
			
		||||
                            local cindex = futil.get_index_by_name(form, "browser_ctn")
 | 
			
		||||
                            local eindex = futil.get_index_by_name(form[cindex], "browser_content")
 | 
			
		||||
                            form[cindex][eindex].text = data
 | 
			
		||||
                        end
 | 
			
		||||
                    else
 | 
			
		||||
                        computers.api.chat_send_player(player, "[computers]: not attached to a network")
 | 
			
		||||
                    end
 | 
			
		||||
 | 
			
		||||
                    return form
 | 
			
		||||
                end,
 | 
			
		||||
            },
 | 
			
		||||
        },
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    futil.show_formspec(clicker, "computers:gui", formspec)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--legacy compat
 | 
			
		||||
computers.load_gui = computers.gui.load
 | 
			
		||||
 | 
			
		||||
--note you can create to many pages thuse overflowing the formspec, need to be fixed
 | 
			
		||||
function computers.gui.add_tab(player, tname, tab)
 | 
			
		||||
    local name = player
 | 
			
		||||
    if type(player) == "userdata" then name = player:get_player_name() end
 | 
			
		||||
 | 
			
		||||
    assert(tab, "[computers.sandbox]: new tab for " .. name .. " not found")
 | 
			
		||||
    assert(tab.type == "container", "[computers.sandbox]: invalid new tab format for " .. name)
 | 
			
		||||
    assert(tab.name:split("_")[2] == "ctn", "[computers.sandbox]: invalid tab name for " .. name)
 | 
			
		||||
    assert(tab.x == 0 and tab.y == 1, "[computers.sandbox]: invalid tab name for " .. name)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    local formspec = table.copy(computers.formspec.registered_kast[name])
 | 
			
		||||
    local fs = {}
 | 
			
		||||
    local btn
 | 
			
		||||
 | 
			
		||||
    for key, val in pairs(formspec) do
 | 
			
		||||
        if type(key) == "string" then
 | 
			
		||||
            fs[key] = val
 | 
			
		||||
        elseif type(val) == "table" then
 | 
			
		||||
            if val.name and #val.name:split("_") >= 2 and val.name:split("_")[2] == "btn" then
 | 
			
		||||
                btn = 1
 | 
			
		||||
            elseif btn and btn == 1 then
 | 
			
		||||
                table.insert(fs, {
 | 
			
		||||
                    type = "button",
 | 
			
		||||
                    x = #formspec.tabs*2,
 | 
			
		||||
                    y = 0,
 | 
			
		||||
                    w = 2,
 | 
			
		||||
                    h = 1,
 | 
			
		||||
                    name = tname:lower() .. "_btn",
 | 
			
		||||
                    label = tname,
 | 
			
		||||
                    on_event = function(form, _, element)
 | 
			
		||||
                        select_btn(form, tname:lower())
 | 
			
		||||
 | 
			
		||||
                        return form
 | 
			
		||||
                    end,
 | 
			
		||||
                    props = {
 | 
			
		||||
                        border = false,
 | 
			
		||||
                        bgimg = "kuto_button.png^[combine:16x16^[noalpha^[colorize:#ffffff70",
 | 
			
		||||
                        bgimg_hovered = "kuto_button.png^[combine:16x16^[noalpha^[colorize:#ffffff90",
 | 
			
		||||
                        bgimg_middle = "4,4",
 | 
			
		||||
                    }
 | 
			
		||||
                })
 | 
			
		||||
 | 
			
		||||
                btn = nil
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            table.insert(fs, val)
 | 
			
		||||
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    table.insert(fs, tab)
 | 
			
		||||
    table.insert(fs.tabs, tname:lower())
 | 
			
		||||
 | 
			
		||||
    return fs
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--[[ minetest.register_on_player_receive_fields(function(player, formname, fields)
 | 
			
		||||
    minetest.chat_send_all(dump(fields))
 | 
			
		||||
end) ]]
 | 
			
		||||
							
								
								
									
										7
									
								
								computers/core/init.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,7 @@
 | 
			
		||||
local path = computers.modpath .. "/core"
 | 
			
		||||
 | 
			
		||||
dofile(path .. "/api.lua")
 | 
			
		||||
dofile(path .. "/networks.lua")
 | 
			
		||||
dofile(path .. "/formspec.lua")
 | 
			
		||||
dofile(path .. "/commands.lua")
 | 
			
		||||
dofile(path .. "/gui.lua")
 | 
			
		||||
							
								
								
									
										152
									
								
								computers/core/networks.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,152 @@
 | 
			
		||||
local networks = {}
 | 
			
		||||
local network_lookup = {}
 | 
			
		||||
computers.networks = {}
 | 
			
		||||
 | 
			
		||||
local function init_networks()
 | 
			
		||||
    local path = computers.networkpath
 | 
			
		||||
    local files = minetest.get_dir_list(computers.networkpath, false)
 | 
			
		||||
    for _, file in pairs(files) do
 | 
			
		||||
        local id = file:sub(1,-6)
 | 
			
		||||
        local f = io.open(path .. "/" .. file)
 | 
			
		||||
        networks[id] = minetest.parse_json(f:read("*all"))
 | 
			
		||||
        f:close()
 | 
			
		||||
 | 
			
		||||
        if not network_lookup[networks[id].pname] then network_lookup[networks[id].pname] = {} end
 | 
			
		||||
        network_lookup[networks[id].pname][networks[id].net_name] = id
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
init_networks()
 | 
			
		||||
 | 
			
		||||
local function update_file(id)
 | 
			
		||||
    local data = networks[id]
 | 
			
		||||
    local path = computers.networkpath .. "/" .. id .. ".json"
 | 
			
		||||
    minetest.safe_file_write(path, minetest.write_json(data))
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function computers.networks.create(player, net_name)
 | 
			
		||||
    local pname = player
 | 
			
		||||
    if type(player) == "userdata" then pname = player:get_player_name() end
 | 
			
		||||
    local id = pname .. "_" .. minetest.get_us_time()
 | 
			
		||||
 | 
			
		||||
    if net_name:match("%W") then return false end --pnly accept alphanumerics
 | 
			
		||||
    if not network_lookup[pname] then network_lookup[pname] = {} end
 | 
			
		||||
    if network_lookup[pname][net_name] then return false end
 | 
			
		||||
    if networks[id] then return false end
 | 
			
		||||
 | 
			
		||||
    --create storage on disk
 | 
			
		||||
    local path = computers.networkpath .. "/" .. id .. ".json"
 | 
			
		||||
    local data = {
 | 
			
		||||
        pname = pname,
 | 
			
		||||
        net_name = net_name,
 | 
			
		||||
        devices = {},
 | 
			
		||||
        dns = {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    minetest.safe_file_write(path, minetest.write_json(data))
 | 
			
		||||
 | 
			
		||||
    --store data in memory
 | 
			
		||||
    networks[id] = data
 | 
			
		||||
    network_lookup[pname][net_name] = id
 | 
			
		||||
 | 
			
		||||
    return true, id
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function computers.networks.verify_network(id)
 | 
			
		||||
    if networks[id] then return true else return false end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function computers.networks.get_net_name(id)
 | 
			
		||||
    return networks[id].net_name
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function computers.networks.get_network_devices(id)
 | 
			
		||||
    return table.copy(networks[id].devices)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function computers.networks.get_network_dns(id)
 | 
			
		||||
    return table.copy(networks[id].dns)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function computers.networks.get_id_by_net_name(player, net_name)
 | 
			
		||||
    local pname = player
 | 
			
		||||
    if type(player) == "userdata" then pname = player:get_player_name() end
 | 
			
		||||
    if not network_lookup[pname] then network_lookup[pname] = {} end
 | 
			
		||||
    return network_lookup[pname][net_name]
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function computers.networks.get_networks_in_area(pos, rad)
 | 
			
		||||
    rad = rad or 10
 | 
			
		||||
    local locations = {}
 | 
			
		||||
    local keyed_locations = {}
 | 
			
		||||
    local meta_nodes = minetest.find_nodes_with_meta(
 | 
			
		||||
        vector.new(pos.x+rad, pos.y+rad, pos.z+rad),
 | 
			
		||||
        vector.new(pos.x-rad, pos.y-rad, pos.z-rad)
 | 
			
		||||
    )
 | 
			
		||||
    for _, location in pairs(meta_nodes) do
 | 
			
		||||
        local status = minetest.get_meta(location):get("net_id")
 | 
			
		||||
        if status and networks[status] then
 | 
			
		||||
            table.insert(locations, status)
 | 
			
		||||
            keyed_locations[status] = true
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    return locations, keyed_locations
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function computers.networks.get_net_names_in_area(pos, rad)
 | 
			
		||||
    rad = rad or 10
 | 
			
		||||
    local locations = {}
 | 
			
		||||
    local keyed_locations = {}
 | 
			
		||||
    local meta_nodes = minetest.find_nodes_with_meta(
 | 
			
		||||
        vector.new(pos.x+rad, pos.y+rad, pos.z+rad),
 | 
			
		||||
        vector.new(pos.x-rad, pos.y-rad, pos.z-rad)
 | 
			
		||||
    )
 | 
			
		||||
    for _, location in pairs(meta_nodes) do
 | 
			
		||||
        local status = minetest.get_meta(location):get("net_id")
 | 
			
		||||
        if status and networks[status] and not keyed_locations[networks[status].net_name] then
 | 
			
		||||
            table.insert(locations, networks[status].net_name)
 | 
			
		||||
            keyed_locations[networks[status].net_name] = true
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    return locations, keyed_locations
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function computers.networks.add_device(id, pos)
 | 
			
		||||
    if type(pos) ~= "table" or not networks[id] then return false end
 | 
			
		||||
    networks[id].devices[minetest.pos_to_string(pos)] = minetest.get_node(pos).name
 | 
			
		||||
    minetest.get_meta(pos):set_string("net_id", id)
 | 
			
		||||
    update_file(id)
 | 
			
		||||
    return true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function computers.networks.remove_device(id, pos)
 | 
			
		||||
    if type(pos) ~= "table" or not networks[id] then return false end
 | 
			
		||||
    networks[id].devices[minetest.pos_to_string(pos)] = nil
 | 
			
		||||
    minetest.get_meta(pos):set_string("net_id", "")
 | 
			
		||||
    update_file(id)
 | 
			
		||||
    return true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function computers.networks.set_dns(id, pos, url)
 | 
			
		||||
    if type(pos) ~= "table" or not networks[id] then return false end
 | 
			
		||||
    if url:match("%W") then return false end
 | 
			
		||||
    networks[id].dns = networks[id].dns or {}
 | 
			
		||||
    networks[id].dns[url] = minetest.hash_node_position(pos) .. "/public_pages"
 | 
			
		||||
 | 
			
		||||
    update_file(id)
 | 
			
		||||
    return true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function computers.networks.resolve_url(id, pos, url)
 | 
			
		||||
    if type(pos) ~= "table" or not networks[id] then return false end
 | 
			
		||||
    if networks[id].dns[url:split("/")[1]] then
 | 
			
		||||
        local path = computers.devicepath .. "/" .. networks[id].dns[url:split("/")[1]].."/index.page"
 | 
			
		||||
        local f = io.open(path)
 | 
			
		||||
        if not f then return false end
 | 
			
		||||
        local data = f:read("*all")
 | 
			
		||||
        f:close()
 | 
			
		||||
        if data then return true, data else return false end
 | 
			
		||||
    else
 | 
			
		||||
        return false
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										18
									
								
								computers/default_page.page
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,18 @@
 | 
			
		||||
<global margin=20>
 | 
			
		||||
<normal>ㅤ</normal>
 | 
			
		||||
<center><bigger>Welcome to ARPANET</bigger></center>
 | 
			
		||||
<big>How to use it</big>
 | 
			
		||||
<normal>on the bottom of this pane is field input which allows you to enter site urls</normal>
 | 
			
		||||
<normal>example: <mono><style color=blue>domain</style></mono></normal>
 | 
			
		||||
<normal>example: <mono><style color=blue>domain/demo_page.page</style></mono></normal>
 | 
			
		||||
<normal>ㅤ</normal>
 | 
			
		||||
 | 
			
		||||
<big>Try it out</big>
 | 
			
		||||
<action name=demo_link _href=demo_page>test url</action>
 | 
			
		||||
<normal>ㅤ</normal>
 | 
			
		||||
 | 
			
		||||
<big>How can I host my own sites?</big>
 | 
			
		||||
<normal>you will need to set up the server node</normal>
 | 
			
		||||
<normal>put your webfiles in there in hypertext format in the public_html folder</normal>
 | 
			
		||||
<normal>domainname/ and domainname/folder/ will connect to the indexpage file found in the DIR</normal>
 | 
			
		||||
<normal>ㅤ</normal>
 | 
			
		||||
							
								
								
									
										23
									
								
								computers/demo.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,23 @@
 | 
			
		||||
local old_node = minetest.registered_nodes["computers:shefriendSOO"]
 | 
			
		||||
old_node.groups.not_in_creative_inventory = 1
 | 
			
		||||
minetest.override_item("computers:shefriendSOO", {
 | 
			
		||||
    on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
 | 
			
		||||
        computers.load_gui(pos, node, clicker)
 | 
			
		||||
    end,
 | 
			
		||||
    groups = old_node.groups
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
old_node = minetest.registered_nodes["computers:shefriendSOO_off"]
 | 
			
		||||
old_node.groups.not_in_creative_inventory = nil
 | 
			
		||||
minetest.override_item("computers:shefriendSOO_off", {
 | 
			
		||||
    groups = old_node.groups
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
old_node = minetest.registered_nodes["computers:server_on"]
 | 
			
		||||
old_node.groups.computers_server = 1
 | 
			
		||||
minetest.override_item("computers:server_on", {
 | 
			
		||||
    on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
 | 
			
		||||
        computers.load_gui(pos, node, clicker)
 | 
			
		||||
    end,
 | 
			
		||||
    groups = old_node.groups
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										7
									
								
								computers/demo_page.page
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,7 @@
 | 
			
		||||
<global margin=20>
 | 
			
		||||
<normal>ㅤ</normal>
 | 
			
		||||
<center><bigger>Welcome to Demo Page</bigger></center>
 | 
			
		||||
<normal>ㅤ</normal>
 | 
			
		||||
 | 
			
		||||
<action name=default_link _href=default_page>go back</action>
 | 
			
		||||
<normal>ㅤ</normal>
 | 
			
		||||
@@ -1,354 +0,0 @@
 | 
			
		||||
local S = minetest.get_translator("computers")
 | 
			
		||||
 | 
			
		||||
-- Sony PlayStation lookalike
 | 
			
		||||
computers.register("computers:slaystation", {
 | 
			
		||||
	description = S("Pony SlayStation"),
 | 
			
		||||
	inventory_image = "computers_ps1_inv.png",
 | 
			
		||||
	tiles_off = { top=true },
 | 
			
		||||
	node_box = computers.pixelnodebox(32, {
 | 
			
		||||
		-- X   Y   Z   W   H   L
 | 
			
		||||
		{  0,  0, 11, 32,  6, 21 },   -- Console
 | 
			
		||||
		{  1,  0,  1,  4,  2,  9 },   -- Controller 1 L Grip
 | 
			
		||||
		{ 10,  0,  1,  4,  2,  9 },   -- Controller 1 R Grip
 | 
			
		||||
		{  5,  0,  4,  5,  2,  5 },   -- Controller 1 Center
 | 
			
		||||
		{ 18,  0,  1,  4,  2,  9 },   -- Controller 2 L Grip
 | 
			
		||||
		{ 27,  0,  1,  4,  2,  9 },   -- Controller 2 R Grip
 | 
			
		||||
		{ 22,  0,  4,  5,  2,  5 }   -- Controller 2 Center
 | 
			
		||||
	})
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
-- Sony PlayStation 2 lookalike
 | 
			
		||||
computers.register("computers:slaystation2", {
 | 
			
		||||
	description = S("Pony SlayStation 2"),
 | 
			
		||||
	inventory_image = "computers_ps2_inv.png",
 | 
			
		||||
	tiles_off = { front=true },
 | 
			
		||||
	node_box = computers.pixelnodebox(32, {
 | 
			
		||||
		-- X   Y   Z   W   H   L
 | 
			
		||||
		{  2,  2, 11, 28,  3, 19 },   -- Console (Upper part)
 | 
			
		||||
		{  2,  0, 11, 26,  2, 19 },   -- Console (Lower part)
 | 
			
		||||
		{  1,  0,  1,  4,  2,  9 },   -- Controller 1 L Grip
 | 
			
		||||
		{ 10,  0,  1,  4,  2,  9 },   -- Controller 1 R Grip
 | 
			
		||||
		{  5,  0,  1,  5,  2,  8 },   -- Controller 1 Center
 | 
			
		||||
		{ 18,  0,  1,  4,  2,  9 },   -- Controller 2 L Grip
 | 
			
		||||
		{ 27,  0,  1,  4,  2,  9 },   -- Controller 2 R Grip
 | 
			
		||||
		{ 22,  0,  1,  5,  2,  8 }   -- Controller 2 Center
 | 
			
		||||
	})
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
-- Nintendo Wii lookalike
 | 
			
		||||
computers.register("computers:wee", {
 | 
			
		||||
	description = S("Nientiendo Wee"),
 | 
			
		||||
	inventory_image = "computers_wii_inv.png",
 | 
			
		||||
	tiles_off = { front=true },
 | 
			
		||||
	node_box = computers.pixelnodebox(32, {
 | 
			
		||||
		-- X   Y   Z   W   H   L
 | 
			
		||||
		{ 11,  0,  3, 10,  6, 26 },   -- Base
 | 
			
		||||
		{ 12,  6,  4,  8, 22, 24 }   -- Top
 | 
			
		||||
	})
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
-- XBox lookalike
 | 
			
		||||
computers.register("computers:hueg_box", {
 | 
			
		||||
	description = S("HUEG Box"),
 | 
			
		||||
	tiles_off = { },
 | 
			
		||||
	node_box = computers.pixelnodebox(16, {
 | 
			
		||||
		-- X   Y   Z   W   H   L
 | 
			
		||||
		{  0,  0,  7, 16,  6, 9 },   -- Console
 | 
			
		||||
		{  2,  0,  1, 11,  3, 6 },   -- Controller
 | 
			
		||||
		{  2,  0,  0,  2,  3, 1 },
 | 
			
		||||
		{ 11,  0,  0,  2,  3, 1 },
 | 
			
		||||
	})
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
-- Tetris arcade machine
 | 
			
		||||
 | 
			
		||||
local shapes = {
 | 
			
		||||
   {  { x = {0, 1, 0, 1}, y = {0, 0, 1, 1} } },
 | 
			
		||||
 | 
			
		||||
   {  { x = {1, 1, 1, 1}, y = {0, 1, 2, 3} },
 | 
			
		||||
      { x = {0, 1, 2, 3}, y = {1, 1, 1, 1} } },
 | 
			
		||||
 | 
			
		||||
   {  { x = {0, 0, 1, 1}, y = {0, 1, 1, 2} },
 | 
			
		||||
      { x = {1, 2, 0, 1}, y = {0, 0, 1, 1} } },
 | 
			
		||||
 | 
			
		||||
   {  { x = {1, 0, 1, 0}, y = {0, 1, 1, 2} },
 | 
			
		||||
      { x = {0, 1, 1, 2}, y = {0, 0, 1, 1} } },
 | 
			
		||||
 | 
			
		||||
   {  { x = {1, 2, 1, 1}, y = {0, 0, 1, 2} },
 | 
			
		||||
      { x = {0, 1, 2, 2}, y = {1, 1, 1, 2} },
 | 
			
		||||
      { x = {1, 1, 0, 1}, y = {0, 1, 2, 2} },
 | 
			
		||||
      { x = {0, 0, 1, 2}, y = {0, 1, 1, 1} } },
 | 
			
		||||
 | 
			
		||||
   {  { x = {1, 1, 1, 2}, y = {0, 1, 2, 2} },
 | 
			
		||||
      { x = {0, 1, 2, 0}, y = {1, 1, 1, 2} },
 | 
			
		||||
      { x = {0, 1, 1, 1}, y = {0, 0, 1, 2} },
 | 
			
		||||
      { x = {0, 1, 2, 2}, y = {1, 1, 1, 0} } },
 | 
			
		||||
 | 
			
		||||
   {  { x = {1, 0, 1, 2}, y = {0, 1, 1, 1} },
 | 
			
		||||
      { x = {1, 1, 1, 2}, y = {0, 1, 2, 1} },
 | 
			
		||||
      { x = {0, 1, 2, 1}, y = {1, 1, 1, 2} },
 | 
			
		||||
      { x = {0, 1, 1, 1}, y = {1, 0, 1, 2} } } }
 | 
			
		||||
 | 
			
		||||
local colors = { "computers_cyan.png", "computers_magenta.png", "computers_red.png",
 | 
			
		||||
	"computers_blue.png", "computers_green.png", "computers_orange.png", "computers_yellow.png" }
 | 
			
		||||
 | 
			
		||||
local background = "image[0,0;3.55,6.66;computers_black.png]"
 | 
			
		||||
local buttons = "button[3,4.5;0.6,0.6;left;<]"
 | 
			
		||||
	.."button[3.6,4.5;0.6,0.6;rotateleft;"..minetest.formspec_escape(S("L")).."]"
 | 
			
		||||
	.."button[4.2,4.5;0.6,0.6;down;v]"
 | 
			
		||||
	.."button[4.2,5.3;0.6,0.6;drop;V]"
 | 
			
		||||
	.."button[4.8,4.5;0.6,0.6;rotateright;"..minetest.formspec_escape(S("R")).."]"
 | 
			
		||||
	.."button[5.4,4.5;0.6,0.6;right;>]"
 | 
			
		||||
	.."button[3.5,3;2,2;new;"..minetest.formspec_escape(S("New Game")).."]"
 | 
			
		||||
 | 
			
		||||
local formsize = "size[5.9,5.7]"
 | 
			
		||||
local boardx, boardy = 0, 0
 | 
			
		||||
local sizex, sizey, size = 0.29, 0.29, 0.31
 | 
			
		||||
 | 
			
		||||
local comma = ","
 | 
			
		||||
local semi = ";"
 | 
			
		||||
local close = "]"
 | 
			
		||||
 | 
			
		||||
local concat = table.concat
 | 
			
		||||
local insert = table.insert
 | 
			
		||||
 | 
			
		||||
local draw_shape = function(id, x, y, rot, posx, posy)
 | 
			
		||||
	local d = shapes[id][rot]
 | 
			
		||||
	local scr = {}
 | 
			
		||||
	local ins = #scr
 | 
			
		||||
 | 
			
		||||
	for i=1,4 do
 | 
			
		||||
		local tmp = { "image[",
 | 
			
		||||
			(d.x[i]+x)*sizex+posx, comma,
 | 
			
		||||
			(d.y[i]+y)*sizey+posy, semi,
 | 
			
		||||
			size, comma, size, semi,
 | 
			
		||||
			colors[id], close }
 | 
			
		||||
 | 
			
		||||
		ins = ins + 1
 | 
			
		||||
		scr[ins] = concat(tmp)
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	return concat(scr)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function step(pos, fields)
 | 
			
		||||
	local meta = minetest.get_meta(pos)
 | 
			
		||||
	local t = minetest.deserialize(meta:get_string("tetris"))
 | 
			
		||||
 | 
			
		||||
	local function new_game(p)
 | 
			
		||||
		local nex = math.random(7)
 | 
			
		||||
 | 
			
		||||
		t = {
 | 
			
		||||
			board = {},
 | 
			
		||||
			boardstring = "",
 | 
			
		||||
			previewstring = draw_shape(nex, 0, 0, 1, 4, 1),
 | 
			
		||||
			score = 0,
 | 
			
		||||
			cur = math.random(7),
 | 
			
		||||
			nex = nex,
 | 
			
		||||
			x=4, y=0, rot=1
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		local timer = minetest.get_node_timer(p)
 | 
			
		||||
		timer:set(0.3, 0)
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	local function update_boardstring()
 | 
			
		||||
		local scr = {}
 | 
			
		||||
		local ins = #scr
 | 
			
		||||
 | 
			
		||||
		for i, line in pairs(t.board) do
 | 
			
		||||
			for _, tile in pairs(line) do
 | 
			
		||||
				local tmp = { "image[",
 | 
			
		||||
					tile[1]*sizex+boardx, comma,
 | 
			
		||||
					i*sizey+boardy, semi,
 | 
			
		||||
					size, comma, size, semi,
 | 
			
		||||
					colors[tile[2]], close }
 | 
			
		||||
 | 
			
		||||
				ins = ins + 1
 | 
			
		||||
				scr[ins] = concat(tmp)
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		t.boardstring = concat(scr)
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	local function add()
 | 
			
		||||
		local d = shapes[t.cur][t.rot]
 | 
			
		||||
 | 
			
		||||
		for i=1,4 do
 | 
			
		||||
			local l = d.y[i] + t.y
 | 
			
		||||
			if not t.board[l] then t.board[l] = {} end
 | 
			
		||||
			insert(t.board[l], {d.x[i] + t.x, t.cur})
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	local function scroll(l)
 | 
			
		||||
		for i=l, 1, -1 do
 | 
			
		||||
			t.board[i] = t.board[i-1] or {}
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	local function check_lines()
 | 
			
		||||
		for i, line in pairs(t.board) do
 | 
			
		||||
			if #line >= 10 then
 | 
			
		||||
				scroll(i)
 | 
			
		||||
				t.score = t.score + 20
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	local function check_position(x, y, rot)
 | 
			
		||||
		local d = shapes[t.cur][rot]
 | 
			
		||||
 | 
			
		||||
		for i=1,4 do
 | 
			
		||||
			local cx, cy = d.x[i]+x, d.y[i]+y
 | 
			
		||||
 | 
			
		||||
			if cx < 0 or cx > 9 or cy < 0 or cy > 19 then
 | 
			
		||||
				return false
 | 
			
		||||
			end
 | 
			
		||||
 | 
			
		||||
			for _, tile in pairs(t.board[ cy ] or {}) do
 | 
			
		||||
				if tile[1] == cx then return false end
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		return true
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	local function stuck()
 | 
			
		||||
		if check_position(t.x, t.y+1, t.rot) then return false end
 | 
			
		||||
		return true
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	local function tick()
 | 
			
		||||
		if stuck() then
 | 
			
		||||
			if t.y <= 0 then
 | 
			
		||||
				return false end
 | 
			
		||||
			add()
 | 
			
		||||
			check_lines()
 | 
			
		||||
			update_boardstring()
 | 
			
		||||
			t.cur, t.nex = t.nex, math.random(7)
 | 
			
		||||
			t.x, t.y, t.rot = 4, 0, 1
 | 
			
		||||
			t.previewstring = draw_shape(t.nex, 0, 0, 1, 4.1, 0.6)
 | 
			
		||||
		else
 | 
			
		||||
			t.y = t.y + 1
 | 
			
		||||
		end
 | 
			
		||||
		return true
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	local function move(dx, dy)
 | 
			
		||||
		local newx, newy = t.x+dx, t.y+dy
 | 
			
		||||
		if not check_position(newx, newy, t.rot) then return end
 | 
			
		||||
		t.x, t.y = newx, newy
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	local function rotate(dr)
 | 
			
		||||
		local no = #(shapes[t.cur])
 | 
			
		||||
		local newrot = (t.rot+dr) % no
 | 
			
		||||
 | 
			
		||||
		if newrot<1 then newrot = newrot+no end
 | 
			
		||||
		if not check_position(t.x, t.y, newrot) then return end
 | 
			
		||||
		t.rot = newrot
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	local function key()
 | 
			
		||||
		if fields.left then
 | 
			
		||||
			move(-1, 0)
 | 
			
		||||
		end
 | 
			
		||||
		if fields.rotateleft then
 | 
			
		||||
			rotate(-1)
 | 
			
		||||
		end
 | 
			
		||||
		if fields.down then
 | 
			
		||||
			t.score = t.score + 1
 | 
			
		||||
			move(0, 1)
 | 
			
		||||
		end
 | 
			
		||||
		if fields.drop then
 | 
			
		||||
		   while not stuck() do
 | 
			
		||||
			  t.score = t.score + 2
 | 
			
		||||
		      move(0, 1)
 | 
			
		||||
		   end
 | 
			
		||||
		end
 | 
			
		||||
		if fields.rotateright then
 | 
			
		||||
			rotate(1)
 | 
			
		||||
		end
 | 
			
		||||
		if fields.right then
 | 
			
		||||
			move(1, 0)
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	local run = true
 | 
			
		||||
 | 
			
		||||
	if fields then
 | 
			
		||||
		if fields.new then
 | 
			
		||||
			new_game(pos)
 | 
			
		||||
		elseif t then
 | 
			
		||||
			key(fields)
 | 
			
		||||
		end
 | 
			
		||||
	elseif t then
 | 
			
		||||
		run = tick()
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	if t then
 | 
			
		||||
	local scr = { formsize, background,
 | 
			
		||||
		t.boardstring, t.previewstring,
 | 
			
		||||
		draw_shape(t.cur, t.x, t.y, t.rot, boardx, boardy),
 | 
			
		||||
		"label[3.8,0.1;"..S("Next...").."]label[3.8,2.7;"..S("Score: "),
 | 
			
		||||
		t.score, close, buttons }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		meta:set_string("formspec", concat(scr)
 | 
			
		||||
			..default.gui_bg..default.gui_bg_img..default.gui_slots)
 | 
			
		||||
		meta:set_string("tetris", minetest.serialize(t))
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	return run
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
minetest.register_node("computers:tetris_arcade", {
 | 
			
		||||
	description=S("Tetris Arcade"),
 | 
			
		||||
	drawtype = "mesh",
 | 
			
		||||
	mesh = "computers_tetris_arcade.obj",
 | 
			
		||||
	tiles = {"computers_tetris_arcade.png"},
 | 
			
		||||
	paramtype = "light",
 | 
			
		||||
	paramtype2 = "facedir",
 | 
			
		||||
	groups = {snappy=3},
 | 
			
		||||
	on_rotate = minetest.get_modpath("screwdriver") and screwdriver.rotate_simple or nil,
 | 
			
		||||
	selection_box = {
 | 
			
		||||
		type = "fixed",
 | 
			
		||||
		fixed = {-0.5, -0.5, -0.5, 0.5, 1.5, 0.5}
 | 
			
		||||
	},
 | 
			
		||||
	collision_box = {
 | 
			
		||||
		type = "fixed",
 | 
			
		||||
		fixed = {-0.5, -0.5, -0.5, 0.5, 1.5, 0.5}
 | 
			
		||||
	},
 | 
			
		||||
	on_construct = function(pos)
 | 
			
		||||
		local meta = minetest.get_meta(pos)
 | 
			
		||||
		meta:set_string("formspec", formsize
 | 
			
		||||
			.."button[2,2.5;2,2;new;"..minetest.formspec_escape(S("New Game")).."]"
 | 
			
		||||
			..default.gui_bg..default.gui_bg_img..default.gui_slots)
 | 
			
		||||
	end,
 | 
			
		||||
	on_timer = function(pos)
 | 
			
		||||
		return step(pos, nil)
 | 
			
		||||
	end,
 | 
			
		||||
	on_receive_fields = function(pos, formanme, fields, sender)
 | 
			
		||||
		step(pos, fields)
 | 
			
		||||
	end,
 | 
			
		||||
	on_place = function(itemstack, placer, pointed_thing)
 | 
			
		||||
		local pos = pointed_thing.above
 | 
			
		||||
		if minetest.is_protected(pos, placer:get_player_name()) or
 | 
			
		||||
			minetest.is_protected({x=pos.x, y=pos.y+1, z=pos.z}, placer:get_player_name()) then
 | 
			
		||||
			return itemstack
 | 
			
		||||
		end
 | 
			
		||||
		if minetest.get_node({x=pos.x, y=pos.y+1, z=pos.z}).name ~= "air" then
 | 
			
		||||
			minetest.chat_send_player(placer:get_player_name(), S("No room for place the Arcade!"))
 | 
			
		||||
			return itemstack
 | 
			
		||||
		end
 | 
			
		||||
		local dir = placer:get_look_dir()
 | 
			
		||||
		local node = {name="computers:tetris_arcade", param1=0, param2 = minetest.dir_to_facedir(dir)}
 | 
			
		||||
		minetest.set_node(pos, node)
 | 
			
		||||
		itemstack:take_item()
 | 
			
		||||
		return itemstack
 | 
			
		||||
	end
 | 
			
		||||
})
 | 
			
		||||
@@ -1,98 +1,20 @@
 | 
			
		||||
computers = {}
 | 
			
		||||
computers.modpath = minetest.get_modpath("computers")
 | 
			
		||||
computers.storagepath = minetest.get_worldpath() .. "/computers"
 | 
			
		||||
computers.devicepath = computers.storagepath .. "/devices"
 | 
			
		||||
computers.networkpath = computers.storagepath .. "/networks"
 | 
			
		||||
minetest.mkdir(computers.storagepath) --make sure it exists
 | 
			
		||||
minetest.mkdir(computers.devicepath) --make sure it exists
 | 
			
		||||
minetest.mkdir(computers.networkpath) --make sure it exists
 | 
			
		||||
 | 
			
		||||
computers.register = function (name, def)
 | 
			
		||||
	if (name:sub(1, 1) == ":") then name = name:sub(2) end
 | 
			
		||||
	local modname, basename = name:match("^([^:]+):(.*)")
 | 
			
		||||
	local TEXPFX = modname.."_"..basename.."_"
 | 
			
		||||
	local ONSTATE = modname..":"..basename
 | 
			
		||||
	local OFFSTATE = modname..":"..basename.."_off"
 | 
			
		||||
	local cdef = table.copy(def)
 | 
			
		||||
	minetest.register_node(ONSTATE, {
 | 
			
		||||
		drawtype = "nodebox",
 | 
			
		||||
		paramtype = "light",
 | 
			
		||||
		paramtype2 = "facedir",
 | 
			
		||||
		description = cdef.description,
 | 
			
		||||
		inventory_image = cdef.inventory_image,
 | 
			
		||||
		groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2},
 | 
			
		||||
		tiles = {
 | 
			
		||||
			TEXPFX.."tp.png",
 | 
			
		||||
			TEXPFX.."bt.png",
 | 
			
		||||
			TEXPFX.."rt.png",
 | 
			
		||||
			TEXPFX.."lt.png",
 | 
			
		||||
			TEXPFX.."bk.png",
 | 
			
		||||
			TEXPFX.."ft.png"
 | 
			
		||||
		},
 | 
			
		||||
		node_box = cdef.node_box,
 | 
			
		||||
		selection_box = cdef.node_box,
 | 
			
		||||
		on_rightclick = function (pos, node, clicker, itemstack)
 | 
			
		||||
			if cdef.on_turn_off and cdef.on_turn_off(pos, node, clicker, itemstack) then
 | 
			
		||||
				return itemstack
 | 
			
		||||
			end
 | 
			
		||||
			node.name = OFFSTATE
 | 
			
		||||
			minetest.set_node(pos, node)
 | 
			
		||||
			return itemstack
 | 
			
		||||
		end
 | 
			
		||||
	})
 | 
			
		||||
	minetest.register_node(OFFSTATE, {
 | 
			
		||||
		drawtype = "nodebox",
 | 
			
		||||
		paramtype = "light",
 | 
			
		||||
		paramtype2 = "facedir",
 | 
			
		||||
		groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2, not_in_creative_inventory=1},
 | 
			
		||||
		tiles = {
 | 
			
		||||
			(TEXPFX.."tp"..(cdef.tiles_off.top    and "_off" or "")..".png"),
 | 
			
		||||
			(TEXPFX.."bt"..(cdef.tiles_off.bottom and "_off" or "")..".png"),
 | 
			
		||||
			(TEXPFX.."rt"..(cdef.tiles_off.right  and "_off" or "")..".png"),
 | 
			
		||||
			(TEXPFX.."lt"..(cdef.tiles_off.left   and "_off" or "")..".png"),
 | 
			
		||||
			(TEXPFX.."bk"..(cdef.tiles_off.back   and "_off" or "")..".png"),
 | 
			
		||||
			(TEXPFX.."ft"..(cdef.tiles_off.front  and "_off" or "")..".png")
 | 
			
		||||
		},
 | 
			
		||||
		node_box = cdef.node_box_off or cdef.node_box,
 | 
			
		||||
		selection_box = cdef.node_box_off or cdef.node_box,
 | 
			
		||||
		on_rightclick = function (pos, node, clicker, itemstack)
 | 
			
		||||
			if cdef.on_turn_on and cdef.on_turn_on(pos, node, clicker, itemstack) then
 | 
			
		||||
				return itemstack
 | 
			
		||||
			end
 | 
			
		||||
			node.name = ONSTATE
 | 
			
		||||
			minetest.set_node(pos, node)
 | 
			
		||||
			return itemstack
 | 
			
		||||
		end,
 | 
			
		||||
		drop = ONSTATE
 | 
			
		||||
	})
 | 
			
		||||
end
 | 
			
		||||
computers.os = {
 | 
			
		||||
    version = 0.44,
 | 
			
		||||
    name = "kuto",
 | 
			
		||||
    authors = {"wsor", "luk3yx"},
 | 
			
		||||
    license = "MIT",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
computers.register_handheld = function (name, def)
 | 
			
		||||
	if (name:sub(1, 1) == ":") then name = name:sub(2) end
 | 
			
		||||
	local modname, basename = name:match("^([^:]+):(.*)")
 | 
			
		||||
	local TEXPFX = modname.."_"..basename.."_inv"
 | 
			
		||||
	local ONSTATE = modname..":"..basename
 | 
			
		||||
	minetest.register_craftitem(ONSTATE, {
 | 
			
		||||
		description = def.description,
 | 
			
		||||
		inventory_image = TEXPFX..".png",
 | 
			
		||||
		wield_image = TEXPFX..".png"
 | 
			
		||||
	})
 | 
			
		||||
end
 | 
			
		||||
dofile(computers.modpath .. "/core/init.lua")
 | 
			
		||||
dofile(computers.modpath .. "/nodes/init.lua")
 | 
			
		||||
 | 
			
		||||
computers.pixelnodebox = function (size, boxes)
 | 
			
		||||
	local fixed = { }
 | 
			
		||||
	for _, box in ipairs(boxes) do
 | 
			
		||||
		local x, y, z, w, h, l = unpack(box)
 | 
			
		||||
		fixed[#fixed + 1] = {
 | 
			
		||||
			(x / size) - 0.5,
 | 
			
		||||
			(y / size) - 0.5,
 | 
			
		||||
			(z / size) - 0.5,
 | 
			
		||||
			((x + w) / size) - 0.5,
 | 
			
		||||
			((y + h) / size) - 0.5,
 | 
			
		||||
			((z + l) / size) - 0.5
 | 
			
		||||
		}
 | 
			
		||||
	end
 | 
			
		||||
	return {
 | 
			
		||||
		type = "fixed",
 | 
			
		||||
		fixed = fixed
 | 
			
		||||
	}
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local MODPATH = minetest.get_modpath("computers")
 | 
			
		||||
dofile(MODPATH.."/computers.lua")
 | 
			
		||||
dofile(MODPATH.."/recipes.lua")
 | 
			
		||||
dofile(MODPATH.."/gaming.lua")
 | 
			
		||||
dofile(MODPATH.."/aliases.lua")
 | 
			
		||||
dofile(computers.modpath .. "/demo.lua")
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,3 @@
 | 
			
		||||
name = computers
 | 
			
		||||
depends = default, basic_materials
 | 
			
		||||
optional_depends = screwdriver
 | 
			
		||||
depends = formspec_ast
 | 
			
		||||
optional_depends = screwdriver, default, basic_materials
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								computers/nodes/init.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,11 @@
 | 
			
		||||
local path = computers.modpath .. "/nodes"
 | 
			
		||||
 | 
			
		||||
dofile(path .. "/node_api.lua")
 | 
			
		||||
dofile(path .. "/nodes.lua")
 | 
			
		||||
dofile(path .. "/router.lua")
 | 
			
		||||
dofile(path .. "/tetris.lua")
 | 
			
		||||
dofile(path .. "/aliases.lua")
 | 
			
		||||
 | 
			
		||||
if minetest.get_modpath("default") and minetest.get_modpath("basic_materials") then
 | 
			
		||||
	dofile(path .. "/recipes.lua")
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										78
									
								
								computers/nodes/node_api.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,78 @@
 | 
			
		||||
computers.register = function (name, def)
 | 
			
		||||
	if (name:sub(1, 1) == ":") then name = name:sub(2) end
 | 
			
		||||
	local modname, basename = name:match("^([^:]+):(.*)")
 | 
			
		||||
	local TEXPFX = modname.."_"..basename.."_"
 | 
			
		||||
	local ONSTATE = modname..":"..basename
 | 
			
		||||
	local OFFSTATE = modname..":"..basename.."_off"
 | 
			
		||||
	local cdef = table.copy(def)
 | 
			
		||||
	minetest.register_node(ONSTATE, {
 | 
			
		||||
		drawtype = "nodebox",
 | 
			
		||||
		paramtype = "light",
 | 
			
		||||
		paramtype2 = "facedir",
 | 
			
		||||
		description = cdef.description,
 | 
			
		||||
		inventory_image = cdef.inventory_image,
 | 
			
		||||
		groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2},
 | 
			
		||||
		tiles = {
 | 
			
		||||
			TEXPFX.."tp.png",
 | 
			
		||||
			TEXPFX.."bt.png",
 | 
			
		||||
			TEXPFX.."rt.png",
 | 
			
		||||
			TEXPFX.."lt.png",
 | 
			
		||||
			TEXPFX.."bk.png",
 | 
			
		||||
			TEXPFX.."ft.png"
 | 
			
		||||
		},
 | 
			
		||||
		node_box = cdef.node_box,
 | 
			
		||||
		selection_box = cdef.node_box,
 | 
			
		||||
		on_rightclick = function (pos, node, clicker, itemstack)
 | 
			
		||||
			if cdef.on_turn_off and cdef.on_turn_off(pos, node, clicker, itemstack) then
 | 
			
		||||
				return itemstack
 | 
			
		||||
			end
 | 
			
		||||
			node.name = OFFSTATE
 | 
			
		||||
			minetest.set_node(pos, node)
 | 
			
		||||
			return itemstack
 | 
			
		||||
		end
 | 
			
		||||
	})
 | 
			
		||||
	minetest.register_node(OFFSTATE, {
 | 
			
		||||
		drawtype = "nodebox",
 | 
			
		||||
		paramtype = "light",
 | 
			
		||||
		paramtype2 = "facedir",
 | 
			
		||||
		groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2, not_in_creative_inventory=1},
 | 
			
		||||
		tiles = {
 | 
			
		||||
			(TEXPFX.."tp"..(cdef.tiles_off.top    and "_off" or "")..".png"),
 | 
			
		||||
			(TEXPFX.."bt"..(cdef.tiles_off.bottom and "_off" or "")..".png"),
 | 
			
		||||
			(TEXPFX.."rt"..(cdef.tiles_off.right  and "_off" or "")..".png"),
 | 
			
		||||
			(TEXPFX.."lt"..(cdef.tiles_off.left   and "_off" or "")..".png"),
 | 
			
		||||
			(TEXPFX.."bk"..(cdef.tiles_off.back   and "_off" or "")..".png"),
 | 
			
		||||
			(TEXPFX.."ft"..(cdef.tiles_off.front  and "_off" or "")..".png")
 | 
			
		||||
		},
 | 
			
		||||
		node_box = cdef.node_box_off or cdef.node_box,
 | 
			
		||||
		selection_box = cdef.node_box_off or cdef.node_box,
 | 
			
		||||
		on_rightclick = function (pos, node, clicker, itemstack)
 | 
			
		||||
			if cdef.on_turn_on and cdef.on_turn_on(pos, node, clicker, itemstack) then
 | 
			
		||||
				return itemstack
 | 
			
		||||
			end
 | 
			
		||||
			node.name = ONSTATE
 | 
			
		||||
			minetest.set_node(pos, node)
 | 
			
		||||
			return itemstack
 | 
			
		||||
		end,
 | 
			
		||||
		drop = ONSTATE
 | 
			
		||||
	})
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
computers.pixelnodebox = function (size, boxes)
 | 
			
		||||
	local fixed = { }
 | 
			
		||||
	for _, box in ipairs(boxes) do
 | 
			
		||||
		local x, y, z, w, h, l = unpack(box)
 | 
			
		||||
		fixed[#fixed + 1] = {
 | 
			
		||||
			(x / size) - 0.5,
 | 
			
		||||
			(y / size) - 0.5,
 | 
			
		||||
			(z / size) - 0.5,
 | 
			
		||||
			((x + w) / size) - 0.5,
 | 
			
		||||
			((y + h) / size) - 0.5,
 | 
			
		||||
			((z + l) / size) - 0.5
 | 
			
		||||
		}
 | 
			
		||||
	end
 | 
			
		||||
	return {
 | 
			
		||||
		type = "fixed",
 | 
			
		||||
		fixed = fixed
 | 
			
		||||
	}
 | 
			
		||||
end
 | 
			
		||||
@@ -80,7 +80,7 @@ minetest.register_node("computers:piepad", {
 | 
			
		||||
	walkable = false,
 | 
			
		||||
	groups = {oddly_breakable_by_hand=2},
 | 
			
		||||
	selection_box = {type = "wallmounted"},
 | 
			
		||||
	sounds = default.node_sound_wood_defaults()
 | 
			
		||||
	sounds = default and default.node_sound_wood_defaults() or nil
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
-- Commodore 64 lookalike
 | 
			
		||||
@@ -116,7 +116,9 @@ minetest.register_node("computers:monitor", {
 | 
			
		||||
	inventory_image = "computers_monitor_inv.png",
 | 
			
		||||
	drawtype = "mesh",
 | 
			
		||||
	mesh = "computers_monitor.obj",
 | 
			
		||||
	tiles = {"computers_black.png", "computers_monitor_plastic.png", "computers_black.png", "computers_monitor_plastic.png"},
 | 
			
		||||
	tiles = {
 | 
			
		||||
		"computers_black.png", "computers_monitor_plastic.png", "computers_black.png", "computers_monitor_plastic.png"
 | 
			
		||||
	},
 | 
			
		||||
	paramtype = "light",
 | 
			
		||||
	paramtype2 = "facedir",
 | 
			
		||||
	walkable = false,
 | 
			
		||||
@@ -132,7 +134,12 @@ minetest.register_node("computers:monitor", {
 | 
			
		||||
minetest.register_node("computers:monitor_on", {
 | 
			
		||||
	drawtype = "mesh",
 | 
			
		||||
	mesh = "computers_monitor.obj",
 | 
			
		||||
	tiles = {"computers_monitor_display.png^[transformFX", "computers_monitor_plastic.png", "computers_black.png", "computers_monitor_plastic.png"},
 | 
			
		||||
	tiles = {
 | 
			
		||||
		"computers_monitor_display.png^[transformFX",
 | 
			
		||||
		"computers_monitor_plastic.png",
 | 
			
		||||
		"computers_black.png",
 | 
			
		||||
		"computers_monitor_plastic.png"
 | 
			
		||||
	},
 | 
			
		||||
	paramtype = "light",
 | 
			
		||||
	paramtype2 = "facedir",
 | 
			
		||||
	light_source = 9,
 | 
			
		||||
@@ -147,38 +154,6 @@ minetest.register_node("computers:monitor_on", {
 | 
			
		||||
	end
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
--WIFI Router (linksys look-a-like)
 | 
			
		||||
minetest.register_node("computers:router", {
 | 
			
		||||
	description = S("WIFI Router"),
 | 
			
		||||
	inventory_image = "computers_router_inv.png",
 | 
			
		||||
	tiles = {
 | 
			
		||||
		"computers_router_t.png",
 | 
			
		||||
		"computers_router_bt.png",
 | 
			
		||||
		"computers_router_l.png",
 | 
			
		||||
		"computers_router_r.png",
 | 
			
		||||
		"computers_router_b.png",
 | 
			
		||||
		{
 | 
			
		||||
			name = "computers_router_f_animated.png",
 | 
			
		||||
			animation = {type="vertical_frames", aspect_w=32, aspect_h=32, length=1.0}
 | 
			
		||||
		},
 | 
			
		||||
	}, --"computers_router_f.png"},
 | 
			
		||||
	paramtype = "light",
 | 
			
		||||
	paramtype2 = "facedir",
 | 
			
		||||
	walkable = false,
 | 
			
		||||
	groups = {snappy=3},
 | 
			
		||||
	sound = default.node_sound_wood_defaults(),
 | 
			
		||||
	drawtype = "nodebox",
 | 
			
		||||
	node_box = {
 | 
			
		||||
		type = "fixed",
 | 
			
		||||
		fixed = {
 | 
			
		||||
			{-0.25, -0.5, -0.0625, 0.25, -0.375, 0.3125},
 | 
			
		||||
			{-0.1875, -0.4375, 0.3125, -0.125, -0.1875, 0.375},
 | 
			
		||||
			{0.125, -0.4375, 0.3125, 0.1875, -0.1875, 0.375},
 | 
			
		||||
			{-0.0625, -0.4375, 0.3125, 0.0625, -0.25, 0.375}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
local pct_cbox = {
 | 
			
		||||
	type = "fixed",
 | 
			
		||||
	fixed = { -0.1875, -0.5, -0.36, 0.1875, 0.34, 0.46 }
 | 
			
		||||
@@ -194,7 +169,7 @@ minetest.register_node("computers:tower", {
 | 
			
		||||
	paramtype = "light",
 | 
			
		||||
	paramtype2 = "facedir",
 | 
			
		||||
	groups = {snappy=3},
 | 
			
		||||
	sound = default.node_sound_wood_defaults(),
 | 
			
		||||
	sound = default and default.node_sound_wood_defaults() or nil,
 | 
			
		||||
	selection_box = pct_cbox,
 | 
			
		||||
	collision_box = pct_cbox
 | 
			
		||||
})
 | 
			
		||||
@@ -223,7 +198,7 @@ minetest.register_node("computers:server", {
 | 
			
		||||
		type = "fixed",
 | 
			
		||||
		fixed = {-0.5, -0.5, -0.25, 0.5, 1.125, 0.4375}
 | 
			
		||||
	},
 | 
			
		||||
	sounds = default.node_sound_wood_defaults(),
 | 
			
		||||
	sounds = default and default.node_sound_wood_defaults() or nil,
 | 
			
		||||
	on_rightclick = function(pos, node, clicker, itemstack)
 | 
			
		||||
		node.name = "computers:server_on"
 | 
			
		||||
		minetest.set_node(pos, node)
 | 
			
		||||
@@ -262,7 +237,7 @@ minetest.register_node("computers:server_on", {
 | 
			
		||||
		type = "fixed",
 | 
			
		||||
		fixed = {-0.5, -0.5, -0.25, 0.5, 1.125, 0.4375}
 | 
			
		||||
	},
 | 
			
		||||
	sounds = default.node_sound_wood_defaults(),
 | 
			
		||||
	sounds = default and default.node_sound_wood_defaults() or nil,
 | 
			
		||||
	drop = 'computers:server',
 | 
			
		||||
	on_rightclick = function(pos, node, clicker, itemstack)
 | 
			
		||||
		node.name = "computers:server"
 | 
			
		||||
@@ -282,7 +257,7 @@ minetest.register_node("computers:printer", {
 | 
			
		||||
	paramtype2 = "facedir",
 | 
			
		||||
	walkable = true,
 | 
			
		||||
	groups = {snappy=3},
 | 
			
		||||
	sound = default.node_sound_wood_defaults(),
 | 
			
		||||
	sound = default and default.node_sound_wood_defaults() or nil,
 | 
			
		||||
	drawtype = "nodebox",
 | 
			
		||||
	node_box = {
 | 
			
		||||
		type = "fixed",
 | 
			
		||||
@@ -298,3 +273,63 @@ minetest.register_node("computers:printer", {
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
-- Sony PlayStation lookalike
 | 
			
		||||
computers.register("computers:slaystation", {
 | 
			
		||||
	description = S("Pony SlayStation"),
 | 
			
		||||
	inventory_image = "computers_ps1_inv.png",
 | 
			
		||||
	tiles_off = { top=true },
 | 
			
		||||
	node_box = computers.pixelnodebox(32, {
 | 
			
		||||
		-- X   Y   Z   W   H   L
 | 
			
		||||
		{  0,  0, 11, 32,  6, 21 },   -- Console
 | 
			
		||||
		{  1,  0,  1,  4,  2,  9 },   -- Controller 1 L Grip
 | 
			
		||||
		{ 10,  0,  1,  4,  2,  9 },   -- Controller 1 R Grip
 | 
			
		||||
		{  5,  0,  4,  5,  2,  5 },   -- Controller 1 Center
 | 
			
		||||
		{ 18,  0,  1,  4,  2,  9 },   -- Controller 2 L Grip
 | 
			
		||||
		{ 27,  0,  1,  4,  2,  9 },   -- Controller 2 R Grip
 | 
			
		||||
		{ 22,  0,  4,  5,  2,  5 }   -- Controller 2 Center
 | 
			
		||||
	})
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
-- Sony PlayStation 2 lookalike
 | 
			
		||||
computers.register("computers:slaystation2", {
 | 
			
		||||
	description = S("Pony SlayStation 2"),
 | 
			
		||||
	inventory_image = "computers_ps2_inv.png",
 | 
			
		||||
	tiles_off = { front=true },
 | 
			
		||||
	node_box = computers.pixelnodebox(32, {
 | 
			
		||||
		-- X   Y   Z   W   H   L
 | 
			
		||||
		{  2,  2, 11, 28,  3, 19 },   -- Console (Upper part)
 | 
			
		||||
		{  2,  0, 11, 26,  2, 19 },   -- Console (Lower part)
 | 
			
		||||
		{  1,  0,  1,  4,  2,  9 },   -- Controller 1 L Grip
 | 
			
		||||
		{ 10,  0,  1,  4,  2,  9 },   -- Controller 1 R Grip
 | 
			
		||||
		{  5,  0,  1,  5,  2,  8 },   -- Controller 1 Center
 | 
			
		||||
		{ 18,  0,  1,  4,  2,  9 },   -- Controller 2 L Grip
 | 
			
		||||
		{ 27,  0,  1,  4,  2,  9 },   -- Controller 2 R Grip
 | 
			
		||||
		{ 22,  0,  1,  5,  2,  8 }   -- Controller 2 Center
 | 
			
		||||
	})
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
-- Nintendo Wii lookalike
 | 
			
		||||
computers.register("computers:wee", {
 | 
			
		||||
	description = S("Nientiendo Wee"),
 | 
			
		||||
	inventory_image = "computers_wii_inv.png",
 | 
			
		||||
	tiles_off = { front=true },
 | 
			
		||||
	node_box = computers.pixelnodebox(32, {
 | 
			
		||||
		-- X   Y   Z   W   H   L
 | 
			
		||||
		{ 11,  0,  3, 10,  6, 26 },   -- Base
 | 
			
		||||
		{ 12,  6,  4,  8, 22, 24 }   -- Top
 | 
			
		||||
	})
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
-- XBox lookalike
 | 
			
		||||
computers.register("computers:hueg_box", {
 | 
			
		||||
	description = S("HUEG Box"),
 | 
			
		||||
	tiles_off = { },
 | 
			
		||||
	node_box = computers.pixelnodebox(16, {
 | 
			
		||||
		-- X   Y   Z   W   H   L
 | 
			
		||||
		{  0,  0,  7, 16,  6, 9 },   -- Console
 | 
			
		||||
		{  2,  0,  1, 11,  3, 6 },   -- Controller
 | 
			
		||||
		{  2,  0,  0,  2,  3, 1 },
 | 
			
		||||
		{ 11,  0,  0,  2,  3, 1 },
 | 
			
		||||
	})
 | 
			
		||||
})
 | 
			
		||||
@@ -1,5 +1,3 @@
 | 
			
		||||
-- Copyright (C) 2012-2013 Diego Martínez <kaeza@users.sf.net>
 | 
			
		||||
 | 
			
		||||
minetest.register_craft({
 | 
			
		||||
	output = "computers:shefriendSOO",
 | 
			
		||||
	recipe = {
 | 
			
		||||
							
								
								
									
										227
									
								
								computers/nodes/router.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,227 @@
 | 
			
		||||
local S = minetest.get_translator("computers")
 | 
			
		||||
 | 
			
		||||
minetest.register_node("computers:router", {
 | 
			
		||||
	description = S("WIFI Router"),
 | 
			
		||||
	inventory_image = "computers_router_inv.png",
 | 
			
		||||
	tiles = {
 | 
			
		||||
		"computers_router_t.png",
 | 
			
		||||
		"computers_router_bt.png",
 | 
			
		||||
		"computers_router_l.png",
 | 
			
		||||
		"computers_router_r.png",
 | 
			
		||||
		"computers_router_b.png",
 | 
			
		||||
		{
 | 
			
		||||
			name = "computers_router_f_animated.png",
 | 
			
		||||
			animation = {type="vertical_frames", aspect_w=32, aspect_h=32, length=1.0}
 | 
			
		||||
		},
 | 
			
		||||
	}, --"computers_router_f.png"},
 | 
			
		||||
	paramtype = "light",
 | 
			
		||||
	paramtype2 = "facedir",
 | 
			
		||||
	walkable = false,
 | 
			
		||||
	groups = {snappy=3},
 | 
			
		||||
	sound = default and default.node_sound_wood_defaults() or nil,
 | 
			
		||||
	drawtype = "nodebox",
 | 
			
		||||
	node_box = {
 | 
			
		||||
		type = "fixed",
 | 
			
		||||
		fixed = {
 | 
			
		||||
			{-0.25, -0.5, -0.0625, 0.25, -0.375, 0.3125},
 | 
			
		||||
			{-0.1875, -0.4375, 0.3125, -0.125, -0.1875, 0.375},
 | 
			
		||||
			{0.125, -0.4375, 0.3125, 0.1875, -0.1875, 0.375},
 | 
			
		||||
			{-0.0625, -0.4375, 0.3125, 0.0625, -0.25, 0.375}
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
    on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
 | 
			
		||||
        local formspec = {
 | 
			
		||||
            formspec_version = 4,
 | 
			
		||||
            {
 | 
			
		||||
                type = "size",
 | 
			
		||||
                w = 10,
 | 
			
		||||
                h = 5,
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                type = "no_prepend"
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                type = "bgcolor",
 | 
			
		||||
                bgcolor = "black",
 | 
			
		||||
                fullscreen = "neither"
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                type = "background9",
 | 
			
		||||
                x = 0,
 | 
			
		||||
                y = 0,
 | 
			
		||||
                w = 10,
 | 
			
		||||
                h = 5,
 | 
			
		||||
                texture_name = "kuto_button.png^[combine:16x16^[noalpha^[colorize:#ffffff70",
 | 
			
		||||
                auto_clip = false,
 | 
			
		||||
                middle_x = 4,
 | 
			
		||||
                middle_y = 4,
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                type = "hypertext",
 | 
			
		||||
                name = "label",
 | 
			
		||||
                x = 0,
 | 
			
		||||
                y = 0,
 | 
			
		||||
                w = 10,
 | 
			
		||||
                h = 2,
 | 
			
		||||
                text = "<global valign=middle><center><big>Choose Option Below</big></center>",
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                type = "button",
 | 
			
		||||
                x = 0.5,
 | 
			
		||||
                y = 3.5,
 | 
			
		||||
                w = 4,
 | 
			
		||||
                h = 1,
 | 
			
		||||
                name = "newnetwork_btn",
 | 
			
		||||
                label = "New Network",
 | 
			
		||||
                on_event = function(form, player, element, value, fields)
 | 
			
		||||
                    if element.label == "New Network" then
 | 
			
		||||
                        element.label = "Submit"
 | 
			
		||||
                        table.remove(form, computers.formspec.get_index_by_name(form, "existingnetwork_btn"))
 | 
			
		||||
                        form[computers.formspec.get_index_by_name(form, "label")].text = [[
 | 
			
		||||
                            <global valign=middle><center><big>Enter New Network Name</big></center>
 | 
			
		||||
                            ]]
 | 
			
		||||
                        table.insert(
 | 
			
		||||
                            form,
 | 
			
		||||
                            {
 | 
			
		||||
                                type = "box",
 | 
			
		||||
                                x = 3,
 | 
			
		||||
                                y = 1.75,
 | 
			
		||||
                                w = 4,
 | 
			
		||||
                                h = 1,
 | 
			
		||||
                                color = "#ffffff"
 | 
			
		||||
                            }
 | 
			
		||||
                        )
 | 
			
		||||
                        table.insert(
 | 
			
		||||
                            form,
 | 
			
		||||
                            {
 | 
			
		||||
                                type = "field",
 | 
			
		||||
                                x = 3,
 | 
			
		||||
                                y = 1.75,
 | 
			
		||||
                                w = 4,
 | 
			
		||||
                                h = 1,
 | 
			
		||||
                                name = "id_field",
 | 
			
		||||
                                close_on_enter = false,
 | 
			
		||||
                                props = {
 | 
			
		||||
                                    border = false,
 | 
			
		||||
                                },
 | 
			
		||||
                            }
 | 
			
		||||
                        )
 | 
			
		||||
                    else
 | 
			
		||||
                        if fields.id_field == "" and not computers.formspec.get_index_by_name(form, "warning") then
 | 
			
		||||
                            table.insert(
 | 
			
		||||
                                form,
 | 
			
		||||
                                {
 | 
			
		||||
                                    type = "hypertext",
 | 
			
		||||
                                    name = "warning",
 | 
			
		||||
                                    x = 5.5,
 | 
			
		||||
                                    y = 3.5,
 | 
			
		||||
                                    w = 4,
 | 
			
		||||
                                    h = 1,
 | 
			
		||||
                                    text = [[
 | 
			
		||||
                                        <global valign=middle>
 | 
			
		||||
                                        <center><style color=red>empty or invalid network name</style></center>
 | 
			
		||||
                                        ]]
 | 
			
		||||
                                }
 | 
			
		||||
                            )
 | 
			
		||||
                        elseif fields.id_field ~= "" then
 | 
			
		||||
                            local status, id = computers.networks.create(player, fields.id_field)
 | 
			
		||||
                            if status then
 | 
			
		||||
                                form = nil
 | 
			
		||||
                                minetest.get_meta(pos):set_string("net_id", id)
 | 
			
		||||
                                computers.networks.add_device(id, pos)
 | 
			
		||||
                                computers.api.chat_send_player(player, "network " .. fields.id_field .. " created")
 | 
			
		||||
                                computers.formspec.close_formspec(player)
 | 
			
		||||
                            elseif not computers.formspec.get_index_by_name(form, "warning") then
 | 
			
		||||
                                table.insert(
 | 
			
		||||
                                    form,
 | 
			
		||||
                                    {
 | 
			
		||||
                                        type = "hypertext",
 | 
			
		||||
                                        name = "warning",
 | 
			
		||||
                                        x = 5.5,
 | 
			
		||||
                                        y = 3.5,
 | 
			
		||||
                                        w = 4,
 | 
			
		||||
                                        h = 1,
 | 
			
		||||
                                        text = [[
 | 
			
		||||
                                            <global valign=middle>
 | 
			
		||||
                                            <center><style color=red>empty or invalid network name</style></center>
 | 
			
		||||
                                            ]]
 | 
			
		||||
                                    }
 | 
			
		||||
                                )
 | 
			
		||||
                            end
 | 
			
		||||
                        end
 | 
			
		||||
                    end
 | 
			
		||||
                    --minetest.chat_send_all("test")
 | 
			
		||||
 | 
			
		||||
                    if form then return form end
 | 
			
		||||
                end,
 | 
			
		||||
                props = {
 | 
			
		||||
                    border = false,
 | 
			
		||||
                    bgimg = "kuto_button.png^[combine:16x16^[noalpha^[colorize:#ffffff70",
 | 
			
		||||
                    bgimg_hovered = "kuto_button.png^[combine:16x16^[noalpha^[colorize:#ffffff90",
 | 
			
		||||
                    bgimg_middle = "4,4",
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                type = "button",
 | 
			
		||||
                x = 5.5,
 | 
			
		||||
                y = 3.5,
 | 
			
		||||
                w = 4,
 | 
			
		||||
                h = 1,
 | 
			
		||||
                name = "existingnetwork_btn",
 | 
			
		||||
                label = "Existing Network",
 | 
			
		||||
                on_event = function(form, player, element, value, fields)
 | 
			
		||||
                    if element.label == "Existing Network" then
 | 
			
		||||
                        element.label = "Submit"
 | 
			
		||||
                        table.remove(form, computers.formspec.get_index_by_name(form, "newnetwork_btn"))
 | 
			
		||||
                        form[computers.formspec.get_index_by_name(form, "label")].text = [[
 | 
			
		||||
                            <global valign=middle><center>Enter Network</center>
 | 
			
		||||
                            ]]
 | 
			
		||||
                        table.insert(
 | 
			
		||||
                            form,
 | 
			
		||||
                            {
 | 
			
		||||
                                type = "box",
 | 
			
		||||
                                x = 3,
 | 
			
		||||
                                y = 1.75,
 | 
			
		||||
                                w = 4,
 | 
			
		||||
                                h = 1,
 | 
			
		||||
                                color = "#ffffff"
 | 
			
		||||
                            }
 | 
			
		||||
                        )
 | 
			
		||||
                        table.insert(
 | 
			
		||||
                            form,
 | 
			
		||||
                            {
 | 
			
		||||
                                type = "field",
 | 
			
		||||
                                x = 3,
 | 
			
		||||
                                y = 1.75,
 | 
			
		||||
                                w = 4,
 | 
			
		||||
                                h = 1,
 | 
			
		||||
                                name = "id_field",
 | 
			
		||||
                                close_on_enter = false,
 | 
			
		||||
                                props = {
 | 
			
		||||
                                    border = false,
 | 
			
		||||
                                },
 | 
			
		||||
                            }
 | 
			
		||||
                        )
 | 
			
		||||
                    else
 | 
			
		||||
                        minetest.chat_send_all("submitted")
 | 
			
		||||
                    end
 | 
			
		||||
 | 
			
		||||
                    return form
 | 
			
		||||
                end,
 | 
			
		||||
                props = {
 | 
			
		||||
                    border = false,
 | 
			
		||||
                    bgimg = "kuto_button.png^[combine:16x16^[noalpha^[colorize:#ffffff70",
 | 
			
		||||
                    bgimg_hovered = "kuto_button.png^[combine:16x16^[noalpha^[colorize:#ffffff90",
 | 
			
		||||
                    bgimg_middle = "4,4",
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if minetest.get_meta(pos):get("net_id") then
 | 
			
		||||
            local net_name = computers.networks.get_net_name(minetest.get_meta(pos):get("net_id"))
 | 
			
		||||
            computers.api.chat_send_player(clicker, "router attached to network: " .. net_name)
 | 
			
		||||
        else
 | 
			
		||||
            computers.formspec.show_formspec(clicker, "computers:router", formspec)
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										289
									
								
								computers/nodes/tetris.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,289 @@
 | 
			
		||||
-- Tetris arcade machine
 | 
			
		||||
local S = minetest.get_translator("computers")
 | 
			
		||||
 | 
			
		||||
local shapes = {
 | 
			
		||||
    {  { x = {0, 1, 0, 1}, y = {0, 0, 1, 1} } },
 | 
			
		||||
 | 
			
		||||
    {  { x = {1, 1, 1, 1}, y = {0, 1, 2, 3} },
 | 
			
		||||
       { x = {0, 1, 2, 3}, y = {1, 1, 1, 1} } },
 | 
			
		||||
 | 
			
		||||
    {  { x = {0, 0, 1, 1}, y = {0, 1, 1, 2} },
 | 
			
		||||
       { x = {1, 2, 0, 1}, y = {0, 0, 1, 1} } },
 | 
			
		||||
 | 
			
		||||
    {  { x = {1, 0, 1, 0}, y = {0, 1, 1, 2} },
 | 
			
		||||
       { x = {0, 1, 1, 2}, y = {0, 0, 1, 1} } },
 | 
			
		||||
 | 
			
		||||
    {  { x = {1, 2, 1, 1}, y = {0, 0, 1, 2} },
 | 
			
		||||
       { x = {0, 1, 2, 2}, y = {1, 1, 1, 2} },
 | 
			
		||||
       { x = {1, 1, 0, 1}, y = {0, 1, 2, 2} },
 | 
			
		||||
       { x = {0, 0, 1, 2}, y = {0, 1, 1, 1} } },
 | 
			
		||||
 | 
			
		||||
    {  { x = {1, 1, 1, 2}, y = {0, 1, 2, 2} },
 | 
			
		||||
       { x = {0, 1, 2, 0}, y = {1, 1, 1, 2} },
 | 
			
		||||
       { x = {0, 1, 1, 1}, y = {0, 0, 1, 2} },
 | 
			
		||||
       { x = {0, 1, 2, 2}, y = {1, 1, 1, 0} } },
 | 
			
		||||
 | 
			
		||||
    {  { x = {1, 0, 1, 2}, y = {0, 1, 1, 1} },
 | 
			
		||||
       { x = {1, 1, 1, 2}, y = {0, 1, 2, 1} },
 | 
			
		||||
       { x = {0, 1, 2, 1}, y = {1, 1, 1, 2} },
 | 
			
		||||
       { x = {0, 1, 1, 1}, y = {1, 0, 1, 2} } } }
 | 
			
		||||
 | 
			
		||||
local colors = { "computers_cyan.png", "computers_magenta.png", "computers_red.png",
 | 
			
		||||
    "computers_blue.png", "computers_green.png", "computers_orange.png", "computers_yellow.png" }
 | 
			
		||||
 | 
			
		||||
local background = "image[0,0;3.55,6.66;computers_black.png]"
 | 
			
		||||
local buttons = "button[3,4.5;0.6,0.6;left;<]"
 | 
			
		||||
    .."button[3.6,4.5;0.6,0.6;rotateleft;"..minetest.formspec_escape(S("L")).."]"
 | 
			
		||||
    .."button[4.2,4.5;0.6,0.6;down;v]"
 | 
			
		||||
    .."button[4.2,5.3;0.6,0.6;drop;V]"
 | 
			
		||||
    .."button[4.8,4.5;0.6,0.6;rotateright;"..minetest.formspec_escape(S("R")).."]"
 | 
			
		||||
    .."button[5.4,4.5;0.6,0.6;right;>]"
 | 
			
		||||
    .."button[3.5,3;2,2;new;"..minetest.formspec_escape(S("New Game")).."]"
 | 
			
		||||
 | 
			
		||||
local formsize = "size[5.9,5.7]"
 | 
			
		||||
local boardx, boardy = 0, 0
 | 
			
		||||
local sizex, sizey, size = 0.29, 0.29, 0.31
 | 
			
		||||
 | 
			
		||||
local comma = ","
 | 
			
		||||
local semi = ";"
 | 
			
		||||
local close = "]"
 | 
			
		||||
 | 
			
		||||
local concat = table.concat
 | 
			
		||||
local insert = table.insert
 | 
			
		||||
 | 
			
		||||
local draw_shape = function(id, x, y, rot, posx, posy)
 | 
			
		||||
    local d = shapes[id][rot]
 | 
			
		||||
    local scr = {}
 | 
			
		||||
    local ins = #scr
 | 
			
		||||
 | 
			
		||||
    for i=1,4 do
 | 
			
		||||
        local tmp = { "image[",
 | 
			
		||||
            (d.x[i]+x)*sizex+posx, comma,
 | 
			
		||||
            (d.y[i]+y)*sizey+posy, semi,
 | 
			
		||||
            size, comma, size, semi,
 | 
			
		||||
            colors[id], close }
 | 
			
		||||
 | 
			
		||||
        ins = ins + 1
 | 
			
		||||
        scr[ins] = concat(tmp)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    return concat(scr)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function step(pos, fields)
 | 
			
		||||
    local meta = minetest.get_meta(pos)
 | 
			
		||||
    local t = minetest.deserialize(meta:get_string("tetris"))
 | 
			
		||||
 | 
			
		||||
    local function new_game(p)
 | 
			
		||||
        local nex = math.random(7)
 | 
			
		||||
 | 
			
		||||
        t = {
 | 
			
		||||
            board = {},
 | 
			
		||||
            boardstring = "",
 | 
			
		||||
            previewstring = draw_shape(nex, 0, 0, 1, 4, 1),
 | 
			
		||||
            score = 0,
 | 
			
		||||
            cur = math.random(7),
 | 
			
		||||
            nex = nex,
 | 
			
		||||
            x=4, y=0, rot=1
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        local timer = minetest.get_node_timer(p)
 | 
			
		||||
        timer:set(0.3, 0)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    local function update_boardstring()
 | 
			
		||||
        local scr = {}
 | 
			
		||||
        local ins = #scr
 | 
			
		||||
 | 
			
		||||
        for i, line in pairs(t.board) do
 | 
			
		||||
            for _, tile in pairs(line) do
 | 
			
		||||
                local tmp = { "image[",
 | 
			
		||||
                    tile[1]*sizex+boardx, comma,
 | 
			
		||||
                    i*sizey+boardy, semi,
 | 
			
		||||
                    size, comma, size, semi,
 | 
			
		||||
                    colors[tile[2]], close }
 | 
			
		||||
 | 
			
		||||
                ins = ins + 1
 | 
			
		||||
                scr[ins] = concat(tmp)
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        t.boardstring = concat(scr)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    local function add()
 | 
			
		||||
        local d = shapes[t.cur][t.rot]
 | 
			
		||||
 | 
			
		||||
        for i=1,4 do
 | 
			
		||||
            local l = d.y[i] + t.y
 | 
			
		||||
            if not t.board[l] then t.board[l] = {} end
 | 
			
		||||
            insert(t.board[l], {d.x[i] + t.x, t.cur})
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    local function scroll(l)
 | 
			
		||||
        for i=l, 1, -1 do
 | 
			
		||||
            t.board[i] = t.board[i-1] or {}
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    local function check_lines()
 | 
			
		||||
        for i, line in pairs(t.board) do
 | 
			
		||||
            if #line >= 10 then
 | 
			
		||||
                scroll(i)
 | 
			
		||||
                t.score = t.score + 20
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    local function check_position(x, y, rot)
 | 
			
		||||
        local d = shapes[t.cur][rot]
 | 
			
		||||
 | 
			
		||||
        for i=1,4 do
 | 
			
		||||
            local cx, cy = d.x[i]+x, d.y[i]+y
 | 
			
		||||
 | 
			
		||||
            if cx < 0 or cx > 9 or cy < 0 or cy > 19 then
 | 
			
		||||
                return false
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            for _, tile in pairs(t.board[ cy ] or {}) do
 | 
			
		||||
                if tile[1] == cx then return false end
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        return true
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    local function stuck()
 | 
			
		||||
        if check_position(t.x, t.y+1, t.rot) then return false end
 | 
			
		||||
        return true
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    local function tick()
 | 
			
		||||
        if stuck() then
 | 
			
		||||
            if t.y <= 0 then
 | 
			
		||||
                return false end
 | 
			
		||||
            add()
 | 
			
		||||
            check_lines()
 | 
			
		||||
            update_boardstring()
 | 
			
		||||
            t.cur, t.nex = t.nex, math.random(7)
 | 
			
		||||
            t.x, t.y, t.rot = 4, 0, 1
 | 
			
		||||
            t.previewstring = draw_shape(t.nex, 0, 0, 1, 4.1, 0.6)
 | 
			
		||||
        else
 | 
			
		||||
            t.y = t.y + 1
 | 
			
		||||
        end
 | 
			
		||||
        return true
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    local function move(dx, dy)
 | 
			
		||||
        local newx, newy = t.x+dx, t.y+dy
 | 
			
		||||
        if not check_position(newx, newy, t.rot) then return end
 | 
			
		||||
        t.x, t.y = newx, newy
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    local function rotate(dr)
 | 
			
		||||
        local no = #(shapes[t.cur])
 | 
			
		||||
        local newrot = (t.rot+dr) % no
 | 
			
		||||
 | 
			
		||||
        if newrot<1 then newrot = newrot+no end
 | 
			
		||||
        if not check_position(t.x, t.y, newrot) then return end
 | 
			
		||||
        t.rot = newrot
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    local function key()
 | 
			
		||||
        if fields.left then
 | 
			
		||||
            move(-1, 0)
 | 
			
		||||
        end
 | 
			
		||||
        if fields.rotateleft then
 | 
			
		||||
            rotate(-1)
 | 
			
		||||
        end
 | 
			
		||||
        if fields.down then
 | 
			
		||||
            t.score = t.score + 1
 | 
			
		||||
            move(0, 1)
 | 
			
		||||
        end
 | 
			
		||||
        if fields.drop then
 | 
			
		||||
        while not stuck() do
 | 
			
		||||
            t.score = t.score + 2
 | 
			
		||||
            move(0, 1)
 | 
			
		||||
        end
 | 
			
		||||
        end
 | 
			
		||||
        if fields.rotateright then
 | 
			
		||||
            rotate(1)
 | 
			
		||||
        end
 | 
			
		||||
        if fields.right then
 | 
			
		||||
            move(1, 0)
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    local run = true
 | 
			
		||||
 | 
			
		||||
    if fields then
 | 
			
		||||
        if fields.new then
 | 
			
		||||
            new_game(pos)
 | 
			
		||||
        elseif t then
 | 
			
		||||
            key(fields)
 | 
			
		||||
        end
 | 
			
		||||
    elseif t then
 | 
			
		||||
        run = tick()
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    if t then
 | 
			
		||||
    local scr = { formsize, background,
 | 
			
		||||
        t.boardstring, t.previewstring,
 | 
			
		||||
        draw_shape(t.cur, t.x, t.y, t.rot, boardx, boardy),
 | 
			
		||||
        "label[3.8,0.1;"..S("Next...").."]label[3.8,2.7;"..S("Score: "),
 | 
			
		||||
        t.score, close, buttons }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        meta:set_string("formspec", concat(scr))
 | 
			
		||||
        meta:set_string("tetris", minetest.serialize(t))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    return run
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
minetest.register_node("computers:tetris_arcade", {
 | 
			
		||||
    description=S("Tetris Arcade"),
 | 
			
		||||
    drawtype = "mesh",
 | 
			
		||||
    mesh = "computers_tetris_arcade.obj",
 | 
			
		||||
    tiles = {"computers_tetris_arcade.png"},
 | 
			
		||||
    paramtype = "light",
 | 
			
		||||
    paramtype2 = "facedir",
 | 
			
		||||
    groups = {snappy=3},
 | 
			
		||||
    on_rotate = minetest.get_modpath("screwdriver") and screwdriver.rotate_simple or nil,
 | 
			
		||||
    selection_box = {
 | 
			
		||||
        type = "fixed",
 | 
			
		||||
        fixed = {-0.5, -0.5, -0.5, 0.5, 1.5, 0.5}
 | 
			
		||||
    },
 | 
			
		||||
    collision_box = {
 | 
			
		||||
        type = "fixed",
 | 
			
		||||
        fixed = {-0.5, -0.5, -0.5, 0.5, 1.5, 0.5}
 | 
			
		||||
    },
 | 
			
		||||
    on_construct = function(pos)
 | 
			
		||||
        local meta = minetest.get_meta(pos)
 | 
			
		||||
        meta:set_string("formspec", formsize
 | 
			
		||||
            .."button[2,2.5;2,2;new;"..minetest.formspec_escape(S("New Game")).."]")
 | 
			
		||||
    end,
 | 
			
		||||
    on_timer = function(pos)
 | 
			
		||||
        return step(pos, nil)
 | 
			
		||||
    end,
 | 
			
		||||
    on_receive_fields = function(pos, formanme, fields, sender)
 | 
			
		||||
        step(pos, fields)
 | 
			
		||||
    end,
 | 
			
		||||
    on_place = function(itemstack, placer, pointed_thing)
 | 
			
		||||
        local pos = pointed_thing.above
 | 
			
		||||
        if minetest.is_protected(pos, placer:get_player_name()) or
 | 
			
		||||
            minetest.is_protected({x=pos.x, y=pos.y+1, z=pos.z}, placer:get_player_name()) then
 | 
			
		||||
            return itemstack
 | 
			
		||||
        end
 | 
			
		||||
        if minetest.get_node({x=pos.x, y=pos.y+1, z=pos.z}).name ~= "air" then
 | 
			
		||||
            minetest.chat_send_player(placer:get_player_name(), S("No room for place the Arcade!"))
 | 
			
		||||
            return itemstack
 | 
			
		||||
        end
 | 
			
		||||
        local dir = placer:get_look_dir()
 | 
			
		||||
        local node = {name="computers:tetris_arcade", param1=0, param2 = minetest.dir_to_facedir(dir)}
 | 
			
		||||
        minetest.set_node(pos, node)
 | 
			
		||||
        itemstack:take_item()
 | 
			
		||||
        return itemstack
 | 
			
		||||
    end
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								computers/textures/kuto_button.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 504 B  | 
							
								
								
									
										59
									
								
								home_vending_machines/api.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,59 @@
 | 
			
		||||
local registered_currency = {}
 | 
			
		||||
 | 
			
		||||
function home_vending_machines.register_currency(name, worth)
 | 
			
		||||
    registered_currency[name] = worth
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function reg_simple(name, def)
 | 
			
		||||
    minetest.register_node(":" .. name, {
 | 
			
		||||
        description = def.description,
 | 
			
		||||
        drawtype = "mesh",
 | 
			
		||||
        mesh = "home_vending_machines_machine.obj",
 | 
			
		||||
        tiles = def.tiles,
 | 
			
		||||
        paramtype = "light",
 | 
			
		||||
        paramtype2 = "facedir",
 | 
			
		||||
        groups = def.groups or {snappy=3},
 | 
			
		||||
        selection_box = {
 | 
			
		||||
            type = "fixed",
 | 
			
		||||
            fixed = {-0.5, -0.5, -0.5, 0.5, 1.5, 0.5}
 | 
			
		||||
        },
 | 
			
		||||
        collision_box = {
 | 
			
		||||
            type = "fixed",
 | 
			
		||||
            fixed = {-0.5, -0.5, -0.5, 0.5, 1.5, 0.5}
 | 
			
		||||
        },
 | 
			
		||||
        sounds = def.sounds,
 | 
			
		||||
        on_rotate = function(pos, node, user, mode, new_param2)
 | 
			
		||||
            if minetest.get_modpath("screwdriver") then
 | 
			
		||||
                return screwdriver.rotate_simple(pos, node, user, mode, new_param2)
 | 
			
		||||
            end
 | 
			
		||||
        end,
 | 
			
		||||
        on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
 | 
			
		||||
            local pname = clicker:get_player_name()
 | 
			
		||||
            local iname = itemstack:get_name()
 | 
			
		||||
            local dpos = vector.add((vector.multiply(minetest.facedir_to_dir(node.param2), -1)), pos)
 | 
			
		||||
 | 
			
		||||
            if registered_currency[iname] and registered_currency[iname] == 1 then
 | 
			
		||||
                local item = def._vmachine.item
 | 
			
		||||
                if type(item) == "table" then
 | 
			
		||||
                    item = item[math.random(#item)]
 | 
			
		||||
                end
 | 
			
		||||
 | 
			
		||||
                minetest.add_item(dpos, item)
 | 
			
		||||
 | 
			
		||||
                if not minetest.is_creative_enabled(pname) then
 | 
			
		||||
                    itemstack:take_item()
 | 
			
		||||
                    return itemstack
 | 
			
		||||
                end
 | 
			
		||||
            else
 | 
			
		||||
                minetest.chat_send_player(pname, "Please insert valid currency.")
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
    })
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function home_vending_machines.register_machine(type, name, def)
 | 
			
		||||
    if type == "simple" then
 | 
			
		||||
        reg_simple(name, def)
 | 
			
		||||
    end
 | 
			
		||||
    --TODO: add more complex machine type with formspec and selections
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										32
									
								
								home_vending_machines/crafts.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,32 @@
 | 
			
		||||
if minetest.get_modpath("default") then
 | 
			
		||||
    if minetest.get_modpath("dye") then
 | 
			
		||||
        minetest.register_craft({
 | 
			
		||||
            output = "home_workshop_misc:soda_machine",
 | 
			
		||||
            recipe = {
 | 
			
		||||
                {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
 | 
			
		||||
                {"default:steel_ingot", "dye:red",             "default:steel_ingot"},
 | 
			
		||||
                {"default:steel_ingot", "default:copperblock", "default:steel_ingot"},
 | 
			
		||||
            },
 | 
			
		||||
        })
 | 
			
		||||
    end
 | 
			
		||||
    if minetest.get_modpath("vessel") then
 | 
			
		||||
        minetest.register_craft({
 | 
			
		||||
            output = "home_vending_machines:drink_machine",
 | 
			
		||||
            recipe = {
 | 
			
		||||
                {"default:steel_ingot", "group:vessel", "default:steel_ingot"},
 | 
			
		||||
                {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
 | 
			
		||||
                {"default:steel_ingot", "default:copperblock", "default:steel_ingot"},
 | 
			
		||||
            },
 | 
			
		||||
        })
 | 
			
		||||
    end
 | 
			
		||||
    if minetest.get_modpath("farming") then
 | 
			
		||||
        minetest.register_craft({
 | 
			
		||||
            output = "home_vending_machines:sweet_machine",
 | 
			
		||||
            recipe = {
 | 
			
		||||
                {"default:steel_ingot", "group:food_sugar",    "default:steel_ingot"},
 | 
			
		||||
                {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
 | 
			
		||||
                {"default:steel_ingot", "default:copperblock", "default:steel_ingot"},
 | 
			
		||||
            },
 | 
			
		||||
        })
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										9
									
								
								home_vending_machines/init.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,9 @@
 | 
			
		||||
local modpath = minetest.get_modpath("home_vending_machines")
 | 
			
		||||
home_vending_machines = {}
 | 
			
		||||
 | 
			
		||||
dofile(modpath .. "/api.lua")
 | 
			
		||||
dofile(modpath .. "/machines.lua")
 | 
			
		||||
dofile(modpath .. "/items.lua")
 | 
			
		||||
dofile(modpath .. "/crafts.lua")
 | 
			
		||||
 | 
			
		||||
home_vending_machines.init = true
 | 
			
		||||
							
								
								
									
										12
									
								
								home_vending_machines/items.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,12 @@
 | 
			
		||||
local function reg_item(name, evalue)
 | 
			
		||||
    minetest.register_craftitem("home_vending_machines:" .. name, {
 | 
			
		||||
        description = string.gsub(name, "_", " "),
 | 
			
		||||
        inventory_image = "home_vending_machines_" .. name .. ".png",
 | 
			
		||||
        on_use = minetest.item_eat(evalue),
 | 
			
		||||
    })
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
reg_item("soda_can", 2)
 | 
			
		||||
minetest.register_alias("home_workshop_misc:soda_can", "home_vending_machines:soda_can")
 | 
			
		||||
 | 
			
		||||
reg_item("water_bottle", 3)
 | 
			
		||||
							
								
								
									
										29
									
								
								home_vending_machines/machines.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,29 @@
 | 
			
		||||
home_vending_machines.register_currency("default:gold_ingot", 1)
 | 
			
		||||
home_vending_machines.register_currency("currency:minegeld_cent_25", 1)
 | 
			
		||||
 | 
			
		||||
home_vending_machines.register_machine("simple", "home_workshop_misc:soda_machine", {
 | 
			
		||||
    description = "Soda vending machine",
 | 
			
		||||
    tiles = {"home_vending_machines_soda_machine.png"},
 | 
			
		||||
    sounds = nil,
 | 
			
		||||
    _vmachine = {
 | 
			
		||||
        item = "home_vending_machines:soda_can"
 | 
			
		||||
    }
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
home_vending_machines.register_machine("simple", "home_vending_machines:drink_machine", {
 | 
			
		||||
    description = "Drinks vending machine",
 | 
			
		||||
    tiles = {"home_vending_machines_drink_machine.png"},
 | 
			
		||||
    sounds = nil,
 | 
			
		||||
    _vmachine = {
 | 
			
		||||
        item = {"home_vending_machines:soda_can", "home_vending_machines:water_bottle"}
 | 
			
		||||
    }
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
home_vending_machines.register_machine("simple", "home_vending_machines:sweet_machine", {
 | 
			
		||||
    description = "Sweets vending machine",
 | 
			
		||||
    tiles = {"home_vending_machines_sweet_machine.png"},
 | 
			
		||||
    sounds = nil,
 | 
			
		||||
    _vmachine = {
 | 
			
		||||
        item = "home_vending_machines:soda_can"
 | 
			
		||||
    }
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										1
									
								
								home_vending_machines/mod.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1 @@
 | 
			
		||||
optional_depends = screwdriver
 | 
			
		||||
							
								
								
									
										11
									
								
								home_vending_machines/readme.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,11 @@
 | 
			
		||||
code wsor MIT
 | 
			
		||||
 | 
			
		||||
VanessaE (cc-by-sa 4.0):
 | 
			
		||||
home_vending_machines_machine.obj
 | 
			
		||||
home_vending_machines_soda_can.png
 | 
			
		||||
home_vending_machines_soda_machine.png
 | 
			
		||||
 | 
			
		||||
Andrey01 (CC BY-SA 3.0):
 | 
			
		||||
home_vending_machines_drimk_machine.png
 | 
			
		||||
home_vending_machines_sweet_machine.png
 | 
			
		||||
home_vending_machines_water_bottle.png
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 155 B After Width: | Height: | Size: 155 B  | 
| 
		 After Width: | Height: | Size: 381 B  | 
| 
		 After Width: | Height: | Size: 920 B  | 
| 
		 Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB  | 
| 
		 After Width: | Height: | Size: 1.3 KiB  | 
@@ -1,2 +0,0 @@
 | 
			
		||||
-- nothing to see here :P
 | 
			
		||||
-- this is just a stub to provide a few textures
 | 
			
		||||
@@ -17,7 +17,7 @@ minetest.register_node("home_workshop_machines:3dprinter_bedflinger", {
 | 
			
		||||
	paramtype = "light",
 | 
			
		||||
	walkable = true,
 | 
			
		||||
	groups = {snappy=3, ud_param2_colorable = 1},
 | 
			
		||||
	sound = default.node_sound_wood_defaults(),
 | 
			
		||||
	sound = default and default.node_sound_wood_defaults() or nil,
 | 
			
		||||
	drawtype = "mesh",
 | 
			
		||||
	mesh = "home_workshop_machines_3dprinter_bedflinger.obj",
 | 
			
		||||
	paramtype2 = "colorwallmounted",
 | 
			
		||||
@@ -47,7 +47,7 @@ minetest.register_node("home_workshop_machines:3dprinter_corexy", {
 | 
			
		||||
	paramtype = "light",
 | 
			
		||||
	walkable = true,
 | 
			
		||||
	groups = {snappy=3, ud_param2_colorable = 1},
 | 
			
		||||
	sound = default.node_sound_wood_defaults(),
 | 
			
		||||
	sound = default and default.node_sound_wood_defaults() or nil,
 | 
			
		||||
	drawtype = "mesh",
 | 
			
		||||
	mesh = "home_workshop_machines_3dprinter_corexy.obj",
 | 
			
		||||
	paramtype2 = "colorwallmounted",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,4 @@
 | 
			
		||||
name = home_workshop_machines
 | 
			
		||||
depends = default, unifieddyes
 | 
			
		||||
depends = unifieddyes
 | 
			
		||||
optional_depends = default
 | 
			
		||||
optional_depends = screwdriver
 | 
			
		||||
 
 | 
			
		||||
@@ -14,13 +14,4 @@ minetest.register_craft({
 | 
			
		||||
		{ "basic_materials:steel_bar", "default:steel_ingot", "basic_materials:steel_bar" },
 | 
			
		||||
		{ "default:steel_ingot",       "default:steel_ingot", "default:steel_ingot" }
 | 
			
		||||
	},
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
minetest.register_craft({
 | 
			
		||||
	output = "homedecor:soda_machine",
 | 
			
		||||
	recipe = {
 | 
			
		||||
		{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
 | 
			
		||||
		{"default:steel_ingot", "dye:red",             "default:steel_ingot"},
 | 
			
		||||
		{"default:steel_ingot", "default:copperblock", "default:steel_ingot"},
 | 
			
		||||
	},
 | 
			
		||||
})
 | 
			
		||||
})
 | 
			
		||||
@@ -48,9 +48,9 @@ minetest.register_node("home_workshop_misc:beer_tap", {
 | 
			
		||||
		local wieldname = itemstack:get_name()
 | 
			
		||||
		if wieldname == "vessels:drinking_glass" then
 | 
			
		||||
			if inv:room_for_item("main", "home_workshop_misc:beer_mug 1") then
 | 
			
		||||
				inv:add_item("main", "home_workshop_misc:beer_mug 1")
 | 
			
		||||
				itemstack:take_item()
 | 
			
		||||
				clicker:set_wielded_item(itemstack)
 | 
			
		||||
				inv:add_item("main", "home_workshop_misc:beer_mug 1")
 | 
			
		||||
				minetest.chat_send_player(clicker:get_player_name(),
 | 
			
		||||
						S("Ahh, a frosty cold beer - look in your inventory for it!"))
 | 
			
		||||
			else
 | 
			
		||||
@@ -76,74 +76,29 @@ minetest.register_node("home_workshop_misc:beer_mug", {
 | 
			
		||||
	paramtype2 = "facedir",
 | 
			
		||||
	groups = { snappy=3, oddly_breakable_by_hand=3 },
 | 
			
		||||
	walkable = false,
 | 
			
		||||
	sounds = default.node_sound_glass_defaults(),
 | 
			
		||||
	sounds = default and default.node_sound_glass_defaults() or nil,
 | 
			
		||||
	selection_box = beer_cbox,
 | 
			
		||||
	on_use = function(itemstack, user, pointed_thing)
 | 
			
		||||
		if not creative.is_enabled_for(user:get_player_name()) then
 | 
			
		||||
		if not minetest.is_creative_enabled(user:get_player_name()) then
 | 
			
		||||
			minetest.do_item_eat(2, "vessels:drinking_glass 1", itemstack, user, pointed_thing)
 | 
			
		||||
			return itemstack
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
local svm_cbox = {
 | 
			
		||||
	type = "fixed",
 | 
			
		||||
	fixed = {-0.5, -0.5, -0.5, 0.5, 1.5, 0.5}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
minetest.register_node("home_workshop_misc:soda_machine", {
 | 
			
		||||
	description = S("Soda vending machine"),
 | 
			
		||||
	drawtype = "mesh",
 | 
			
		||||
	mesh = "home_workshop_misc_soda_machine.obj",
 | 
			
		||||
	tiles = {"home_workshop_misc_soda_machine.png"},
 | 
			
		||||
	paramtype = "light",
 | 
			
		||||
	paramtype2 = "facedir",
 | 
			
		||||
	groups = {snappy=3},
 | 
			
		||||
	selection_box = svm_cbox,
 | 
			
		||||
	collision_box = svm_cbox,
 | 
			
		||||
	expand = { top="placeholder" },
 | 
			
		||||
	sounds = default.node_sound_wood_defaults(),
 | 
			
		||||
	on_rotate = minetest.get_modpath("screwdriver") and screwdriver.rotate_simple or nil,
 | 
			
		||||
	on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
 | 
			
		||||
		local playername = clicker:get_player_name()
 | 
			
		||||
		local wielditem = clicker:get_wielded_item()
 | 
			
		||||
		local wieldname = wielditem:get_name()
 | 
			
		||||
		local fdir_to_fwd = { {0, -1}, {-1, 0}, {0, 1}, {1, 0} }
 | 
			
		||||
		local fdir = node.param2
 | 
			
		||||
		local pos_drop = { x=pos.x+fdir_to_fwd[fdir+1][1], y=pos.y, z=pos.z+fdir_to_fwd[fdir+1][2] }
 | 
			
		||||
		if wieldname == "currency:minegeld_cent_25" then
 | 
			
		||||
			minetest.spawn_item(pos_drop, "home_workshop_misc:soda_can")
 | 
			
		||||
			minetest.sound_play("insert_coin", {
 | 
			
		||||
				pos=pos, max_hear_distance = 5
 | 
			
		||||
			})
 | 
			
		||||
			if not creative.is_enabled_for(playername) then
 | 
			
		||||
				wielditem:take_item()
 | 
			
		||||
				clicker:set_wielded_item(wielditem)
 | 
			
		||||
				return wielditem
 | 
			
		||||
			end
 | 
			
		||||
		else
 | 
			
		||||
			minetest.chat_send_player(playername, S("Please insert a 25 Mg cent coin in the machine."))
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
minetest.register_craftitem("home_workshop_misc:soda_can", {
 | 
			
		||||
	description = S("Soda Can"),
 | 
			
		||||
	inventory_image = "home_workshop_misc_soda_can.png",
 | 
			
		||||
	on_use = minetest.item_eat(2),
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
if minetest.get_modpath("homedecor_common") then
 | 
			
		||||
	minetest.register_alias("home_workshop_misc:drawer_small", "homedecor:drawer_small")
 | 
			
		||||
else
 | 
			
		||||
	minetest.register_craftitem("home_workshop_misc:drawer_small", {
 | 
			
		||||
			description = S("Small Wooden Drawer"),
 | 
			
		||||
			inventory_image = "home_workshop_machines_drawer_small.png",
 | 
			
		||||
			inventory_image = "home_workshop_common_drawer_small.png",
 | 
			
		||||
	})
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local MODPATH = minetest.get_modpath("home_workshop_misc")
 | 
			
		||||
dofile(MODPATH.."/crafts.lua")
 | 
			
		||||
if minetest.get_modpath("default") and minetest.get_modpath("basic_materials") then
 | 
			
		||||
	dofile(MODPATH.."/crafts.lua")
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
minetest.register_alias("homedecor:tool_cabinet",        "home_workshop_misc:tool_cabinet")
 | 
			
		||||
minetest.register_alias("homedecor:tool_cabinet_bottom", "home_workshop_misc:tool_cabinet")
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,2 @@
 | 
			
		||||
name = home_workshop_misc
 | 
			
		||||
depends = default, home_workshop_common
 | 
			
		||||
optional_depends = currency, screwdriver, homedecor_common
 | 
			
		||||
optional_depends = currency, screwdriver, homedecor_common, default
 | 
			
		||||
 
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 225 B After Width: | Height: | Size: 225 B  | 
| 
		 Before Width: | Height: | Size: 218 B After Width: | Height: | Size: 218 B  | 
| 
		 Before Width: | Height: | Size: 186 B After Width: | Height: | Size: 186 B  | 
							
								
								
									
										2
									
								
								license.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,2 @@
 | 
			
		||||
LGPL-3.0 for code,
 | 
			
		||||
CC-BY-SA-4.0 for media.
 | 
			
		||||