Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local Clients = {} -- Stores all info on each client. Clients X/Y is based on their screen cords. use x y for client itself.
- local ClientsNo = {}
- local Servers = {} -- ID's of all the servers which rebroadcast the game for more range
- local Maps = {} -- Stores maps in it in another table. Can host unlimited maps.
- local MapInfo = {} -- Stuff that was in the "Info:" This is so if there was a spawn then they spawn there. Or if you need to check so and so.
- local Data = {} -- Stores data on each map, Is there a enemy here? A pickup pack?
- local ViewMap = {} -- Every players viewable map is in here stored in its own seperate table
- local Spawn = {} -- Define the spawn for each map
- local DefaultMap = "Default" -- Map everyone first spawns on
- local ChangedLines = {} -- Stores lines changed so it can try update the map with min lag
- local ClientData = {"ID", "Name", "Map", "X", "Y", "Height", "Width"} -- Just add a bunch of names for each thingy so it knows it exists and can save it
- local Explosions = {}
- local MapSize = {}
- function setDefault(map)
- DefaultMap = map
- end
- function sendClients(Info) -- Send the clients the info. This sends them all it :\
- for n=1,#Clients do
- rednet.send(Clients[n], Info)
- end
- end
- function sendServers(Info) -- Send the servers the info. Sends them all of it.
- for n=1,#Servers do
- rednet.send(Servers[n], Info)
- end
- end
- function tag(sTag) -- Tags the messages so tagView can use it
- return "["..string.gsub(string.gsub(sTag, "%[", "~RightBracket~"), "%]", "~LeftBracket~").."]"
- end
- function tagView(msg) -- libraryaddict's little thingy ;D
- local ReturnMsg = msg
- local ReturnTag = {}
- if string.find(ReturnMsg, "%[") and string.find(ReturnMsg, "%]") then
- while true do
- first = string.find(ReturnMsg, "%[", 1)
- last = string.find(ReturnMsg, "%]", 2)
- if first and last then ReturnTag[#ReturnTag+1] = string.gsub(string.gsub(string.sub(ReturnMsg, first+1, last-1), "~RightBracket~", "%["), "~LeftBracket", "%]")
- ReturnMsg = string.sub(ReturnMsg, last+1, string.len(msg))
- else
- break
- end
- end
- ReturnTag[#ReturnTag+1] = ReturnMsg
- return unpack(ReturnTag)
- else
- return false
- end
- end
- function loadMap(MapName, TableName) -- Loads a map into a table, The info included is loaded into another table
- if not MapName then error("function loadMap, Please use loadMap(MapNameAndDir, TableNameYouWantToAccessItWith)") end
- if not fs.exists(MapName) then error("Please use a map that exists!") end
- Maps[TableName] = {}
- local MapLoadVari = io.open(MapName, "r")
- local i = 1
- local a = 0
- local b = 0
- local Returns = {}
- for line in MapLoadVari:lines() do
- if not string.sub(line, 1, 5) == "Info:" then
- Map[TableName][i] = line
- b = b+1
- if string.len(line) > a then
- a = string.len(line)
- end
- else
- Returns[#Returns+1] = string.sub(line, 6)
- end
- i = i+1
- end
- MapSize[TableName] = {}
- MapSize[TableName]["X"] = a
- MapSize[TableName]["Y"] = b
- loadObjects(TableName)
- Returns[#Returns+1] = TableName
- return unpack(Returns)
- end
- function setData(xInfo, yInfo, Map, InfoTable, InfoName, Info) -- Used for map data. Bahahaha confuse my stealers!
- local xInfo = tonumber(xInfo)
- local yInfo = tonumber(yInfo)
- if not Data[Map][yInfo] then
- Data[Map][yInfo] = {}
- end
- if not Data[Map][yInfo][xInfo] then
- Data[Map][yInfo][xInfo] = {}
- end
- if not Data[Map][yInfo][xInfo][InfoTable] then
- Data[Map][yInfo][xInfo][InfoTable] = {}
- end
- Data[Map][yInfo][xInfo][InfoTable][InfoName] = Info
- end
- function checkData(xInfo, yInfo, Map, InfoTable, InfoName) -- Return data at these cords.
- local xInfo = tonumber(xInfo)
- local yInfo = tonumber(yInfo)
- if InfoName then
- if Data[Map][yInfo][xInfo][InfoTable][InfoName] then
- return unpack(Data[Map][yInfo][xInfo][InfoTable][InfoName])
- end
- else
- if Data[Map][yInfo][xInfo][InfoTable] then
- return unpack(Data[Map][yInfo][xInfo][InfoTable])
- end
- end
- end
- function deleteData(xInfo, yInfo, Map, InfoTable)
- if Data[Map][yInfo][xInfo][InfoTable] then
- Data[Map][yInfo][xInfo][InfoTable] = nil
- end
- end
- function screenOptions(Locked, Width, Height, ID) -- No idea what screenlocked is gonna be good for, Locked must be true or false.
- Clients[ClientsNo[ID]]["LockedScreen"] = Locked
- Clients[ClientsNo[ID]]["ScreenWidth"] = Width
- Clients[ClientsNo[ID]]["ScreenHeight"] = Height
- end
- function moveScreen(Side, UpDown, ID, Map)
- if Clients[ClientsNo[ID]]["Y"]+UpDown >= 1 then
- Clients[ClientsNo[ID]]["Y"] = Clients[ClientsNo[ID]]["Y"]+UpDown
- elseif Clients[ClientsNo[ID]]["Y"]+UpDown <= MapSize[Map]["Y"] then
- Clients[ClientsNo[ID]]["Y"] = Clients[ClientsNo[ID]]["Y"]+UpDown
- else -- Wrap screen to edges.
- Clients[ClientsNo[ID]]["Y"] = MapSize[Map]["Y"]
- end
- if Clients[ClientsNo[ID]]["X"]+Side >= 1 then
- Clients[ClientsNo[ID]]["X"] = Clients[ClientsNo[ID]]["X"]+Side
- elseif Clients[ClientsNo[ID]]["X"]+Side <= MapSize[Map]["X"] then
- Clients[ClientsNo[ID]]["X"] = Clients[ClientsNo[ID]]["X"]+Side
- else -- wrap
- Clients[ClientsNo[ID]]["X"] = MapSize[Map]["X"]
- end
- draw("all", ID, Map)
- end
- function setSpawn(MapName, XCord, YCord)
- Spawn[MapName] = {}
- Spawn[MapName]["X"] = XCord
- Spawn[MapName]["Y"] = YCord
- end
- function playerDataLoad(Name, ID)
- if fs.exists("PlayerData/"..Name) then
- Clients[#Clients+1] = {}
- local PlayerLoad = io.open(Name, "r")
- Clients[#Clients] = textutils.unserialize(PlayerLoad.readAll())
- ClientsNo[ID] = #Clients
- return true
- end
- return false
- end
- function playerJoin(ID, Name) -- When they sucessfully join. Assign them info.
- if not playerDataLoad(Name, ID) then
- ClientsNo[ID] = #Clients+1
- Clients[ClientsNo[ID]] = {}
- print("h:"..ClientsNo[ID])
- Clients[ClientsNo[ID]]["Name"] = Name
- Clients[ClientsNo[ID]]["ID"] = ID
- setPlayerMap(ID, "OrigSpawn")
- end
- end
- function setPlayerMap(ID, Place, X, Y)
- if Place == "OrigSpawn" then
- Clients[ClientsNo[ID]]["Map"] = DefaultMap
- local x, y = getSpawn(DefaultMap)
- Clients[ClientsNo[ID]]["X"] = x
- Clients[ClientsNo[ID]]["Y"] = y
- else
- Clients[ClientsNo[ID]]["Map"] = Place
- Clients[ClientsNo[ID]]["X"] = X
- Clients[ClientsNo[ID]]["Y"] = Y
- end
- end
- function playerDataSave(Name, ID)
- if not fs.exists("PlayerData") then
- fs.makeDir("PlayerData")
- end
- local PlayerSaving = io.open("PlayerData/"..Name, "w")
- PlayerSaving:write(textutils.serialize(Clients[ClientsNo[ID]]))
- PlayerSaving:close()
- end
- function split(str, pat)
- local t = {} -- NOTE: use {n = 0} in Lua-5.0
- local fpat = "(.-)" .. pat
- local last_end = 1
- local s, e, cap = str:find(fpat, 1)
- while s do
- if s ~= 1 or cap ~= "" then
- table.insert(t,cap)
- end
- last_end = e+1
- s, e, cap = str:find(fpat, last_end)
- end
- if last_end <= #str then
- cap = str:sub(last_end)
- table.insert(t, cap)
- end
- return unpack(t)
- end
- function getSpawn(Map) -- Get the point newbies spawn at
- return Spawn[Map]["X"], Spawn[Map]["Y"]
- end
- function draw(Info, ClientNo, Map) -- redraws for the client. Does NOT send the info out! Does NOT edit the map! Well it prob have to send it..
- if not ClientNo then error("draw(Info, ClientNo, Map) ClientNo not found. ClientNo is needed") end
- if Info == "all" then -- Draw every single appropriate line for the client. They now see the proper screen! Basically forcing a complete redraw. Eg if the screen moved.
- ViewMap[ClientNo] = {} -- Reset client map data. They now see a blank screen
- for n=1,Clients[ClientNo]["ScreenHeight"] do -- Client number bla bla. This will do it for their screenheight amount
- ViewMap[ClientNo][n] = string.sub(Map[Clients[ClientNo]["Y"]+n], Clients[ClientNo]["X"], Clients[ClientNo]["ScreenWidth"])
- end
- elseif Info == "lines" then -- redraws a single line on their client. This should limit lag/flickering.
- for n=1,#ChangedLines do -- Gonna check with all the changed lines. But only the correct ones will be updated.
- local Stuff = {split(ChangedLines[n], ":")}
- if Clients[ClientNo]["Map"] == Stuff[1] then -- If the changed line is on the same map as the client
- --They are the same. You can now check if this client needs to see this line drawn. Or if its outside their screen scope
- -- OR I could just redraw it anyways >.>
- -- Wait a sec. The ChangedLines should just give the Map:Line:X thats being redrawn.
- -- So I need to check if the screen is in the X and Y of the changed.
- -- Could define each line like this. MAP:Y:X:X:X:X:X:X
- -- So the map got edited on line x. Each of these X's got edited. No way could it all be edited?
- -- I think I'll go with that
- if tonumber(Stuff[2]) >= Clients[ClientsNo[ID]]["Y"] and tonumber(Stuff[2]) <= Clients[ClientsNo[ID]]["Height"] then
- local p = 3
- repeat
- if tonumber(Stuff[p]) >= Clients[ClientsNo[ID]]["X"] and tonumber(Stuff[p]) <= Clients[ClientsNo[ID]]["Width"] then
- --Ok. So you can redraw that line..
- ViewMap[ClientNo][n] = string.sub(Map[Clients[ClientNo]["Map"]], Clients[ClientNo]["X"], Clients[ClientNo]["ScreenWidth"])
- p = p+1
- end
- until not Stuff[p]
- end
- end
- end
- end
- end
- function loadObjects(sTableName) -- Define the objects in here to be loaded into the data. This is for stuff like healthpacks etc defined with the map itself.
- if not sTableName then error("sTableName dont exist") end
- Objects = {"S", "L", "P"} -- Sample! Replace with your own. Letters it finds in the map..
- ObjectsData = {"Sample", "Libraryaddict", "Player"}
- for n=1,#Maps[sTableName] do -- For lines in that table do
- for q=1,string.len(Map[sTableName][n]) do
- local sLetter = string.sub(Map[sTableName][n], q, q)
- for p=1,#Objects do
- if Objects[p] == sLetter then
- setData(xInfo, yInfo, sTableName, ObjectsData[p], "Type", ObjectsData[p])
- end
- end
- end
- end
- end
- function editMap(xCord, yCord, Maps, Stuff) -- Edit data shown to player. Aka the map view. thingy.
- if Map[Maps][yCord] then
- Map[Maps][yCord] = string.sub(Map[Maps][yCord], 1, xCord-1)..Stuff..string.sub(Map[Maps][yCord], xCord+1, string.len(Map[Maps][yCord]))
- else error("editMap(), You wanted a yCord thats outside of the maps range.") end
- end
- function Tick() -- This defines the actions of everything that isnt the player. Eg explosion decay.
- spreadExplosion()
- MoveFired()
- MoveNPC()
- TheTick = os.startTimer(0.1)
- end
- function createExplosion(xCord, yCord, MapName, Spread, SpreadRate, DecayRate, Characters, ExplosionName, ...) -- All of this is needed. The "..." is directions. Use left, right, up, down if you want it to act like a normal explosion. ExplosionName is the kind of explosion this is, Eg. a nuke.
- --DataName is what you will see when you check Data
- setData(xInfo, yInfo, MapName, "Explosion", "Type", ExplosionName)
- local eNum = #Explosions+1
- Explosions[eNum] = {}
- local dirs = {...}
- local function def(sName, sData)
- Explosions[eNum][sName] = sData
- end
- for n=1,#dirs do
- dirs[n] = string.lower(dirs[n])
- if n == 5 then
- error("Why are there 5 sides? error at createExplosion()")
- end
- end
- for n=1,#dirs do
- if dirs[n] == "up" then
- def("Up", true)
- elseif dirs[n] == "down" then
- def("Down", true)
- elseif dirs[n] == "left" then
- def("Left", true)
- elseif dirs[n] == "right" then
- def("Right", true)
- end
- end
- def("Map", MapName)
- def("X", xCord)
- def("Y", yCord)
- def("Spread", Spread)
- def("Rate", SpreadRate)
- def("Decay", DecayRate)
- def("Char", Character)
- def("Name", ExplosionName)
- def("STimer", 0)
- def("DTimer", DecayRate)
- setData(Explosions[EN]["X"], Explosions[EN]["Y"], Explosions[EN]["Map"], "Explosion", "Type", "Explosion")
- doExplosion(eNum)
- end
- --Add dirs! This is check for when I get back
- function spreadExplosion() -- Finds all explosions and calls them. Pretty basic function but eh. I should stick this in Tick()
- for n=1,#Explosions do
- doExplosion(n)
- end
- end
- function deleteAllData(xInfo, yInfo, Map) -- Deletes all data there. Good for rewriting it :\
- Data[Map][yInfo][xInfo] = {}
- end
- function isSolid(xInfo, yInfo, Map)
- if checkData(xInfo, yInfo, Map, "Solid", "Solid") == "Solid" then
- return true
- else
- return false
- end
- end
- function setSolid(xInfo, yInfo, Map)
- setData(xInfo, yInfo, Map, "Solid", "Solid", "Solid")
- end
- function unsetSolid(xInfo, yInfo, Map)
- setData(xInfo, yInfo, Map, "Solid", "Solid", "Not Solid")
- end
- function returnSide(xCord, yCord, Side)
- local Side = string.lower(Side)
- if Side == "left" then
- return (xCord-1), yCord
- elseif Side == "right" then
- return (xCord+1), yCord
- elseif Side == "up" then
- return xCord, (yCord-1)
- elseif Side == "down" then
- return xCord, (yCord+1)
- end
- end
- function returnExplodeData(EN)
- local KO = {}
- if Explosions[EN] then
- for n,a in ipairs(Explosions[EN]) do
- KO[n] = a
- end
- end
- return unpack(KO)
- end
- function returnMap(ID)
- return unpack(ViewMap[ID])
- end
- --[[function doExplosion(EN) -- EN = ExplosionsNumber. This function auctally does the explosion checking.
- Explosions[EN]["STimer"] = Explosions[EN]["STimer"]-1
- Explosions[EN]["DTimer"] = Explosions[EN]["DTimer"]-1
- if Explosions[EN]["DTimer"] == 0 then -- Delete this one
- deleteData(Explosions[EN]["X"], Explosions[EN]["Y"], Explosions[EN]["Map"], "Explosion")
- table.remove(Explosions, EN)
- return
- end -- checkData(xInfo, yInfo, Map, InfoTable, InfoName)
- if Explosions[EN]["STimer"] <= 0 then--Spread
- Explosions[EN]["STimer"] = Explosions[EN]["SpreadRate"]
- local Side = {Explosions[EN]["Up"], Explosions[EN]["Down"], Explosions[EN]["Left"], Explosions[EN]["Right"]}
- local Sides = {Explosions[EN]["Up"], Explosions[EN]["Down"], Explosions[EN]["Left"], Explosions[EN]["Right"]}
- for n=1,Side do
- local PigSnout = math.random(1,#Side) -- function createExplosion(xCord, yCord, MapName, Spread, SpreadRate, DecayRate, Characters, ExplosionName, ...) -- All of this is needed. The "..." is directions. Use left, right, up, down if you want it to act like a normal explosion. ExplosionName is the kind of explosion this is, Eg. a nuke.
- if isSolid(returnSide(xInfo, yInfo, Side[PigSnout]), Map) == false then
- doExplosion(returnSide(xInfo, yInfo, Side[PigSnout])
- table.remove(Side, PigSnout)
- end
- end
- end
- end
- end]]
Advertisement
Add Comment
Please, Sign In to add comment