Files
2025-12-17 19:13:10 -08:00

253 lines
10 KiB
C#

using System;
using Godot;
public partial class GameHandler : Node3D {
Reference _Reference;
Options _Options;
[Export]
public PackedScene[] MapList;
[Export]
public PackedScene Player;
[Export]
public PackedScene Sun;
public bool serverRunning = false;
public override void _Ready() {
_Options = GetNode<Options>( "/root/Options" );
_Reference = GetNode<Reference>("/root/Reference");
_Reference.GameHandler = this;
_Reference.GameUI = GetNode<Control>("/root/GameRoot/UI/GameUI");
_Reference.Lighting = GetNode<WorldEnvironment>("/root/GameRoot/Lighting");
_Reference.ItemSpawner = GetNode<MultiplayerSpawner>("/root/GameRoot/ItemSpawner");
_Reference.ItemSpawnPath = GetNode<Node>("/root/GameRoot/PickupItems");
_Reference.ToolBar = GetNode<Control>("/root/GameRoot/UI/GameUI/Game/ToolBar");
string[] CMDS = OS.GetCmdlineArgs();
bool temp_launch_as_server = false;
for( int i = 0; i < CMDS.Length; i++ ) {
if( CMDS [i].ToLower() == "--map" | CMDS [i].ToLower() == "/map" ) {
_Options.SelectedMap = Convert.ToInt32( CMDS [i + 1] );
} else if( CMDS [i].ToLower() == "--port" | CMDS [i].ToLower() == "/port" ) {
_Options.Port = Convert.ToInt32( CMDS [i + 1] );
} else if( CMDS [i].ToLower() == "--players" | CMDS [i].ToLower() == "/players" ) {
_Options.maxPlayers = Convert.ToInt32( CMDS [i + 1] );
} else if( CMDS [i].ToLower() == "--host" | CMDS [i].ToLower() == "/host" ) {
_Options.Host = CMDS [i + 1];
} else if( CMDS [i].ToLower() == "server" ) {
temp_launch_as_server = true;
}
}
if( OS.HasFeature( "dedicated_server" ) || DisplayServer.GetName() == "headless" || temp_launch_as_server ) {
StartServer();
}
}
public void StartServer(){
_Options.isServer = true;
_Options.connection = new ENetMultiplayerPeer();
_Options.connection.CreateServer( _Options.Port, _Options.maxPlayers );
Multiplayer.MultiplayerPeer = _Options.connection;
_Options.connection.PeerConnected += peerConnected;
_Options.connection.PeerDisconnected += peerDisconnected;
Node3D MapSelected = _Reference.GameHandler.MapList[_Options.SelectedMap].Instantiate<Node3D>();
MapSelected.SetMultiplayerAuthority(Multiplayer.GetUniqueId());
MapSelected.Name = "Workspace";
_Reference.Workspace = MapSelected;
_Reference.GameHandler.AddChild( MapSelected );
// Spawn the sun
AddChild( Sun.Instantiate<Node3D>() );
ResetItemDrops();
serverRunning = true;
}
public void StopServer(){
serverRunning = false;
}
public void StopClient(){
_Options.connection.PeerConnected -= peerConnected;
_Options.connection.PeerDisconnected -= peerDisconnected;
_Reference.Workspace.Multiplayer.ConnectedToServer -= ConnectedToServer;
_Reference.Workspace.Multiplayer.ConnectionFailed -= ConnectionFailed;
_Reference.Workspace.Multiplayer.ServerDisconnected -= DisconnectedFromServer;
}
public void StartClient(){
_Options.connection = new ENetMultiplayerPeer();
_Options.connection.CreateClient( _Options.Host, _Options.Port );
Multiplayer.MultiplayerPeer = _Options.connection;
Multiplayer.ConnectedToServer += ConnectedToServer;
Multiplayer.ConnectionFailed += ConnectionFailed;
Multiplayer.ServerDisconnected += DisconnectedFromServer;
}
public void RemovePlayer(int id){
if (HasNode(id.ToString())) {
GetNode(id.ToString()).QueueFree();
}
}
double timeElapsed = 0;
void ResetItemDrops(){
foreach( Node3D cur in _Reference.ItemSpawnPath.GetChildren()){
cur.QueueFree();
}
foreach( Node3D cur in _Reference.ItemSpawnPoints.GetChildren() ){
string[] PickupItems = _Reference.ItemSpawner._SpawnableScenes;
int chosenItem = new Random(DateTime.Now.Millisecond).Next(0, PickupItems.Length);
PackedScene ps = GD.Load<PackedScene>(PickupItems[chosenItem]);
Node3D prefab = ps.Instantiate<Node3D>();
prefab.Name = Guid.NewGuid().ToString();
_Reference.ItemSpawnPath.AddChild( prefab );
prefab.GlobalPosition = cur.GlobalPosition;
}
}
public override void _Process(double delta) {
if(serverRunning){
timeElapsed += delta;
if (timeElapsed > _Options.timeBetweenDropsReset * 60){
ResetItemDrops();
timeElapsed = 0;
}
}
}
// Called on server
public void peerConnected( long peerID ) {
}
public void peerDisconnected( long peerID ) {
RemovePlayer(Convert.ToInt32(peerID));
}
// Called on client
public void ConnectedToServer() {
_Reference.Alert.PerformAlert( "Connected to server successfully" );
}
public void ConnectionFailed() {
_Reference.Alert.PerformAlert( "Connection failed" );
}
public void DisconnectedFromServer() {
_Reference.Alert.PerformAlert( "Disconnected from server" );
}
///////////////////////////////////////////////////////////////////////
/// RPC's
///////////////////////////////////////////////////////////////////////
[Rpc( MultiplayerApi.RpcMode.AnyPeer, CallLocal = true, TransferChannel = 1, TransferMode = MultiplayerPeer.TransferModeEnum.Reliable)]
void _takeDamage(float DMG, int Creator, int Hit){
// Take Damage
Humanoid HitUser = null;
foreach(Node cur in _Reference.GameHandler.GetChildren()){
if ( cur.Name.ToString().Split(new char[]{','})[0] == Hit.ToString() ){
HitUser = (Humanoid)cur;
break;
}
}
Humanoid CreatorUser = null;
foreach(Node cur in _Reference.GameHandler.GetChildren()){
if ( cur.Name.ToString().Split(new char[]{','})[0] == Creator.ToString() ){
CreatorUser = (Humanoid)cur;
break;
}
}
HitUser.Health -= DMG;
// If Player Died
if( HitUser.Health <= 0 ) {
// Stuff to do on the died players computer
if (HitUser.GetMultiplayerAuthority() == Multiplayer.GetUniqueId()){
Input.MouseMode = Input.MouseModeEnum.Visible;
_Reference.Alert.PerformAlert("You died from Player : " + CreatorUser.PlayerName);
}
// Stuff to do on the killers computer
else if (CreatorUser.GetMultiplayerAuthority() == Multiplayer.GetUniqueId()){
_Reference.Alert.PerformAlert("You killed Player : " + HitUser.PlayerName);
}
// Stuff to do on Server
else if ( Multiplayer.GetUniqueId() == 1 ){
}
// Stuff to perform for everybody
// Award the player points
// Notify Player of kill
// Reset Dead player
}
// Update UI For Hit Player
if (HitUser.GetMultiplayerAuthority() == Multiplayer.GetUniqueId()){
HitUser.HealthBar.MaxValue = HitUser.MaxHealth;
HitUser.HealthBar.Value = Convert.ToDouble( HitUser.Health );
}
}
public void TakeDamage(float DMG, int Creator, int Hit){
Rpc("_takeDamage", DMG, Creator, Hit);
}
[Rpc( MultiplayerApi.RpcMode.AnyPeer, CallLocal = false, TransferChannel = 1, TransferMode = MultiplayerPeer.TransferModeEnum.Reliable)]
void _Shoot(int Creator, int itemID, Vector3 initialPosition, Vector3 ImpulseVector){
if (Multiplayer.GetUniqueId() == 1){
PackedScene ps = GD.Load<PackedScene>("res://Prefab/bullet.tscn");
Bullet physicsBullet = ps.Instantiate<Bullet>();
physicsBullet.Name = Guid.NewGuid().ToString();
physicsBullet.Creator = Creator;
physicsBullet.Damage = new GameItem(itemID).ItemStats.ToolDamage;
GetNode<Node3D>("/root/GameRoot/Game").AddChild(physicsBullet);
physicsBullet.SetDeferred("global_position", initialPosition);
physicsBullet.CallDeferred("apply_impulse", ImpulseVector);
}
}
public void Shoot(int ToolID, Vector3 LookVector, float ImpulseForce){
Rpc("_Shoot", Multiplayer.GetUniqueId(), ToolID, _Reference.Humanoid.GlobalPosition + LookVector * 4, LookVector * ImpulseForce);
}
[Rpc( MultiplayerApi.RpcMode.AnyPeer, CallLocal = false, TransferChannel = 1, TransferMode = MultiplayerPeer.TransferModeEnum.Reliable)]
void _SpawnPlayer( int UniqueID, string PlayerName, int AbilityIndex ){
if (Multiplayer.IsServer()){
Humanoid playerCharacter = _Reference.GameHandler.Player.Instantiate<Humanoid>();
playerCharacter.Name = UniqueID.ToString() + "," + AbilityIndex + "," + PlayerName;
playerCharacter.PlayerName = PlayerName;
AddChild(playerCharacter, true);
playerCharacter.SetMultiplayerAuthority( UniqueID );
}
}
public void SpawnPlayer( int UniqueID, string PlayerName, Ability _Ability ){
Rpc( "_SpawnPlayer", UniqueID, PlayerName, (int)_Ability );
}
[Rpc( MultiplayerApi.RpcMode.AnyPeer, CallLocal = true, TransferChannel = 1, TransferMode = MultiplayerPeer.TransferModeEnum.Reliable)]
void _clearItemNetworked(string ItemName){
Node3D item = _Reference.ItemSpawnPath.GetNode<Node3D>(ItemName);
if (item != null){
try{
item.QueueFree();
}catch{}
}
}
public void ClearItemNetworked( string ItemName ){
Rpc("_clearItemNetworked", ItemName);
}
public class HumanoidStats {
public int HumanoidOwner { get; set; }
public string UserName { get; set; }
public int MaxHealth { get; set; }
public int Health { get; set; }
}
}