Ejemplo n.º 1
0
 private void StartMonitoringActors()
 {
     if (monitoringActors)
     {
         return;
     }
     monitoringActors             = true;
     engine.onActorCreated       += OnActorCreated;
     engine.onBeforeActorDestroy += OnActorDestroyed;
     foreach (VoosActor actor in engine.EnumerateActors())
     {
         StartMonitoringActor(actor);
     }
 }
Ejemplo n.º 2
0
    private void RefreshActorList()
    {
        List <VoosActor> onList = new List <VoosActor>(engine.EnumerateActors().Where(actor => ShouldActorBeListed(false, actor)));

        // Include a "None" option so the user can choose to fill in a field with "no actor".
        // A null in the list means None.
        onList.Insert(0, null);
        onStageList.SetActors(onList);
        onStageList.AddClickListener(OnActorClicked);

        if (allowOffstageActors)
        {
            offStageList.SetActors(engine.EnumerateActors().Where(actor => ShouldActorBeListed(true, actor)));
            offStageList.AddClickListener(OnActorClicked);
        }
    }
Ejemplo n.º 3
0
    void NotifyCardRemovedLocal(string brainId, string useId)
    {
        if (!HasBrain(brainId))
        {
            return;
        }
        // Check the useId is still on the brain..
        var brain = GetBrain(brainId);

        if (!brain.HasUse(useId))
        {
            // Ignore it - could be a reflected duplicate call.
            return;
        }

        foreach (VoosActor actor in voosEngine.EnumerateActors().
                 Where(actor => actor.GetBrainName() == brainId))
        {
            // Only call for my local actors (remote owners will take care of calling this for their actors).
            if (actor.IsLocallyOwned())
            {
                CallBehaviorUseMethod <object, object>(
                    useId,
                    actor.GetName(),
                    "onCardRemoved",
                    null);
            }
        }
    }
    private void HandleModuleCompileError(VoosEngine.ModuleCompileError error)
    {
        string behaviorUri = error.moduleKey;

        var beh  = behaviorSystem.GetBehaviorData(behaviorUri);
        var meta = JsonUtility.FromJson <BehaviorCards.CardMetadata>(beh.metadataJson);

        HashSet <string> usingBrainIds = new HashSet <string>(from entry in behaviorSystem.BrainsForBehavior(behaviorUri)
                                                              select entry.id);

        VoosActor oneActor = (from actor in voosEngine.EnumerateActors()
                              where usingBrainIds.Contains(actor.GetBrainName())
                              select actor).FirstOrDefault();

        string actorsUsing = oneActor == null ? "No actors using it" : $"One actor using it: {oneActor.GetDebugName()}";
        string msg         = $"<color=yellow>Error with card '{meta.cardSystemCardData.title}' (line {error.lineNum}). {actorsUsing}. The error:</color>\n<color=red>{error.message}</color>";

        CommandTerminal.HeadlessTerminal.Buffer.HandleLog(msg, TerminalLogType.Error, null);

        // NOTE: Ideally, we'd do this if we know the code editor isn't viewing this particular behavior
        if (Time.timeSinceLevelLoad < 5f && (!IsCodeEditorOpen() || error.lineNum == -1))
        {
            popup.Show($"There was an error with card '{meta.cardSystemCardData.title}' (line {error.lineNum}):\n{error.message}\n<color=#666666>{actorsUsing}.</color>", "OK", null, 1400f);
        }
    }
