Files
reallife-gamemode/ReallifeGamemode.Server/Managers/InventoryManager.cs
2021-05-27 21:11:11 +02:00

690 lines
22 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Timers;
using GTANetworkAPI;
using Newtonsoft.Json;
using ReallifeGamemode.Database.Entities;
using ReallifeGamemode.Database.Models;
using ReallifeGamemode.Server.Extensions;
using ReallifeGamemode.Server.Inventory;
using ReallifeGamemode.Server.Inventory.Interfaces;
using ReallifeGamemode.Server.Services;
using ReallifeGamemode.Server.Util;
using ReallifeGamemode.Services;
using ReallifeGamemode.Server.Types;
using Microsoft.Extensions.Logging;
using ReallifeGamemode.Server.Log;
/**
* @overview Life of German Reallife - Managers InventoryManager (InventoryManager.cs)
* @author hydrant, VegaZ, balbo
* @copyright (c) 2008 - 2018 Life of German
*/
namespace ReallifeGamemode.Server.Managers
{
public class InventoryManager : Script
{
public const int MAX_USER_INVENTORY = 40000;
private static readonly ILogger logger = LogManager.GetLogger<InventoryManager>();
public static List<IItem> itemList;
private static Dictionary<int, (int[], int[])> TradeItems { get; set; } = new Dictionary<int, (int[], int[])>();
private static Dictionary<int, Timer> TradeTimer { get; set; } = new Dictionary<int, Timer>();
private static Dictionary<int, int> TradeValue { get; set; } = new Dictionary<int, int>();
public static Dictionary<Player, List<InventoryItem>> backpackItems { get; set; } = new Dictionary<Player, List<InventoryItem>>();
public static Dictionary<Player, List<InventoryItem>> vehicleItems { get; set; } = new Dictionary<Player, List<InventoryItem>>();
public static Dictionary<int, DateTime> itemCooldown = new Dictionary<int, DateTime>();
public class InventoryItem
{
public string Name;
public int Amount;
public int ItemId;
public int Weight;
public ushort vehicle;
}
public static void SetBackpackItems(Player player)
{
List<UserItem> itemList = GetUserItems(player);
if (itemList == null) return;
if (!backpackItems.ContainsKey(player))
backpackItems.Add(player, new List<InventoryItem>());
backpackItems[player] = new List<InventoryItem>();
foreach (var i in itemList)
{
var newItem = new InventoryItem()
{
Name = GetItemById(i.ItemId).Name,
Amount = i.Amount,
ItemId = i.ItemId,
Weight = GetUserInventoryWeight(player),
};
backpackItems[player].Add(newItem);
}
player.SetSharedData("backpackItems", JsonConvert.SerializeObject(backpackItems[player].ToArray()));
}
internal static T GetItem<T>() where T : IItem
{
return (T)itemList.Where(i => i.GetType() == typeof(T)).First();
}
[RemoteEvent("CLIENT:getVehicleInventory")]
public static void SetVehicleItems(Player player)
{
if (player.IsInVehicle)
{
player.TriggerEvent("Error", "Du kannst deinen Kofferraum gerade nicht öffnen.");
return;
}
Vehicle veh = NAPI.Pools.GetAllVehicles()
.ToList()
.Where(v => v.Position.DistanceTo(player.Position) <= 4)
.OrderBy(v => v.Position.DistanceTo(player.Position))
.FirstOrDefault();
if (veh == null)
{
player.TriggerEvent("Error", "Kein Fahrzeug in der Nähe!");
return;
}
using (var dbContext = new DatabaseContext())
{
ServerVehicle carlocked = veh.GetServerVehicle(dbContext);
if (carlocked == null || carlocked.Locked == true)
{
player.TriggerEvent("Error", "Das Fahrzeug ist abgeschlossen!");
return;
}
}
List<VehicleItem> itemList = GetVehicleItems(veh);
if (itemList == null)
{
player.TriggerEvent("Error", "Kofferraum ist leer !");
return;
}
if (!vehicleItems.ContainsKey(player))
vehicleItems.Add(player, new List<InventoryItem>());
//VehicleStreaming.SetDoorState(veh, DoorID.DoorTrunk, DoorState.DoorOpen);
vehicleItems[player] = new List<InventoryItem>();
foreach (var i in itemList)
{
var newItem = new InventoryItem
{
Name = GetItemById(i.ItemId).Name,
Amount = i.Amount,
ItemId = i.ItemId,
Weight = GetVehicleInventoryWeight(veh),
vehicle = veh.Handle.Value,
};
vehicleItems[player].Add(newItem);
}
player.SetSharedData("setVehicleTrunk", veh.GetVehicleTrunkSize());
player.SetSharedData("vehicleItems", JsonConvert.SerializeObject(vehicleItems[player].ToArray()));
}
public static bool CanPlayerHoldMoreWeight(Player player, int moreWeight)
{
return GetUserInventoryWeight(player) + moreWeight <= MAX_USER_INVENTORY;
}
public static void LoadItems()
{
itemList = new List<IItem>();
Type[] allTypes = Assembly.GetExecutingAssembly().GetTypes();
foreach (Type item in allTypes)
{
if (item.GetInterfaces().Contains((typeof(IItem))) && !item.IsAbstract)
{
NAPI.Util.ConsoleOutput($"Loading Item {item.Name}");
if (Activator.CreateInstance(item) is IItem o)
{
if (GetItemById(o.Id) != null)
{
throw new InvalidOperationException($"Double ItemID found: {o.Id} | {o.Name}");
}
itemList.Add(o);
}
}
}
}
public static IItem GetItemById(int id)
{
return itemList.Find(i => i.Id == id);
}
public static IItem GetItemByName(string name)
{
return itemList.Find(i => i.Name.ToLower() == name.ToLower());
}
public static void RemoveUserItem(User user, UserItem item, int amount)
{
using (var dbContext = new DatabaseContext())
{
var userItem = dbContext.UserItems.FirstOrDefault(i => i.Id == item.Id);
userItem.Amount -= amount;
dbContext.SaveChanges();
if (userItem.Amount == 0)
{
dbContext.Remove(userItem);
}
dbContext.SaveChanges();
}
}
public static void RemoveVehicleItem(ServerVehicle sVeh, VehicleItem item, int amount, Player player)
{
if (item == null)
{
return;
}
using (var dbContext = new DatabaseContext())
{
var vehicleItem = dbContext.VehicleItems.FirstOrDefault(i => i.Id == item.Id);
vehicleItem.Amount -= amount;
dbContext.SaveChanges();
if (vehicleItem.Amount == 0)
{
dbContext.Remove(vehicleItem);
dbContext.SaveChanges();
}
Vehicle vehicle = sVeh.GetVehicle();
List<VehicleItem> itemList = GetVehicleItems(vehicle);
if (itemList == null) return;
dbContext.SaveChanges();
}
}
public static List<VehicleItem> GetVehicleItems(Vehicle vehicle)
{
return new DatabaseContext().VehicleItems.ToList().FindAll(i => i.GetVehicle().GetVehicle() == vehicle);
}
public static List<UserItem> GetUserItems(Player player, DatabaseContext dbContext = null)
{
if (dbContext == null)
{
using (dbContext = new DatabaseContext())
{
return GetUserItemsInternal(player, dbContext);
}
}
else
{
return GetUserItemsInternal(player, dbContext);
}
}
private static List<UserItem> GetUserItemsInternal(Player player, DatabaseContext dbContext)
{
var user = player.GetUser(dbContext);
return dbContext.UserItems.ToList().FindAll(i => i.UserId == user.Id);
}
public static int GetUserInventoryWeight(Player player)
{
var user = player.GetUser();
var inventoryWeight = 0;
using (var context = new DatabaseContext())
{
List<UserItem> userItems = context.UserItems.Where(i => i.UserId == user.Id).ToList();
foreach (var item in userItems)
{
IItem iItem = GetItemById(item.ItemId);
var currentItemWeight = iItem.Gewicht * item.Amount;
inventoryWeight += currentItemWeight;
}
}
return inventoryWeight;
}
public static int GetVehicleInventoryWeight(Vehicle veh)
{
var inventoryWeight = 0;
using (var context = new DatabaseContext())
{
ServerVehicle serverVehicle = VehicleManager.GetServerVehicleFromVehicle(veh, context);
List<VehicleItem> vehItems = context.VehicleItems.Where(i => i.VehicleId == serverVehicle.Id).ToList();
foreach (var item in vehItems)
{
IItem iItem = GetItemById(item.ItemId);
var currentItemWeight = iItem.Gewicht * item.Amount;
inventoryWeight += currentItemWeight;
}
}
return inventoryWeight;
}
public static UserItem UserHasThisItem(Player player, int itemId)
{
var user = player.GetUser();
using (var context = new DatabaseContext())
{
UserItem existingItem = context.UserItems.FirstOrDefault(i => i.UserId == user.Id && i.ItemId == itemId);
return existingItem;
}
}
public static void GetUserItemsAsAdmin(Player admin, User user)
{
var inventoryWeight = 0;
using (var context = new DatabaseContext())
{
List<UserItem> userItems = context.UserItems.ToList().FindAll(i => i.UserId == user.Id);
string[][] items = new string[userItems.Count][];
foreach (var item in userItems)
{
IItem iItem = GetItemById(item.ItemId);
var currentItemWeight = iItem.Gewicht * item.Amount;
inventoryWeight += currentItemWeight;
items[userItems.IndexOf(item)] = new string[6];
items[userItems.IndexOf(item)][0] = iItem.Name;
items[userItems.IndexOf(item)][1] = iItem.Description;
items[userItems.IndexOf(item)][2] = iItem.Gewicht.ToString();
items[userItems.IndexOf(item)][3] = item.Amount.ToString();
items[userItems.IndexOf(item)][4] = item.Slot.ToString();
items[userItems.IndexOf(item)][5] = item.Id.ToString();
}
admin.TriggerEvent("showInventoryToAdmin", user.Name, inventoryWeight, items);
}
}
[RemoteEvent("transferToBackpack")]
public void TransferToBackpack(Player player, string jsonItemID, string jsonItemAmount)
{
var itemID = JsonConvert.DeserializeObject<int>(jsonItemID);
var itemAmount = JsonConvert.DeserializeObject<int>(jsonItemAmount);
using (var context = new DatabaseContext())
{
User user = player.GetUser(context);
if (!vehicleItems.ContainsKey(player))
vehicleItems.Add(player, new List<InventoryItem>());
Vehicle veh = null;
if (vehicleItems[player].Count != 0)
veh = new NetHandle(vehicleItems[player].FirstOrDefault().vehicle, EntityType.Vehicle).Entity<Vehicle>();
ServerVehicle serverVehicle = VehicleManager.GetServerVehicleFromVehicle(veh, context);
VehicleItem vehItem = context.VehicleItems.Where(v => v.VehicleId == serverVehicle.Id && v.ItemId == itemID).FirstOrDefault();
if (vehItem == null)
{
player.TriggerEvent("Error", "Transfer nicht möglich.");
return;
}
if (serverVehicle is FactionVehicle factionVehicle)
{
IItem item = GetItemById(itemID);
if (factionVehicle.Model == VehicleHash.Riot && user.Faction?.StateOwned == true)
{
player.TriggerEvent("Error", "Transfer nicht möglich.");
return;
}
}
RemoveVehicleItem(serverVehicle, vehItem, itemAmount, player);
SetVehicleItems(player);
AddItemToInventory(player, itemID, itemAmount);
SetBackpackItems(player);
context.SaveChanges();
IItem iItem = GetItemById(vehItem.ItemId);
}
}
[RemoteEvent("transferToVehicle")]
public void TransferToVehicle(Player player, string jsonItemID, string jsonItemAmount)
{
var user = player.GetUser();
var itemID = JsonConvert.DeserializeObject<int>(jsonItemID);
var itemAmount = JsonConvert.DeserializeObject<int>(jsonItemAmount);
using (var context = new DatabaseContext())
{
UserItem item = context.UserItems.Where(u => u.UserId == user.Id && u.ItemId == itemID && u.Amount >= itemAmount).FirstOrDefault();
if (item == null)
{
player.TriggerEvent("Error", "Transfer nicht möglich.");
return;
}
/*
if (!vehicleItems.ContainsKey(player))
{
player.TriggerEvent("Error", "Transfer nicht möglich.");
return;
}
if (!vehicleItems.ContainsKey(player))
vehicleItems.Add(player, new List<InventoryItem>());
Vehicle veh = null;
if (vehicleItems[player].Count != 0)
veh = vehicleItems[player].FirstOrDefault().vehicle;
*/
Vehicle veh = NAPI.Pools.GetAllVehicles().ToList().Where(v => v.Position.DistanceTo(player.Position) <= 2).FirstOrDefault();
if (veh == null)
{
player.TriggerEvent("Error", "Transfer nicht möglich.");
return;
}
RemoveUserItem(user, item, itemAmount);
AddItemToVehicleInventory(veh, itemID, itemAmount);
SetBackpackItems(player);
VehicleItem vehicleItem = context.VehicleItems.Where(f => f.ItemId == itemID && f.Vehicle == VehicleManager.GetServerVehicleFromVehicle(veh, context)).FirstOrDefault();
context.SaveChanges();
IItem iItem = GetItemById(itemID);
player.TriggerEvent("aproveTransfer", vehicleItem.Amount, iItem.Name, "Kofferraum");
}
}
public static void AddItemToInventory(Player player, int itemId, int amount)
{
var user = player.GetUser();
using (var context = new DatabaseContext())
{
int setAmount = 0;
for (int i = 1; i <= amount; i++)
{
if (GetUserInventoryWeight(player) + (i * GetItemById(itemId).Gewicht) > MAX_USER_INVENTORY)
{
break;
}
else
{
setAmount = i;
}
}
if (setAmount == 0)
{
player.TriggerEvent("Error", "Du kannst nicht so viel tragen.");
return;
}
UserItem existingItem = context.UserItems.FirstOrDefault(i => i.ItemId == itemId && i.UserId == user.Id);
if (existingItem != null)
{
existingItem.Amount += setAmount;
}
else
{
var newItem = new UserItem()
{
ItemId = itemId,
Amount = setAmount,
Slot = -1,
UserId = user.Id,
};
context.UserItems.Add(newItem);
}
context.SaveChanges();
IItem iItem = GetItemById(itemId);
player.TriggerEvent("aproveTransfer", setAmount, iItem.Name, "Rucksack");
}
}
public static void AddItemToVehicleInventory(Vehicle veh, int itemId, int amount)
{
using (var context = new DatabaseContext())
{
int setAmount = 0;
for (int i = 1; i <= amount; i++)
{
if (GetVehicleInventoryWeight(veh) + (i * GetItemById(itemId).Gewicht) > veh.GetVehicleTrunkSize())
{
break;
}
else
{
setAmount = i;
}
}
if (setAmount == 0)
{
return;
}
ServerVehicle sVeh = VehicleManager.GetServerVehicleFromVehicle(veh);
VehicleItem existingItem = context.VehicleItems.FirstOrDefault(i => i.ItemId == itemId && i.VehicleId == sVeh.Id);
if (existingItem != null)
{
existingItem.Amount += amount;
}
else
{
var newVehItem = new VehicleItem()
{
ItemId = itemId,
Amount = amount,
Slot = -1,
VehicleId = sVeh.Id,
};
context.VehicleItems.Add(newVehItem);
}
context.SaveChanges();
}
}
public static void RemoveAllItemsfromVehicleInventory(Vehicle veh)
{
using (var context = new DatabaseContext())
{
ServerVehicle sVeh = VehicleManager.GetServerVehicleFromVehicle(veh);
var allItemsByVehicle = context.VehicleItems.Where(i => i.VehicleId == sVeh.Id);
context.VehicleItems.RemoveRange(allItemsByVehicle);
context.SaveChanges();
}
}
[RemoteEvent("removeItemAsAdmin")]
public void RemoveAsAdminInventory(Player player, string amount, string userItemId, string targetPlayerName)
{
using (var context = new DatabaseContext())
{
UserItem fItem = context.UserItems.FirstOrDefault(j => j.Id == int.Parse(userItemId));
Player targetPlayer = PlayerService.GetPlayerByNameOrId(targetPlayerName);
if (amount == "stack")
{
var itemSlot = fItem.Slot;
targetPlayer.TriggerEvent("removeItem", userItemId, fItem.Amount);
context.UserItems.Remove(fItem);
}
else if (amount == "one")
{
var itemSlot = fItem.Slot;
targetPlayer.TriggerEvent("removeItem", userItemId, 1);
fItem.Amount--;
}
context.SaveChanges();
}
}
[RemoteEvent("itemInteract")]
public void ItemInteract(Player player, string jsonType, string jsonAmount, string jsonItemId)
{
int amount = JsonConvert.DeserializeObject<int>(jsonAmount);
int itemId = JsonConvert.DeserializeObject<int>(jsonItemId);
string type = JsonConvert.DeserializeObject<string>(jsonType);
using (var context = new DatabaseContext())
{
User user = player.GetUser(context);
UserItem fItem = context.UserItems.Where(u => u.UserId == user.Id && u.ItemId == itemId).FirstOrDefault();
IItem iItem = GetItemById(fItem.ItemId);
switch (type)
{
case "use":
if (iItem == null)
{
player.TriggerEvent("Error", "Dieses Item existiert nicht.");
return;
}
if (fItem == null)
{
player.TriggerEvent("Error", "Du hast dieses Item nicht");
return;
}
if (iItem is IUsableItem usableItemObj)
{
logger.LogInformation("Player {0} used the item {1} ({2})", player.Name, iItem.Name, iItem.Id);
if (usableItemObj.Use(player, user, context))
{
if (usableItemObj.RemoveWhenUsed)
{
RemoveUserItem(user, fItem, 1);
SetBackpackItems(player);
player.TriggerEvent("aproveUse", 1, iItem.Name);
}
}
}
else player.TriggerEvent("Error", "Du kannst dieses Item nicht benutzen.");
break;
case "drop":
if (iItem == null)
{
player.TriggerEvent("Error", "Dieses Item existiert nicht.");
return;
}
if (fItem == null)
{
player.TriggerEvent("Error", "Du hast dieses Item nicht");
return;
}
if (iItem is IDroppableItem usableItemObj2)
{
logger.LogInformation("Player {0} dropped the item {1} ({2})", player.Name, iItem.Name, iItem.Id);
Vector3 dropPosition = PlayerExtension.GetPositionFromPlayer(player, 0.6f, 0);
//new Vector3(player.Position.X, player.Position.Y, player.Position.Z - 0.8f);
Random r = new Random();
GTANetworkAPI.Object grndObject;
Vector3 textPos = dropPosition;
if (iItem is IWeaponDealItem obj)
{
player.ClearAttachments();
player.ClearAnimation();
dropPosition.Z -= 1.05f;
grndObject = NAPI.Object.CreateObject(3666746839, dropPosition, new Vector3(0, 0, r.Next(0, 360)), 255, 0);
}
else
{
dropPosition.Z -= 0.8f;
grndObject = NAPI.Object.CreateObject(3777723516, dropPosition, new Vector3(0, 0, r.Next(0, 360)), 255, 0);
}
GroundItem grndItem = new GroundItem { ItemId = iItem.Id, Amount = amount, Position = dropPosition };
TextLabel grndTxtLbl = NAPI.TextLabel.CreateTextLabel(iItem.Name + " ~s~(~y~" + amount + "~s~)", textPos, 5, 0.5f, 4, new Color(255, 255, 255), false, 0);
GroundItem.AddGroundItem(grndItem, grndObject, grndTxtLbl);
if (fItem.Amount > amount)
{
fItem.Amount -= amount;
}
else if (fItem.Amount == amount)
{
context.UserItems.Remove(fItem);
}
context.SaveChanges();
SetBackpackItems(player);
player.TriggerEvent("aproveThrow", amount, iItem.Name);
}
break;
}
context.SaveChanges();
}
}
[RemoteEvent("SERVER:BuyItems")]
public void SrvEvent_BuyItem(Player client, string itemName)
{
IItem shopItem = GetItemByName(itemName);
using (var dbContext = new DatabaseContext())
{
User user = client.GetUser(dbContext);
if (user.Handmoney < shopItem.Price)
{
client.TriggerEvent("itemMenu:Error");
return;
}
logger.LogInformation("Player {0} bought the item {1} for {2} dollars", client.Name, shopItem.Name, shopItem.Price);
if (GetUserInventoryWeight(client) + shopItem.Gewicht > MAX_USER_INVENTORY)
{
return;
}
UserItem item = dbContext.UserItems.Where(i => i.ItemId == shopItem.Id && i.UserId == user.Id).FirstOrDefault();
if (item == null)
{
var newItem = new UserItem
{
ItemId = shopItem.Id,
UserId = user.Id,
Amount = 1,
Slot = -1
};
dbContext.UserItems.Add(newItem);
}
else
{
item.Amount += 1;
}
user.Handmoney -= shopItem.Price;
dbContext.SaveChanges();
//client.TriggerEvent("SERVER:SET_HANDMONEY", user.Handmoney);
}
}
}
}