@dave1707, I’ve updated the code above so that you control YOUR player and not get mixed with anybody else’s player. Also, I will start to work on that issue you brought up.
@Creator27 I got 2 spheres on each iPad no matter how many times I tapped on join.
@dave1707, hopefully this code works. When you close the project, the client leaving should send a message to the server, which will send a server to all other clients and tell them to remove that entity. Here is the code:
function setup()
scene = craft.scene()
craft.scene.main = scene
socket = require("socket")
messenger = socket.udp()
messenger:setoption("broadcast", true)
messenger:settimeout(0)
parameter.action("Host", createServer)
entities = {}
my_client = nil
client_entities = {}
my_entity = nil
connected = false
client_count = 0
my_server = {server = nil, entities = {}, client_data = {}, ids = {}}
-- Something to land on so the clients dont fall endlessly into the void
ground = scene:entity()
ground.model = craft.model(asset.builtin.Primitives.RoundedCube)
ground.position = vec3(0, -2, 10)
ground.scale = vec3(10, 0.1, 10)
gbody = ground:add(craft.rigidbody, STATIC)
ground:add(craft.shape.model, ground.model)
-- Setup camera
scene.camera.position = vec3(0, 8, -10)
scene.camera.rotation = quat.eulerAngles(25, 0, 0)
end
function joinServer(ip, port)
if my_client == nil then
local client = socket.udp()
client:settimeout(0)
my_client = client
client:setpeername(ip, port)
client:send("join"..string.sub(tostring(client), 17, #tostring(client)))
parameter.action("Disconnect", function() disconnectFromServer() end)
end
end
function receiveUpdate()
if my_client ~= nil then
local data = my_client:receive()
if data ~= nil then
if string.find(data, "somebody joined") then
local entity = makePlayer(vec3(0, 0, 10))
table.insert(client_entities, entity)
elseif string.find(data, "you joined") then
local c = string.match(data, "%d")
local tab = json.decode(string.sub(data, 11 + #c, #data))
-- Make your player first
local your_player = makePlayer(vec3(0, 0, 10), my_client)
table.insert(client_entities, your_player)
-- Then, make everybody else's player
for i = 1, (tonumber(c) - 1) do
local other_player = makePlayer(vec3(0, 0, 10))
table.insert(client_entities, other_player)
end
elseif string.find(data, "remove player") then
for i,e in pairs(client_entities) do
if e.status == "disconnected" then
e:destroy()
end
end
end
end
end
end
function willClose()
disconnectFromServer()
end
function disconnectFromServer()
if my_client ~= nil then
my_entity.status = "disconnected"
my_client:send("disconnected")
my_client:close()
my_client = nil
my_entity = nil
parameter.clear()
parameter.action("Host", createServer)
for i,e in pairs(client_entities) do
e:destroy()
end
end
end
function createServer()
if my_server.server == nil then
server = socket.udp()
server:setsockname("*", 14285)
server:setoption("broadcast", true)
server:settimeout(0)
my_server.server = server
server_name = Server_Name
end
end
function stopServer()
if my_server ~= nil then
server:close()
end
end
function makePlayer(pos, client)
if not entities[entity] then
entity = scene:entity()
entity.model = craft.model(asset.builtin.Primitives.Sphere)
entity.position = pos
entity.scale = vec3(0.7, 0.7, 0.7)
body = entity:add(craft.rigidbody, DYNAMIC)
entity:add(craft.shape.sphere, 0.85)
entity.material = craft.material(asset.builtin.Materials.Specular)
entity.material.diffuse = color(math.random(0, 255), math.random(0, 255), math.random(0, 255))
body.linearDamping = 0.3
table.insert(entities, entity)
if my_entity == nil then
my_entity = entity
end
if client ~= nil then
entity.master = client
end
entity.status = "connected to server"
return entity
end
end
function touched(touch)
if touch.state == MOVING then
if touch.deltaX > 0 then
for i,e in pairs(entities) do
if e == my_entity then
e:get(craft.rigidbody):applyForce(vec3(-30, 0, 0))
end
end
elseif touch.deltaX < 0 then
for i,e in pairs(entities) do
if e == my_entity then
e:get(craft.rigidbody):applyForce(vec3(30, 0, 0))
end
end
elseif touch.deltaY > 0 then
for i,e in pairs(entities) do
if e == my_entity then
e:get(craft.rigidbody):applyForce(vec3(0, 0, 30))
end
end
elseif touch.deltaY < 0 then
for i,e in pairs(entities) do
if e == my_entity then
e:get(craft.rigidbody):applyForce(vec3(0, 0, -30))
end
end
end
elseif touch.state == BEGAN then
if touch.tapCount == 2 then
for i,e in pairs(entities) do
if e == my_entity then
e:get(craft.rigidbody):applyForce(vec3(0, 450, 0))
end
end
end
end
end
function draw()
if my_client == nil then
messenger:sendto("checking for servers", "255.255.255.255", "14285")
end
if my_server.server ~= nil then
local data, ip, port = my_server.server:receivefrom()
if data == "checking for servers" then
my_server.server:sendto("server available", ip, port)
elseif data ~= nil then
if string.find(data, "join") then
local uid = {ip = ip, port = port}
if not my_server.client_data[uid] then
table.insert(my_server.client_data, uid)
end
for i,c in pairs(my_server.client_data) do
if c ~= uid then
my_server.server:sendto("somebody joined", c.ip, c.port)
else
my_server.server:sendto("you joined"..tostring(#my_server.client_data)..json.encode(uid), c.ip, c.port)
end
end
elseif string.find(data, "disconnected") then
local uid = {ip = ip, port = port}
for i,c in pairs(my_server.client_data) do
if c ~= uid then
my_server.server:sendto("remove player", c.ip, c.port)
end
end
table.remove(my_server.client_data, my_server.client_data[uid])
else
print(data)
end
end
end
if my_client == nil then
local data, ip, port = messenger:receivefrom()
if data ~= nil then
if data == "server available" then
parameter.action(tostring(ip).." - Join", function() joinServer(ip, port) end)
end
end
end
receiveUpdate()
end
@dave1707, I’ve just updated the code above so it hopefully works, because it wasn’t before.
@Creator27 I only got 1 sphere per iPad no matter how many times I tapped on join. Each sphere disappeared on the iPad that I pressed disconnect on.
@dave1707, I have programmed the game so that hopefully, each client should send the server it’s position and then the server should send everybody else the coordinates and each client would update each sphere on their device accordingly. Here’s the code:
function setup()
scene = craft.scene()
craft.scene.main = scene
socket = require("socket")
messenger = socket.udp()
messenger:setoption("broadcast", true)
messenger:settimeout(0)
parameter.action("Host", createServer)
entities = {}
my_client = nil
my_entity = nil
client_entities = {}
my_server = {server = nil, clients = {}, client_data = {}, ids = {}}
-- Something to land on so the clients dont fall endlessly into the void
ground = scene:entity()
ground.model = craft.model(asset.builtin.Primitives.RoundedCube)
ground.position = vec3(0, -2, 10)
ground.scale = vec3(10, 0.1, 10)
gbody = ground:add(craft.rigidbody, STATIC)
ground:add(craft.shape.model, ground.model)
-- Setup camera
scene.camera.position = vec3(0, 8, -10)
scene.camera.rotation = quat.eulerAngles(25, 0, 0)
end
function joinServer(ip, port)
if my_client == nil then
local client = socket.udp()
client:settimeout(0)
my_client = client
client:setpeername(ip, port)
client:send("join"..string.sub(tostring(client), 17, #tostring(client)))
end
end
function receiveUpdate()
if my_client ~= nil then
local data = my_client:receive()
if data ~= nil then
if string.find(data, "somebody joined") then
makeOtherPlayer(vec3(0, 0, 10))
elseif string.find(data, "you joined") then
local c = string.match(data, "%d")
local tab = json.decode(string.sub(data, 11 + #c, #data))
-- Make your player first
makeYourPlayer(vec3(0, 0, 10))
-- Then, make everybody else's player
for i = 1, (tonumber(c) - 1) do
makeOtherPlayer(vec3(0, 0, 10))
end
elseif string.find(data, "new player position") then
-- We first convert the message into the table that contains the new set of coordinates
local tab = json.decode(string.sub(data, 20, #data))
for i,e in pairs(client_entities) do
if tostring(e) == tab.entity then
e.position = vec3(tab.x, tab.y, tab.z)
end
end
end
end
if my_entity ~= nil then
local tab = {x = my_entity.position.x, y = my_entity.position.y, z = my_entity.position.z, entity = tostring(my_entity)}
my_client:send("player position"..json.encode(tab))
end
end
end
function createServer()
if my_server.server == nil then
server = socket.udp()
server:setsockname("*", 14285)
server:setoption("broadcast", true)
server:settimeout(0)
my_server.server = server
server_name = Server_Name
end
end
function makeYourPlayer(pos)
entity = scene:entity()
entity.model = craft.model(asset.builtin.Primitives.Sphere)
entity.position = pos
entity.scale = vec3(0.7, 0.7, 0.7)
body = entity:add(craft.rigidbody, DYNAMIC)
entity:add(craft.shape.sphere, 0.85)
entity.material = craft.material(asset.builtin.Materials.Specular)
entity.material.diffuse = color(math.random(0, 255), math.random(0, 255), math.random(0, 255))
body.linearDamping = 0.3
my_entity = entity
table.insert(client_entities, entity)
end
function makeOtherPlayer(pos)
entity = scene:entity()
entity.model = craft.model(asset.builtin.Primitives.Sphere)
entity.position = pos
entity.scale = vec3(0.7, 0.7, 0.7)
body = entity:add(craft.rigidbody, DYNAMIC)
entity:add(craft.shape.sphere, 0.85)
entity.material = craft.material(asset.builtin.Materials.Specular)
entity.material.diffuse = color(math.random(0, 255), math.random(0, 255), math.random(0, 255))
body.linearDamping = 0.3
table.insert(client_entities, entity)
end
function touched(touch)
if touch.state == MOVING then
if touch.deltaX > 0 then
for i,e in pairs(client_entities) do
if e == my_entity then
e:get(craft.rigidbody):applyForce(vec3(-30, 0, 0))
end
end
elseif touch.deltaX < 0 then
for i,e in pairs(client_entities) do
if e == my_entity then
e:get(craft.rigidbody):applyForce(vec3(30, 0, 0))
end
end
elseif touch.deltaY > 0 then
for i,e in pairs(client_entities) do
if e == my_entity then
e:get(craft.rigidbody):applyForce(vec3(0, 0, 30))
end
end
elseif touch.deltaY < 0 then
for i,e in pairs(client_entities) do
if e == my_entity then
e:get(craft.rigidbody):applyForce(vec3(0, 0, -30))
end
end
end
elseif touch.state == BEGAN then
if touch.tapCount == 2 then
for i,e in pairs(entities) do
if e == my_entity then
e:get(craft.rigidbody):applyForce(vec3(0, 450, 0))
end
end
end
end
end
function draw()
if my_client == nil then
messenger:sendto("checking for servers", "255.255.255.255", "14285")
end
if my_server.server ~= nil then
local data, ip, port = my_server.server:receivefrom()
if data == "checking for servers" then
my_server.server:sendto("server available", ip, port)
elseif data ~= nil then
if string.find(data, "join") then
local uid = {ip = ip, port = port}
if not my_server.client_data[uid] then
table.insert(my_server.client_data, uid)
end
for i,c in pairs(my_server.client_data) do
if c ~= uid then
my_server.server:sendto("somebody joined", c.ip, c.port)
else
my_server.server:sendto("you joined"..tostring(#my_server.client_data)..json.encode(uid), c.ip, c.port)
end
end
elseif string.find(data, "player position") then
local uid = {ip = ip, port = port}
local tab = string.sub(data, 16, #data)
for i,c in pairs(my_server.client_data) do
if c ~= uid then
my_server.server:sendto("new player position"..tab, c.ip, c.port)
end
end
end
end
end
if my_client == nil then
local data, ip, port = messenger:receivefrom()
if data ~= nil then
if data == "server available" then
parameter.action(tostring(ip).." - Join", function() joinServer(ip, port) end)
end
end
end
receiveUpdate()
end
@Creator27 There are 3 spheres on each iPad with 2 of the spheres constantly redrawing themselves on top (near) each other. Tried to post a video, but it’s not allowed. A picture just shows 2 spheres. So it looks like the 2 spheres are really just 1 sphere but constantly redrawing itself in different positions, but close to each other.
What format video did you try to post? I can see if I can change the allowed file extensions for the forums to include it
I’m just doing the screen video from Codea using the icon in the lower left of the screen. Here’s a picture of the info of the video and the message I get when I try to include it.
@dave1707, after a long break from the project I have tried once again to sync player positions across every device connected to the current server/s. Here’s the code:
function setup()
scene = craft.scene()
craft.scene.main = scene
socket = require("socket")
messenger = socket.udp()
messenger:setoption("broadcast", true)
messenger:settimeout(0)
parameter.action("Host", createServer)
parameter.text("Server Name", "")
parameter.text("Player Name", "")
servers = {}
client_entities = {}
my_client = nil
my_entity = nil
my_server = {server = nil, name = "", client_data = {}, master_client = nil}
-- Something to land on so the clients dont fall endlessly into the void
ground = scene:entity()
ground.model = craft.model(asset.builtin.Primitives.RoundedCube)
ground.position = vec3(0, -2, 10)
ground.scale = vec3(10, 0.1, 10)
gbody = ground:add(craft.rigidbody, STATIC)
ground:add(craft.shape.model, ground.model)
-- Setup camera
scene.camera.position = vec3(0, 8, -10)
scene.camera.rotation = quat.eulerAngles(25, 0, 0)
end
function joinServer(ip, port)
if Player_Name ~= "" then
if my_client == nil then
local client = socket.udp()
client:settimeout(0)
my_client = client
client:setpeername(ip, port)
client:send("join")
return client
end
else
print("Please enter a valid player name!")
end
end
function receiveUpdate()
if my_client ~= nil then
local data = my_client:receive()
if data ~= nil then
if string.find(data, "somebody joined") then
makePlayer(vec3(0, 0, 10))
elseif string.find(data, "you joined") then
local c = string.match(data, "%d")
local tab = json.decode(string.sub(data, 11 + #c, #data))
-- Make your player first
makePlayer(vec3(0, 0, 10))
-- Then, make everybody else's player
for i = 1, (tonumber(c) - 1) do
makePlayer(vec3(0, 0, 10))
end
elseif string.find(data, "new position for a player") then
local tab = json.decode(string.sub(data, 26, #data))
if my_entity.name == tab.entity then
print("its me, nothing happened")
else
for i,e in pairs(client_entities) do
if e.name == tab.entity and e ~= my_entity then
e.position = vec3(tab.x, tab.y, tab.z)
end
end
end
end
end
-- Continously send your position to the server
if my_entity ~= nil then
local tab = {x = my_entity.position.x, y = my_entity.position.y, z = my_entity.position.z, entity = my_entity.name}
tab = json.encode(tab)
my_client:send("my position"..tab)
end
end
end
function createServer()
if Server_Name ~= "" and Player_Name ~= "" then
if my_server.server == nil then
local server = socket.udp()
server:setsockname("*", 14285)
server:setoption("broadcast", true)
server:settimeout(0)
my_server.server = server
my_server.name = Server_Name
local ip, port = server:getsockname()
local client = joinServer(ip, port)
my_server.master_client = client
end
else
print("You need to include a name for the server!")
end
end
function stopServer()
if my_server ~= nil then
server:close()
end
end
function makePlayer(pos)
if not client_entities[entity] then
entity = scene:entity()
entity.model = craft.model(asset.builtin.Primitives.RoundedCube)
entity.position = pos
entity.scale = vec3(0.5, 1, 0.5)
body = entity:add(craft.rigidbody, DYNAMIC)
body.angularFactor = vec3(0, 0, 0)
entity:add(craft.shape.box, vec3(1.5, 2, 1.5))
entity.material = craft.material(asset.builtin.Materials.Specular)
entity.material.diffuse = color(math.random(0, 255), math.random(0, 255), math.random(0, 255))
if my_entity == nil then
my_entity = entity
end
entity.name = Player_Name
table.insert(client_entities, entity)
end
end
function touched(touch)
if touch.state == MOVING then
if touch.deltaX > 0 then
for i,e in pairs(client_entities) do
if e == my_entity then
e:get(craft.rigidbody):applyForce(vec3(-15, 0, 0))
end
end
elseif touch.deltaX < 0 then
for i,e in pairs(client_entities) do
if e == my_entity then
e:get(craft.rigidbody):applyForce(vec3(15, 0, 0))
end
end
elseif touch.deltaY > 0 then
for i,e in pairs(client_entities) do
if e == my_entity then
e:get(craft.rigidbody):applyForce(vec3(0, 0, 15))
end
end
elseif touch.deltaY < 0 then
for i,e in pairs(client_entities) do
if e == my_entity then
e:get(craft.rigidbody):applyForce(vec3(0, 0, -15))
end
end
end
elseif touch.state == BEGAN then
if touch.tapCount == 2 then
for i,e in pairs(client_entities) do
if e == my_entity then
e:get(craft.rigidbody):applyForce(vec3(0, 450, 0))
end
end
end
end
end
function draw()
if my_client == nil then
messenger:sendto("checking for servers", "255.255.255.255", "14285")
end
if my_server.server ~= nil then
local data, ip, port = my_server.server:receivefrom()
if data == "checking for servers" then
my_server.server:sendto("server available"..my_server.name, ip, port)
elseif data ~= nil then
if string.find(data, "join") then
local uid = {ip = ip, port = port}
if not my_server.client_data[uid] then
table.insert(my_server.client_data, uid)
end
for i,c in pairs(my_server.client_data) do
if c ~= uid then
my_server.server:sendto("somebody joined", c.ip, c.port)
else
my_server.server:sendto("you joined"..tostring(#my_server.client_data)..json.encode(uid), c.ip, c.port)
end
end
elseif string.find(data, "my position") then
local uid = {ip = ip, port = port}
local tab = string.sub(data, 12, #data)
for i,c in pairs(my_server.client_data) do
if c ~= uid then
my_server.server:sendto("new position for a player"..tab, c.ip, c.port)
end
end
end
end
end
if my_client == nil then
local data, ip, port = messenger:receivefrom()
if data ~= nil then
if string.find(data, "server available") then
local server_name = string.sub(data, 17, #data)
local new_server = {ip = ip, port = port, name = server_name}
if not servers[new_server] then
table.insert(servers, new_server)
end
for i,s in pairs(servers) do
parameter.action(s.name.." - Join", function() joinServer(s.ip, s.port) end)
end
end
end
end
receiveUpdate()
end
When I run the code, I get 2 objects on each device. I can move 1 object to push the other around, but what I do on one device doesn’t affect anything on the other device.
@dave1707, try this instead I added one minor change:
function setup()
scene = craft.scene()
craft.scene.main = scene
socket = require("socket")
messenger = socket.udp()
messenger:setoption("broadcast", true)
messenger:settimeout(0)
parameter.action("Host", createServer)
parameter.text("Server Name", "")
parameter.text("Player Name", "")
servers = {}
client_entities = {}
my_client = nil
my_entity = nil
my_server = {server = nil, name = "", client_data = {}, master_client = nil}
-- Something to land on so the clients dont fall endlessly into the void
ground = scene:entity()
ground.model = craft.model(asset.builtin.Primitives.RoundedCube)
ground.position = vec3(0, -2, 10)
ground.scale = vec3(10, 0.1, 10)
gbody = ground:add(craft.rigidbody, STATIC)
ground:add(craft.shape.model, ground.model)
-- Setup camera
scene.camera.position = vec3(0, 8, -10)
scene.camera.rotation = quat.eulerAngles(25, 0, 0)
end
function joinServer(ip, port)
if Player_Name ~= "" then
if my_client == nil then
local client = socket.udp()
client:settimeout(0)
my_client = client
client:setpeername(ip, port)
client:send("join")
return client
end
else
print("Please enter a valid player name!")
end
end
function receiveUpdate()
if my_client ~= nil then
local data = my_client:receive()
if data ~= nil then
if string.find(data, "somebody joined") then
makePlayer(vec3(0, 0, 10))
elseif string.find(data, "you joined") then
local c = string.match(data, "%d")
local tab = json.decode(string.sub(data, 11 + #c, #data))
-- Make your player first
makePlayer(vec3(0, 0, 10))
-- Then, make everybody else's player
for i = 1, (tonumber(c) - 1) do
makePlayer(vec3(0, 0, 10))
end
elseif string.find(data, "new position for a player") then
local tab = json.decode(string.sub(data, 26, #data))
if my_entity.name == tab.entity then
print("its me, nothing happened")
else
for i,e in pairs(client_entities) do
if e.name == tab.entity and e ~= my_entity then
e.position = vec3(tab.x, tab.y, tab.z)
end
end
end
end
end
-- Continously send your position to the server
if my_entity ~= nil then
local tab = {x = my_entity.position.x, y = my_entity.position.y, z = my_entity.position.z, entity = my_entity.name}
tab = json.encode(tab)
my_client:send("my position"..tab)
end
end
end
function createServer()
if Server_Name ~= "" and Player_Name ~= "" then
if my_server.server == nil then
local server = socket.udp()
server:setsockname("*", 14285)
server:setoption("broadcast", true)
server:settimeout(0)
my_server.server = server
my_server.name = Server_Name
local ip, port = server:getsockname()
local client = joinServer(ip, port)
my_server.master_client = client
end
else
print("You need to include a name for the server!")
end
end
function stopServer()
if my_server ~= nil then
server:close()
end
end
function makePlayer(pos)
if not client_entities[entity] then
entity = scene:entity()
entity.model = craft.model(asset.builtin.Primitives.RoundedCube)
entity.position = pos
entity.scale = vec3(0.5, 1, 0.5)
body = entity:add(craft.rigidbody, DYNAMIC)
body.angularFactor = vec3(0, 0, 0)
entity:add(craft.shape.box, vec3(1.5, 2, 1.5))
entity.material = craft.material(asset.builtin.Materials.Specular)
entity.material.diffuse = color(math.random(0, 255), math.random(0, 255), math.random(0, 255))
if my_entity == nil then
my_entity = entity
end
entity.name = Player_Name
table.insert(client_entities, entity)
end
end
function touched(touch)
if touch.state == MOVING then
if touch.deltaX > 0 then
for i,e in pairs(client_entities) do
if e == my_entity then
e:get(craft.rigidbody):applyForce(vec3(-15, 0, 0))
end
end
elseif touch.deltaX < 0 then
for i,e in pairs(client_entities) do
if e == my_entity then
e:get(craft.rigidbody):applyForce(vec3(15, 0, 0))
end
end
elseif touch.deltaY > 0 then
for i,e in pairs(client_entities) do
if e == my_entity then
e:get(craft.rigidbody):applyForce(vec3(0, 0, 15))
end
end
elseif touch.deltaY < 0 then
for i,e in pairs(client_entities) do
if e == my_entity then
e:get(craft.rigidbody):applyForce(vec3(0, 0, -15))
end
end
end
elseif touch.state == BEGAN then
if touch.tapCount == 2 then
for i,e in pairs(client_entities) do
if e == my_entity then
e:get(craft.rigidbody):applyForce(vec3(0, 450, 0))
end
end
end
end
end
function draw()
if my_client == nil then
messenger:sendto("checking for servers", "255.255.255.255", "14285")
end
if my_server.server ~= nil then
local data, ip, port = my_server.server:receivefrom()
if data == "checking for servers" then
my_server.server:sendto("server available"..my_server.name, ip, port)
elseif data ~= nil then
if string.find(data, "join") then
local uid = {ip = ip, port = port}
if not my_server.client_data[uid] then
table.insert(my_server.client_data, uid)
end
for i,c in pairs(my_server.client_data) do
if c ~= uid then
my_server.server:sendto("somebody joined", c.ip, c.port)
else
my_server.server:sendto("you joined"..tostring(#my_server.client_data)..json.encode(uid), c.ip, c.port)
end
end
elseif string.find(data, "my position") then
local uid = {ip = ip, port = port}
local tab = string.sub(data, 12, #data)
for i,c in pairs(my_server.client_data) do
my_server.server:sendto("new position for a player"..tab, c.ip, c.port)
end
end
end
end
if my_client == nil then
local data, ip, port = messenger:receivefrom()
if data ~= nil then
if string.find(data, "server available") then
local server_name = string.sub(data, 17, #data)
local new_server = {ip = ip, port = port, name = server_name}
if not servers[new_server] then
table.insert(servers, new_server)
end
for i,s in pairs(servers) do
parameter.action(s.name.." - Join", function() joinServer(s.ip, s.port) end)
end
end
end
end
receiveUpdate()
end
Now there’s only 1 object on each device.
@dave1707, when two players join the game, the second player should see every other player as usual, but instead they should be in the position they spawned in when they joined the game.
function setup()
scene = craft.scene()
craft.scene.main = scene
socket = require("socket")
messenger = socket.udp()
messenger:setoption("broadcast", true)
messenger:settimeout(0)
parameter.action("Host", createServer)
parameter.text("Server Name", "")
parameter.text("Player Name", "")
servers = {}
client_entities = {}
your_name = ""
my_client = nil
my_entity = nil
my_server = {server = nil, name = "", client_data = {}, master_client = nil, entities = {}}
-- Something to land on so the clients dont fall endlessly into the void
ground = scene:entity()
ground.model = craft.model(asset.builtin.Primitives.RoundedCube)
ground.position = vec3(0, -2, 10)
ground.scale = vec3(10, 0.1, 10)
gbody = ground:add(craft.rigidbody, STATIC)
ground:add(craft.shape.model, ground.model)
-- Setup camera
scene.camera.position = vec3(0, 8, -10)
scene.camera.rotation = quat.eulerAngles(25, 0, 0)
end
function joinServer(ip, port)
if Player_Name ~= "" then
if my_client == nil then
local client = socket.udp()
client:settimeout(0)
my_client = client
client:setpeername(ip, port)
client:send("join")
return client
end
else
print("Please enter a valid player name!")
end
end
function receiveUpdate()
if my_client ~= nil then
local data = my_client:receive()
if data ~= nil then
if string.find(data, "somebody joined") then
makePlayer(vec3(0, 0, 10))
elseif string.find(data, "you joined") then
local c = string.match(data, "%d")
local tab = json.decode(string.sub(data, 11 + #c, #data))
-- Make your player first
makePlayer(vec3(0, 0, math.random(-4, 19)))
-- Then, make everybody else's player
for i = 1, (tonumber(c) - 1) do
makePlayer(vec3(0, 0, math.random(-4, 19)))
end
elseif string.find(data, "client positions") then
local tab = json.decode(string.sub(data, 17, #data))
for i,e in pairs(tab) do
local entity = json.decode(e)
if client_entities[i].name == entity.name then
client_entities[i].position = vec3(entity.x, entity.y, entity.z)
end
end
end
end
end
end
function createServer()
if Server_Name == "" then
print("Please enter a name for the server")
elseif Player_Name == "" then
print("Please enter a valid player name")
else
if my_server.server == nil then
local server = socket.udp()
server:setsockname("*", 14285)
server:setoption("broadcast", true)
server:settimeout(0)
my_server.server = server
my_server.name = Server_Name
local ip, port = server:getsockname()
local client = joinServer(ip, port)
my_server.master_client = client
end
end
end
function stopServer()
if my_server ~= nil then
server:close()
end
end
function makePlayer(pos)
if not client_entities[entity] then
entity = scene:entity()
entity.model = craft.model(asset.builtin.Primitives.RoundedCube)
entity.position = pos
entity.scale = vec3(0.5, 1, 0.5)
body = entity:add(craft.rigidbody, DYNAMIC)
body.angularFactor = vec3(0, 0, 0)
entity:add(craft.shape.box, vec3(1.5, 2, 1.5))
entity.material = craft.material(asset.builtin.Materials.Specular)
entity.material.diffuse = color(math.random(0, 255), math.random(0, 255), math.random(0, 255))
if my_entity == nil then
my_entity = entity
end
entity.name = Player_Name
your_name = Player_Name
table.insert(client_entities, entity)
local tab = {x = pos.x, y = pos.y, z = pos.z}
my_client:send("add player to server"..json.encode(tab))
return entity
end
end
function touched(touch)
if touch.state == MOVING then
if touch.deltaX > 0 then
for i,e in pairs(client_entities) do
if e == my_entity then
e:get(craft.rigidbody):applyForce(vec3(-15, 0, 0))
end
end
elseif touch.deltaX < 0 then
for i,e in pairs(client_entities) do
if e == my_entity then
e:get(craft.rigidbody):applyForce(vec3(15, 0, 0))
end
end
elseif touch.deltaY > 0 then
for i,e in pairs(client_entities) do
if e == my_entity then
e:get(craft.rigidbody):applyForce(vec3(0, 0, 15))
end
end
elseif touch.deltaY < 0 then
for i,e in pairs(client_entities) do
if e == my_entity then
e:get(craft.rigidbody):applyForce(vec3(0, 0, -15))
end
end
end
elseif touch.state == BEGAN then
if touch.tapCount == 2 then
for i,e in pairs(client_entities) do
if e == my_entity then
e:get(craft.rigidbody):applyForce(vec3(0, 450, 0))
end
end
end
end
end
function draw()
if my_client == nil then
messenger:sendto("checking for servers", "255.255.255.255", "14285")
end
if my_server.server ~= nil then
local data, ip, port = my_server.server:receivefrom()
if data == "checking for servers" then
my_server.server:sendto("server available"..my_server.name, ip, port)
elseif data ~= nil then
if string.find(data, "join") then
local uid = {ip = ip, port = port}
if not my_server.client_data[uid] then
table.insert(my_server.client_data, uid)
end
for i,c in pairs(my_server.client_data) do
if c ~= uid then
my_server.server:sendto("somebody joined", c.ip, c.port)
else
my_server.server:sendto("you joined"..tostring(#my_server.client_data)..json.encode(uid), c.ip, c.port)
end
end
elseif string.find(data, "add player to server") then
local tab = json.decode(string.sub(data, 21, #data))
local entity = {name = your_name, x = tab.x, y = tab.y, z = tab.z}
if not my_server.entities[entity] then
if not my_server.entities[entity] then
table.insert(my_server.entities, entity)
end
end
local tab = {}
for i,e in pairs(my_server.entities) do
if not tab[json.encode(e)] then
table.insert(tab, json.encode(e))
end
end
for i,c in pairs(my_server.client_data) do
my_server.server:sendto("client positions"..json.encode(tab), c.ip, c.port)
end
end
end
end
if my_client == nil then
local data, ip, port = messenger:receivefrom()
if data ~= nil then
if string.find(data, "server available") then
local server_name = string.sub(data, 17, #data)
local new_server = {ip = ip, port = port, name = server_name}
if not servers[new_server] then
table.insert(servers, new_server)
end
for i,s in pairs(servers) do
parameter.action(s.name.." - Join", function() joinServer(s.ip, s.port) end)
end
end
end
end
receiveUpdate()
end
Only one rounded cube per iPad is showing. Maybe you should wait until you have access to 2 iPads/iPhones, that would make it a lot easier for you to see what’s happening. It doesn’t seem like you’re making any progress, but then I’m not really sure what you’re trying to do anyways.
@dev1707, I have started a completely new multiplayer project with code that was taken from somebody else who made me a simple multiplayer project and was slightly tweaked/changed to fit what I wanted. Nothing happens so far, but I just want to you to see if you can get a print statement saying “Successfully connected to the server!” on one iPad. Here’s the code:
function setup()
socket = require("socket")
parameter.action("Create Room", createRoom)
parameter.action("Join Room", function()
if other_ip and other_port then
joinRoom(other_ip, other_port)
else
parameter.text("IP", "", function(t)
other_ip = t
end)
parameter.text("Port", "", function(t)
other_port = t
end)
end
end)
client = socket.udp()
client:settimeout(0)
other_ip, other_port = nil, nil
current_time = nil
server = false
end
function createRoom()
-- We need to find your address, so we create a new UDP socket and assign it a random IP
local udp = socket.udp()
udp:setpeername("192.167.188.122", "14285")
local ip, port = udp:getsockname()
udp:close()
client:setsockname(ip, port)
client:setoption("broadcast", true)
print("Server created!")
print("Connect to "..ip.." : "..port)
server = true
end
function joinRoom(ip, port)
if server == false then
print("Attempting to join the server...")
client:setpeername(ip, port)
client:send("connection confirmation")
current_time = os.time()
end
end
function receiveData()
if server == true then
local msg, ip, port = client:receivefrom()
if msg ~= nil then
if msg == "connection confirmation" then
client:sendto("valid confirmation", ip, port)
end
end
else
local result = client:receive()
if result == "valid confirmation" then
print("Successfully connected to server!")
current_time = nil
else
if current_time ~= nil then
if os.time() > current_time + 10 then
-- If we get no response back for 10 seconds or more, we know it didn't work
print("Failed to connect, please try again later")
current_time = nil
end
end
end
end
end
-- This function gets called once every frame
function draw()
-- This sets a dark background color
background(40, 40, 50)
-- This sets the line thickness
strokeWidth(5)
-- Do your drawing here
receiveData()
end
The only thing it would print was “Server created” and “Connect to” with an ip and port number. I tried different things with the Create Room and Join Room with different ip and port numbers but didn’t get anything different.
@dave1707, I have no hope that this will work at all, but I’ve added a “Find Room” button that will automatically find a room for you to join. I also changed the address that the server is set when you make a room to “*”, so it accepts any local address on the network. Here’s the code:
function setup()
socket = require("socket")
parameter.action("Create Room", createRoom)
parameter.action("Join Room", function()
if other_ip and other_port then
joinRoom(other_ip, other_port)
else
parameter.text("IP", "", function(t)
other_ip = t
end)
parameter.text("Port", "", function(t)
other_port = t
end)
end
end)
parameter.action("Find Room", function()
findRoom(current_room_count)
end)
client = socket.udp()
client:settimeout(0)
other_ip, other_port = nil, nil
current_time = nil
current_room_count = 1
tick = 0
finding_room = false
server = false
end
function createRoom()
-- We need to find your address, so we create a new UDP socket and assign it a random IP
local udp = socket.udp()
udp:setpeername("192.167.188.122", "14285")
local ip, port = udp:getsockname()
udp:close()
client:setsockname("*", "14285")
local ip2, port2 = client:getsockname()
client:setoption("broadcast", true)
your_ip = ip2
your_port = port2
print("Room created!")
print("Connect to "..ip.." : "..port2)
server = true
end
function joinRoom(ip, port)
print("Attempting to join the room...")
client:setpeername(ip, port)
client:send("connection confirmation")
current_time = os.time()
end
function findRoom(count)
if count == 1 then
print("Attempting to find a room...")
end
finding_room = true
-- We need to send a broadcast message to every room open, so we create a UDP socket and broadcast a packet
-- But first, we need to find your IP
local udp = socket.udp()
udp:setpeername("192.167.188.122", "14285")
local ip, port = udp:getsockname()
udp:close()
local ip1, ip2 = string.match(ip, "(%d+.%d+.%d+.)(%d+)")
client:setpeername(ip1..count, "14285")
client:send("connection confirmation")
current_time = tick
end
function receiveData()
if server == true then
local msg, ip, port = client:receivefrom()
if msg ~= nil then
if msg == "connection confirmation" then
client:sendto("valid confirmation", ip, port)
end
end
else
local result = client:receive()
if result == "valid confirmation" then
print("Successfully joined the room!")
current_time = nil
elseif result == nil then
if current_time ~= nil then
if finding_room == false then
if os.time() > current_time + 5 then
-- If we get no response back for 5 seconds or more, we know it didn't work
print("Failed to connect, please try again later")
current_time = nil
end
else
-- If the time limit has passed, we can check the next address for a room
if tick > current_time + 0.001 then
current_room_count = current_room_count + 1
if current_room_count < 256 then
findRoom(current_room_count)
end
end
end
end
end
end
end
-- This function gets called once every frame
function draw()
-- This sets a dark background color
background(40, 40, 50)
-- This sets the line thickness
strokeWidth(5)
-- Do your drawing here
receiveData()
tick = tick + 1
end
@Creator27 Got this error.
Main:71: calling ‘receivefrom’ on bad self (udp{unconnected} expected, got udp{connected})
stack traceback:
[C]: in method ‘receivefrom’
Main:71: in function ‘receiveData’
Main:113: in function ‘draw’
function setup()
socket = require("socket")
parameter.action("Create Room", createRoom)
parameter.action("Join Room", function()
if other_ip and other_port then
joinRoom(other_ip, other_port)
else
parameter.text("IP", "", function(t)
other_ip = t
end)
parameter.text("Port", "", function(t)
other_port = t
end)
end
end)
parameter.action("Find Room", function()
findRoom(current_room_count)
end)
client = socket.udp()
client:settimeout(0)
other_ip, other_port = nil, nil
current_time = nil
current_room_count = 1
tick = 0
finding_room = false
server = false
end
function createRoom()
-- We need to find your address, so we create a new UDP socket and assign it a random IP
local udp = socket.udp()
udp:setpeername("192.167.188.122", "14285")
local ip, port = udp:getsockname()
udp:close()
client:setsockname("*", "14285")
local ip2, port2 = client:getsockname()
client:setoption("broadcast", true)
your_ip = ip2
your_port = port2
print("Room created!")
print("Connect to "..ip.." : "..port2)
server = true
end
function joinRoom(ip, port)
if server == false then
print("Attempting to join the room...")
client:setpeername(ip, port)
client:send("connection confirmation")
current_time = os.time()
else
print("You are already hosting a room, so you can't join another!")
end
end
function findRoom(count)
if server == false then
if count == 1 then
print("Attempting to find a room...")
end
finding_room = true
-- We need to send a broadcast message to every room open, so we create a UDP socket and broadcast a packet
-- But first, we need to find your IP
local udp = socket.udp()
udp:setpeername("192.167.188.122", "14285")
local ip, port = udp:getsockname()
udp:close()
local ip1, ip2 = string.match(ip, "(%d+.%d+.%d+.)(%d+)")
client:setpeername(ip1..count, "14285")
client:send("connection confirmation")
current_time = tick
else
print("You are already hosting a server, so you can't join another!")
end
end
function receiveData()
if server == true then
local msg, ip, port = client:receivefrom()
if msg ~= nil then
if msg == "connection confirmation" then
client:sendto("valid confirmation", ip, port)
end
end
else
local result = client:receive()
if result == "valid confirmation" then
print("Successfully joined the room!")
current_time = nil
elseif result == nil then
if current_time ~= nil then
if finding_room == false then
if os.time() > current_time + 5 then
-- If we get no response back for 5 seconds or more, we know it didn't work
print("Failed to connect, please try again later")
current_time = nil
end
else
-- If the time limit has passed, we can check the next address for a room
if tick > current_time + 0.001 then
current_room_count = current_room_count + 1
if current_room_count < 256 then
findRoom(current_room_count)
end
end
end
end
end
end
end
-- This function gets called once every frame
function draw()
-- This sets a dark background color
background(40, 40, 50)
-- This sets the line thickness
strokeWidth(5)
-- Do your drawing here
receiveData()
tick = tick + 1
end