Categories
Uncategorized

4 new arenas

figured I’d add some documentation here as well since I almost lost this all 3 nights ago. Here’s the full arenamanager and teleport script just incase I get sloppy again!

using UnityEngine;
using UnityEngine.UI;
using Mirror;
using System.Collections.Generic;

namespace GameZero
{
    [DisallowMultipleComponent]
    public class ArenaManager : NetworkBehaviour
    {
        [SerializeField] private bool allowSolo;
        [SerializeField] private Instance arena1;
        [SerializeField] private Instance arena2;
        [SerializeField] private Instance arena3;
        [SerializeField] private Instance arena4;
        [SerializeField] private GameObject preview1Prefab;
        [SerializeField] private GameObject preview2Prefab;
        [SerializeField] private GameObject preview3Prefab;
        [SerializeField] private GameObject preview4Prefab;
        [SyncVar] public int instanceId = -1;
        private RawImage selectedPreview;
        private Instance selectedArena;
        public static ArenaManager singleton;

        private void Awake()
        {
            // Initialize singleton
            if (singleton == null) singleton = this;
        }

        private void Start()
        {
            // Hide all preview images at start
            preview1Prefab.SetActive(false);
            preview2Prefab.SetActive(false);
            preview3Prefab.SetActive(false);
            preview4Prefab.SetActive(false);
        }

        [Command(requiresAuthority = false)]
        public void CmdSetSelectedArena(int instanceId)
        {
            Instance arena = GetInstanceTemplate(instanceId);
            if (arena != null)
            {
                GameObject previewPrefab = GetPreviewPrefabForArena(arena);

                // Update the selected arena on the client only
                selectedArena = arena;
                selectedPreview = previewPrefab.GetComponent<RawImage>();
                this.instanceId = instanceId;

                // Show the preview image of the selected arena
                previewPrefab.SetActive(true);

                // Hide the preview images of other arenas
                if (arena != arena1) preview1Prefab.SetActive(false);
                if (arena != arena2) preview2Prefab.SetActive(false);
                if (arena != arena3) preview3Prefab.SetActive(false);
                if (arena != arena4) preview4Prefab.SetActive(false);

                // Update the preview images on all clients
                imagepreviewsRpc();
            }
        }

        [ClientRpc]
        public void imagepreviewsRpc()
        {
            if (instanceId == 1)
                preview1Prefab.SetActive(selectedPreview == preview1Prefab.GetComponent<RawImage>());
            else if (instanceId == 2)
                preview2Prefab.SetActive(selectedPreview == preview2Prefab.GetComponent<RawImage>());
            else if (instanceId == 3)
                preview3Prefab.SetActive(selectedPreview == preview3Prefab.GetComponent<RawImage>());
            else if (instanceId == 4)
                preview4Prefab.SetActive(selectedPreview == preview4Prefab.GetComponent<RawImage>());
        }

        private GameObject GetPreviewPrefabForArena(Instance arena)
        {
            if (arena == arena1)
                return preview1Prefab;
            else if (arena == arena2)
                return preview2Prefab;
            else if (arena == arena3)
                return preview3Prefab;
            else if (arena == arena4)
                return preview4Prefab;
            else
                return null;
        }
        public void OnArena1ButtonClicked()
        {
            Debug.Log("Arena 1 selected");
            CmdSetSelectedArena(arena1.instanceId);
        }

        public void OnArena2ButtonClicked()
        {
            Debug.Log("Arena 2 selected");
            CmdSetSelectedArena(arena2.instanceId);
        }

        public void OnArena3ButtonClicked()
        {
            Debug.Log("Arena 3 selected");
            CmdSetSelectedArena(arena3.instanceId);
        }

        public void OnArena4ButtonClicked()
        {
            Debug.Log("Arena 4 selected");
            CmdSetSelectedArena(arena4.instanceId);
        }

        public void OnRandomArenaButtonClicked()
        {
            Instance[] arenas = new Instance[] { arena1, arena2, arena3, arena4 };

            int index = Random.Range(0, arenas.Length);

            CmdSetSelectedArena(arenas[index].instanceId);
        }

        public void CreateInstance()
        {
            if (selectedArena != null)
            {
                arenaonoff.onoff.SetArena(selectedArena.arenaName);
                arenaonoff.onoff.StartArena();
            }
            else
            {
                Debug.LogError("No selected arena!");
            }
        }

