Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Maple2.Server.Core/Packets/UgcPacket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public static ByteWriter ProfilePicture(Character character) {
return pWriter;
}

public static ByteWriter UpdateItem(int objectId, Item item, long createPrice, UgcType ugcType) {
public static ByteWriter UpdateItem(int objectId, long uid, Item item, long createPrice, UgcType ugcType) {
var pWriter = Packet.Of(SendOp.Ugc);
switch (ugcType) {
case UgcType.Item:
Expand All @@ -94,7 +94,7 @@ public static ByteWriter UpdateItem(int objectId, Item item, long createPrice, U

pWriter.WriteInt(objectId);

pWriter.WriteLong(item.Uid);
pWriter.WriteLong(uid);
pWriter.WriteInt(item.Id);
pWriter.WriteInt(item.Amount);
pWriter.WriteUnicodeString(item.Template!.Name);
Expand Down
2 changes: 1 addition & 1 deletion Maple2.Server.Game/Manager/HousingManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,7 @@ public bool TryPlaceCube(HeldCube cube, Plot plot, ItemMetadata itemMetadata, in
}

if (!session.Item.Furnishing.TryPlaceCube(cube.Id, out result)) {
long itemUid = session.Item.Furnishing.AddCube(cube.ItemId);
long itemUid = session.Item.Furnishing.AddCube(cube);
if (itemUid == 0) {
session.Send(CubePacket.Error(UgcMapError.s_ugcmap_not_for_sale));
return false;
Expand Down
62 changes: 50 additions & 12 deletions Maple2.Server.Game/Manager/Items/FurnishingManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,23 @@ public bool PurchaseCube(FurnishingShopTable.Entry furnishingShopMetadata) {
return true;
}

public long AddCube(HeldCube cube) {
const int amount = 1;
lock (session.Item) {
int count = storage.Count;
long itemUid = AddStorage(cube);
if (itemUid == 0) {
return 0;
}

session.Send(FurnishingStoragePacket.Purchase(cube.ItemId, amount));
if (storage.Count != count) {
session.Send(FurnishingStoragePacket.Count(storage.Count));
}
return itemUid;
}
}

// TODO: NOTE - This should also be called for opening a furnishing box
public long AddCube(int id) {
const int amount = 1;
Expand Down Expand Up @@ -193,7 +210,7 @@ public bool RetrieveCube(long uid) {
return false;
}

long itemUid = AddStorage(cube.ItemId);
long itemUid = AddStorage(cube);
if (itemUid == 0) {
logger.Fatal("Failed to return cube: {CubeId} to storage", cube.Id);
throw new InvalidOperationException($"Failed to return cube: {cube.Id} to storage");
Expand All @@ -203,6 +220,15 @@ public bool RetrieveCube(long uid) {
}
}

private long AddStorage(HeldCube cube) {
Item? item = session.Field.ItemDrop.CreateItem(cube.ItemId);
if (item == null) {
return 0;
}

return AddStorage(item, cube.Template);
}

private long AddStorage(int itemId) {
Item? item = session.Field.ItemDrop.CreateItem(itemId);
if (item == null) {
Expand All @@ -212,28 +238,26 @@ private long AddStorage(int itemId) {
return AddStorage(item);
}

public long AddStorage(Item? item) {
public long AddStorage(Item item, UgcItemLook? template = null) {
const int amount = 1;
if (item == null) {
return 0;
}

lock (session.Item) {
Item? stored = storage.FirstOrDefault(existing => existing.Id == item.Id);
Item? stored = storage.FirstOrDefault(existing => existing.Id == item.Id && existing.Template?.Url == template?.Url);
if (stored == null) {
item.Group = ItemGroup.Furnishing;
using GameStorage.Request db = session.GameStorage.Context();
item = db.CreateItem(session.AccountId, item);
if (item == null) {
Item? newItem = db.CreateItem(session.AccountId, item);
if (newItem == null) {
return 0;
}

if (storage.Add(item).Count <= 0) {
db.SaveItems(0, item);
if (storage.Add(newItem).Count <= 0) {
db.SaveItems(0, newItem);
return 0;
}

session.Send(FurnishingStoragePacket.Add(item));
return item.Uid;
session.Send(FurnishingStoragePacket.Add(newItem));
return newItem.Uid;
}

if (stored.Amount + amount > item.Metadata.Property.SlotMax) {
Expand Down Expand Up @@ -270,6 +294,20 @@ private bool RemoveInventory(long uid, [NotNullWhen(true)] out PlotCube? cube) {
return true;
}

public void RemoveItem(long itemUid) {
lock (session.Item) {
Item? item = storage.Get(itemUid);
if (item is null) {
return;
}

item.Amount = 0;

session.Send(FurnishingStoragePacket.Remove(itemUid));
return;
}
}

public void SendStorageCount() {
lock (session.Item) {
session.Send(FurnishingStoragePacket.Count(storage.Count));
Expand Down
2 changes: 1 addition & 1 deletion Maple2.Server.Game/Manager/Items/InventoryManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ public bool Add(Item add, bool notifyNew = false, bool commit = false) {
}

if (add.Type.IsFurnishing) {
session.Item.Furnishing.AddStorage(add);
session.Item.Furnishing.AddStorage(add, add.Template);
session.Item.Inventory.Discard(add);
return true;
}
Expand Down
49 changes: 0 additions & 49 deletions Maple2.Server.Game/Manager/Items/ItemManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,55 +46,6 @@ public ItemManager(GameStorage.Request db, GameSession session, ItemStatsCalcula
return item ?? Equips.Outfit.Values.FirstOrDefault(outfit => outfit.Uid == uid);
}

[Obsolete("Use in actor.ItemDrop instead")]
public Item? CreateItem(int itemId, int rarity = -1, int amount = 1) {
if (!session.ItemMetadata.TryGet(itemId, out ItemMetadata? itemMetadata)) {
return null;
}

if (rarity <= 0) {
if (itemMetadata.Option != null && itemMetadata.Option.ConstantId is < 6 and > 0) {
rarity = itemMetadata.Option.ConstantId;
} else {
rarity = 1;
}
}

var item = new Item(itemMetadata, rarity, amount);
item.Stats = itemStatsCalc.GetStats(item);
item.Socket = itemStatsCalc.GetSockets(item);

if (item.Appearance != null) {
item.Appearance.Color = GetColor(item.Metadata.Customize);
}

return item;
}

[Obsolete]
private EquipColor GetColor(ItemMetadataCustomize metadata) {
// Item has no color
if (metadata.ColorPalette == 0 ||
!session.TableMetadata.ColorPaletteTable.Entries.TryGetValue(metadata.ColorPalette, out IReadOnlyDictionary<int, ColorPaletteTable.Entry>? palette)) {
return default;
}

// Item has random color
if (metadata.DefaultColorIndex < 0) {
// random entry from palette
int index = Random.Shared.Next(palette.Count);
ColorPaletteTable.Entry randomEntry = palette.Values.ElementAt(index);
return new EquipColor(randomEntry.Primary, randomEntry.Secondary, randomEntry.Tertiary, metadata.ColorPalette, index);
}

// Item has specified color
if (palette.TryGetValue(metadata.DefaultColorIndex, out ColorPaletteTable.Entry? entry)) {
return new EquipColor(entry.Primary, entry.Secondary, entry.Tertiary, metadata.ColorPalette, metadata.DefaultColorIndex);
}

return default;
}

public void Bind(Item item) {
if (item.Transfer?.Bind(session.Player.Value.Character) == true) {
session.Send(ItemInventoryPacket.UpdateItem(item));
Expand Down
28 changes: 28 additions & 0 deletions Maple2.Server.Game/PacketHandlers/FurnishingStorageHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using Maple2.PacketLib.Tools;
using Maple2.Server.Core.Constants;
using Maple2.Server.Core.PacketHandlers;
using Maple2.Server.Game.Session;

namespace Maple2.Server.Game.PacketHandlers;

public class FurnishingStorageHandler : PacketHandler<GameSession> {
public override RecvOp OpCode => RecvOp.FurnishingStorage;

private enum Command : byte {
Delete = 6,
}

public override void Handle(GameSession session, IByteReader packet) {
var command = packet.Read<Command>();
switch (command) {
case Command.Delete:
HandleDelete(session, packet);
return;
}
}

private static void HandleDelete(GameSession session, IByteReader packet) {
long itemUid = packet.ReadLong();
session.Item.Furnishing.RemoveItem(itemUid);
}
}
15 changes: 12 additions & 3 deletions Maple2.Server.Game/PacketHandlers/UgcHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -448,15 +448,24 @@ void ConfirmItem() {
}

item.Template.Url = resource.Path;
long uid;

// Dont create the item if it's a furniture since it's tied to account id
if (info.Type is UgcType.Furniture) {
session.Item.Furnishing.AddCube(item);
uid = session.Item.Furnishing.AddCube(item);
} else {
session.Item.Inventory.Add(item, notifyNew: true);
using GameStorage.Request db = session.GameStorage.Context();
Item? newAdd = db.CreateItem(session.CharacterId, item);
if (newAdd == null) {
Logger.Error("Failed to create UGC item {ItemId}", item.Id);
return;
}

uid = newAdd.Uid;
session.Item.Inventory.Add(newAdd, notifyNew: true);
}

session.Send(UgcPacket.UpdateItem(session.Player.ObjectId, item, ugcMetadata.CreatePrice, info.Type));
session.Send(UgcPacket.UpdateItem(session.Player.ObjectId, uid, item, ugcMetadata.CreatePrice, info.Type));
session.Send(UgcPacket.UpdatePath(resource));
}

Expand Down