Ejemplo n.º 5
0
    public override void OnPhotonPlayerDisconnected(PhotonPlayer otherPlayer)
    {
        Util.Log($"Player {otherPlayer.ID} disconnected.");

        var cms = FindObjectOfType <HudNotifications>();

        if (cms != null)
        {
            cms.AddMessage($"'{otherPlayer.NickName}' left");
        }

        if (!PhotonNetwork.isMasterClient)
        {
            return;
        }

        // Inefficient and global, but whatever...
        foreach (UserBody body in FindObjectsOfType <UserBody>())
        {
            if (body.GetComponent <PhotonView>().OwnerActorNr == otherPlayer.ID)
            {
                PhotonNetwork.Destroy(body.gameObject);
            }
        }

        // Reclaim all actors owned by this player. A bit surprised photon doesn't
        // do this for us..
        foreach (VoosActor actor in voosEngine.EnumerateActors())
        {
            if (actor.reliablePhotonView != null && actor.reliablePhotonView.OwnerActorNr == otherPlayer.ID)
            {
                // Why not call actor.RequestOwnership here? That would result in
                // nothing happening, because the other player is definitely gone. But
                // calling view.RequestOwnership() directly will go through the normal
                // Photon flow, bypassing all our logic, and Photon should just grant us
                // ownership.
                actor.reliablePhotonView.RequestOwnership();
            }
        }

        // Broadcast a message saying the player disconnected.
        PlayerLeftMessage playerLeftMessage = new PlayerLeftMessage();

        playerLeftMessage.id       = otherPlayer.ID;
        playerLeftMessage.nickName = otherPlayer.NickName;
        voosEngine.BroadcastMessage("PlayerLeft", playerLeftMessage);
    }
Ejemplo n.º 6
0
    public void OnGUI()
    {
        if (DebugLevel % 3 == 0 || PhotonNetwork.offlineMode)
        {
            return;
        }

        GUI.skin = this.Skin;

        int height = 600;

        GUILayout.BeginArea(new Rect(0, Screen.height / 2 - height / 2, 300, height));

        string stateColorString = PhotonNetwork.inRoom ? "#00ff88" : "yellow";

        GUILayout.Label($"<color={stateColorString}>{PhotonNetwork.connectionStateDetailed.ToString()}</color>");

        if (PhotonNetwork.inRoom)
        {
            GUILayout.Label($"Room: {PhotonNetwork.room.name}");

            System.Action <PhotonPlayer> emitLabel = (PhotonPlayer player) =>
            {
                int    localPlayerId  = player.ID;
                string playerIsMaster = player.IsMasterClient ? "(master) " : "";
                string you            = player == PhotonNetwork.player ? "(you)" : "";
                string playerLabel    = Util.GetPlayerName(player.GetRoomIndex());
                GUILayout.Label(string.Format("P{3} ({0}), {1} {2}{4}", localPlayerId, playerLabel, playerIsMaster, player.GetRoomIndex(), you));
            };

            emitLabel(PhotonNetwork.player);
            foreach (PhotonPlayer otherPlayer in PhotonNetwork.otherPlayers)
            {
                emitLabel(otherPlayer);
            }

            GUILayout.Label($"{PhotonNetwork.otherPlayers.Length} other players in room");
        }

        if (unreliable != null)
        {
            var diag = unreliable.GetDiagnostics();
            GUILayout.Label($"Unreliable diag:\n{JsonUtility.ToJson(diag, true)}");
        }
        else
        {
            GUILayout.Label($"Unreliable DNE");
        }

        GUILayout.EndArea();

        if (DebugLevel % 3 == 2)
        {
            foreach (VoosActor actor in engine.EnumerateActors())
            {
                DrawActorDebugGUI(actor);
            }
        }
    }
    static void CommandActors(CommandArg[] args)
    {
        if (consoleInstance == null)
        {
            return;
        }

        string substring = args.Length > 0 ? args[0].ToString().ToLowerInvariant() : null;

        int i = 0;

        foreach (var actor in consoleInstance.EnumerateActors())
        {
            if (substring == null || (actor.GetDisplayName() ?? "").ToLowerInvariant().Contains(substring))
            {
                HeadlessTerminal.Log($"#{i}: {actor.GetDisplayName()} ({actor.GetName()})");
            }
            i++;
        }
    }
