@Creator27 Just woke up, been sleeping all day. I tried your code on 1 iPad and 2 spheres showed up. Tried on 2 iPads and there were 2 spheres on both iPads but there was no communication between the 2 iPads.
@Creator27 This program when run on 2 iPads will move a circle on the other iPad as you move your finger on your iPad. Someone moving their finger on the other ipad would be moving the circle on your ipad. Since you only have 1 ipad, I commented out the if code in the function remoteDevice:getTheirIp so you’ll be sending messages to yourself. You can put print statements in the function remoteDevice:receiveTheirMessage() to see the messages being received. This is close to what you want to do in your code, so maybe if you see what’s happening here you can do it in yours.
I’m feeling a little better, so I though I’d try to help out a little.
viewer.mode=STANDARD
function setup()
mx,my=0,0
fill(255)
delay=0
rd=remoteDevice()
end
function draw()
background()
rd:getIp()
rd:receiveTheirMessage()
ellipse(mx,my,50)
end
function touched(t)
if t.state==BEGAN or t.state==CHANGED then
str=string.format("moveXY%04d%04d",t.x//1,t.y//1)
rd:sendMessage(str)
end
end
remoteDevice=class()
function remoteDevice:init()
self.socket=require("socket")
self.myIp="0.0.0.0"
self.theirIp="0.0.0.0"
self:getMyIp()
self:setMySocket()
self:setTheirSocket()
self:getTheirIp()
end
function remoteDevice:getIp()
if not gotMyIp or not gotTheirIp then
if delay>60 then
delay=0
if not gotMyIp then
rd:getMyIp()
end
if not gotTheirIp then
rd:getTheirIp()
end
end
delay=delay+1
end
end
function remoteDevice:setMySocket()
self.server=self.socket.udp()
self.server:setsockname(self.myIp,5544)
self.server:settimeout(0)
end
function remoteDevice:setTheirSocket()
self.client=self.socket.udp()
self.client:settimeout(0)
end
function remoteDevice:getMyIp()
self.server=self.socket.udp()
self.server:setpeername("1.1.1.1",80)
self.myIp,self.myPort=self.server:getsockname()
self.ip1,self.ip2=string.match(self.myIp,"(%d+.%d+.%d+.)(%d+)")
print("my IP = "..self.ip1..self.ip2)
gotMyIp=true
end
function remoteDevice:getTheirIp()
self.client=self.socket.udp()
self.client:settimeout(0)
-- send a message to everyone on this network except to myself
print("Getting their IP")
for z=1,255 do
--if z~=tonumber(self.ip2) then
self.client:setpeername(self.ip1..z,5544)
self.client:send("get their ip")
--end
end
end
function remoteDevice:receiveTheirMessage()
local data,msg,port=self.server:receivefrom()
if data~=nil then
if data=="get their ip" then
self.client=self.socket.udp()
self.client:settimeout(0)
self.client:setpeername(msg,5544)
self.client:send("got their ip"..self.myIp)
elseif string.sub(data,1,12)=="got their ip" then
self.theirIp=msg
print("their IP = "..self.theirIp)
viewer.mode=FULLSCREEN
gotTheirIp=true
elseif string.sub(data,1,6)=="moveXY" then
mx=string.sub(data,7,10)
my=string.sub(data,11,14)
end
end
end
function remoteDevice:sendMessage(tempStr)
self.client = self.socket.udp()
self.client:setpeername(self.theirIp,5544)
self.client:settimeout(0)
self.client:send(tempStr)
end
@dave1707, thank you for this it’s very helpful. Just one thing though, I only want to send a message to people that are connected to the server that you are on. Is there anyway to possibly do that?
@Creator27 The above code will send a message to the 255 addresses on a router and only get a response from any device that’s running the code. Currently it’s only looking for 1 other device, but it could be changed to handle multiple devices. I never tried this on my iPhone that doesn’t use my router. Not sure what it would do, I’ll have to give it a try.
PS. Tried it on my iPhone and it crashed. I’ll check later to see what it crashed on.
PS. It works on my iPhone when I switch to WiFi.
@Creator27 @dave1707 Here is a multiplayer sample I collected before, maybe you can make a reference.
To dave: I wish you a speedy recovery?
-- MultiPlayerSample
--all code by JakAttak
--# Main
function setup()
local connectionMade = function()
output.clear()
parameter.clear()
print("Connected!")
gameSetup()
end
multihandler = Multiplayer(receiveData, connectionMade)
parameter.action("Host Game", function()
multihandler:hostGame()
end)
parameter.action("Find Game", function()
multihandler:findGame()
end)
parameter.action("Join Game", function()
if other_ip then
multihandler:joinGame(other_ip, other_port)
else
parameter.text("other_ip", "")
parameter.text("other_port", "")
print("Fill in the host's ip and port, then click join game again")
end
end)
end
function gameSetup()
canvas = image(WIDTH, HEIGHT)
parameter.color("pen_col", color(0, 255, 0))
parameter.integer("pen_size", 2, 100, 10)
parameter.action("clear", function()
clear()
multihandler:sendData("clear")
end)
pen_touch = nil
last_point = vec2(0, 0)
end
function clear()
canvas = image(WIDTH, HEIGHT)
end
function receiveData(d)
if d == "clear" then
clear()
else
local tb = load("return " .. d)()
drawPoint(tb.point, tb.last_point, tb.drawing_line, tb.pen_size, tb.pen_col)
end
end
function drawPoint(point, lastPoint, drawingLine, penSize, penCol)
pushStyle()
setContext(canvas) -- Start drawing to screen image
fill(penCol) stroke(penCol) -- Set draw color to color var
strokeWidth(penSize)
if drawingLine then
line(point.x, point.y, lastPoint.x, lastPoint.y) -- draw a line between the two points
else
ellipse(point.x, point.y, penSize) -- Place a dot there
end
setContext()
popStyle()
end
function draw()
background(255, 255, 255, 255)
multihandler:update()
if multihandler.connected then
sprite(canvas, WIDTH/2, HEIGHT/2, WIDTH, HEIGHT) -- Draw the image onto the screen
else
fill(0)
text("Waiting for connection...", WIDTH / 2, HEIGHT / 2)
end
end
function vec2ToStr(vec)
return "vec2" .. tostring(vec)
end
function colToStr(col)
return "color(" .. col.r .. ", " .. col.g .. ", " .. col.b.. ", " .. col.a .. ")"
end
function touched(t)
if multihandler.connected then
local p, lp, d, ps, pc = vec2(t.x, t.y), last_point, drawing_line, pen_size, pen_col
if t.state == BEGAN then
pen_touch = t.id
end
if t.id == pen_touch then
drawPoint(vec2(t.x, t.y), last_point, drawing_line, pen_size, pen_col)
drawing_line = true
last_point = vec2(t.x, t.y)
end
if t.state == ENDED then
drawing_line = false
pen_touch = nil
end
multihandler:sendData("{ point = " .. vec2ToStr(p) .. ", last_point = " .. vec2ToStr(lp) .. ", drawing_line = " .. tostring(d) .. ", pen_size = " .. ps .. ", pen_col = " .. colToStr(pc) .. " }")
end
end
--multiplayer library follows
--# Multiplayer
local socket = require("socket")
Multiplayer = class()
function Multiplayer:init(dcb, ccb)
self.my_ip, self.my_port = self:getLocalIP(), 5400
self.peer_ip, self.peer_port = nil, self.my_port
self.client = socket.udp()
self.client:settimeout(0)
self.connected = false
self.is_host = false
self.searching = false
self.dataCallback = dcb or function() end
self.connectedCallback = ccb or function() end
end
-- Returns this iPad's local ip
function Multiplayer:getLocalIP()
local randomIP = "192.167.188.122"
local randomPort = "3102"
local randomSocket = socket.udp()
randomSocket:setpeername(randomIP,randomPort)
local localIP, somePort = randomSocket:getsockname()
randomSocket:close()
randomSocket = nil
return localIP
end
-- Set the connected status and call the connection callback if needed
function Multiplayer:setConnectedVal(bool)
self.connected = bool
if self.connected then
self.connectedCallback()
end
end
function Multiplayer:setHostVal(bool)
self.is_host = bool
end
-- Prepare to be the host
function Multiplayer:hostGame()
print("Connect to " .. self.my_ip .. ":" .. self.my_port)
self.client:setsockname(self.my_ip, self.my_port)
self:setConnectedVal(false)
self.is_host = true
self.searching = false
end
-- Find a host
function Multiplayer:findGame()
print("Searching for games...")
self.searching = true
local ip_start, ip_end = self.my_ip:match("(%d+.%d+.%d+.)(%d+)")
for i = 1, 255 do
if i ~= tonumber(ip_end) then
tween.delay(0.01 * i, function()
self.client:setsockname(ip_start .. i, self.my_port)
self.client:sendto("connection_confirmation", ip_start .. i, self.my_port)
end)
end
end
end
-- Prepare to join a host
function Multiplayer:joinGame(ip, port)
self.peer_ip, self.peer_port = ip, port
self.client:setsockname(ip, port)
self.is_host = false
self.searching = false
self:sendData("connection_confirmation")
end
-- Send data to the other client
function Multiplayer:sendData(msg_to_send)
if self.peer_ip then
self.client:sendto(msg_to_send, self.peer_ip, self.peer_port)
end
end
-- Check for data received from the other client
function Multiplayer:checkForReceivedData()
local data, msg_or_ip, port_or_nil = self.client:receivefrom()
if data then
-- Store the ip of this new client so you can send data back
self.peer_ip, self.peer_port = msg_or_ip, port_or_nil
if not self.connected and data == "connection_confirmation" then
self:sendData("connection_confirmation")
self:setConnectedVal(true)
end
-- Call callback with received data
if data ~= "connection_confirmation" then
self.dataCallback(data)
end
end
end
function Multiplayer:update()
self:checkForReceivedData()
end
@Creator27 Here’s an updated version for my above code. I ran this on 3 iPads and as I moved my finger on the different iPads, a circle on the other 2 iPads moved around. I tried moving a finger on 2 ipads at the same time, it worked, but the messages were getting backed up. So I’m not sure how much or how fast the message traffic can be. Still needs more tweaking, but I thought I’d post what I have just in case I don’t feel like coding at some point.
@binaryblues Thanks for the speedy recovery message. I have good days and bad days, but things are getting better.
PS. Updated the below code.
viewer.mode=STANDARD
function setup()
ipTab={}
myX,myY=0,0
fill(255)
delay=0
rd=remoteDevice()
parameter.action("get other ips",getIps)
end
function draw()
background()
rd:getIp()
rd:receiveTheirMessage()
for a,b in pairs(ipTab) do
if b.x~=nil then
fill(255)
ellipse(b.x,b.y,50)
fill(255,0,0)
text(b.ip,b.x,b.y+40)
end
end
fill(0,255,0)
text(rd.myIp,myX,myY+40)
text("my circle",myX,myY-40)
ellipse(myX,myY,40)
end
function touched(t)
if t.state==BEGAN or t.state==CHANGED then
myX,myY=t.x//1,t.y//1
for a,b in pairs(ipTab) do
a={id="move X Y",x=myX,y=myY,ip=rd.myIp}
str=json.encode(a)
rd:sendMessage(str,b.ip)
end
end
end
function getIps()
rd:getTheirIp()
end
remoteDevice=class()
function remoteDevice:init()
self.socket=require("socket")
self.myIp="0.0.0.0"
self.theirIp="0.0.0.0"
self:getMyIp()
self:setMySocket()
end
function remoteDevice:getIp()
if not gotMyIp then
if delay>60 then
delay=0
rd:getMyIp()
end
delay=delay+1
end
end
function remoteDevice:setMySocket()
self.server=self.socket.udp()
self.server:setsockname(self.myIp,5544)
self.server:settimeout(0)
end
function remoteDevice:getMyIp()
self.server=self.socket.udp()
self.server:setpeername("1.1.1.1",80)
self.myIp,self.myPort=self.server:getsockname()
self.ip1,self.ip2=string.match(self.myIp,"(%d+.%d+.%d+.)(%d+)")
print("my IP = "..self.ip1..self.ip2)
gotMyIp=true
end
function remoteDevice:getTheirIp()
self.client=self.socket.udp()
self.client:settimeout(0)
print("Getting their IP")
-- send a message to everyone on this network except to myself
for z=1,255 do
if z~=tonumber(self.ip2) then
self.client:setpeername(self.ip1..z,5544)
local temp={id="get their ip"}
local str=json.encode(temp)
self.client:send(str)
end
end
end
function remoteDevice:receiveTheirMessage()
local data,msg,port=self.server:receivefrom()
if data~=nil then
local jd=json.decode(data)
if jd.id=="get their ip" then
self.client=self.socket.udp()
self.client:settimeout(0)
self.client:setpeername(msg,5544)
local temp={id="got their ip",ip=self.myIp}
local str=json.encode(temp)
self.client:send(str)
elseif jd.id=="got their ip" then
print("their ip ",jd.ip)
self.theirIp=jd.ip
viewer.mode=FULLSCREEN
ipTab[self.theirIp]={ip=self.theirIp,x=0,y=0}
elseif jd.id=="move X Y" then
ipTab[jd.ip]=jd
end
end
end
function remoteDevice:sendMessage(tempStr,theirIp)
self.client = self.socket.udp()
self.client:setpeername(theirIp,5544)
self.client:settimeout(0)
self.client:send(tempStr)
end
@binaryblues and @dave1707, thank you guys for the examples. I’ve edited my code so that hopefully on the first iPad there will be one ball and on the second iPad there will be two balls. [EDIT]: I had to change the code because sometimes the game wouldn’t create any new player objects. Pretty sure it works now
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
connected = false
client_count = 0
my_server = {server = nil, clients = {}, client_data = {}}
-- 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)
table.insert(my_server.clients, client)
my_client = client
local ip1, ip2 = string.match(ip,"(%d+.%d+.%d+.)(%d+)")
for z = 1, 255 do
client:setsockname(ip1..z, port)
client:sendto("join"..tostring(client), ip1..z, port)
end
end
end
function receiveUpdate()
if connected == false then
local data, ip, port = my_client:receivefrom()
if data ~= nil then
for i = 1, tonumber(data) do
makePlayer(vec3(0, 0, 10))
end
my_client:setpeername(ip, port)
my_client:send("confirmed"..tostring(my_client))
connected = true
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
if my_entity == nil then
my_entity = entity
end
if client ~= nil then
entity.master = client
end
table.insert(entities, 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
if client_count ~= #my_server.clients then
my_server.server:sendto(tostring(#my_server.clients), ip, port)
client_count = #my_server.clients
else
print("we already have this player")
end
elseif string.find(data, "confirmed") then
print("noice!")
end
end
end
if my_client == nil then
local data, ip, port = messenger:receivefrom()
if data == "server available" then
parameter.action(tostring(port).." - Join", function() joinServer(ip, port) end)
end
else
receiveUpdate()
end
for i,c in pairs(my_server.clients) do
if my_client == c and connected == true then
local data = c:receive()
if data ~= nil then
print(data)
end
end
end
end
@Creator27 Tried your latest code on 2 iPads. Same thing, 1 sphere per iPad.
@Creator27 I updated my code above. I think it works better than it did before.
@dave1707, If I’m being completely honest with you I have no hope that this is gonna work, but here it is.
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
connected = false
client_count = 0
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 == "make player" then
makePlayer(vec3(0, 0, 10))
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
if my_entity == nil then
my_entity = entity
end
if client ~= nil then
entity.master = client
end
table.insert(entities, 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
my_server.server:sendto("make player", c.ip, c.port)
end
elseif string.find(data, "confirmed") then
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(port).." - Join", function() joinServer(ip, port) end)
end
end
end
receiveUpdate()
end
@Creator27 Ran your latest code on 2 iPads. When I pressed join on 1 iPad, a sphere appeared on it. When I pressed join on the other iPad, a sphere appeared on both iPads. So 1 iPad had 1 sphere and the other had 2. The ipad that created the sphere on the other ipad didn’t have any control on the other sphere. I could move 1 sphere on each ipad, and I could push the second sphere around on the one that had 2 spheres. I’m assuming that both iPad should have 2 spheres and the object is that each iPad should be able to try and push the opponents sphere off the platform.
@dave1707, what happened like with one sphere on iPad and two on the other is exactly what I wanted to happen! The reason there was only one sphere on the second iPad, is because I haven’t programmed anything to happen when you join, except give yourself a player. I’m just really happy that I’ve (partially) got syncing players across devices working!
@dave1707, now that the syncing players across devices is half-functional, I programmed the other half. Here it is:
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
connected = false
client_count = 0
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 == "make player" then
makePlayer(vec3(0, 0, 10))
my_client:send("confirmed")
else
if data ~= nil then
if string.find(data, "client count") then
local count = tonumber(string.sub(data, 13, #data))
for i = 1, count - 1 do
makePlayer(vec3(0, 0, 10))
end
end
end
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
if my_entity == nil then
my_entity = entity
end
if client ~= nil then
entity.master = client
end
table.insert(entities, 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
my_server.server:sendto("make player", c.ip, c.port)
end
elseif string.find(data, "confirmed") then
my_server.server:sendto("client count"..tostring(#my_server.client_data), ip, port)
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(port).." - Join", function() joinServer(ip, port) end)
end
end
end
receiveUpdate()
end
@Creator27 I got 2 spheres on 1 iPad and 3 spheres on the other.
@dave1707, try this.
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
connected = false
client_count = 0
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 == "make player" then
makePlayer(vec3(0, 0, 10))
my_client:send("confirmed")
else
if data ~= nil then
if string.find(data, "client count") then
local count = tonumber(string.sub(data, 13, #data))
for i = 1, count do
makePlayer(vec3(0, 0, 10))
end
elseif string.find(data, "new player") then
local count = tonumber(string.sub(data, 11, #data))
makePlayer(vec3(0, 0, 10))
for i = 1, count do
makePlayer(vec3(0, 0, 10))
end
end
end
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
if my_entity == nil then
my_entity = entity
end
if client ~= nil then
entity.master = client
end
table.insert(entities, 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 not c == uid then
my_server.server:sendto("make player", c.ip, c.port)
else
my_server.server:sendto("new player"..tostring(#my_server.client_data - 1), c.ip, c.port)
end
end
elseif string.find(data, "confirmed") then
my_server.server:sendto("client count"..tostring(#my_server.client_data - 1), ip, port)
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(port).." - Join", function() joinServer(ip, port) end)
end
end
end
receiveUpdate()
end
@Creator27 I show 2 spheres on 1 iPad and 3 spheres on the other. If I double tap the screen, one of the spheres jumps.
@dave1707, hopefully the 3 sphere bug is fixed. Try this:
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
connected = false
client_count = 0
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, "make player") then
local count = string.match(data, "%d")
local uid = json.decode(string.sub(data, 12 + #count, #data))
local ip, port = my_client:getpeername()
if ip ~= uid.ip then
-- We know it isnt the new player so we create a new player
makePlayer(vec3(0, 0, 10))
else
-- It's the player that just joined so we let him/her see everybody, including his/her player
for i = 1, tonumber(count) do
makePlayer(vec3(0, 0, 10))
end
end
end
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
if my_entity == nil then
my_entity = entity
end
if client ~= nil then
entity.master = client
end
table.insert(entities, 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
my_server.server:sendto("make player"..tostring(#my_server.client_data)..json.encode(uid), c.ip, c.port)
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(port).." - Join", function() joinServer(ip, port) end)
end
end
end
receiveUpdate()
end
@Creator27 Sometimes I had 2 spheres on 1 ipad and 3 on the other. Other times I had 1 sphere on 1 iPad and 2 on the other. It kind of depended on which iPad I pressed join first.
@dave1707, I also have no hope that this will work, but I’ve reprogrammed my code so that hopefully when somebody joins everybody else will see them and if you are the player who just joined, you will see everybody connected to the server including yourself. As always, 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
connected = false
client_count = 0
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
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
end
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
if my_entity == nil then
my_entity = entity
end
if client ~= nil then
entity.master = client
end
table.insert(entities, 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
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