499 lines
13 KiB
Lua
499 lines
13 KiB
Lua
local hd=9
|
|
local cw=500
|
|
local zres=16
|
|
local zfac=3
|
|
|
|
local cmi=-(math.floor(cw/2))
|
|
local md=hd-1
|
|
local cma=cmi+cw-1
|
|
local zs=cw/zres
|
|
local zw=math.floor(cw/zfac+0.5)
|
|
local zo=zs/2-zw/2
|
|
local colf=("%."..(#(("%x"):format(md))).."x")
|
|
local function col(r)
|
|
return math.floor((r/(md))*255+0.5)
|
|
end
|
|
local function pngtex(w,h,tex)
|
|
return "[png:"..minetest.encode_base64(minetest.encode_png(w,h,tex))
|
|
end
|
|
local function colr(r,g,b,a)
|
|
r=math.min(255,math.max(0,math.floor(col(r)+0.5)))
|
|
g=math.min(255,math.max(0,math.floor(col(g)+0.5)))
|
|
b=math.min(255,math.max(0,math.floor(col(b)+0.5)))
|
|
a=math.min(255,math.max(0,math.floor((a and a/255 or 255)+0.5)))
|
|
return {r=r,g=g,b=b,a=a}
|
|
end
|
|
local function coltex(r,g,b,a)
|
|
local c=colr(r,g,b,a)
|
|
return ("^[colorize:#%.2X%.2X%.2X%.2X:255"):format(c.r,c.g,c.b,c.a)
|
|
end
|
|
local function colnode_old(r,g,b)
|
|
return ("r:%i_%i_%i"):format(r,g,b)
|
|
end
|
|
local function colnode(r,g,b)
|
|
return (colf:rep(3)):format(r,g,b)
|
|
end
|
|
minetest.override_item("",{
|
|
range=1000
|
|
})
|
|
minetest.register_node(":_",{
|
|
sunlight_propagates=true,
|
|
pointable=false,
|
|
paramtype="light",
|
|
drawtype="airlike",
|
|
})
|
|
minetest.register_alias("r:_","_")
|
|
minetest.register_alias("mapgen_stone","air")
|
|
minetest.register_alias("mapgen_water_source","air")
|
|
minetest.register_alias("mapgen_river_water_source","air")
|
|
local function dp(n)
|
|
local po=math.floor(n/(md)*30+0.5)
|
|
local ne=30-po
|
|
return "["..("|"):rep(po)..("."):rep(ne).."]"
|
|
end
|
|
local function coloff(r)
|
|
return r>md-md/4 and r-md/4 or r+md/4
|
|
end
|
|
local function invtex(r,g,b)
|
|
local img={}
|
|
local is=9
|
|
local isa=is-1
|
|
for y=0,isa do
|
|
for x=0,isa do
|
|
if y==0 or x==0 or y==isa or x==isa then
|
|
img[#img+1]=colr(coloff(r),coloff(g),coloff(b))
|
|
else
|
|
img[#img+1]=colr(r,g,b)
|
|
end
|
|
end
|
|
end
|
|
return pngtex(is,is,img)
|
|
end
|
|
local record
|
|
for r=0,md do
|
|
for g=0,md do
|
|
for b=0,md do
|
|
minetest.register_node(":"..colnode(r,g,b),{
|
|
description=("%s R\n%s G\n%s B")
|
|
:format(dp(r),dp(g),dp(b)),
|
|
tiles={coltex(r,g,b)},
|
|
inventory_image=invtex(r,g,b),
|
|
wield_image="^[colorize:#00000000:255",
|
|
col={r,g,b},
|
|
range=2000,
|
|
stack_max=1,
|
|
paramtype="light",
|
|
light_source=14,
|
|
sunlight_propagates=true,
|
|
is_ground_content=false,
|
|
after_place_node=function()return true end,
|
|
on_drop=function(stack,ref,pos)
|
|
return ItemStack""
|
|
end,
|
|
on_rightclick=function(pos,node,pl)
|
|
return node.name
|
|
end,
|
|
on_punch=function(pos,node,puncher)
|
|
local witem=puncher:get_wielded_item()
|
|
if witem:get_count()==0 then return end
|
|
if minetest.is_protected(pos,puncher:get_player_name()) then return end
|
|
local wname=witem:get_name()
|
|
if wname==node.name then return end
|
|
local def=minetest.registered_items[wname]
|
|
if not def then return end
|
|
if not def.col then return end
|
|
record(pos.x+cmi,pos.z+cmi,name,def.col)
|
|
minetest.set_node(pos,{name=wname})
|
|
end,
|
|
})
|
|
minetest.register_alias(colnode_old(r,g,b),colnode(r,g,b))
|
|
end end end
|
|
do
|
|
local c1,c2,c3={},{},{}
|
|
for a=0,md do
|
|
for b=0,md do
|
|
c1[#c1+1]=colr(md,a,b)
|
|
c2[#c2+1]=colr(a,md,b)
|
|
c3[#c3+1]=colr(a,b,md)
|
|
end end
|
|
local cc1,cc2,cc3={},{},{}
|
|
for a=0,md do
|
|
cc1[#cc1+1]=colr(a,md,md)
|
|
cc2[#cc2+1]=colr(md,a,md)
|
|
cc3[#cc3+1]=colr(md,md,a)
|
|
end
|
|
for a=1,256 do
|
|
c1[a]=c1[a] or colr(0,0,0,0)
|
|
c2[a]=c2[a] or colr(0,0,0,0)
|
|
c3[a]=c3[a] or colr(0,0,0,0)
|
|
end
|
|
c1=pngtex(256,1,c1)
|
|
c2=pngtex(256,1,c2)
|
|
c3=pngtex(256,1,c3)
|
|
cc1=pngtex(hd,1,cc1)
|
|
cc2=pngtex(hd,1,cc2)
|
|
cc3=pngtex(hd,1,cc3)
|
|
for k,v in pairs{r={c1,cc1},g={c2,cc2},b={c3,cc3}} do
|
|
minetest.register_craftitem(":".."pld"..k,{
|
|
inventory_image=v[2],
|
|
palette=v[1]
|
|
})
|
|
end
|
|
end
|
|
do
|
|
local data={}
|
|
local ai=minetest.get_content_id("air")
|
|
local gr=minetest.get_content_id(colnode(md,md,md))
|
|
local bd=minetest.get_content_id("r:_")
|
|
local cids=setmetatable({},{
|
|
__index=function(s,i)
|
|
s[i]=minetest.get_content_id(i)
|
|
return s[i]
|
|
end
|
|
})
|
|
minetest.register_on_generated(function(mi,ma)
|
|
local vm=minetest.get_mapgen_object("voxelmanip")
|
|
vm:get_data(data)
|
|
local emi,ema=vm:get_emerged_area()
|
|
local ar=VoxelArea:new{MinEdge=emi,MaxEdge=ema}
|
|
for z=mi.z,ma.z do
|
|
for y=mi.y,ma.y do
|
|
local i=ar:index(mi.x,y,z)
|
|
for x=mi.x,ma.x do
|
|
local i=i+(x-mi.x)
|
|
data[i]=y==0 and gr or ai
|
|
if y>300 or y<0 or x>cma or x<cmi or z>cma or z<cmi then
|
|
data[i]=bd
|
|
end
|
|
end end end
|
|
vm:set_data(data)
|
|
vm:calc_lighting()
|
|
vm:write_to_map()
|
|
end)
|
|
end
|
|
function minetest.is_protected(pos,name)
|
|
if pos.y~=0 then return true end
|
|
return false
|
|
end
|
|
minetest.register_on_player_hpchange(function(ref,ch,reas)
|
|
return 0
|
|
end,true)
|
|
local function sendworld(name)
|
|
minetest.emerge_area({x=cmi,y=0,z=cmi},{x=cma,y=0,z=cma},function(bp,act,rem)
|
|
if rem~=0 then return end
|
|
local ref=minetest.get_player_by_name(name)
|
|
if not ref then return end
|
|
for x=math.floor(cmi/16),math.floor(cma/16) do
|
|
for z=math.floor(cmi/16),math.floor(cma/16) do
|
|
local p={x=x*16,y=0,z=z*16}
|
|
minetest.load_area(p,vector.add(p,vector.new(16,16,16)))
|
|
ref:send_mapblock({x=x,y=0,z=z})
|
|
end end
|
|
end)
|
|
end
|
|
local function dirs(...)
|
|
return table.concat({...},DIR_DELIM)
|
|
end
|
|
local map=""
|
|
local mapdata={}
|
|
local wroot=minetest.get_worldpath()
|
|
local mroot=dirs(wroot,"canvas")
|
|
local histdir=dirs(mroot,"history")
|
|
--local history={}
|
|
--local torecord={}
|
|
--local prevgtime=minetest.get_gametime()
|
|
function record(x,y,name,col)
|
|
-- torecord[#torecord+1]={x,y,name,col}
|
|
end
|
|
--local function recer()
|
|
-- local gtime=minetest.get_gametime()
|
|
-- if gtime~=prevgtime then return end
|
|
-- for k,v in ipairs(torecord) do
|
|
-- end
|
|
-- minetest.after(1,recer)
|
|
-- prevgtime=gtime
|
|
--end
|
|
--minetest.after(1,recer)
|
|
local imapsdir=dirs(mroot,"imaps")
|
|
local vmapsdir=dirs(mroot,"vmaps")
|
|
minetest.mkdir(mroot)
|
|
minetest.mkdir(histdir)
|
|
do
|
|
local mdat={}
|
|
local nams=setmetatable({},{
|
|
__index=function(s,i)
|
|
local name=minetest.get_name_from_content_id(i)
|
|
local def=minetest.registered_nodes[name]
|
|
if def and def.col then
|
|
name=colr(unpack(def.col))
|
|
else
|
|
name=colr(0,0,0,0)
|
|
end
|
|
s[i]=name
|
|
return s[i]
|
|
end
|
|
})
|
|
local function genmap()
|
|
local sta=minetest.get_us_time()
|
|
local p1,p2=vector.new(cmi,0,cmi),vector.new(cma,0,cma)
|
|
minetest.load_area(p1,p2)
|
|
local sta2=minetest.get_us_time()
|
|
local vm=VoxelManip(p1,p2)
|
|
local e1,e2=vm:get_emerged_area()
|
|
local ar=VoxelArea:new{MinEdge=e1,MaxEdge=e2}
|
|
vm:get_data(mdat)
|
|
local pic={}
|
|
local ii=0
|
|
local iy,ix=0,0
|
|
for z=p2.z,p1.z,-1 do
|
|
iy=iy+1
|
|
ix=0
|
|
for y=p1.y,p2.y do
|
|
local i=ar:index(p1.x,y,z)
|
|
for x=p1.x,p2.x do
|
|
ii=ii+1
|
|
ix=ix+1
|
|
local i=i+x-p1.x
|
|
mapdata[iy]=mapdata[iy] or {}
|
|
local nam=nams[mdat[i]]
|
|
mapdata[iy][ix]=nam
|
|
pic[ii]=nam
|
|
end end end
|
|
for k,v in pairs(minetest.get_connected_players()) do
|
|
sendworld(v:get_player_name())
|
|
end
|
|
map=minetest.encode_png(cw,cw,pic,9)
|
|
local file=io.open(dirs(mroot,"map.png"),"w")
|
|
file:write(map)
|
|
file:close()
|
|
local eti=minetest.get_us_time()
|
|
minetest.log("info","Generated map in "..(eti-sta)/1000 .."/"..(sta2-sta)/1000 .."ms; "..(#map/1000).."Kb")
|
|
minetest.after(10,genmap)
|
|
end
|
|
minetest.after(0,genmap)
|
|
end
|
|
local esc=minetest.formspec_escape
|
|
local nullimg=esc(coltex(0,0,0,0))
|
|
local nullcol={r=0,g=0,b=0,a=0}
|
|
local formI=[=[
|
|
formspec_version[3]
|
|
size[12,8]
|
|
list[current_player;main;0.5,2.75;9,4;]
|
|
button[0.5,0.5;11,1;psw;Color picker]
|
|
button[0.5,1.5;11,1;map;Map]
|
|
]=]
|
|
local formP=function(name,r,g,b)
|
|
local aa=[=[
|
|
formspec_version[3]
|
|
size[12,10]
|
|
list[current_player;main;0.5,4.75;9,4;]
|
|
button[0,0;1,1;inv;<-]
|
|
scrollbaroptions[min=0;max=]=]..(md)..[=[;smallstep=1]
|
|
scrollbar[1,1;10,0.75;horizontal;s_red;]=]..r..[=[]
|
|
scrollbar[1,2;10,0.75;horizontal;s_green;]=]..g..[=[]
|
|
scrollbar[1,3;10,0.75;horizontal;s_blue;]=]..b..[=[]
|
|
style_type[list;size=8.5,0.25]
|
|
list[detached:colors_]=]..name..[=[;main;1.75,1.75;1,1;0]
|
|
list[detached:colors_]=]..name..[=[;main;1.75,2.75;1,1;1]
|
|
list[detached:colors_]=]..name..[=[;main;1.75,3.75;1,1;2]
|
|
style_type[image_button;border=false]
|
|
image_button[1.75,1.75;8.5,0.25;;;]
|
|
image_button[1.75,2.75;8.5,0.25;;;]
|
|
image_button[1.75,3.75;8.5,0.25;;;]
|
|
]=]
|
|
return aa
|
|
end
|
|
local formM=[=[
|
|
formspec_version[3]
|
|
size[22,22]
|
|
padding[0,0]
|
|
image[1,1;20,20;%s]
|
|
button[0,0;1,1;inv;<-]
|
|
button[1,0;3,1;%s;refresh]
|
|
style_type[image_button;border=false]
|
|
]=]
|
|
local formM0=formM
|
|
for x=0,zres-1 do
|
|
for y=0,zres-1 do
|
|
formM0=formM0..
|
|
("image_button[%f,%f;%f,%f;;mapzoom_%i_%i;]\n")
|
|
:format(1+x/zres*20,1+y/zres*20,20/zres,20/zres,x,y)
|
|
end end
|
|
local formM1=formM.."image_button[1,1;20,20;"..nullimg..";map;]\n"
|
|
minetest.register_chatcommand("killme",{
|
|
func=function(name,param)
|
|
minetest.show_formspec(name,"skull_emoji","image[0,0;0,0;\\[png:]")
|
|
end
|
|
})
|
|
minetest.register_chatcommand("kill",{
|
|
privs={kick=true},
|
|
func=function(name,param)
|
|
minetest.show_formspec(param,"skull_emoji","image[0,0;0,0;\\[png:]")
|
|
end
|
|
})
|
|
local sev=minetest.explode_scrollbar_event
|
|
local plrc={}
|
|
local pldata={}
|
|
local function set_pldinv(data,r,g,b)
|
|
local list={
|
|
minetest.itemstring_with_palette("pldr",g*hd+b),
|
|
minetest.itemstring_with_palette("pldg",r*hd+b),
|
|
minetest.itemstring_with_palette("pldb",r*hd+g)
|
|
}
|
|
local ll={}
|
|
for k,v in pairs(list) do
|
|
ll[k]=ItemStack(v):to_table()
|
|
end
|
|
data.ccol={r,g,b}
|
|
data.pldinv:set_list("main",list)
|
|
end
|
|
local function geticol(i)
|
|
if not (i and i:get_count()>0) then return end
|
|
local def=minetest.registered_items[i:get_name()]
|
|
if not (def and def.col) then return end
|
|
return def.col
|
|
end
|
|
local function playerstep(ref)
|
|
local name=ref:get_player_name()
|
|
local data=pldata[name]
|
|
if not data then return end
|
|
local inv=ref:get_inventory()
|
|
local list=inv:get_list("main")
|
|
for k,v in ipairs(list) do
|
|
if v:get_count()==0 then
|
|
inv:set_stack("main",k,ItemStack(colnode(md,md,md)))
|
|
end
|
|
end
|
|
if data.ccol then
|
|
local wcol=geticol(ref:get_wielded_item())
|
|
local a,b=wcol,data.ccol
|
|
if wcol and (a[1]~=b[1] or a[2]~=b[2] or a[3]~=b[3]) then
|
|
local r,g,b=unpack(wcol)
|
|
set_pldinv(data,r,g,b)
|
|
data.pcol=nil
|
|
ref:set_inventory_formspec(formP(name,r,g,b))
|
|
end
|
|
end
|
|
end
|
|
minetest.register_globalstep(function(dt)
|
|
for _,ref in pairs(minetest.get_connected_players()) do
|
|
playerstep(ref)
|
|
end
|
|
end)
|
|
minetest.register_on_player_receive_fields(function(ref,form,fields)
|
|
if form~="" then return end
|
|
local name=ref:get_player_name()
|
|
local data=pldata[name]
|
|
if not data then return end
|
|
if fields.s_red and fields.s_green and fields.s_blue then
|
|
local r,g,b=sev(fields.s_red),sev(fields.s_green),sev(fields.s_blue)
|
|
local r,g,b,rr,gg,bb=
|
|
math.min(md,math.max(tonumber(r.value) or 0)),
|
|
math.min(md,math.max(tonumber(g.value) or 0)),
|
|
math.min(md,math.max(tonumber(b.value) or 0)),
|
|
r,g,b
|
|
if rr.type=="CHG" or gg.type=="CHG" or bb.type=="CHG" then
|
|
data.pcol={r,g,b}
|
|
set_pldinv(data,r,g,b)
|
|
ref:set_wielded_item(colnode(r,g,b))
|
|
end
|
|
end
|
|
if fields.quit and data.pcol then
|
|
ref:set_inventory_formspec(formP(name,unpack(data.pcol)))
|
|
data.pcol=nil
|
|
end
|
|
if fields.psw then
|
|
local stack=ref:get_wielded_item()
|
|
local def=minetest.registered_nodes[stack:get_name()]
|
|
if not (def and def.col) then
|
|
stack=ItemStack(colnode(0,0,0))
|
|
end
|
|
def=minetest.registered_nodes[stack:get_name()]
|
|
local r,g,b=unpack(def.col)
|
|
ref:set_wielded_item(stack)
|
|
set_pldinv(data,r,g,b)
|
|
data.pcol=nil
|
|
ref:set_inventory_formspec(formP(name,r,g,b))
|
|
elseif fields.map and map~="" then
|
|
local form=formM0:format(minetest.formspec_escape("[png:"..minetest.encode_base64(map)),"map")
|
|
ref:set_inventory_formspec(form)
|
|
elseif fields.inv then
|
|
data.ccol=nil
|
|
ref:set_inventory_formspec(formI)
|
|
end
|
|
for k,v in pairs(fields) do
|
|
local x,y=k:match("mapzoom_([^_]+)_([^_]+)")
|
|
x,y=tonumber(x),tonumber(y)
|
|
if x and y and map~="" then
|
|
local xx=math.floor(math.max(1,math.min(cw-zw+1,x*zs+zo)))
|
|
local yy=math.floor(math.max(1,math.min(cw-zw+1,y*zs+zo)))
|
|
local img={}
|
|
local ii=0
|
|
for y=yy,yy+zw-1 do
|
|
for x=xx,xx+zw-1 do
|
|
ii=ii+1
|
|
local dat=mapdata[y] and mapdata[y][x]
|
|
img[ii]=dat or nullcol
|
|
end end
|
|
local form=formM1:format(minetest.formspec_escape("[png:"..minetest.encode_base64(minetest.encode_png(zw,zw,img))),k)
|
|
ref:set_inventory_formspec(form)
|
|
end
|
|
end
|
|
end)
|
|
minetest.register_on_joinplayer(function(ref)
|
|
local name=ref:get_player_name()
|
|
if not name then return end
|
|
local privs=minetest.get_player_privs(name)
|
|
privs.fly=true
|
|
privs.fast=true
|
|
minetest.set_player_privs(name,privs)
|
|
local inv=ref:get_inventory()
|
|
inv:set_size("craft",0)
|
|
inv:set_size("craftpreview",0)
|
|
inv:set_size("craftresult",0)
|
|
inv:set_size("main",9*4)
|
|
local list=inv:get_list("main") or {}
|
|
for n=1,9*4 do
|
|
if not list[n] or list[n]:get_count()==0 then
|
|
list[n]=ItemStack(colnode(md,md,md))
|
|
end
|
|
end
|
|
inv:set_list("main",list)
|
|
ref:set_inventory_formspec(formI)
|
|
ref:hud_set_hotbar_itemcount(9)
|
|
ref:set_physics_override{speed=4}
|
|
ref:set_sky{
|
|
type="plain",
|
|
base_color={r=128,g=128,b=255},
|
|
clouds=false
|
|
}
|
|
ref:set_moon{visible=false}
|
|
ref:set_sun{visible=false,sunrise_visible=false}
|
|
ref:set_stars{
|
|
day_opacity=1
|
|
}
|
|
ref:set_armor_groups{immortal=1}
|
|
ref:hud_set_flags({
|
|
basic_debug=true,
|
|
healthbar=false,
|
|
breathbar=false,
|
|
})
|
|
local function no()
|
|
return 0
|
|
end
|
|
pldata[name]={
|
|
pldinv=minetest.create_detached_inventory("colors_"..name,{
|
|
allow_put=no,
|
|
allow_take=no,
|
|
allow_move=no
|
|
},name)
|
|
}
|
|
sendworld(name)
|
|
ref:override_day_night_ratio(1)
|
|
end)
|
|
minetest.register_on_leaveplayer(function(ref)
|
|
local name=ref:get_player_name()
|
|
minetest.remove_detached_inventory("colors_"..name)
|
|
pldata[name]=nil
|
|
end)
|