Compare commits

..

No commits in common. "development" and "master" have entirely different histories.

50 changed files with 196 additions and 1120 deletions

View File

@ -28,12 +28,15 @@ public static class CommandAdd
case "item":
Item item=target.inventoryManager.AddItem(args[1], int.Parse(args[2]));
message = $"Item {args[1]} was added to {target.nickname}";
target.Send(new PacketScItemBagScopeModify(target, item));
break;
case "weapon":
Item wep = target.inventoryManager.AddWeapon(args[1], Convert.ToUInt64(args[2]));
message = $"Weapon {args[1]} was added to {target.nickname}";
target.Send(new PacketScItemBagScopeModify(target, wep));
break;
case "char":
@ -74,7 +77,7 @@ public static class CommandAdd
return;
}
target.inventoryManager.Save();
CommandManager.SendMessage(sender, $"{message}.");
}
catch (Exception err)

View File

@ -61,7 +61,7 @@ namespace Campofinale.Game.Character
}
int updatedItemCount = 0;
foreach (var item in target.inventoryManager.items.items)
foreach (var item in target.inventoryManager.items)
{
if (item.id.StartsWith("wpn_"))
{

View File

@ -19,6 +19,11 @@ namespace Campofinale.Commands.Handlers
return;
}
for (int i=0; i < args.Length; i++)
{
args[i] = Uri.UnescapeDataString(args[i]);
}
target.nickname = string.Join(" ", args);
target.Save();
target.Send(new PacketScSetName(target, target.nickname));

View File

@ -6,7 +6,6 @@ using System.Threading.Tasks;
using static Campofinale.Resource.ResourceManager;
using Campofinale.Packets.Sc;
using MongoDB.Bson;
using System.Globalization;
namespace Campofinale.Commands.Handlers
{
@ -24,25 +23,20 @@ namespace Campofinale.Commands.Handlers
for (int i=0; i < args.Length; i++)
{
args[i] = args[i].Replace(",", ".");
args[i] = Uri.UnescapeDataString(args[i]).Replace(".", ",");
}
float[] pos = [target.position.x, target.position.y, target.position.z];
float x, y, z;
for (int i=0; i < args.Length; i++) {
if(args[i] == "~") continue;
float curPos = pos[i];
pos[i] = float.Parse(args[i].StartsWith("--") ? args[i].Trim('-') : args[i], CultureInfo.InvariantCulture);
if (args[i].StartsWith('+')) pos[i] += curPos;
if (args[i].StartsWith("--")) pos[i] = curPos - pos[i];
}
x = args[0] == "~" ? target.position.x : float.Parse(args[0]);
y = args[1] == "~" ? target.position.y : float.Parse(args[1]);
z = args[2] == "~" ? target.position.z : float.Parse(args[2]);
Vector3f position = new Vector3f(new Vector()
{
X = pos[0],
Y = pos[1],
Z = pos[2]
X = x,
Y = y,
Z = z
});
target.position = position;

View File

@ -1,5 +1,4 @@
using Newtonsoft.Json;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@ -15,28 +14,21 @@ namespace Campofinale
public ServerOptions serverOptions = new();
public LogSettings logOptions = new();
}
public class ServerOptions
public struct ServerOptions
{
public int defaultSceneNumId = 98;
public int maxPlayers = 20;
public CharactersOptions defaultCharacters = new();
public ServerOptions()
{
}
public class CharactersOptions
{
public int defaultLevel = 1;
public bool giveAllCharacters = true;
public List<string> characters = new List<string>(); //used if giveAllCharacters is false
public CharactersOptions() { }
}
/* public struct WelcomeMail
{
}*/
}
public class LogSettings
public struct LogSettings
{
public bool packets;
public bool debugPrint=false;
@ -45,7 +37,7 @@ namespace Campofinale
{
}
}
public class GameserverSettings
public struct GameserverSettings
{
public string bindAddress = "127.0.0.1";
public int bindPort = 30000;
@ -55,9 +47,10 @@ namespace Campofinale
{
}
}
public class DispatchServerSettings
public struct DispatchServerSettings
{
public string bindAddress = "127.0.0.1";
public int bindPort = 5000;
public string accessAddress = "127.0.0.1";
public int accessPort = 5000;
@ -67,7 +60,7 @@ namespace Campofinale
}
}
public class MongoDatabaseSettings
public struct MongoDatabaseSettings
{
public string uri = "mongodb://localhost:27017";
public string collection = "Campofinale";

View File

@ -154,7 +154,7 @@
try {
const url = new URL('%dispatchip%/pcSdk/console');
url.searchParams.append('command', btoa(unescape(encodeURIComponent(command))));
url.searchParams.append('command', command);
url.searchParams.append('token', token);
const response = await fetch(url.toString(), {

View File

@ -42,8 +42,6 @@ namespace Campofinale.Database
public List<Scene> scenes = new();
public Dictionary<int, List<int>> bitsets = new();
public PlayerSafeZoneInfo savedSafeZone = new();
public Gender gender = Gender.GenFemale;
public Dictionary<int, Item> bag = new();
}
public class Account
{
@ -143,9 +141,7 @@ namespace Campofinale.Database
noSpawnAnymore = player.noSpawnAnymore,
scenes=player.sceneManager.scenes,
bitsets=player.bitsetManager.bitsets,
savedSafeZone = player.savedSaveZone,
gender=player.gender,
bag=player.inventoryManager.items.bag
savedSafeZone = player.savedSaveZone
};
UpsertPlayerData(data);
}

View File

@ -9,7 +9,6 @@ using MongoDB.Bson.IO;
using MongoDB.Bson;
using System.Reflection;
using static Campofinale.Game.Factory.FactoryNode;
using Campofinale.Game.Inventory;
namespace Campofinale.Database
{
@ -69,8 +68,6 @@ namespace Campofinale.Database
{
BsonSerializer.RegisterSerializer(typeof(Dictionary<int, ulong>), new CustomDictionarySerializer<int, ulong>());
BsonSerializer.RegisterSerializer(typeof(Dictionary<int, List<int>>), new CustomDictionarySerializer<int, List<int>>());
BsonSerializer.RegisterSerializer(typeof(Dictionary<int, Item>), new CustomDictionarySerializer<int, Item>());
RegisterSubclasses<FComponent>();
Logger.Print("Connecting to MongoDB...");
try

View File

@ -149,11 +149,6 @@ namespace Campofinale.Game.Character
guid = GetOwner().random.Next();
this.weaponGuid = GetOwner().inventoryManager.AddWeapon(ResourceManager.charGrowthTable[id].defaultWeaponId, 1).guid;
this.curHp = CalcAttributes()[AttributeType.MaxHp].val;
if (level < 20) breakNode = "";
if (level >= 20 && level <= 40) breakNode = "charBreak20";
if (level > 40 && level <= 60) breakNode = "charBreak40";
if (level > 60 && level <= 70) breakNode = "charBreak60";
if (level > 70) breakNode = "charBreak70";
}
public int GetSkillMaxLevel()
{

View File

@ -16,7 +16,7 @@ namespace Campofinale.Game.Gacha
public Player player;
internal ulong upSeqId;
const double fiftyfifty = 0.50;
const double fiftyfifty = 0.45; // 50% (make it less than real 50, because the randomness make win fifty fifty every time
private static readonly Random random = new Random();
public GachaManager(Player player)
@ -176,6 +176,7 @@ namespace Campofinale.Game.Gacha
RewardIds =
{
$"reward_{transaction.rarity}starChar_weaponCoin",
},
});
@ -219,7 +220,11 @@ namespace Campofinale.Game.Gacha
}
else
{
int index = random.Next(0,items.Count);
int index = random.Next(0,items.Count); // Miglior randomizzazione
// index = (int)((1 - Math.Pow(random.NextDouble(), 2)) * (items.Count - 1));
// Se vuoi evitare di prendere spesso i primi 2-3 elementi:
// index = (int)Math.Pow(random.NextDouble(), 1.5) * items.Count;
if (index > items.Count-1)
{
index = items.Count-1;

View File

@ -1,277 +0,0 @@
using Campofinale.Database;
using Campofinale.Packets.Sc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Campofinale.Game.Inventory
{
public class InventoryList
{
public List<Item> items = new();
public Dictionary<int, Item> bag = new();
public int maxBagSize = 30;
public Player player;
public InventoryList(Player player)
{
this.player = player;
}
public enum FindType
{
Items,
FactoryDepots,
Bag
}
public void UpdateInventoryPacket()
{
}
public void UpdateBagInventoryPacket()
{
player.Send(new PacketScItemBagScopeSync(this.player,Resource.ItemValuableDepotType.Invalid));
}
private void AddToBagAvailableSlot(Item item)
{
for (int i = 0; i < maxBagSize; i++)
{
if (!bag.ContainsKey(i))
{
bag.Add(i, item);
return;
}
}
}
///
///<summary>Add a item directly to the bag if there is enough space or increment current stack value</summary>
///
public bool AddToBag(Item item)
{
Item existOne = Find(i=>i.id == item.id && i.amount < item.GetItemTable().maxStackCount,FindType.Bag);
if (existOne != null)
{
if(existOne.amount+item.amount > item.GetItemTable().maxStackCount)
{
int max = existOne.GetItemTable().maxStackCount;
int toAddInNewSlotAmount = existOne.amount + item.amount - max;
item.amount = toAddInNewSlotAmount;
if (SlotAvailableInBag())
{
existOne.amount = max;
AddToBagAvailableSlot(item);
UpdateBagInventoryPacket();
return true;
}
else
{
return false;
}
}
else
{
existOne.amount += item.amount;
UpdateBagInventoryPacket();
return true;
}
}
else
{
if(bag.Count < maxBagSize)
{
AddToBagAvailableSlot(item);
UpdateBagInventoryPacket();
return true;
}
else
{
return false;
}
}
}
public bool SlotAvailableInBag()
{
bool availableSlot = false;
for (int i = 0; i < maxBagSize; i++)
{
if (!bag.ContainsKey(i))
{
return true;
}
}
return availableSlot;
}
public Item FindInAll(Predicate<Item> match)
{
var item = items.Find(match);
if (item != null)
{
return item;
}
var itemB = bag.Values.ToList().Find(match);
if (itemB != null)
{
return itemB;
}
return null;
}
public Item Find(Predicate<Item> match,FindType findType = FindType.Items)
{
switch (findType)
{
case FindType.Items:
var item = items.Find(match);
if (item != null)
{
return item;
}
break;
case FindType.FactoryDepots:
//TODO
break;
case FindType.Bag:
var itemB = bag.Values.ToList().Find(match);
if (itemB != null)
{
return itemB;
}
break;
}
return null;
}
public List<Item> FindAll(Predicate<Item> match, FindType findType = FindType.Items)
{
switch (findType)
{
case FindType.Items:
return items.FindAll(match);
break;
case FindType.FactoryDepots:
//TODO
break;
case FindType.Bag:
var itemB = bag.Values.ToList().FindAll(match);
if (itemB != null)
{
return itemB;
}
break;
}
return null;
}
///<summary>
///Add an item to the inventory (or increment it's amount if it's not an instance type, else add a new one or add to bag if it's a Factory item
///</summary>
public Item Add(Item item)
{
if (item.StorageSpace() == Resource.ItemStorageSpace.BagAndFactoryDepot)
{
AddToBag(item);
return null;
}
if (item.InstanceType())
{
items.Add(item);
DatabaseManager.db.UpsertItem(item);
return item;
}
else
{
Item exist=Find(i=>i.id==item.id);
if (exist != null)
{
exist.amount += item.amount;
DatabaseManager.db.UpsertItem(exist);
return exist;
}
else
{
items.Add(item);
DatabaseManager.db.UpsertItem(item);
return item;
}
}
}
/// <summary>
/// Get the item amount from all depots
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public int GetItemAmount(string id)
{
int amt = 0;
Item item=Find(i=>i.id==id);
if (item != null)
{
amt += item.amount;
}
List<Item> bagItems = FindAll(i=>i.id==id,FindType.Bag);
foreach (Item bagItem in bagItems)
{
amt += bagItem.amount;
}
return amt;
}
public void Remove(Item item)
{
if (items.Remove(item))
{
this.player.Send(new PacketScItemBagScopeModify(this.player, item));
DatabaseManager.db.DeleteItem(item);
}
else if (RemoveFromBag(item))
{
UpdateBagInventoryPacket();
}
}
private bool RemoveFromBag(Item item)
{
for (int i = 0; i < maxBagSize; i++)
{
Item bagItem = null;
if (bag.ContainsKey(i))
{
bagItem = bag[i];
if (bagItem.guid == item.guid)
{
bag.Remove(i);
return true;
}
}
}
return false;
}
/// <summary>
/// Move item from bag grid to another position
/// </summary>
/// <param name="fromGrid"></param>
/// <param name="toGrid"></param>
public void MoveBagItem(int fromGrid, int toGrid)
{
Item item1 = bag[fromGrid];
Item item2 = null;
if (bag.ContainsKey(toGrid))
{
item2 = bag[toGrid];
}
bag[toGrid] = item1;
if (item2 != null)
{
bag[fromGrid] = item2;
}
else
{
bag.Remove(fromGrid);
}
UpdateBagInventoryPacket();
}
}
}

View File

@ -5,7 +5,6 @@ using Google.Protobuf.Collections;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
@ -16,7 +15,7 @@ namespace Campofinale.Game.Inventory
public class InventoryManager
{
public Player owner;
public InventoryList items;
public List<Item> items= new List<Item>();
public int item_diamond_amt
{
@ -37,12 +36,12 @@ namespace Campofinale.Game.Inventory
public Item GetItemById(string id)
{
return items.FindInAll(i => i.id == id);
return items.Find(i => i.id == id);
}
public InventoryManager(Player o) {
owner = o;
items=new(o);
}
public void AddRewards(string rewardTemplateId, Vector3f pos, int sourceType=1)
{
@ -111,72 +110,56 @@ namespace Campofinale.Game.Inventory
}
public void Save()
{
foreach (Item item in items.items)
foreach (Item item in items)
{
DatabaseManager.db.UpsertItem(item);
}
}
public void Load()
{
items.items = DatabaseManager.db.LoadInventoryItems(owner.roleId);
items = DatabaseManager.db.LoadInventoryItems(owner.roleId);
}
public Item AddItem(string id, int amt, bool notify=false)
public Item AddItem(string id, int amt)
{
Item it = new()
{
id = id,
};
if(!it.InstanceType())
{
Item item = new Item(owner.roleId, id, amt);
Item itemNew = items.Add(item);
if (notify && itemNew != null)
Item item = items.Find(i=>i.id == id);
if (item != null)
{
this.owner.Send(new PacketScItemBagScopeModify(this.owner, itemNew));
}
// Logger.Print(id + ": " + amt+" added to existing");
item.amount += amt;
return item;
}
else
{
// Logger.Print(id + ": " + amt + " added to new");
item = new Item(owner.roleId, id, amt);
items.Add(item);
return item;
}
}
else
{
//Logger.Print(id + ": " + amt + " added to new as instance");
Item item = new Item(owner.roleId, id, amt);
items.Add(item);
return item;
}
}
public void RemoveItem(Item item,int amt)
{
item.amount -= amt;
if(item.amount <= 0)
{
items.Remove(item);
DatabaseManager.db.DeleteItem(item);
}
else
{
this.owner.Send(new PacketScItemBagScopeModify(this.owner, item));
items.UpdateBagInventoryPacket();
}
}
public bool ConsumeItem(string id, int amt)
{
Item item=items.FindInAll(i=>i.id== id);
if (item != null)
{
if(item.amount >= amt)
{
item.amount -= amt;
if(item.amount < 1)
{
items.Remove(item);
}
else
{
this.owner.Send(new PacketScItemBagScopeModify(this.owner, item));
items.UpdateBagInventoryPacket();
}
return true;
}
else
{
int toConsume = amt - item.amount;
item.amount = 0;
items.Remove(item);
return ConsumeItem(id, toConsume);
}
}
else
{
return false;
}
}
public bool ConsumeItems(MapField<string, ulong> costItemId2Count)
{
@ -196,8 +179,16 @@ namespace Campofinale.Game.Inventory
bool found = true;
foreach (ItemInfo item in items)
{
int amount = this.items.GetItemAmount(item.ResId);
if(amount < item.ResCount)
Item i= GetItemById(item.ResId);
if (i != null)
{
if(i.amount < item.ResCount)
{
found = false;
break;
}
}
else
{
found = false;
break;
@ -205,7 +196,14 @@ namespace Campofinale.Game.Inventory
}
foreach (ItemInfo item in items)
{
ConsumeItem(item.ResId, item.ResCount);
Item i = GetItemById(item.ResId);
if (i != null)
{
if (i.amount >= item.ResCount)
{
RemoveItem(i,item.ResCount);
}
}
}
return found;
}
@ -213,37 +211,13 @@ namespace Campofinale.Game.Inventory
public Dictionary<uint, int> GetInventoryChapter(string chapterId)
{
Dictionary<uint, int> dir= new Dictionary<uint, int>();
/*List<Item> citems = items.FindAll(i=>!i.InstanceType());
List<Item> citems = items.FindAll(i=>!i.InstanceType());
foreach (Item item in citems)
{
dir.Add((uint)ResourceManager.strIdNumTable.item_id.dic[item.id], item.amount);
}*/
}
return dir;
}
public void DropItemsBag(CsItemBagAbandonInBag req)
{
if(req.TargetObjectId == 0)
{
foreach (var i in req.GridCut)
{
Item item = items.bag[i.Key];
item.amount -= i.Value;
if(item.amount <= 0)
{
items.bag.Remove(i.Key);
}
owner.sceneManager.CreateDrop(owner.position, new RewardTable.ItemBundle()
{
count=i.Value,
id=item.id,
});
}
}
items.UpdateBagInventoryPacket();
}
}
}

View File

@ -48,10 +48,6 @@ namespace Campofinale.Game.Inventory
this.level = level;
guid = GetOwner().random.Next();
}
public ItemStorageSpace StorageSpace()
{
return ResourceManager.itemTypeTable[GetItemTable().type].storageSpace;
}
public ulong GetDefaultLevel()
{
switch (ItemType)
@ -72,15 +68,10 @@ namespace Campofinale.Game.Inventory
}
public ItemValuableDepotType ItemType
{
get
{
get{
return ResourceManager.GetItemTable(id).valuableTabType;
}
}
public ItemTable GetItemTable()
{
return ResourceManager.GetItemTable(id);
}
public virtual ScdItemGrid ToProto()
{
try

View File

@ -379,16 +379,8 @@ namespace Campofinale.Game
if (!en.spawned)
{
en.spawned = true;
try
{
GetOwner().Send(new PacketScObjectEnterView(GetOwner(), new List<Entity>() { en }));
}
catch(Exception e)
{
}
}
}
else
{

View File

@ -46,7 +46,6 @@ namespace Campofinale.Game.Spaceship
IsWorking = isWorking,
PhysicalStrength = physicalStrength,
StationedRoomId = stationedRoomId,
Skills =
{
new ScdSpaceshipCharSkill()

View File

@ -10,7 +10,6 @@ using System.Threading.Tasks;
using MongoDB.Bson.Serialization.IdGenerators;
using static Campofinale.Resource.ResourceManager;
using Campofinale.Resource;
using Campofinale.Resource.Table;
namespace Campofinale.Game.Spaceship
{
@ -85,39 +84,6 @@ namespace Campofinale.Game.Spaceship
}
}
}
public void GiftToChar(CsSpaceshipPresentGiftToChar req)
{
SpaceshipChar chara = GetChar(req.CharId);
if (chara != null)
{
foreach (var item in req.Gifts)
{
GiftItemTable giftItem = ResourceManager.giftItemTable[item.Id];
chara.favorability += giftItem.favorablePoint * item.Count;
//TODO item consume
}
ScSpaceshipPresentGiftToChar confirm = new()
{
CurFav = chara.favorability,
CharId = chara.id,
RecvGiftCnt = req.Gifts.Count,
};
//TODO packet class
/*ScSpaceshipCharFavorabilityChange change = new()
{
ChangeInfos =
{
new SpaceshipCharFavorabilityChangeInfo()
{
CharId = chara.id,
CurFav=chara.favorability,
}
}
};*/
owner.Send(Protocol.ScMsgId.ScSpaceshipPresentGiftToChar, confirm);
}
}
}

View File

@ -65,17 +65,7 @@ namespace Campofinale.Http
await data(ctx);
}
[StaticRoute(HttpServerLite.HttpMethod.GET, "/serverStatus")]
public static async Task serverStatus(HttpContext ctx)
{
string resp = "{\"maxPlayers\":" + Server.config.serverOptions.maxPlayers + ", \"players\":" + Server.clients.Count + ", \"status\":\"Online\", \"gameVersion\": \"" + GameConstants.GAME_VERSION + "\", \"serverVersion\": \"" + Server.ServerVersion + "\"}";
ctx.Response.StatusCode = 200;
ctx.Response.ContentLength = resp.Length;
ctx.Response.ContentType = "application/json";
await ctx.Response.SendAsync(resp);
}
[StaticRoute(HttpServerLite.HttpMethod.POST, "/u8/pay/getAllProductList")]
public static async Task getAllProductList(HttpContext ctx)
{

View File

@ -30,8 +30,7 @@ namespace Campofinale.Http
[StaticRoute(HttpServerLite.HttpMethod.GET, "/pcSdk/console")]
public static async Task ConsoleResponce(HttpContext ctx)
{
string encodedCmd = Uri.UnescapeDataString(ctx.Request.Query.Elements["command"]);
string cmd = Encoding.UTF8.GetString(Convert.FromBase64String(encodedCmd));
string cmd = ctx.Request.Query.Elements["command"].Replace("+"," ");
string token = ctx.Request.Query.Elements["token"];
string message = "";
string[] split = cmd.Split(" ");

View File

@ -20,10 +20,6 @@ public static class Logger
var method = frame?.GetMethod();
return method?.DeclaringType?.Name ?? "Server";
}
/// <summary>
/// Print a text in the console
/// </summary>
/// <param name="text"></param>
public static void Print(string text)
{
string className = GetCallingClassName();
@ -31,10 +27,6 @@ public static class Logger
string prefix = "<" + "INFO".Pastel("03fcce") + $":{className.Pastel("999")}>";
Console.WriteLine($"{prefix} " + text);
}
/// <summary>
/// Print a text in the console as Error
/// </summary>
/// <param name="text"></param>
public static void PrintError(string text)
{
string className = GetCallingClassName();
@ -42,10 +34,6 @@ public static class Logger
string prefix = "<" + "ERROR".Pastel("eb4034") + $":{className.Pastel("999")}>";
Console.WriteLine($"{prefix} " + text.Pastel("917e7e"));
}
/// <summary>
/// Print a text in the console as a Warn
/// </summary>
/// <param name="text"></param>
public static void PrintWarn(string text)
{
string className = GetCallingClassName();
@ -66,10 +54,7 @@ public static class Logger
Logger.hideLogs = hideLogs;
logWriter = new StreamWriter("latest.log", false);
}
/// <summary>
/// Log a message
/// </summary>
/// <param name="message"></param>
public static void Log(string message)
{
if (!hideLogs)

View File

@ -61,11 +61,6 @@ namespace Campofinale.Network
byte networkValue = buf[index];
return networkValue;
}
/// <summary>
/// Parse the body using a specific IMessage proto class
/// </summary>
/// <typeparam name="TBody"></typeparam>
/// <returns></returns>
public TBody DecodeBody<TBody>() where TBody : IMessage<TBody>, new()
{
return new MessageParser<TBody>(() => new()).ParseFrom(finishedBody);
@ -81,10 +76,35 @@ namespace Campofinale.Network
Buffer.BlockCopy(source, 0, destination, offset, source.Length);
}
public static byte[] ToByteArray(IntPtr ptr, int length)
{
if (ptr == IntPtr.Zero)
{
throw new ArgumentException("Pointer cannot be null", nameof(ptr));
}
byte[] byteArray = new byte[length];
Marshal.Copy(ptr, byteArray, 0, length);
return byteArray;
}
public static IntPtr ByteArrayToIntPtr(byte[] data)
{
if (data == null) throw new ArgumentNullException(nameof(data));
// Allocate unmanaged memory
IntPtr ptr = Marshal.AllocHGlobal(data.Length);
// Copy the byte array to the unmanaged memory
Marshal.Copy(data, 0, ptr, data.Length);
return ptr;
}
public static byte[] EncryptWithPublicKey(byte[] data, string publicKey)
{
// Crea un oggetto RSA
using (RSA rsa = RSA.Create())
{
publicKey = publicKey.Replace("-----BEGIN PUBLIC KEY-----", "");
publicKey = publicKey.Replace("\r", "");
publicKey = publicKey.Replace("\n", "");
@ -92,44 +112,24 @@ namespace Campofinale.Network
publicKey = publicKey.Trim();
Logger.Print(publicKey);
byte[] publicKey_ = Convert.FromBase64String(publicKey);
// Importa la chiave pubblica
rsa.ImportSubjectPublicKeyInfo(publicKey_, out _);
// Crittografa i dati
return rsa.Encrypt(data, RSAEncryptionPadding.OaepSHA256);
}
}
/// <summary>
/// Set the data of the packet with the Message Id and the body
/// </summary>
/// <param name="msgId"></param>
/// <param name="body">The proto message</param>
/// <returns>The current Packet</returns>
public Packet SetData(ScMsgId msgId, IMessage body)
{
set_body = body;
cmdId = (int)msgId;
return this;
}
/// <summary>
/// Encode the packet using the Packet class
/// </summary>
/// <param name="packet">The packet</param>
/// <param name="seq">the sequence id</param>
/// <param name="totalPackCount">the pack count</param>
/// <param name="currentPackIndex"></param>
/// <returns></returns>
public static byte[] EncodePacket(Packet packet,ulong seq = 0, uint totalPackCount = 1, uint currentPackIndex = 0)
{
return EncodePacket(packet.cmdId,packet.set_body,seq, totalPackCount, currentPackIndex);
}
public static ulong seqNext = 1;
/// <summary>
/// Encode the packet using the msgId and the body
/// </summary>
/// <param name="msgId"></param>
/// <param name="body"></param>
/// <param name="seqNext_"></param>
/// <param name="totalPackCount"></param>
/// <param name="currentPackIndex"></param>
/// <returns></returns>
public static byte[] EncodePacket(int msgId, IMessage body, ulong seqNext_ = 0, uint totalPackCount=1,uint currentPackIndex=0)
{
if (seqNext_ == 0)
@ -149,15 +149,6 @@ namespace Campofinale.Network
return data;
}
/// <summary>
/// Encode the packet with msgId and body as byte array
/// </summary>
/// <param name="msgId"></param>
/// <param name="body"></param>
/// <param name="seqNext_"></param>
/// <param name="totalPackCount"></param>
/// <param name="currentPackIndex"></param>
/// <returns></returns>
public static byte[] EncodePacket(int msgId, byte[] body, ulong seqNext_ = 0, uint totalPackCount = 1, uint currentPackIndex = 0)
{
if (seqNext_ == 0)
@ -181,12 +172,6 @@ namespace Campofinale.Network
return data;
}
/// <summary>
/// Read the byteArray as a valid packet
/// </summary>
/// <param name="client"></param>
/// <param name="byteArray"></param>
/// <returns>The decoded packet</returns>
public static Packet Read(Player client,byte[] byteArray)
{
byte headLength = GetByte(byteArray, 0);

View File

@ -26,7 +26,6 @@ namespace Campofinale.Packets.Cs
if (character != null)
{
character.potential=req.Level;
//TODO consume Item ID
ScCharPotentialUnlock unlock = new()

View File

@ -1,27 +0,0 @@
using Campofinale.Network;
using Campofinale.Packets.Sc;
using Campofinale.Protocol;
using Google.Protobuf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Campofinale.Packets.Cs
{
public class HandleCsItemBagAbandonInBag
{
[Server.Handler(CsMsgId.CsItemBagAbandonInBag)]
public static void Handle(Player session, CsMsgId cmdId, Packet packet)
{
CsItemBagAbandonInBag req = packet.DecodeBody<CsItemBagAbandonInBag>();
session.inventoryManager.DropItemsBag(req);
}
}
}

View File

@ -1,27 +0,0 @@
using Campofinale.Network;
using Campofinale.Packets.Sc;
using Campofinale.Protocol;
using Google.Protobuf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Campofinale.Packets.Cs
{
public class HandleCsItemBagMoveInBag
{
[Server.Handler(CsMsgId.CsItemBagMoveInBag)]
public static void Handle(Player session, CsMsgId cmdId, Packet packet)
{
CsItemBagMoveInBag req = packet.DecodeBody<CsItemBagMoveInBag>();
session.inventoryManager.items.MoveBagItem(req.FromGrid, req.ToGrid);
}
}
}

View File

@ -65,18 +65,9 @@ namespace Campofinale.Packets.Cs
session.Disconnect();
return;
}
bool exist=session.Load(account.id);
session.Load(account.id);
rsp.Uid = ""+session.accountId;
if (!exist)
{
rsp.IsFirstLogin = true;
//session.gender = Gender.GenInvalid;
//session.Send(ScMsgId.ScLogin, rsp);
//session.Send(new PacketScSyncBaseData(session));
//return;
}
session.Send(ScMsgId.ScLogin, rsp);
}
@ -241,7 +232,7 @@ namespace Campofinale.Packets.Cs
session.Send(new PacketScSpaceshipSync(session));
session.Send(new PacketScSyncFullDungeonStatus(session));
session.Send(new PacketScActivitySync(session));
session.Send(new PacketScSnsGetChatList(session));
session.Send(ScMsgId.ScSyncFullDataEnd, new ScSyncFullDataEnd());
session.EnterScene();
session.Initialized = true;

View File

@ -1,28 +0,0 @@
using Campofinale.Network;
using Campofinale.Packets.Sc;
using Campofinale.Protocol;
using Google.Protobuf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Campofinale.Packets.Cs
{
public class HandleCsSpaceshipPresentGiftToChar
{
[Server.Handler(CsMsgId.CsSpaceshipPresentGiftToChar)]
public static void Handle(Player session, CsMsgId cmdId, Packet packet)
{
CsSpaceshipPresentGiftToChar req = packet.DecodeBody<CsSpaceshipPresentGiftToChar>();
session.spaceshipManager.GiftToChar(req);
}
}
}

View File

@ -15,11 +15,6 @@ namespace Campofinale.Packets.Sc
public PacketScItemBagScopeModify(Player client, Item item) {
if (item == null)
{
SetData(ScMsgId.ScItemBagScopeModify, new ScItemBagScopeModify());
return;
}
ScItemBagScopeModify proto = new ScItemBagScopeModify()
{
Depot =

View File

@ -19,10 +19,10 @@ namespace Campofinale.Packets.Sc
{
Bag = new()
{
GridLimit = client.inventoryManager.items.maxBagSize,
GridLimit = 30,
Grids =
{
/*new ScdItemGrid()
new ScdItemGrid()
{
GridIndex=0,
Count=1,
@ -79,7 +79,7 @@ namespace Campofinale.Packets.Sc
InstId=300000000004,
},
}*/
}
}
},
FactoryDepot =
@ -114,18 +114,7 @@ namespace Campofinale.Packets.Sc
proto.Bag = null;
}
proto.Depot.Add(i, new ScdItemDepot());
if(proto.Bag!=null)
foreach (var item in client.inventoryManager.items.bag)
{
proto.Bag.Grids.Add(new ScdItemGrid()
{
Count=item.Value.amount,
GridIndex=item.Key,
Id=item.Value.id,
Inst=item.Value.ToProto().Inst,
});
}
List<Item> items = client.inventoryManager.items.items.FindAll(item => item.ItemType == (ItemValuableDepotType)i);
List<Item> items = client.inventoryManager.items.FindAll(item => item.ItemType == (ItemValuableDepotType)i);
items.ForEach(item =>
{
if (item.InstanceType())

View File

@ -1,33 +0,0 @@
using Campofinale.Network;
using Campofinale.Protocol;
using Campofinale.Resource;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace Campofinale.Packets.Sc
{
public class PacketScSnsGetChatList : Packet
{
public PacketScSnsGetChatList(Player player) {
ScSnsGetChatList proto = new ScSnsGetChatList() {
};
foreach (var chat in ResourceManager.snsChatTable)
{
var chatInfo = new SnsChatInfo()
{
ChatId = chat.Value.chatId,
ChatType = chat.Value.chatType,
Timestamp = DateTime.UtcNow.ToUnixTimestampMilliseconds(),
};
proto.ChatList.Add(chatInfo);
}
SetData(ScMsgId.ScSnsGetChatList, proto);
}
}
}

View File

@ -20,7 +20,7 @@ namespace Campofinale.Packets.Sc
Level = client.level,
Exp=client.xp,
RoleName = client.nickname,
Gender = client.gender,
Gender = Gender.GenFemale,
ShortId="1",
};

View File

@ -89,7 +89,6 @@ namespace Campofinale
public string accountId = "";
public string nickname = "Endministrator";
public ulong roleId= 1;
public Gender gender=Gender.GenFemale;
public uint level = 20;
public uint xp = 0;
//
@ -140,7 +139,7 @@ namespace Campofinale
{
return chars.FindAll(c=> teams[teamIndex].members.Contains(c.guid));
}
public bool Load(string accountId)
public void Load(string accountId)
{
this.accountId = accountId;
PlayerData data = DatabaseManager.db.GetPlayerById(this.accountId);
@ -162,12 +161,9 @@ namespace Campofinale
maxDashEnergy = data.maxDashEnergy;
curStamina = data.curStamina;
nextRecoverTime=data.nextRecoverTime;
if (data.gender > 0) gender = data.gender;
LoadCharacters();
mails = DatabaseManager.db.LoadMails(roleId);
inventoryManager.Load();
if (data.bag != null) inventoryManager.items.bag = data.bag;
spaceshipManager.Load();
if (data.scenes != null)
{
@ -182,52 +178,30 @@ namespace Campofinale
}
sceneManager.Load();
factoryManager.Load();
return (data != null);
}
public void LoadCharacters()
{
chars = DatabaseManager.db.LoadCharacters(roleId);
}
/// <summary>
/// Get the character using the guid *Added in 1.0.7*
/// </summary>
/// <param name="guid"></param>
/// <returns></returns>
//Added in 1.0.7
public Character GetCharacter(ulong guid)
{
return chars.Find(c => c.guid == guid);
}
/// <summary>
/// Get the character using the template id
/// </summary>
/// <param name="templateId"></param>
/// <returns>Character</returns>
public Character GetCharacter(string templateId)
{
return chars.Find(c => c.id==templateId);
}
public void Initialize()
{
if (Server.config.serverOptions.defaultCharacters.giveAllCharacters)
{
foreach (var item in ResourceManager.characterTable)
{
chars.Add(new Character(roleId, item.Key, Server.config.serverOptions.defaultCharacters.defaultLevel));
chars.Add(new Character(roleId,item.Key,20));
}
}
else
{
foreach (var item in Server.config.serverOptions.defaultCharacters.characters)
{
chars.Add(new Character(roleId, item, Server.config.serverOptions.defaultCharacters.defaultLevel));
}
}
foreach(var item in itemTable)
{
if(item.Value.GetStorage()!= ItemStorageSpace.BagAndFactoryDepot)
{
if (item.Value.maxStackCount == -1)
if(item.Value.maxStackCount == -1)
{
inventoryManager.items.Add(new Item(roleId, item.Value.id, 10000000));
}
@ -235,8 +209,6 @@ namespace Campofinale
{
inventoryManager.items.Add(new Item(roleId, item.Value.id, item.Value.maxStackCount));
}
}
}
teams.Add(new Team()

View File

@ -1,100 +0,0 @@
using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Campofinale.Resource
{
public class ResourceLoader
{
/// <summary>
/// Load table cfg automatically inside ResourceManager fields
/// </summary>
public static void LoadTableCfg()
{
var tableCfgTypes = GetAllTableCfgTypes();
foreach (var type in tableCfgTypes)
{
var attr = type.GetCustomAttribute<TableCfgTypeAttribute>();
string json = ResourceManager.ReadJsonFile(attr.Name);
FieldInfo field = GetResourceField(type);
if (field != null && json.Length > 0)
{
object deserializedData = DeserializeJson(json, field.FieldType, type);
field.SetValue(null, deserializedData);
//Logger.Print($"Loaded {attr.Name} into {field.Name}");
}
}
}
private static object DeserializeJson(string json, Type fieldType, Type valueType)
{
if (fieldType.IsGenericType)
{
var genericTypeDef = fieldType.GetGenericTypeDefinition();
if (genericTypeDef == typeof(Dictionary<,>))
{
var keyType = fieldType.GetGenericArguments()[0];
var valType = fieldType.GetGenericArguments()[1];
return JsonConvert.DeserializeObject(json, typeof(Dictionary<,>).MakeGenericType(keyType, valType));
}
else if (genericTypeDef == typeof(List<>))
{
return JsonConvert.DeserializeObject(json, typeof(List<>).MakeGenericType(valueType));
}
}
return JsonConvert.DeserializeObject(json, valueType);
}
public static List<Type> GetAllTableCfgTypes()
{
return Assembly.GetExecutingAssembly()
.GetTypes()
.Where(t => t.IsClass && !t.IsAbstract && t.GetCustomAttribute<TableCfgTypeAttribute>() != null)
.ToList();
}
public static FieldInfo GetResourceField(Type type)
{
var resourceManagerType = typeof(ResourceManager);
var fields = resourceManagerType.GetFields(BindingFlags.Public | BindingFlags.Static);
foreach (var field in fields)
{
var fieldType = field.FieldType;
if (fieldType.IsGenericType)
{
var genericTypeDef = fieldType.GetGenericTypeDefinition();
if (genericTypeDef == typeof(Dictionary<,>))
{
var valueType = fieldType.GetGenericArguments()[1];
if (valueType == type)
{
return field;
}
}
else if (genericTypeDef == typeof(List<>) && fieldType.GetGenericArguments()[0] == type)
{
return field;
}
}
else
{
if (fieldType == type)
{
return field;
}
}
}
return null;
}
}
}

View File

@ -28,19 +28,19 @@ namespace Campofinale.Resource
public class ResourceManager
{
public static Dictionary<string, SceneAreaTable> sceneAreaTable = new();
public static StrIdNumTable strIdNumTable = new StrIdNumTable();//
public static Dictionary<string, CharacterTable> characterTable = new(); //
public static Dictionary<string, SystemJumpTable> systemJumpTable = new(); //
public static StrIdNumTable strIdNumTable = new StrIdNumTable();
public static Dictionary<string, CharacterTable> characterTable = new();
public static Dictionary<string, SystemJumpTable> systemJumpTable = new();
public static Dictionary<string, SettlementBasicDataTable> settlementBasicDataTable = new();
public static Dictionary<string, BlocMissionTable> blocMissionTable = new();
public static MissionAreaTable missionAreaTable = new(); //
public static MissionAreaTable missionAreaTable = new();
public static Dictionary<string, DialogTextTable> dialogTextTable = new();
public static Dictionary<string, GameSystemConfigTable> gameSystemConfigTable = new();
public static Dictionary<string, WikiGroupTable> wikiGroupTable = new();
public static Dictionary<string, object> blocUnlockTable = new();
public static Dictionary<string, GameMechanicTable> gameMechanicTable = new();
public static Dictionary<string, WeaponBasicTable> weaponBasicTable= new();
public static Dictionary<string, BlocDataTable> blocDataTable = new(); //
public static Dictionary<string, BlocDataTable> blocDataTable = new();
public static Dictionary<string, ItemTable> itemTable = new();
public static Dictionary<string, DomainDataTable> domainDataTable = new();
public static Dictionary<string, CollectionTable> collectionTable = new();
@ -59,18 +59,15 @@ namespace Campofinale.Resource
public static Dictionary<string, SpaceShipCharBehaviourTable> spaceShipCharBehaviourTable = new();
public static Dictionary<string, SpaceshipRoomInsTable> spaceshipRoomInsTable = new();
public static Dictionary<string, DungeonTable> dungeonTable = new();
public static Dictionary<string, LevelGradeTable> levelGradeTable = new(); //
public static Dictionary<string, LevelGradeTable> levelGradeTable = new();
public static Dictionary<string, RewardTable> rewardTable = new();
public static Dictionary<string, AdventureTaskTable> adventureTaskTable = new();
public static DialogIdTable dialogIdTable = new();//
public static StrIdNumTable dialogIdTable = new();
public static Dictionary<string, LevelShortIdTable> levelShortIdTable = new();
public static Dictionary<string, FactoryBuildingTable> factoryBuildingTable = new();
public static Dictionary<string, FacSTTNodeTable> facSTTNodeTable = new();
public static Dictionary<string, FacSTTLayerTable> facSTTLayerTable = new();
public static Dictionary<int, ItemTypeTable> itemTypeTable = new(); //
public static Dictionary<string, SNSChatTable> snsChatTable = new();//
public static Dictionary<string, GiftItemTable> giftItemTable = new();
public static InteractiveTable interactiveTable = new(); //
public static InteractiveTable interactiveTable = new();
public static List<LevelScene> levelDatas = new();
public static List<InteractiveData> interactiveData = new();
@ -80,11 +77,6 @@ namespace Campofinale.Resource
return levelDatas.Find(a => a.id == name).idNum;
}
public static bool missingResources = false;
/// <summary>
/// Utility method for read a json file
/// </summary>
/// <param name="path">The file path</param>
/// <returns>Return the file content if the file exist, else it return an empty string</returns>
public static string ReadJsonFile(string path)
{
try
@ -111,7 +103,7 @@ namespace Campofinale.Resource
dialogTextTable = JsonConvert.DeserializeObject<Dictionary<string, DialogTextTable>>(ReadJsonFile("TableCfg/DialogTextTable.json"));
gameSystemConfigTable = JsonConvert.DeserializeObject<Dictionary<string, GameSystemConfigTable>>(ReadJsonFile("TableCfg/GameSystemConfigTable.json"));
wikiGroupTable = JsonConvert.DeserializeObject<Dictionary<string, WikiGroupTable>>(ReadJsonFile("TableCfg/WikiGroupTable.json"));
dialogIdTable = JsonConvert.DeserializeObject<DialogIdTable>(ReadJsonFile("Json/GameplayConfig/DialogIdTable.json"));
dialogIdTable = JsonConvert.DeserializeObject<StrIdNumTable>(ReadJsonFile("Json/GameplayConfig/DialogIdTable.json"));
blocUnlockTable = JsonConvert.DeserializeObject<Dictionary<string, object>>(ReadJsonFile("TableCfg/BlocUnlockTable.json"));
gameMechanicTable= JsonConvert.DeserializeObject<Dictionary<string, GameMechanicTable>>(ReadJsonFile("TableCfg/GameMechanicTable.json"));
weaponBasicTable = JsonConvert.DeserializeObject<Dictionary<string, WeaponBasicTable>>(ReadJsonFile("TableCfg/WeaponBasicTable.json"));
@ -142,11 +134,9 @@ namespace Campofinale.Resource
factoryBuildingTable = JsonConvert.DeserializeObject<Dictionary<string, FactoryBuildingTable>>(ReadJsonFile("TableCfg/FactoryBuildingTable.json"));
facSTTNodeTable = JsonConvert.DeserializeObject<Dictionary<string, FacSTTNodeTable>>(ReadJsonFile("TableCfg/FacSTTNodeTable.json"));
facSTTLayerTable = JsonConvert.DeserializeObject<Dictionary<string, FacSTTLayerTable>>(ReadJsonFile("TableCfg/FacSTTLayerTable.json"));
itemTypeTable = JsonConvert.DeserializeObject<Dictionary<int, ItemTypeTable>>(ReadJsonFile("TableCfg/ItemTypeTable.json"));
interactiveTable = JsonConvert.DeserializeObject<InteractiveTable>(ReadJsonFile("Json/Interactive/InteractiveTable.json"));
LoadInteractiveData();
LoadLevelDatas();
ResourceLoader.LoadTableCfg();
if (missingResources)
{
@ -416,7 +406,15 @@ namespace Campofinale.Resource
{
public List<WikiGroup> list;
}
public class InteractiveTable
{
public Dictionary<string, InteractiveTemplate> interactiveDataDict = new();
public class InteractiveTemplate
{
public string templateId;
}
}
public class WikiGroup
{
public string groupId;
@ -785,6 +783,19 @@ namespace Campofinale.Resource
public string settlementId;
public string domainId;
}
public class StrIdNumTable
{
public StrIdDic skill_group_id;
public StrIdDic item_id;
public Dictionary<string, int> dialogStrToNum;
public StrIdDic chapter_map_id;
public StrIdDic char_voice_id;
public StrIdDic char_doc_id;
public StrIdDic area_id;
public StrIdDic map_mark_temp_id;
public StrIdDic wiki_id;
public StrIdDic client_game_var_string_id;
}
public class GachaCharPoolTable
{
public string id;
@ -812,7 +823,10 @@ namespace Campofinale.Resource
{
}
public class SystemJumpTable
{
public int bindSystem;
}
public class StrIdDic
{
public Dictionary<string, int> dic;
@ -829,7 +843,6 @@ namespace Campofinale.Resource
public string enemyId;
public string templateId;
}
public class ItemTable
{
public ItemValuableDepotType valuableTabType;
@ -837,12 +850,6 @@ namespace Campofinale.Resource
public int maxStackCount;
public bool backpackCanDiscard;
public string modelKey;
public int type;
public ItemStorageSpace GetStorage()
{
return ResourceManager.itemTypeTable[type].storageSpace;
}
}
public class WeaponBasicTable
{
@ -901,7 +908,15 @@ namespace Campofinale.Resource
public string id;
public int count;
}
public class CharacterTable
{
public List<Attributes> attributes;
public string charId;
public int weaponType;
public string engName;
public int rarity;
}
public class Attributes
{
public int breakStage;

View File

@ -6,8 +6,7 @@ using System.Threading.Tasks;
namespace Campofinale.Resource.Table
{
[TableCfgType("TableCfg/BlocDataTable.json", LoadPriority.LOW)]
public class BlocDataTable : TableCfgResource
public class BlocDataTable
{
public string blocId;
}

View File

@ -1,20 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Campofinale.Resource.ResourceManager;
namespace Campofinale.Resource.Table
{
[TableCfgType("TableCfg/CharacterTable.json", LoadPriority.LOW)]
public class CharacterTable : TableCfgResource
{
public List<Attributes> attributes;
public string charId;
public int weaponType;
public string engName;
public int rarity;
}
}

View File

@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Campofinale.Resource.ResourceManager;
namespace Campofinale.Resource.Table
{
[TableCfgType("Json/GameplayConfig/DialogIdTable.json", LoadPriority.LOW)]
public class DialogIdTable : StrIdNumTable
{
}
}

View File

@ -1,15 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Campofinale.Resource.Table
{
[TableCfgType("TableCfg/GiftItemTable.json", LoadPriority.LOW)]
public class GiftItemTable
{
public int favorablePoint;
public string id;
}
}

View File

@ -1,19 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Campofinale.Resource.Table
{
[TableCfgType("Json/Interactive/InteractiveTable.json", LoadPriority.LOW)]
public class InteractiveTable : TableCfgResource
{
public Dictionary<string, InteractiveTemplate> interactiveDataDict = new();
public class InteractiveTemplate
{
public string templateId;
}
}
}

View File

@ -1,15 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Campofinale.Resource.Table
{
[TableCfgType("TableCfg/ItemTypeTable.json", LoadPriority.LOW)]
public class ItemTypeTable
{
public int itemType;
public ItemStorageSpace storageSpace;
}
}

View File

@ -6,8 +6,7 @@ using System.Threading.Tasks;
namespace Campofinale.Resource.Table
{
[TableCfgType("TableCfg/LevelGradeTable.json", LoadPriority.LOW)]
public class LevelGradeTable : TableCfgResource
public class LevelGradeTable
{
public string name;
public List<LevelGradeInfo> grades;

View File

@ -6,8 +6,7 @@ using System.Threading.Tasks;
namespace Campofinale.Resource.Table
{
[TableCfgType("Json/GameplayConfig/MissionAreaTable.json", LoadPriority.LOW)]
public class MissionAreaTable : TableCfgResource
public class MissionAreaTable
{
public Dictionary<string, Dictionary<string, object>> m_areas;
}

View File

@ -1,16 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Campofinale.Resource.Table
{
[TableCfgType("TableCfg/SNSChatTable.json", LoadPriority.LOW)]
public class SNSChatTable
{
public string chatId;
public int chatType;
public int tagType;
}
}

View File

@ -1,24 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Campofinale.Resource.ResourceManager;
namespace Campofinale.Resource.Table
{
[TableCfgType("TableCfg/StrIdNumTable.json", LoadPriority.LOW)]
public class StrIdNumTable : TableCfgResource
{
public StrIdDic skill_group_id;
public StrIdDic item_id;
public Dictionary<string, int> dialogStrToNum;
public StrIdDic chapter_map_id;
public StrIdDic char_voice_id;
public StrIdDic char_doc_id;
public StrIdDic area_id;
public StrIdDic map_mark_temp_id;
public StrIdDic wiki_id;
public StrIdDic client_game_var_string_id;
}
}

View File

@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Campofinale.Resource.Table
{
[TableCfgType("TableCfg/SystemJumpTable.json", LoadPriority.LOW)]
public class SystemJumpTable
{
public int bindSystem;
}
}

View File

@ -1,44 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Campofinale.Resource
{
public abstract class TableCfgResource
{
/// <summary>
/// Not implemented yet
/// </summary>
public void OnLoad()
{
}
}
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public class TableCfgTypeAttribute : Attribute
{
/// <summary>
/// Path of the Resource
/// </summary>
public string Name { get; }
/// <summary>
/// Priority of load (still not implemented)
/// </summary>
public LoadPriority Priority { get; }
public TableCfgTypeAttribute(string name, LoadPriority priority)
{
Name = name;
Priority = priority;
}
}
public enum LoadPriority
{
HIGH,
MEDIUM,
LOW
}
}

View File

@ -1,9 +1,9 @@
# Campofinale
[EN](README.md) | [IT](docs/README_it-IT.md) | [RU](docs/README_ru-RU.md) | [CN](docs/README_zh-CN.md) | [NL](docs/README_nl-NL.md)
Campofinale is a experimental server implementation for a certain factory building game.
![Logo]()
> **NOTICE: Our old Discord server was raided (all members were removed), please rejoin our community using this new invite link: https://discord.gg/YZGYtAxeZk**
Campofinale is a experimental server implementation for a certain factory building game.
## Current Features
@ -23,13 +23,10 @@ The list of all characters is [here](docs/CharactersTable.md).<br>
The list of all items is [here](docs/ItemsTable.md).<br>
If you want to open the in-game console, go to `Settings -> Platform & Account -> Account Settings (Access Account button)`. To view available commands, type `help`.
## Tutorial
New tutorial will be added in the next days on the wiki, in the meanwhile you can ask help in the Discord server
## Discord for support
If you want to discuss, ask for support or help with this project, join our [Discord Server](https://discord.gg/YZGYtAxeZk)!
If you want to discuss, ask for support or help with this project, join our [Discord Server](https://discord.gg/gPvqhfdMU6)!
## Note

View File

@ -24,5 +24,5 @@
| idlist | 显示所有角色(chars)、敌人(enemies)和场景(scenes)的id | `<chars\|enemies\|scenes>` | 否 | idlist `<chars\|enemies\|scenes>` | idlist chars |
---
> [!WARNING]
> [!WARNING]警告
> `level` 指令: 如果你没有指定具体的`id`字段, 那么等级变化将会被应用在**所有**武器和干员身上

View File

@ -25,7 +25,7 @@
| eny_0059_erhound | Blighted Tuskbeast| 侵蚀牙兽 |
| eny_0060_lbmad | Blighted Klaw| 侵蚀爪牙 |
| eny_0061_palecore | Marble Agellomoirai| 白垩界卫一阶段 |
| eny_0062_paletent | Marble Appendage| 白垩附肢 |
| eny_0062_paletent | Marble Appendage| 白垩界卫一阶段触手 |
| eny_0063_agmelee2 | Ram α | 大角天使α |
| eny_0064_agrange2 | Sting α | 针刺天使α |
| eny_0065_lbmob2 | Elite Raider | 精锐劫掠者 |

View File

@ -1,32 +0,0 @@
# Campofinale
[EN](/README.md) | [IT](./README_it-IT.md) | [RU](./README_ru-RU.md) | [CN](./README_zh-CN.md) | [NL](./README_nl-NL.md)
Campofinale - экспериментальная реализация сервера для кое-какой игры по постройке фабрик.
> **Внимание: наш старый Discord сервер был подвергнут крашу (все участники были выгнаны), поэтому настоятельно просим вас присоединиться заново по этой ссылке: https://discord.gg/eGGXymVd4K**
## Текущие возможности
* Переключение персонажей;
* Переключение отрядов;
* Переключение сцен;
* Сохранение данных с помощью MongoDB;
* Система боёвки;
## Дополнительно
Описание всех команд сервера вы можете найти [здесь](./CommandList/commands_ru-RU.md).<br>
Список всех сцен находится [тут](./LevelsTable.md).<br>
Список всех врагов - [тут](./EnemiesTable.md).<br>
Список всех персонажей - [тут](./CharactersTable.md).<br>
Список всех предметов - [тут](./ItemsTable.md).<br>
Вы можете открыть внутриигровую консоль, перейдя во вкладку `Settings -> Platform & Account -> Account Settings (кнопка Access Account)`. Чтобы просмотреть доступные команды, пропишите `help`.
## Discord поддержка
Если вы хотите обсудить проект или помочь в его разработке, присоединяйтесь к нашему [Discord серверу](https://discord.gg/eGGXymVd4K)!
## Примечание
Этот проект разрабатывается независимо от чего-либо, все права на ассеты из оригинальной игры и вся интеллектуальная собственность принадлежит их правообладателям.

View File

@ -1,43 +0,0 @@
# Campofinale
[EN](../README.md) | [IT](./README_it-IT.md) | [RU](./README_ru-RU.md) | [CN](./README_zh-CN.md) | [NL](./README_nl-NL.md)
![Logo]()
Campofinale 是为某个工厂建造游戏提供的实验性本地服务器实现
> **我们的旧 Discord 服务器遭到了袭击(攻击者踢走了所有成员),请使用以下新邀请链接重新加入我们的社区:[https://discord.gg/eGGXymVd4K](https://discord.gg/eGGXymVd4K)**
## 当前功能
* 登录
* 切换角色
* 切换配队
* 场景切换
* 通过MongoDB保存存档
* 战斗系统
## 补充信息
您可以在[这里](./CommandList/commands_zh-CN.md)找到所有服务端指令的详细说明。
所有场景的列表[在此](./LevelsTable.md)。
所有敌人的列表[在此](./EnemiesTable.md)。
所有干员的列表[在此](./CharactersTable.md)。
所有物品的列表[在此](./ItemsTable_zh-CN.md)。
如果你想使用游戏内控制台,请前往 `设置 → 平台与账号 → 账号设置("点击前往"`。要查看可用命令,请输入 `help`
## 教程
新的教程将会在几天后添加到Wiki上目前您可以在Discord服务器上寻求帮助
## 在Discord上寻求帮助
如果你想讨论、寻求帮助或者协助我们完善和改进此项目,请加入我们的[Discord服务器](https://discord.gg/eGGXymVd4K)!
## 附录
本项目为独立开发,所有原始游戏资产和知识产权均归其各自所有者所有