예제 #1
0
        private void OnPlayerChestItem(TSPlayer player, BinaryReader reader)
        {
            var session = player.GetSession();
            var chestId = reader.ReadInt16();

            if (!session.IdToChest.TryGetValue(chestId, out var chest))
            {
                Debug.WriteLine($"DEBUG: {player.Name} attempted to modify chest (ID: {chestId})");
                return;
            }

            Debug.WriteLine($"DEBUG: {player.Name} modified chest at {chest.X}, {chest.Y} (ID: {chestId})");
            var index     = reader.ReadByte();
            var stackSize = reader.ReadInt16();
            var prefixId  = reader.ReadByte();
            var itemId    = reader.ReadInt16();

            chest.Items[index] = new NetItem(itemId, stackSize, prefixId);
            _database.Update(chest);
        }
예제 #2
0
        /// <summary>
        ///     Shows the chest to the specified player.
        /// </summary>
        /// <param name="player">The player, which must not be <c>null</c>.</param>
        /// <param name="newChestId">A new chest ID to use for showing the chest.</param>
        public void ShowTo(TSPlayer player, int newChestId)
        {
            if (RefillTime != null && DateTime.UtcNow - _lastRefill > RefillTime)
            {
                Debug.WriteLine($"DEBUG: Chest at {X}, {Y} was refilled");
                _lastRefill = DateTime.UtcNow;
                for (var i = 0; i < Terraria.Chest.maxItems; ++i)
                {
                    Items[i] = OriginalItems[i];
                }
            }

            var session = player.GetSession();

            if (!session.ChestToId.TryGetValue(this, out var chestId))
            {
                chestId = newChestId;

                // Remove all mappings of the old chest ID.
                foreach (var kvp in session.ChestToId.Where(kvp => kvp.Value == chestId).ToList())
                {
                    session.ChestToId.Remove(kvp);
                }
                session.IdToChest.Remove(chestId);
            }

            session.ChestToId[this]    = chestId;
            session.IdToChest[chestId] = this;

            Debug.WriteLine($"DEBUG: {player.Name} accessing chest at {X}, {Y} (ID: {chestId})");
            lock (ChestLock)
            {
                var terrariaChest = new Terraria.Chest {
                    x = X, y = Y, name = Name
                };
                Main.chest[chestId] = terrariaChest;
                player.SendData(PacketTypes.ChestName, "", chestId, X, Y);
                for (var i = 0; i < Terraria.Chest.maxItems; ++i)
                {
                    var item = new Item();
                    item.SetDefaults(Items[i].NetId);
                    item.stack            = Items[i].Stack;
                    item.prefix           = Items[i].PrefixId;
                    terrariaChest.item[i] = item;
                    player.SendData(PacketTypes.ChestItem, "", chestId, i);
                }
                player.SendData(PacketTypes.ChestOpen, "", chestId);
                Main.chest[chestId] = null;
            }
            player.TPlayer.chest = chestId;

            // Sync player chest indices for everyone. We have to ensure that each player only receives the chest ID
            // that they received for the chest.
            foreach (var player2 in TShock.Players.Where(p => p?.Active == true && p != player))
            {
                var session2 = player2.GetSession();
                if (session2.ChestToId.TryGetValue(this, out var chestId2))
                {
                    player2.SendData(PacketTypes.SyncPlayerChestIndex, "", player.Index, chestId2);
                }
            }
        }