        public Instance GetInstanceTemplate(int instanceId)
        {
            Debug.Log("GetInstanceTemplate called with instanceId = " + instanceId);
            List<Instance> availableInstances = new List<Instance> { arena1, arena2, arena3, arena4 };

            foreach (Instance availableInstance in availableInstances)
            {
                Debug.Log("Checking instance: " + availableInstance.instanceId);
                if (availableInstance.instanceId == instanceId)
                {
                    Debug.Log("Found instance: " + availableInstance);
                    return availableInstance;
                }
            }

            Debug.Log("Instance not found for instanceId = " + instanceId);
            return null;
        }


    }
}
using UnityEngine;
using Mirror;
using HeathenEngineering.SteamworksIntegration;
using System;
using System.Linq;

namespace GameZero
{
    [DisallowMultipleComponent]
    public class PlayerArenaNpcTeleport : NetworkBehaviour
    {
        [Header("Components")]
        public Player player;
        [SyncVar] public int partyIdToJoin = -1; // initialize to -1 to indicate that it is not set yet
        private Vector3 targetPos;
        public static PlayerArenaNpcTeleport singleton;
       
        // Start is called before the first frame update
        void Awake()
        {

            // initialize singleton
            if (singleton == null) singleton = this;
        }

        [Command(requiresAuthority = false)]
        public void CmdLobbyCreator()
        {
            Debug.Log("Player assigned: " + player.name);
            if (player != null) { PartySystem.FormParty(player.name); }
            partyIdToJoin = player.party.party.partyId;
            Debug.Log($"partyId = {partyIdToJoin}");
        }

        [Command(requiresAuthority = false)]
        public void CmdLobbyJoiner()
        {
            Player[] players = FindObjectsOfType<Player>();
            // loop through each player and do something with them
            foreach (Player player in players)
            {
                if (!player.party.InParty())
                {
                    PartySystem.AddToParty(partyIdToJoin, player.name);
                }
            }
        }

       