Ejemplo n.º 8
0
    // Update is called once per frame
    void Update()
    {
        if (!setupComplete)
        {
            return;
        }

        foreach (VoosActor actor in voosEngine.EnumerateActors())
        {
            if (IsActorCenterOnScreen(actor))
            {
                InWorldLogPanel panel = GetOrAddPanel(actor);
                UpdatePanelPosition(panel);
            }
            else
            {
                AttemptRemovePanel(actor);
            }
        }
    }
Ejemplo n.º 9
0
    private void AssignPlayerToActorLocal(int playerNumber, string actorName)
    {
        foreach (VoosActor actor in engine.EnumerateActors())
        {
            // Only act on locally owned actors (all clients are running this method by the miracle of RPCs,
            // so each client will act on the actors they own).
            if (!actor.IsLocallyOwned())
            {
                continue;
            }

            Behaviors.BehaviorUse playerControlsPanel = TryGetPlayerControlsPanel(actor);
            if (playerControlsPanel == null)
            {
                continue;
            }

            if (playerNumber != ASSIGN_ACTOR_AS_NPC)
            {
                // If this actor is set to this player#, set it 0 unless it's the desired actor.
                // If this actor is the desired actor, set its player#.
                int thisPlayerNumber = playerControlsPanel.GetPropertyValue <int>(PLAYER_NUMBER_PROP_NAME, PLAYER_NUMBER_PROP_DEFAULT_VALUE);
                if (thisPlayerNumber == playerNumber && actor.GetName() != actorName)
                {
                    SetPlayerNumberOnPlayerControlsPanel(actor, playerControlsPanel, 0);
                }
                else if (thisPlayerNumber != playerNumber && actor.GetName() == actorName)
                {
                    SetPlayerNumberOnPlayerControlsPanel(actor, playerControlsPanel, playerNumber);
                }
            }
            else
            {
                // Our mission is just to make the desired actor an NPC.
                if (actor.GetName() == actorName)
                {
                    DeletePlayerControlsPanel(actor);
                }
            }
        }
    }
Ejemplo n.º 10
0
    private void RefreshDropdown()
    {
        dropdownActors = new List <VoosActor>(voosEngine.EnumerateActors());

        ClearOptions();
        // TODO wasteful to allocate a new array each time...
        List <string> actorNames = new List <string>(dropdownActors.Count);

        foreach (VoosActor dropdownActor in dropdownActors)
        {
            actorNames.Add(dropdownActor.GetDisplayName());
        }
        AddOptions(actorNames);

        for (int i = 0; i < dropdownActors.Count; i++)
        {
            if (dropdownActors[i] == actor)
            {
                this.value = i;
                return;
            }
        }
    }
