|
|
|
 |
Reply From: |
dezboyle |
I have no experience with multiplayer in 3.5, but I’m making a multiplayer game in 4.0 and the high level multiplayer API has been completely overhauled.
This blog post summarizes all of the changes they made. There are 4 articles linked near the top of the page.
Things work a bit differently, so it’s going to be a bigger task than just fixing some syntax. Also, the c# docs on multiplayer are incorrect or practically nonexistent, so I had to figure a lot of it out through trial and error. Wishing you the best of luck
I read these articles but they are for GDScript. I’m hoping someone can help me with the C# equivalent syntax.
ondesic | 2022-12-19 14:59
Yeah, even though its in GDScript, there is no C# documentation on it, so you just gotta work with what you got and figure out the C# equivalent yourself. It’s a pain though- I hope it gets documented soon.
Here’s one of my network scripts if you need an example of syntax.
public static GameState instance; //maybe bad practice. I only put this here to use with PlayerDebug
public string ConnectionType { get; private set; }
public Godot.Collections.Array<long> PeerIDs { get; private set; }
const int port = 3460;
const string address = "localhost";
[Export] private NodePath nameText;
private ENetMultiplayerPeer peer;
private Player localPlayer;
private string playerName;
private LineEdit nameLineEdit;
private Dictionary<long, Player> players;
public override void _EnterTree()
{
nameLineEdit = GetNode<LineEdit>(nameText);
nameLineEdit.TextChanged += UpdateName;
}
public override void _Ready()
{
if(instance != null)
{
GD.PrintErr("TWO GAMESTATES EXIST");
Free();
return;
}
instance = this;
PeerIDs = new Godot.Collections.Array<long>();
players = new Dictionary<long, Player>();
UpdateName(nameLineEdit.Text);
}
public void HostGameButton()
{
if(peer == null)
{ HostGame(); }
}
public void JoinGameButton()
{
if(peer == null)
{ JoinGame(); }
}
public void UpdateName(string newName)
{
playerName = newName;
}
void HostGame()
{
ConnectionType = "Mr Host Man";
peer = new ENetMultiplayerPeer();
peer.CreateServer(port, 8);
GetTree().GetMultiplayer().MultiplayerPeer = peer;
LoadLevel();
AddPlayer(1);
peer.PeerConnected += PlayerConnected;
GD.Print("Hosting Game");
}
void JoinGame()
{
ConnectionType = "Mrs McClient";
peer = new ENetMultiplayerPeer();
peer.CreateClient(address, port);
GetTree().GetMultiplayer().MultiplayerPeer = peer;
LoadLevel();
GD.Print("Joining Game");
}
async void PlayerConnected(long id)
{
GD.Print("Player Connected " + id);
//HOST
await ToSignal(GetTree().CreateTimer(1), "timeout"); //BUG in godot Alpha. Takes a sec until rpcs can be recieved
Rpc(nameof(AddNewlyConnectedPlayer), id);
if(PeerIDs != null && PeerIDs.Count > 0)
{ RpcId(id, nameof(AddPreviouslyConnectedPlayers), PeerIDs.Duplicate()); }
AddPlayer(id);
}
[RPC(TransferMode = MultiplayerPeer.TransferModeEnum.Reliable)]
private void RemoteSyncPeerIDs(Godot.Collections.Array<long> newPeerIDs)
{
if(!Multiplayer.IsServer())
{ PeerIDs = newPeerIDs; }
}
[RPC(TransferMode = MultiplayerPeer.TransferModeEnum.Reliable)]
private void AddNewlyConnectedPlayer(long id)
{
GD.Print("Adding newly connected players");
AddPlayer(id);
}
[RPC(TransferMode = MultiplayerPeer.TransferModeEnum.Reliable)]
private void AddPreviouslyConnectedPlayers(Godot.Collections.Array<long> ids)
{
GD.Print("Adding previously connected players");
for(int i = 0; i < ids.Count; i++)
{
AddPlayer(ids[i]);
}
}
public void PlayerConnectedFully()
{
RpcId(1, nameof(RemotePlayerConnectedFully));
}
[RPC(MultiplayerAPI.RPCMode.AnyPeer, CallLocal = true)]
private void RemotePlayerConnectedFully()
{
GD.Print("RemotePlayerConnectedFully");
//SERVER callback from player that they loaded in
for(int i = 0; i < PeerIDs.Count; i++)
{
GD.Print("I should refresh " + PeerIDs[i]);
players[PeerIDs[i]].PlayerState.RpcId(PeerIDs[i], nameof(localPlayer.PlayerState.RefreshState));
}
}
public void RPCPeer(Node node, bool callLocal, StringName method, params Variant[] args)
{
if(PeerIDs.Count <= 0 || peer == null)
{ return; }
for(int i = 0; i < PeerIDs.Count; i++)
{
if(callLocal || PeerIDs[i] != peer.GetUniqueId())
{
node.RpcId(PeerIDs[i], method, args);
}
}
}
private void AddPlayer(long id)
{
Player player = GameManager.instance.SpawnLocalPlayer();
player.Name = id.ToString();
player.SetMultiplayerAuthority((int)id);
if(id == peer.GetUniqueId()) //its our player
{
player.PlayerState.PlayerInfo.Add(nameof(PlayerState.PlayerNameDictionaryKey), playerName);
localPlayer = player;
}
GetTree().Root.AddChild(player);
if(Multiplayer.IsServer())
{
PeerIDs.Add(id);
Rpc(new StringName(nameof(RemoteSyncPeerIDs)), PeerIDs.Duplicate());
GD.PrintErr("Adding ID " + id);
players.Add(id, player);
}
}
private void LoadLevel()
{
GameManager.instance.LoadLevel();
UI.instance.TitleScreen.Visible = false;
}
private void EndGame()
{
GameManager.instance.UnLoadLevel();
GetTree().GetMultiplayer().MultiplayerPeer = null;
UI.instance.TitleScreen.Visible = true;
}
dezboyle | 2022-12-19 15:27