예제 #3
0
        private void OnPlayerChestSet(TSPlayer player, BinaryReader reader)
        {
            var chestId = reader.ReadInt16();

            reader.ReadInt16();
            reader.ReadInt16();
            var length = reader.ReadByte();
            var name   = "";

            if (length > 0 && length <= 20)
            {
                name = reader.ReadString();
            }
            else if (length != 255)
            {
                length = 0;
            }

            var tplayer    = player.TPlayer;
            var session    = player.GetSession();
            var oldChestId = tplayer.chest;

            if (session.IdToChest.TryGetValue(oldChestId, out var oldChest))
            {
                oldChest.IsInUse = false;
                if (length != 0)
                {
                    Debug.WriteLine(
                        $"DEBUG: {player.Name} renamed chest at {oldChest.X}, {oldChest.Y} (ID: {chestId})");
                    oldChest.Name = name;
                    _database.Update(oldChest);

                    // Sync chest names for everyone. We have to ensure that each player recieves the chest ID that they
                    // received for the chest.
                    foreach (var player2 in TShock.Players.Where(p => p?.Active == true && p != player))
                    {
                        var session2 = player2.GetSession();
                        if (session2.ChestToId.TryGetValue(oldChest, out var chestId2))
                        {
                            player2.SendData(PacketTypes.ChestName, "", chestId2, oldChest.X, oldChest.Y);
                        }
                    }
                }
            }

            tplayer.chest = chestId;
            // Sync player chest indices for everyone. If the chest ID is positive, we have to ensure that each player
            // receives the chest ID that they received for the chest.
            if (chestId >= 0 && session.IdToChest.TryGetValue(chestId, out var chest))
            {
                foreach (var player2 in TShock.Players.Where(p => p?.Active == true && p != player))
                {
                    var session2 = player2.GetSession();
                    if (session2.ChestToId.TryGetValue(chest, out var chestId2))
                    {
                        player2.SendData(PacketTypes.SyncPlayerChestIndex, "", player.Index, chestId2);
                    }
                }
            }
            else if (chestId == -1)
            {
                Debug.WriteLine($"DEBUG: {player.Name} finished accessing chest (ID: {oldChestId})");
                NetMessage.SendData((int)PacketTypes.SyncPlayerChestIndex, -1, player.Index, null, player.Index, -1);

                // Handle biome mimic spawning.
                if (oldChest == null)
                {
                    return;
                }
                var x = oldChest.X;
                var y = oldChest.Y;
                if (!TileID.Sets.BasicChest[Main.tile[x, y].type])
                {
                    return;
                }

                var npcId      = -1;
                var onlyItemId = oldChest.OnlyItemId;
                if (onlyItemId == ItemID.LightKey)
                {
                    npcId = NPCID.BigMimicHallow;
                }
                else if (onlyItemId == ItemID.NightKey)
                {
                    npcId = WorldGen.crimson ? NPCID.BigMimicCrimson : NPCID.BigMimicCorruption;
                }

                if (npcId > 0)
                {
                    if (!player.HasPermission(Permissions.spawnmob))
                    {
                        Debug.WriteLine($"DEBUG: {player.Name} tried to spawn a biome mimic");
                        player.SendErrorMessage("You don't have access to spawn mobs.");
                        return;
                    }

                    Debug.WriteLine($"DEBUG: {player.Name} spawned a biome mimic");
                    _database.Remove(oldChest);
                    Main.tile[x, y].active(false);
                    Main.tile[x, y + 1].active(false);
                    Main.tile[x + 1, y].active(false);
                    Main.tile[x + 1, y + 1].active(false);
                    TSPlayer.All.SendTileSquare(x, y, 2);

                    var npcIndex = NPC.NewNPC(16 * x + 16, 16 * y + 32, npcId);
                    var npc      = Main.npc[npcIndex];
                    npc.whoAmI = npcIndex;
                    TSPlayer.All.SendData(PacketTypes.NpcUpdate, "", npcIndex);
                    npc.BigMimicSpawnSmoke();
                }
            }
        }