Ejemplo n.º 11
0
    public void Reset(
        Vector2 worldSize, byte[] terrainV2Data,
        bool loadingDataFromBeforeDigging,
        byte[] legacyData,
        ulong[] customStyleWorkshopIds = null,
        string simpleData = null)
    {
        Debug.Assert(worldSize.magnitude > 0f);
        Util.Log($"Resetting terrain!");

        float groundSizeX = worldSize.x;
        float groundSizeZ = worldSize.y;

        var newDims = new Int3(
            Mathf.CeilToInt(groundSizeX / BLOCK_SIZE.x),
            BlocksYCount,
            Mathf.CeilToInt(groundSizeZ / BLOCK_SIZE.z));

        Debug.Assert(newDims >= new Int3(10, 10, 10));

        Int3 newBotCenter = new Int3(newDims.x / 2, 0, newDims.z / 2);

        // If old data exists, make sure we restore it. This is the resize use case.
        byte[] restoreData = null;
        Int3   restoreDims = Int3.zero();

        if (terrainV2 != null)
        {
            var oldDims = terrainV2.GetWorldDimensions();
            restoreDims = Int3.Min(oldDims, newDims);
            Int3 start = oldDims / 2 - restoreDims / 2;
            Int3 end   = start + restoreDims;
            Debug.Assert(start >= Int3.zero());
            Debug.Assert(end <= oldDims);
            restoreData = terrainV2.Serialize(start, end);

            Destroy(terrainV2.gameObject);
            terrainV2 = null;
        }

        using (Util.Profile("terrainV2 instantiate"))
            terrainV2 = Instantiate(terrainV2Prefab, Vector3.zero, Quaternion.identity, this.transform);

        using (Util.Profile("terrainV2 SetWorldDimensions"))
            terrainV2.SetWorldDimensions(newDims);

        terrainV2.SetRootOffset(new Vector3(
                                    -newDims.x / 2 * 2.5f,
                                    BlocksYStart * BlockHeight + BlockHeight / 2f,
                                    -newDims.z / 2 * 2.5f));

        using (Util.Profile("Create color terrain textures"))
        {
            int texSize = terrainV2.GetStyleTextureResolution();
            // Color32 way faster in general than Color.
            for (int i = 0; i < NumSolidColorStyles; i++)
            {
                Color32[] pixels  = new Color32[texSize * texSize];
                Color32   color32 = rendering.blockColors[i];
                for (int j = 0; j < pixels.Length; j++)
                {
                    pixels[j] = color32;
                }
                terrainV2.SetStyleTextures(i, pixels); // color

                // 10 is orange
                if (i == (int)BlockStyle.SolidColor10)
                {
                    fallbackTexture = pixels;
                }
            }
        }

        Debug.Assert(fallbackTexture != null, "Could not find fallbackTexture?");

        // TODO why do we do these specifically? Are they not read in via the loop below?
        terrainV2.SetStyleTextures((int)BlockStyle.Stone, terrainV2Textures[4].GetPixels32());                                                                              // stone
        terrainV2.SetStyleTextures((int)BlockStyle.Space, terrainV2Textures[1].GetPixels32());                                                                              // metal
        terrainV2.SetStyleTextures((int)BlockStyle.Grass, terrainV2Textures[8].GetPixels32(), terrainV2Textures[7].GetPixels32(), terrainV2Textures[6].GetPixels32());      // grass
        terrainV2.SetStyleTextures((int)BlockStyle.SnowRock, terrainV2Textures[11].GetPixels32(), terrainV2Textures[10].GetPixels32(), terrainV2Textures[9].GetPixels32()); // snow

        foreach (object obj in Enum.GetValues(typeof(BlockStyle)))
        {
            BlockStyle style = (BlockStyle)obj;
            if ((int)style <= (int)BlockStyle.SnowRock)
            {
                // We hard code this above for now.
                continue;
            }
            Color32[] topOrAtlas = null;
            Color32[] side       = null;
            Color32[] overflow   = null;
            foreach (var tex in terrainV2Textures)
            {
                if (tex == null)
                {
                    continue;
                }
                if (!tex.name.StartsWith(style.ToString().ToLowerInvariant()))
                {
                    continue;
                }

                if (tex.name.EndsWith("-top") || tex.name == style.ToString().ToLowerInvariant())
                {
                    topOrAtlas = tex.GetPixels32();
                }
                else if (tex.name.EndsWith("-side-ceiling"))
                {
                    side = tex.GetPixels32();
                }
                else if (tex.name.EndsWith("-overflow"))
                {
                    overflow = tex.GetPixels32();
                }
            }

            if (topOrAtlas == null)
            {
                Util.LogWarning($"Had to use fallback texture for terrain style {style}. side={side}, overflow={overflow}");
                topOrAtlas = fallbackTexture;
            }

            if (side != null)
            {
#if UNITY_EDITOR
                Debug.Assert(overflow != null, $"{style.ToString()} style has a side texture but not an overflow?");
#endif
            }
            else
            {
                if (overflow != null)
                {
                    Util.LogWarning($"Style {style} had an overflow texture but not a side? IGNORING overflow.");
                    overflow = null;
                }
            }

            terrainV2.SetStyleTextures((int)style, topOrAtlas, side, overflow);
        }

        // Custom styles
        this.customStyleWorkshopIds.Clear();
        if (customStyleWorkshopIds != null)
        {
            this.customStyleWorkshopIds.AddRange(customStyleWorkshopIds);
        }
        UpdateCustomStyleWorkshopIds();

        if (restoreData != null)
        {
            terrainV2.Deserialize(restoreData, (newDims / 2 - restoreDims / 2));
        }

        if (legacyData != null)
        {
            LoadLegacyTerrainData(legacyData);

            // But move all the blocks to our new system.
            using (Util.Profile("legacySync"))
            {
                foreach (var args in database.EnumerateBlocks())
                {
                    terrainV2.SetCell(args.cell.ToInt3() + GetV2Offset(), (int)args.value.style, (int)args.value.blockType - 1, (int)args.value.direction);
                }
            }
        }

        if (terrainV2Data != null)
        {
            Util.Log($"loading v2 data of {terrainV2Data.Length} bytes");
            using (Util.Profile("terrainV2 Deserialize"))
                terrainV2.Deserialize(terrainV2Data);

            // Legacy upgrade
            if (loadingDataFromBeforeDigging)
            {
                // The serialized data was before digging. We need to move it up, effectively.
                Debug.Assert(BlocksYStart < 0);
                // Copy...
                byte[] temp = terrainV2.Serialize(
                    Int3.zero(),
                    newDims.WithY(newDims.y + BlocksYStart));
                // Move up..
                terrainV2.Deserialize(
                    temp,
                    Int3.zero().WithY(-BlocksYStart));

                // At this point, we actually have 2 copies of the terrain, offset by
                // some Y! heh. But the SetSlices call below will deal with that.
            }
        }

        if (loadingDataFromBeforeDigging)
        {
            // Fill in the ground.
            BlockStyle style = BlockStyle.Grass;
            switch (stage.GetGroundType())
            {
            case GameBuilderStage.GroundType.Snow:
                style = BlockStyle.SnowRock;
                break;

            case GameBuilderStage.GroundType.SolidColor:
            case GameBuilderStage.GroundType.Space:
            case GameBuilderStage.GroundType.Grass:
            default:
                style = BlockStyle.Grass;
                break;
            }
            terrainV2.SetSlices(0, (0 - BlocksYStart), (int)style, 0, 0);
        }

        if (!simpleData.IsNullOrEmpty())
        {
            byte[] zippedBytes = System.Convert.FromBase64String(simpleData);
            using (var zippedStream = new System.IO.MemoryStream(zippedBytes, 0, zippedBytes.Length))
                using (var unzipped = new System.IO.Compression.GZipStream(zippedStream, System.IO.Compression.CompressionMode.Decompress))
                    using (System.IO.BinaryReader reader = new System.IO.BinaryReader(unzipped))
                    {
                        int version = reader.ReadUInt16(); // Unused.
                        Debug.Assert(version == 0, $"Unknown simpleData version: {version}");
                        uint numBlocks = reader.ReadUInt32();
                        Util.Log($"reading in {numBlocks} from simpleData");
                        for (int i = 0; i < numBlocks; i++)
                        {
                            short  x         = reader.ReadInt16();
                            short  y         = reader.ReadInt16();
                            short  z         = reader.ReadInt16();
                            byte   shape     = reader.ReadByte();
                            byte   direction = reader.ReadByte();
                            ushort style     = reader.ReadUInt16();
                            this.SetCellValue(
                                new Cell(x, y, z),
                                new CellValue
                            {
                                blockType = (BlockShape)shape,
                                direction = (BlockDirection)direction,
                                style     = (BlockStyle)style
                            });
                        }
                    }
        }

        // Now mark chunks with actors in them as important
        foreach (var actor in engine.EnumerateActors())
        {
            // Non-dynamic-physics actors don't need terrain to exist...well, less so.
            if (!actor.GetEnablePhysics())
            {
                continue;
            }
            var  pos  = actor.GetSpawnPosition();
            Int3 cell = GetContainingCell(pos).ToInt3();
            terrainV2.ReportRigidbodyAt((cell + GetV2Offset()));
        }
    }