        [Command(requiresAuthority = false)]
        public void CmdPartySetup()
        {
            //ArenaManager am = GameObject.FindWithTag("GameManager").GetComponent<ArenaManager>();
            Instance instanceTemplate = ArenaManager.singleton.GetInstanceTemplate(ArenaManager.singleton.instanceId);

            Debug.Log("Cmdpartysetup called");
            Debug.Log("instanceTemplate = " + instanceTemplate);
            Player[] playersInParty = PartySystem.GetPlayersInParty(partyIdToJoin);
            Debug.Log("Number of players in party: " + playersInParty.Length);
            foreach (Player player in playersInParty)
            {
                Debug.Log("player name = " + player.name);


                // loop through each player and do something with them
                Debug.Log("player isServer: " + player.isServer + " hasAuthority: " + player.hasAuthority + " isClient: " + player.isClient + " isLocalPlayer: " + player.isLocalPlayer);


                // collider might be in player's bone structure. look in parents.

                if (player != null)
                {
                    Debug.Log("player is not null");
                    // only call this for server and for local player. not for other
                    // players on the client. no need in locally creating their
                    // instances too.
                    if (player.isServer || player.isLocalPlayer)
                    {
                        Debug.Log("player is server or local player");
                        // required level?
                        if (player.level.current >= instanceTemplate.requiredLevel)
                        {
                            Debug.Log("player met level requirement");
                            // can only enter with a party
                            if (player.party.InParty())
                            {
                                Debug.Log("player is in a party");
                                // is there an instance for the player's party yet?
                                if (instanceTemplate.instances.TryGetValue(player.party.party.partyId, out Instance existingInstance))
                                {
                                    // teleport player to instance entry
                                    if (player.isServer)
                                    {
                                        Debug.Log("player has authority!!");
                                        Vector3 entry1Pos = existingInstance.entry1?.position ?? Vector3.zero;
                                        Vector3 entry2Pos = existingInstance.entry2?.position ?? Vector3.zero;

                                        // Determine the target position for the player based on the player index

                                        int playerIndex = Array.IndexOf(playersInParty, player);
                                        Vector3 targetPos = (playerIndex % 2 == 0) ? entry2Pos : entry1Pos;

                                        // Call the CmdWarpToEntry() method to move the player to the target position
                                        if (player.isServer || (player.isClient && player.hasAuthority))
                                        {
                                            // Call the CmdWarpDrive() method only if the player is owned by a client
                                            player.movement.Warp(targetPos);
                                        }
                                        Debug.Log("Teleporting " + player.name + " to existing instance=" + existingInstance.name + " with partyId=" + player.party.party.partyId);
                                    }

                                }
                                // otherwise create a new one
                                else
                                {
                                    Instance instance = Instance.CreateInstance(instanceTemplate, player.party.party.partyId);
                                    NetworkServer.Spawn(instance.gameObject);
                                    if (instance != null)
                                    {
                                        Debug.Log("instance is not null");
                                        // teleport player to instance entry
                                        Debug.Log("player isServer: " + player.isServer + " hasAuthority: " + player.hasAuthority + " isClient: " + player.isClient + " isLocalPlayer: " + player.isLocalPlayer + "isowned" + player.isOwned);

                                        if (player.isServer)
                                        {
                                            Debug.Log("has authority");
                                            // Get the entry positions for the instance
                                            Vector3 entry1Pos = instance.entry1?.position ?? Vector3.zero;
                                            Vector3 entry2Pos = instance.entry2?.position ?? Vector3.zero;

                                            // Determine the target position for the player based on the player index

                                            int playerIndex = Array.IndexOf(playersInParty, player);
                                            Vector3 targetPos = (playerIndex % 2 == 0) ? entry2Pos : entry1Pos;

                                            // Call the CmdWarpToEntry() method to move the player to the target position
                                            if (player.isServer || (player.isClient && player.hasAuthority))
                                            {
                                                if (player.GetComponent<NetworkIdentity>().hasAuthority)
                                                {
                                                    Debug.Log("client has authority for cmdwarpdrive");
                                                    // Check if client is still connected
                                                    if (!NetworkServer.connections.ContainsKey(player.GetComponent<NetworkIdentity>().connectionToClient.connectionId))
                                                    {
                                                        // Client has disconnected, do something
                                                        Debug.Log("client has disconnected, do something!");
                                                    }
                                                    else
                                                    {
                                                        // Call the CmdWarpDrive() method only if the player is owned by a client
                                                        player.movement.Warp(targetPos);
                                                        Debug.Log("player passed all checks, warping successfully");
                                                    }
                                                }
                                                Debug.Log("player didn't have authority, still warping just in case");
                                                player.movement.Warp(targetPos);
                                            }
                                            Debug.Log("Teleporting " + player.name + " to new instance=" + instance.name + " with partyId=" + player.party.party.partyId);
                                        }
                                        else { Debug.Log("player is not server!!"); }

                                    }
                                    else if (player.isServer) player.chat.TargetMsgInfo("There are already too many " + instance.name + " instances. Please try again later.");
                                }
                            }

                            else
                            {
                                Debug.LogError("No existing instance found!");
                            }
                        }
                    }

                }
            }

        }
    }
}
Categories
Uncategorized

4-25 update

so I’ve been working on the arena for some time now and thought i’d update you guys with some information about how it works, what it’s capable of and where it’s going in the future.

as you can see in this video there is an npc that opens a dialogue, when you open that dialogue you can create the lobby or browse a lobby. once a lobby is created other players can join in. after everyone selects ready and a map is chosen you can start the session and everyone is ported to their respective entry, odd players go to entry1 even players go to entry 2. after 10 seconds the gates open and they can begin fighting. warcraft has a 20 minute timer(I believe, it could be 25 minuters though?). I would like to have a timer like that eventually, right now everyone is in the same party which could produce problems down the line, but it works for now. The big feature here is synchronizing the maps over the network instead of locally. This means I can add any map and it should work regardless of size or shape. So seeded procedural arenas are a possibility. With that said, this is a huge breakthough for our team and I am proud to announce the arrival of networked arenas to GameZero.

There are 3 scripts that make this work. A player arena npc teleport script which handles all the group management and teleportation, an instance manager which handles synchronizing the instances over the network, and an arenamanager which handles the selection of instances and definition of which instance has been selected during the selection process. Over 400 lines of code were added to the ummorpg data structure to make this a reality. I hope you enjoy the video.