예제 #4
0
        private void OnPlayerChestGet(TSPlayer player, BinaryReader reader)
        {
            var x = reader.ReadInt16();
            var y = reader.ReadInt16();

            var session = player.GetSession();
            var chest   = _database.GetOrConvert(x, y);

            if (chest == null)
            {
                player.SendErrorMessage("This chest is corrupted.");
                session.PendingChestAction = ChestAction.None;
                return;
            }

            switch (session.PendingChestAction)
            {
            case ChestAction.GetInfo:
                Debug.WriteLine($"DEBUG: {player.Name} obtained info about chest at {x}, {y}");
                player.SendInfoMessage(
                    $"X: {x}, Y: {y}, Owner: {chest.OwnerName ?? "N/A"} {(chest.IsPublic ? "(Public)" : "")}");
                if (chest.RefillTime != null)
                {
                    player.SendInfoMessage($"Refill time: {chest.RefillTime}");
                }
                if (chest.AllowedUsernames.Count > 0)
                {
                    player.SendInfoMessage($"Allowed users: {string.Join(", ", chest.AllowedUsernames)}");
                }
                if (chest.AllowedGroupNames.Count > 0)
                {
                    player.SendInfoMessage($"Allowed groups: {string.Join(", ", chest.AllowedGroupNames)}");
                }
                break;

            case ChestAction.TogglePublic:
                if (!chest.IsOwner(player))
                {
                    Debug.WriteLine(
                        $"DEBUG: {player.Name} attempted to toggle public status for chest at {x}, {y}");
                    player.SendErrorMessage("This chest is protected.");
                    break;
                }

                Debug.WriteLine($"DEBUG: {player.Name} toggled public status for chest at {x}, {y}");
                chest.IsPublic = !chest.IsPublic;
                _database.Update(chest);
                player.SendInfoMessage($"This chest is now {(chest.IsPublic ? "public" : "private")}.");
                break;

            case ChestAction.ToggleMultiuse:
                if (!chest.IsOwner(player))
                {
                    Debug.WriteLine(
                        $"DEBUG: {player.Name} attempted to toggle multiuse status for chest at {x}, {y}");
                    player.SendErrorMessage("This chest is protected.");
                    break;
                }

                Debug.WriteLine($"DEBUG: {player.Name} toggled multiuse status for chest at {x}, {y}");
                chest.IsMultiUse = !chest.IsMultiUse;
                _database.Update(chest);
                player.SendInfoMessage(
                    $"This can {(chest.IsMultiUse ? "now" : "no longer")} be used by multiple players.");
                break;

            case ChestAction.SetRefill:
                if (!chest.IsOwner(player))
                {
                    Debug.WriteLine($"DEBUG: {player.Name} attempted to set refill time for chest at {x}, {y}");
                    player.SendErrorMessage("This chest is protected.");
                    break;
                }

                Debug.WriteLine($"DEBUG: {player.Name} set refill time for chest at {x}, {y}");
                chest.RefillTime = session.PendingRefillTime;
                _database.Update(chest);
                player.SendInfoMessage(chest.RefillTime == null
                                               ? "This chest will no longer refill."
                                               : $"This chest will now refill every {chest.RefillTime}.");
                break;

            case ChestAction.ToggleUser:
                if (!chest.IsOwner(player))
                {
                    Debug.WriteLine($"DEBUG: {player.Name} attempted to toggle a user for chest at {x}, {y}");
                    player.SendErrorMessage("This chest is protected.");
                    break;
                }

                Debug.WriteLine($"DEBUG: {player.Name} toggled a user for chest at {x}, {y}");
                if (chest.AllowedUsernames.Contains(session.PendingUsername))
                {
                    chest.AllowedUsernames.Remove(session.PendingUsername);
                    player.SendInfoMessage($"Disallowed {session.PendingUsername} from editing this chest.");
                }
                else
                {
                    chest.AllowedUsernames.Add(session.PendingUsername);
                    player.SendInfoMessage($"Allowed {session.PendingUsername} to edit this chest.");
                }
                _database.Update(chest);
                break;

            case ChestAction.ToggleGroup:
                if (!chest.IsOwner(player))
                {
                    Debug.WriteLine($"DEBUG: {player.Name} attempted to toggle a group for chest at {x}, {y}");
                    player.SendErrorMessage("This chest is protected.");
                    break;
                }

                Debug.WriteLine($"DEBUG: {player.Name} toggled a group for chest at {x}, {y}");
                if (chest.AllowedGroupNames.Contains(session.PendingGroupName))
                {
                    chest.AllowedGroupNames.Remove(session.PendingGroupName);
                    player.SendInfoMessage($"Disallowed the {session.PendingGroupName} group from editing this chest.");
                }
                else
                {
                    chest.AllowedGroupNames.Add(session.PendingGroupName);
                    player.SendInfoMessage($"Allowed the {session.PendingGroupName} group to edit this chest.");
                }
                _database.Update(chest);
                break;

            case ChestAction.Claim:
                if (!string.IsNullOrEmpty(chest.OwnerName))
                {
                    Debug.WriteLine($"DEBUG: {player.Name} attempted to claim a chest at {x}, {y}");
                    player.SendErrorMessage("This chest is already claimed.");
                    return;
                }

                Debug.WriteLine($"DEBUG: {player.Name} claimed a chest at {x}, {y}");
                chest.OwnerName = player.User?.Name;
                _database.Update(chest);
                player.SendInfoMessage("Claimed chest.");
                break;

            case ChestAction.Unclaim:
                if (!chest.IsOwner(player))
                {
                    Debug.WriteLine($"DEBUG: {player.Name} attempted to unclaim a chest at {x}, {y}");
                    player.SendErrorMessage("This chest is protected.");
                    return;
                }

                Debug.WriteLine($"DEBUG: {player.Name} unclaimed a chest at {x}, {y}");
                chest.OwnerName = null;
                _database.Update(chest);
                player.SendInfoMessage("Unclaimed chest.");
                break;

            default:
                if (!chest.IsAllowed(player))
                {
                    Debug.WriteLine($"DEBUG: {player.Name} attempted to access chest at {x}, {y}");
                    player.SendErrorMessage("This chest is protected.");
                    break;
                }
                if (!chest.CanUse)
                {
                    Debug.WriteLine($"DEBUG: {player.Name} attempted to access chest at {x}, {y}");
                    player.SendErrorMessage("This chest is currently in use.");
                    break;
                }

                var oldChestId = player.TPlayer.chest;
                if (session.IdToChest.TryGetValue(oldChestId, out var oldChest))
                {
                    oldChest.IsInUse = false;
                }

                chest.IsInUse = true;
                chest.ShowTo(player, session.GetNextChestId());
                break;
            }
            session.PendingChestAction = ChestAction.None;
        }