Jump to content

Josh

Staff
  • Posts

    24,155
  • Joined

  • Last visited

Everything posted by Josh

  1. Josh

    collisions

    You want a body to have a collision method the way a model does?
  2. What do you mean by "mapping messages to functions"?
  3. There is no problem with making concave physically active objects. A concave object must be made out of multiple convex ones. I looked at your .obj file and it is a single object. Break it up into multiple convex pieces, within one file, and it will work perfectly.
  4. If you are interested in a weapons model pack set up to work with Leadwerks, please browse these weapon packs and tell me which of the realistic weapons you want most: http://www.fpscreator.com/ I will send the list to the artist and have a weapons pack put together. I am trying to determine which are the best to use.
  5. Furniture and props, especially with physics.
  6. Can you post a demo I can try myself? There are many things that can go wrong, so without your actual demo, I am just guessing at what you might be doing.
  7. Can you post a compiled demo? This looks neat.
  8. If you specify a port, it attempts to use it. If no port is specified, it will try a range of ports until it finds one that works. The server connects to a php script and database to list itself. You can get this script from the network documentation, or just use my server.
  9. Everyone is sleeping, I think. We tested it pretty well, and it's working great. I'll have something 3D this week. The entity syncing will be interesting, but I am sure we can do networked physics pretty well.
  10. The problem is the bah.cegui module is designed to work with BRL's graphics commands, and it should have just been designed as a raw import of the library. He tried to make it nice for users, but it makes it so it only works with max2D. Maybe ask on the Blitz forum for a 1:1 library.
  11. Four people have successfully connected. Maybe you did not have a name specified, and you tried to connect when someone else by the same name was on?
  12. Sounds like it is not working for you. Is there anything funny about your configuration? Is your router blocking the program or port? If you don't specify a port, the program will try to find one, and it will probably end up being 7000.
  13. One of the examples actually has a switch the player can switch on and off to enable or disable a large fan. You can use the calc velocity and omega functions to calculate forces to make a body stay at a precise orientation. Another way to do this would be to create a body that represents the player's hands, and create a fixed joint between it and the object you want the player to pick up.
  14. Join my server and let's talk and test. http://www.leadwerks.com/post/chat3.zip ----------------------------- Version 3 is up with asynchrous server pinging.
  15. Here's a more advanced version. This is actually pretty fun once you get into it, because you can design your own protocols as you see fit. This handles chat, whisper, kicking, banning, recurring names, and name changes: SuperStrict Private Const ENET_PACKET_FLAG_UNSEQUENCED:Int=2 Function enet_host_port:Int( peer:Byte Ptr ) Local ip:Int=(Int Ptr peer)[1] Local port:Int=(Short Ptr peer)[4] ?LittleEndian ip=(ip Shr 24) | (ip Shr 8 & $ff00) | (ip Shl 8 & $ff0000) | (ip Shl 24) ? Return port EndFunction Function enet_host_ip:Int( peer:Byte Ptr ) Local ip:Int=(Int Ptr peer)[1] Local port:Int=(Short Ptr peer)[4] ?LittleEndian ip=(ip Shr 24) | (ip Shr 8 & $ff00) | (ip Shl 8 & $ff0000) | (ip Shl 24) ? Return ip EndFunction Function enet_peer_port:Int( peer:Byte Ptr ) Local ip:Int=(Int Ptr peer)[3] Local port:Int=(Short Ptr peer)[8] ?LittleEndian ip=(ip Shr 24) | (ip Shr 8 & $ff00) | (ip Shl 8 & $ff0000) | (ip Shl 24) ? Return port EndFunction Function enet_peer_ip:Int( peer:Byte Ptr ) Local ip:Int=(Int Ptr peer)[3] Local port:Int=(Short Ptr peer)[8] ?LittleEndian ip=(ip Shr 24) | (ip Shr 8 & $ff00) | (ip Shl 8 & $ff0000) | (ip Shl 24) ? Return ip EndFunction Type TNetworkNode Field port:Int Field ip:Int Field enethost:Byte Ptr Field enetpeer:Byte Ptr Method Delete() If enethost enet_host_destroy(enethost) enethost=Null EndIf EndMethod Method Update(callback(client:TClient,id:Int,packet:TPacket)=Null) Local ip:Int,port:Int,client:TClient,ev:ENetEvent=New ENetEvent,id:Byte,packet:TPacket If Not Self.enethost RuntimeError "Can't update a remote server." Repeat If enet_host_service(Self.enethost,ev,0) Select ev.event Case ENET_EVENT_TYPE_CONNECT id=NETWORK_CONNECT Case ENET_EVENT_TYPE_DISCONNECT id=NETWORK_DISCONNECT Case ENET_EVENT_TYPE_RECEIVE Local size:Int=enet_packet_size(ev.packet) Local data:Byte[size] MemCopy(Varptr id,enet_packet_data(ev.packet),1) If size>1 packet=New TPacket packet._bank.resize(size-1) MemCopy(packet._bank.buf(),enet_packet_data(ev.packet)+1,size-1) EndIf Default Continue EndSelect EvaluateEvent(id,packet,ev.peer) Else Exit EndIf Forever EndMethod Method EvaluateEvent(id:Int,packet:TPacket,enetpeer:Byte Ptr) Abstract EndType Public Const NETWORK_CONNECT:Int=1 Const NETWORK_DISCONNECT:Int=2 Const NETWORK_PINGREQUEST:Int=3 Const NETWORK_PINGRESPONSE:Int=4 Const NETWORK_JOINREQUEST:Int=5 Const NETWORK_JOINRESPONSE:Int=6 Const NETWORK_CHAT:Int=7 Const NETWORK_LEAVEGAME:Int=8 Const NETWORK_CHANGENAMEREQUEST:Int=9 Const NETWORK_CHANGENAMERESPONSE:Int=10 Const NETWORK_PLAYERJOINED:Int=11 Const SEND_RELIABLE:Int=ENET_PACKET_FLAG_RELIABLE Const SEND_UNSEQUENCED:Int=ENET_PACKET_FLAG_UNSEQUENCED Type TServer Extends TNetworkNode Const maxplayers:Int=64 Field clients:TList=New TList Field callback(server:TServer,client:TClient,id:Int,packet:TPacket) Field bannedips:Int[] Field clientmap:TMap=New TMap Method Delete() If enethost enet_host_destroy(enethost) enethost=Null EndIf EndMethod Function Create:TServer(ip:Int=0,port:Int=7777) Local server:TServer=New TServer,addr:Byte Ptr If ip server.ip=ip Else server.ip=ENET_HOST_ANY EndIf server.port=port If server.port<>0 Or server.ip<>ENET_HOST_ANY addr=enet_address_create(server.ip,server.port) EndIf server.enethost=enet_host_create(addr,maxplayers,0,0) If addr enet_address_destroy(addr) EndIf If Not server.enethost Return Null EndIf Return server EndFunction Method FindClientByName:TClient(name:String) Return TClient(clientmap.valueforkey(name)) EndMethod Method FindClientByPeer:TClient(peer:Byte Ptr) Local client:TClient For client=EachIn clients If client.enetpeer=peer Return client Next EndMethod Method FindClient:TClient(ip:Int,port:Int) Local client:TClient For client=EachIn clients If client.ip=ip And client.port=port Return client Next EndMethod Method EvaluateEvent(id:Int,packet:TPacket,enetpeer:Byte Ptr) Local client:TClient Local issilent:Int=False client=FindClient(enet_peer_ip(enetpeer),enet_peer_port(enetpeer)) Select id Case NETWORK_JOINREQUEST If client Disconnect(client,1) client=TClient.Find(enet_peer_ip(enetpeer),enet_peer_port(enetpeer)) client.enetpeer=enetpeer If IPBanned(client.ip) Disconnect(client,0) issilent=1 Else client.name=packet.ReadLine() If Not FindClientByName(client.name) clientmap.insert(client.name,client) clients.AddLast(client) Local responsepacket:TPacket=New TPacket responsepacket.WriteByte(1) responsepacket.WriteByte(clients.count()) Local peer:TClient For peer=EachIn clients responsepacket.WriteLine(peer.name) Next Send(client,NETWORK_JOINRESPONSE,responsepacket,SEND_RELIABLE) id=NETWORK_PLAYERJOINED Else packet=New TPacket packet.WriteByte(0)'no, you can't joint packet.WriteByte(1)'reason: name already taken Send(client,NETWORK_JOINRESPONSE,packet,SEND_RELIABLE) 'Disconnect(client,0) issilent=1 EndIf EndIf Case NETWORK_CHANGENAMEREQUEST Local name:String=packet.ReadLine() packet=New TPacket If client If FindClientByName(name)<>Null And client.name<>name packet.WriteByte(0) send(client,NETWORK_CHANGENAMERESPONSE,packet,SEND_RELIABLE) issilent=True Else packet.WriteByte(1) packet.WriteLine(name) send(client,NETWORK_CHANGENAMERESPONSE,packet,SEND_RELIABLE) clientmap.remove(client.name) client.name=name clientmap.insert(name,client) EndIf Else If FindClientByName(name)=Null packet.WriteByte(1) packet.WriteLine(name) send(client,NETWORK_CHANGENAMERESPONSE,packet,SEND_RELIABLE) issilent=True EndIf EndIf Case NETWORK_CONNECT issilent=True Case NETWORK_DISCONNECT client=FindClientByPeer(enetpeer) If client Disconnect(client,0) Else issilent=True EndIf Case NETWORK_PINGREQUEST Send(client,NETWORK_PINGRESPONSE,packet) issilent=True Case NETWORK_CHAT Local relay:TPacket=New TPacket Local count:Int=packet.ReadByte() relay.WriteLine(packet.ReadLine()) If count=0 Broadcast(NETWORK_CHAT,relay) Else For Local n:Int=1 To count client=FindClientByName(packet.ReadLine()) If client Send(client,NETWORK_CHAT,relay) EndIf Next EndIf issilent=True EndSelect If Not issilent If callback If packet packet.seek(0) callback(Self,client,id,packet) EndIf EndIf EndMethod Method Send:Int(client:TClient,id:Int,packet:TPacket=Null,flags:Int=0,channel:Int=0) Local enetpacket:Byte Ptr Local result:Int If Not client.enetpeer RuntimeError "Can't send to local client." Local data:Byte[] If packet If packet._bank.size()=0 packet=Null EndIf If packet data=New Byte[packet._bank.size()+1] MemCopy(Varptr data[1],packet._bank.buf(),packet._bank.size()) Else data=New Byte[1] EndIf data[0]=id enetpacket=enet_packet_create(data,data.length,flags) result=(enet_peer_send(client.enetpeer,channel,enetpacket)=0) Return result EndMethod Method Broadcast:Int(id:Int,packet:TPacket=Null,flags:Int=0,channel:Int=0) Local result:Int=1 For Local client:TClient=EachIn clients If Not Send(client,id,packet,flags,channel) result=0 Next Return result Rem Local enetpacket:Byte Ptr Local result:Int Local data:Byte[] If packet If packet._bank.size()=0 packet=Null EndIf If packet data=New Byte[packet._bank.size()+1] MemCopy(Varptr data[1],packet._bank.buf(),packet._bank.size()) Else data=New Byte[1] EndIf data[0]=id enetpacket=enet_packet_create(data,data.length,flags) enet_host_broadcast(Self.enethost,channel,enetpacket) EndRem EndMethod Method Disconnect(client:TClient,force:Int=False) If client.enetpeer If force enet_peer_reset(client.enetpeer) Else enet_peer_disconnect(client.enetpeer) EndIf clients.remove(client) If Not client.enethost client.link.remove() EndIf If clientmap.valueforkey(client.name)=client clientmap.remove(client.name) EndIf EndIf EndMethod Method BanIP(ip:Int) bannedips=bannedips[..bannedips.length+1] bannedips[bannedips.length-1]=ip EndMethod Method IPBanned:Int(ip:Int) For Local n:Int=0 To bannedips.length-1 If ip=bannedips[n] Return True Next Return False EndMethod Method Kick(client:TClient) BanIP(client.ip) Disconnect(client) EndMethod EndType Type TClient Extends TNetworkNode Const maxplayers:Int=64 Global list:TList=New TList Field name:String Field link:TLink Field server:TServer Field connected:Int Field joined:Int=0 Field callback(client:TClient,id:Int,packet:TPacket) Function Find:TClient(ip:Int,port:Int) Local client:TClient For client=EachIn list If client.ip=ip And client.port=port Return client Next client=New TClient client.ip=ip client.port=port client.link=list.addlast(client) Return client EndFunction Function Create:TClient(ip:Int=0,port:Int=7776) Local client:TClient=Find(ip,port) Local addr:Byte Ptr If ip client.ip=ip Else client.ip=ENET_HOST_ANY EndIf client.port=port If client.port<>0 Or client.ip<>ENET_HOST_ANY addr=enet_address_create(client.ip,client.port) client.enethost=enet_host_create(addr,maxplayers,0,0) If addr enet_address_destroy(addr) If Not client.enethost Return Null EndIf Return client EndFunction Method Disconnect(force:Int=False) If server If force enet_peer_reset(server.enetpeer) Else enet_peer_disconnect(server.enetpeer) EndIf server=Null EndIf EndMethod Method SetName(name:String) If name.length>16 name=name[..16] If server Local packet:TPacket=New TPacket packet.WriteLine(name) Send(NETWORK_CHANGENAMEREQUEST,packet,SEND_RELIABLE) Else Self.name=name EndIf EndMethod Method Connect:Int(ip:Int,port:Int) Local addr:Byte Ptr If Not Self.enethost RuntimeError "Remote client cannot connect to server." If server Disconnect() server=New TServer server.ip=ip server.port=port addr=enet_address_create(server.ip,server.port) server.enetpeer=enet_host_connect(Self.enethost,addr,1) enet_address_destroy(addr) If server.enetpeer=Null server=Null Return 0 EndIf Return 1 EndMethod Method Send:Int(id:Int,packet:TPacket=Null,flags:Int=0,channel:Int=0) Local enetpacket:Byte Ptr Local result:Int If Not connected Return 0 If Not server RuntimeError "Client is not connected." Local data:Byte[] If packet If packet._bank.size()=0 packet=Null EndIf If packet data=New Byte[packet._bank.size()+1] MemCopy(Varptr data[1],packet._bank.buf(),packet._bank.size()) Else data=New Byte[1] EndIf data[0]=id enetpacket=enet_packet_create(data,data.length,flags) result=(enet_peer_send(server.enetpeer,channel,enetpacket)=0) Return result EndMethod Method EvaluateEvent(id:Int,packet:TPacket,enetpeer:Byte Ptr) Local issilent:Int=False Select id Case NETWORK_CONNECT Self.connected=True packet=New TPacket packet.WriteLine(name) Send(NETWORK_JOINREQUEST,packet) Case NETWORK_JOINRESPONSE joined=packet.ReadByte() Case NETWORK_CHANGENAMERESPONSE If packet.ReadByte()=1 name=packet.ReadLine() EndIf Case NETWORK_PINGRESPONSE Case NETWORK_CHAT EndSelect If Not issilent If callback If packet packet.seek(0) callback(Self,id,packet) EndIf EndIf EndMethod Method Join() If Not joined Local packet:TPacket=New TPacket packet.WriteLine(name) Send(NETWORK_JOINREQUEST,packet) EndIf EndMethod Method Ping:Int() Local packet:TPacket=New TPacket packet.WriteInt(MilliSecs()) Return Send(NETWORK_PINGREQUEST,packet) EndMethod Method Say:Int(text:String,recipients:String[]=Null) Local packet:TPacket=New TPacket If recipients packet.WriteByte(recipients.length) packet.WriteLine(text) For Local n:Int=0 To recipients.length-1 packet.WriteLine(recipients[n]) Next Else packet.WriteByte(0) packet.WriteLine(text) EndIf Return Send(NETWORK_CHAT,packet) EndMethod EndType Type TPacket Extends TBankStream Method New() _bank=New TBank EndMethod EndType Function CreatePacket:TPacket() Local packet:TPacket=New TPacket Return packet EndFunction '---------------------------------------------------------------------------------------------------- Local server:TServer Local client1:TClient Local client2:TClient Local ip:Int=HostIp("127.0.0.1") server=TServer.Create(ip,7777) client1=TClient.Create(ip,7776) client2=TClient.Create(ip,7779) client1.name="Steve" client2.name="Bob" client1.connect(server.ip,server.port) client2.connect(server.ip,server.port) client1.callback=ClientCallBack client2.callback=ClientCallBack server.callback=ServerCallBack Repeat server.Update() client1.Update() client2.Update() Delay 1 If Rand(100)=1 client1.SetName("Barney") client1.Disconnect() 'client2.Ping() client2.Say("Hello!") EndIf Forever Function ServerCallBack(server:TServer,client:TClient,id:Int,packet:TPacket) Select id Case NETWORK_PLAYERJOINED Print "New player "+packet.ReadLine()+" joined." Case NETWORK_DISCONNECT If client Print client.name+" disconnected." Else Print "Unknown disconnection" Print server.clients.count()+" players" EndIf Case NETWORK_CONNECT Print "New client connected." EndSelect EndFunction Function ClientCallBack(client:TClient,id:Int,packet:TPacket) Select id Case NETWORK_CHANGENAMERESPONSE If packet.ReadByte()=1 Print "Changed name to "+packet.ReadLine() Else Print "Name change rejected." EndIf Case NETWORK_JOINRESPONSE If packet.ReadByte()=1 Print "Joined game" Local count:Int=packet.ReadByte() Print count+" players" For Local n:Int=1 To count Print n+". "+packet.ReadLine() Next Else Print "Rejected from game" Select packet.ReadByte() Case 1 Print "Name already in use" Default Print "Unknown reason" EndSelect EndIf Case NETWORK_DISCONNECT Print "Disconnected from server." Case NETWORK_CONNECT Print "Connected to server." Case NETWORK_CHAT Print "Says: "+packet.ReadLine() Case NETWORK_PINGRESPONSE Print "Ping = "+(MilliSecs()-packet.ReadInt()) EndSelect EndFunction
  16. Take a look at this. Instead of a host/peer design, this is a more intuitive server/client design. If you are hosting a game, you create a server. If you want to play in the game yourself, create a client. Here, I created two clients. You could create a client for each bot and run them through the network, or just one client for yourself. You'd probably want to always run the game through the network, even if it is single-player, so that you have a uniform design for single and multi player modes. The messages are turned into a form with an ID and a packet, which is a stream of any length. There are built-in message IDs. Some are handled entirely silently. For example, when the server receives a chat message, it just broadcasts the data to all clients, without the user having to do anything. Synced entities would behave this way as well. The user's interaction with the system comes in the form of a callback. The callback can be used to do stuff when messages are received. In the example below, the client callback is used to print the ping and to print any chat messages that are sent. SuperStrict Private Function enet_host_port:Int( peer:Byte Ptr ) Local ip:Int=(Int Ptr peer)[1] Local port:Int=(Short Ptr peer)[4] ?LittleEndian ip=(ip Shr 24) | (ip Shr 8 & $ff00) | (ip Shl 8 & $ff0000) | (ip Shl 24) ? Return port EndFunction Function enet_host_ip:Int( peer:Byte Ptr ) Local ip:Int=(Int Ptr peer)[1] Local port:Int=(Short Ptr peer)[4] ?LittleEndian ip=(ip Shr 24) | (ip Shr 8 & $ff00) | (ip Shl 8 & $ff0000) | (ip Shl 24) ? Return ip EndFunction Function enet_peer_port:Int( peer:Byte Ptr ) Local ip:Int=(Int Ptr peer)[3] Local port:Int=(Short Ptr peer)[8] ?LittleEndian ip=(ip Shr 24) | (ip Shr 8 & $ff00) | (ip Shl 8 & $ff0000) | (ip Shl 24) ? Return port EndFunction Function enet_peer_ip:Int( peer:Byte Ptr ) Local ip:Int=(Int Ptr peer)[3] Local port:Int=(Short Ptr peer)[8] ?LittleEndian ip=(ip Shr 24) | (ip Shr 8 & $ff00) | (ip Shl 8 & $ff0000) | (ip Shl 24) ? Return ip EndFunction Type TNetworkNode Field port:Int Field ip:Int Field enethost:Byte Ptr Field enetpeer:Byte Ptr Method Delete() If enethost enet_host_destroy(enethost) enethost=Null EndIf EndMethod Method Update(callback(client:TClient,id:Int,packet:TPacket)=Null) Local ip:Int,port:Int,client:TClient,ev:ENetEvent=New ENetEvent,id:Byte,packet:TPacket If Not Self.enethost RuntimeError "Can't update a remote server." Repeat If enet_host_service(Self.enethost,ev,0) Select ev.event Case ENET_EVENT_TYPE_CONNECT id=NETWORK_CONNECT Case ENET_EVENT_TYPE_CONNECT id=NETWORK_DISCONNECT Case ENET_EVENT_TYPE_RECEIVE Local size:Int=enet_packet_size(ev.packet) Local data:Byte[size] MemCopy(Varptr id,enet_packet_data(ev.packet),1) If size>1 packet=New TPacket packet._bank.resize(size-1) MemCopy(packet._bank.buf(),enet_packet_data(ev.packet)+1,size-1) EndIf Default Continue EndSelect EvaluateEvent(id,packet,ev.peer) Else Exit EndIf Forever EndMethod Method EvaluateEvent(id:Int,packet:TPacket,enetpeer:Byte Ptr) Abstract EndType Public Const NETWORK_CONNECT:Int=1 Const NETWORK_DISCONNECT:Int=2 Const NETWORK_PINGREQUEST:Int=3 Const NETWORK_PINGRESPONSE:Int=4 Const NETWORK_JOINREQUEST:Int=5 Const NETWORK_JOINREPLY:Int=6 Const NETWORK_CHAT:Int=7 Type TServer Extends TNetworkNode Const maxplayers:Int=64 Field clients:TList=New TList Field callback(server:TServer,id:Int,packet:TPacket) Method Delete() If enetpeer enetpeer=Null EndIf If enethost enet_host_destroy(enethost) enethost=Null EndIf EndMethod Function Create:TServer(ip:Int=0,port:Int=7777) Local server:TServer=New TServer,addr:Byte Ptr If ip server.ip=ip Else server.ip=ENET_HOST_ANY EndIf server.port=port If server.port<>0 Or server.ip<>ENET_HOST_ANY addr=enet_address_create(server.ip,server.port) EndIf server.enethost=enet_host_create(addr,maxplayers,0,0) If addr enet_address_destroy(addr) EndIf If Not server.enethost Return Null EndIf Return server EndFunction Method FindClient:TClient(ip:Int,port:Int) Local client:TClient For client=EachIn clients If client.ip=ip And client.port=port Return client Next EndMethod Method EvaluateEvent(id:Int,packet:TPacket,enetpeer:Byte Ptr) Local client:TClient Local issilent:Int=False client=FindClient(enet_peer_ip(enetpeer),enet_peer_port(enetpeer)) Select id Case NETWORK_CONNECT If client Disconnect(client,True) client=New TClient client.enetpeer=enetpeer client.ip=enet_peer_ip(enetpeer) client.port=enet_peer_port(enetpeer) client.link=clients.AddLast(client) Case NETWORK_PINGREQUEST Send(client,NETWORK_PINGRESPONSE,packet) issilent=True Case NETWORK_CHAT Broadcast(id,packet) issilent=True EndSelect If Not issilent If callback callback(Self,id,packet) EndIf EndIf EndMethod Method Send:Int(client:TClient,id:Int,packet:TPacket=Null,flags:Int=0,channel:Int=0) Local enetpacket:Byte Ptr Local result:Int If Not client.enetpeer RuntimeError "Can't send to local client." Local data:Byte[] If packet If packet._bank.size()=0 packet=Null EndIf If packet data=New Byte[packet._bank.size()+1] MemCopy(Varptr data[1],packet._bank.buf(),packet._bank.size()) Else data=New Byte[1] EndIf data[0]=id enetpacket=enet_packet_create(data,data.length,flags) result=(enet_peer_send(client.enetpeer,channel,enetpacket)=0) Return result EndMethod Method Broadcast(id:Int,packet:TPacket=Null,flags:Int=0,channel:Int=0) Local enetpacket:Byte Ptr Local result:Int Local data:Byte[] If packet If packet._bank.size()=0 packet=Null EndIf If packet data=New Byte[packet._bank.size()+1] MemCopy(Varptr data[1],packet._bank.buf(),packet._bank.size()) Else data=New Byte[1] EndIf data[0]=id enetpacket=enet_packet_create(data,data.length,flags) enet_host_broadcast(Self.enethost,channel,enetpacket) EndMethod Method Disconnect(client:TClient,force:Int=False) If client.enetpeer If force enet_peer_reset(client.enetpeer) Else enet_peer_disconnect(client.enetpeer) EndIf client.link.remove() EndIf EndMethod EndType Type TClient Extends TNetworkNode Const maxplayers:Int=64 Field link:TLink Field server:TServer Field connected:Int Field callback(client:TClient,id:Int,packet:TPacket) Function Create:TClient(ip:Int=0,port:Int=7776) Local client:TClient=New TClient Local addr:Byte Ptr If ip client.ip=ip Else client.ip=ENET_HOST_ANY EndIf client.port=port If client.port<>0 Or client.ip<>ENET_HOST_ANY addr=enet_address_create(client.ip,client.port) client.enethost=enet_host_create(addr,maxplayers,0,0) If addr enet_address_destroy(addr) If Not client.enethost Return Null EndIf Return client EndFunction Method Disconnect(force:Int=False) If server If force enet_peer_reset(server.enetpeer) Else enet_peer_disconnect(server.enetpeer) EndIf server=Null EndIf EndMethod Method Connect:TServer(ip:Int,port:Int) Local addr:Byte Ptr,server:TServer If Not Self.enethost RuntimeError "Remote client cannot connect to server." If server Disconnect() server=New TServer server.ip=ip server.port=port addr=enet_address_create(server.ip,server.port) server.enetpeer=enet_host_connect(Self.enethost,addr,1) enet_address_destroy(addr) If server.enetpeer=Null Return Null Self.server=server Return server EndMethod Method Send:Int(id:Int,packet:TPacket=Null,flags:Int=0,channel:Int=0) Local enetpacket:Byte Ptr Local result:Int If Not connected Return 0 If Not server RuntimeError "Client is not connected." Local data:Byte[] If packet If packet._bank.size()=0 packet=Null EndIf If packet data=New Byte[packet._bank.size()+1] MemCopy(Varptr data[1],packet._bank.buf(),packet._bank.size()) Else data=New Byte[1] EndIf data[0]=id enetpacket=enet_packet_create(data,data.length,flags) result=(enet_peer_send(server.enetpeer,channel,enetpacket)=0) Return result EndMethod Method EvaluateEvent(id:Int,packet:TPacket,enetpeer:Byte Ptr) Local issilent:Int=False Select id Case NETWORK_CONNECT Self.connected=True Case NETWORK_PINGRESPONSE Case NETWORK_CHAT EndSelect If Not issilent If callback callback(Self,id,packet) EndIf EndIf EndMethod Method Ping:Int() Local packet:TPacket=New TPacket packet.WriteInt(MilliSecs()) Return Send(NETWORK_PINGREQUEST,packet) EndMethod Method Say:Int(text:String) Local packet:TPacket=New TPacket packet.WriteLine(text) Return Send(NETWORK_CHAT,packet) EndMethod EndType Type TPacket Extends TBankStream Method New() _bank=New TBank EndMethod EndType Function CreatePacket:TPacket() Local packet:TPacket=New TPacket Return packet EndFunction '---------------------------------------------------------------------------------------------------- Local server:TServer Local client1:TClient Local client2:TClient Local ip:Int=HostIp("127.0.0.1") server=TServer.Create(ip,7777) client1=TClient.Create(ip,7776) client2=TClient.Create(ip,7779) client1.connect(server.ip,server.port) client2.connect(server.ip,server.port) client1.callback=ClientCallBack client2.callback=ClientCallBack server.callback=ServerCallBack Repeat server.Update() client1.Update() client2.Update() Delay 1 If Rand(100)=1 client1.Ping() client2.Say("Hello!") EndIf Forever Function ServerCallBack(server:TServer,id:Int,packet:TPacket) Select id Case NETWORK_CONNECT Print "New client connected." EndSelect EndFunction Function ClientCallBack(client:TClient,id:Int,packet:TPacket) Select id Case NETWORK_CONNECT Print "Connected to server." Case NETWORK_CHAT Print "Says: "+packet.ReadLine() Case NETWORK_PINGRESPONSE Print "Ping = "+(MilliSecs()-packet.ReadInt()) EndSelect EndFunction
  17. It depends mostly on what your criteria is. If you want good graphics and good physics, this engine is your best bet.
  18. Use uncompressed DDS format. DXTC1 is the worst format you can use. It should never be used. Use DXTC5 for compressed textures.
  19. I can't view your animation right now because I do not have 3ds max. If you are not an expert at animating, I would not put any more time into it. Thanks for trying to help, though.
  20. Josh

    Next up...

    The foot placement seen there can be achieved using physics. Inverse Kinematics is physic joints. The two are the same thing. First thing is I need to get the soldier model animated.
  21. How do you want the coordinates? It can be as simple as writing a short script that prints the camera position.
  22. This is amazing. You even used the average pixel color to control the light color.
  23. I am asking because I don't want to waste his time. I also don't expect this to be free.
  24. Josh

    buffer access

    Because C++ programmers want to be able to call framework commands with Lua.
×
×
  • Create New...