Added recipe resolver

This commit is contained in:
Filip Maj 2021-02-23 15:39:46 -05:00
parent 6e1f13d17a
commit df49eefadb
6 changed files with 244 additions and 1 deletions

View File

@ -0,0 +1,51 @@
-- --------------------------------------------------------
-- Host: 127.0.0.1
-- Server version: 5.6.17 - MySQL Community Server (GPL)
-- Server OS: Win64
-- HeidiSQL Version: 10.1.0.5464
-- --------------------------------------------------------
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET NAMES utf8 */;
/*!50503 SET NAMES utf8mb4 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
-- Dumping database structure for ffxiv_server
CREATE DATABASE IF NOT EXISTS `ffxiv_server` /*!40100 DEFAULT CHARACTER SET latin1 */;
USE `ffxiv_server`;
-- Dumping structure for table ffxiv_server.gamedata_recipes
CREATE TABLE IF NOT EXISTS `gamedata_recipes` (
`id` int(4) NOT NULL AUTO_INCREMENT,
`craftedItem` int(11) NOT NULL,
`craftedQuantity` int(11) NOT NULL,
`job` char(4) NOT NULL COMMENT 'A=CRP,B=BSM,C=ARM,D=GSM,E=LTW,F=WVR,G=ALC,H=CUL',
`level` tinyint(1) NOT NULL,
`dated` tinyint(1) DEFAULT NULL,
`kind` varchar(2) NOT NULL COMMENT 'AA=Material,BB=Parts,CC=Finished',
`crystal0ID` int(11) NOT NULL DEFAULT '0',
`crystal0Quantity` int(11) NOT NULL DEFAULT '0',
`crystal1ID` int(11) NOT NULL DEFAULT '0',
`crystal1Quantity` int(11) NOT NULL DEFAULT '0',
`facilities` int(11) DEFAULT NULL,
`material0` int(11) NOT NULL DEFAULT '0',
`material1` int(11) NOT NULL DEFAULT '0',
`material2` int(11) NOT NULL DEFAULT '0',
`material3` int(11) NOT NULL DEFAULT '0',
`material4` int(11) NOT NULL DEFAULT '0',
`material5` int(11) NOT NULL DEFAULT '0',
`material6` int(11) NOT NULL DEFAULT '0',
`material7` int(11) NOT NULL DEFAULT '0',
`subSkill0Job` int(11) DEFAULT NULL,
`subSkill0Level` varchar(5) DEFAULT NULL,
`subSkill1Job` int(11) DEFAULT NULL,
`subSkill1Level` varchar(5) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC;
-- Data exporting was unselected.
/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
/*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;

View File

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Meteor.Map.DataObjects
{
class Recipe
{
public readonly uint resultItemID;
public readonly uint resultQuantity;
public readonly byte[] allowedCrafters;
public readonly byte tier;
public Recipe(uint resultItemID, uint resultQuantity, byte[] allowedCrafters, byte tier)
{
this.resultItemID = resultItemID;
this.resultQuantity = resultQuantity;
this.allowedCrafters = allowedCrafters;
this.tier = tier;
}
}
}

View File

@ -0,0 +1,69 @@
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
namespace Meteor.Map.DataObjects
{
class RecipeResolver
{
Dictionary<uint, Recipe> recipeList;
Dictionary<string, List<Recipe>> matsToRecipes;
private RecipeResolver(Dictionary<uint, Recipe> recipeList, Dictionary<string, List<Recipe>> matsToRecipes)
{
this.recipeList = recipeList;
this.matsToRecipes = matsToRecipes;
}
public static RecipeResolver Init()
{
var recipeList = new Dictionary<uint, Recipe>();
var matToRecipes = new Dictionary<string, List<Recipe>>();
Database.GetRecipeGamedata(recipeList, matToRecipes);
return new RecipeResolver(recipeList, matToRecipes);
}
public List<Recipe> GetRecipeFromMats(uint mat1 = 0, uint mat2 = 0, uint mat3 = 0, uint mat4 = 0, uint mat5 = 0, uint mat6 = 0, uint mat7 = 0, uint mat8 = 0)
{
uint[] mats = new uint[8];
mats[0] = mat1;
mats[1] = mat2;
mats[2] = mat3;
mats[3] = mat4;
mats[4] = mat5;
mats[5] = mat6;
mats[6] = mat7;
mats[7] = mat8;
Array.Sort(mats);
byte[] result = new byte[8 * sizeof(int)];
Buffer.BlockCopy(mats, 0, result, 0, result.Length);
string hash;
using (MD5 md5 = MD5.Create())
{
hash = BitConverter.ToString(md5.ComputeHash(result));
}
if (matsToRecipes.ContainsKey(hash))
return matsToRecipes[hash];
else
return null;
}
public Recipe GetMatsForRecipe(uint recipeID)
{
if (recipeList.ContainsKey(recipeID))
return recipeList[recipeID];
else
return null;
}
public int GetNumRecipes()
{
return recipeList.Count;
}
}
}

View File

@ -33,6 +33,8 @@ using Meteor.Map.packets.receive.supportdesk;
using Meteor.Map.actors.chara.npc;
using Meteor.Map.actors.chara.ai;
using Meteor.Map.packets.send.actor.battle;
using Meteor.Map.DataObjects;
using System.Security.Cryptography;
namespace Meteor.Map
{
@ -168,6 +170,99 @@ namespace Meteor.Map
}
}
public static bool GetRecipeGamedata(Dictionary<uint, Recipe> recipeList, Dictionary<string, List<Recipe>> matToRecipe)
{
using (var conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD)))
{
try
{
conn.Open();
string query = @"
SELECT
id,
craftedItem,
craftedQuantity,
crystal0ID,
crystal0Quantity,
crystal1ID,
crystal1Quantity,
material0,
material1,
material2,
material3,
material4,
material5,
material6,
material7
FROM gamedata_recipes
ORDER BY craftedItem ASC
";
MySqlCommand cmd = new MySqlCommand(query, conn);
using (MySqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
uint recipeID = reader.GetUInt32("id");
uint craftedItem = reader.GetUInt32("craftedItem");
uint craftedQuantity = reader.GetUInt32("craftedQuantity");
uint crystal0ID = reader.GetUInt32("crystal0ID");
uint crystal0Quantity = reader.GetUInt32("crystal0Quantity");
uint crystal1ID = reader.GetUInt32("crystal1ID");
uint crystal1Quantity = reader.GetUInt32("crystal1Quantity");
uint[] mats = new uint[8];
mats[0] = reader.GetUInt32("material0");
mats[1] = reader.GetUInt32("material1");
mats[2] = reader.GetUInt32("material2");
mats[3] = reader.GetUInt32("material3");
mats[4] = reader.GetUInt32("material4");
mats[5] = reader.GetUInt32("material5");
mats[6] = reader.GetUInt32("material6");
mats[7] = reader.GetUInt32("material7");
Array.Sort(mats);
Recipe recipe = new Recipe(craftedItem, craftedQuantity, new byte[] { }, 1);
//Hash for the Mat -> Recipe Dictionary
byte[] result = new byte[8 * sizeof(int)];
Buffer.BlockCopy(mats, 0, result, 0, result.Length);
string hash;
using (MD5 md5 = MD5.Create())
{
hash = BitConverter.ToString(md5.ComputeHash(result));
}
if (!matToRecipe.ContainsKey(hash))
matToRecipe.Add(hash, new List<Recipe>());
//Add to both Dictionaries
recipeList.Add(recipeID, new Recipe(craftedItem, craftedQuantity, new byte[] { }, 1));
matToRecipe[hash].Add(new Recipe(craftedItem, craftedQuantity, new byte[] { }, 1));
}
}
}
catch (MySqlException e)
{
Program.Log.Error(e.ToString());
return false;
}
finally
{
conn.Dispose();
}
return true;
}
}
public static void SavePlayerAppearance(Player player)
{
string query;
@ -2777,6 +2872,6 @@ namespace Meteor.Map
}
}
}
}
}

View File

@ -37,6 +37,7 @@ using Meteor.Map.actors.area;
using System.Threading;
using Meteor.Map.actors.chara.ai;
using Meteor.Map.actors.chara.ai.controllers;
using Meteor.Map.DataObjects;
namespace Meteor.Map.lua
{
@ -850,6 +851,7 @@ namespace Meteor.Map.lua
script.Globals["GetWorldMaster"] = (Func<Actor>)Server.GetWorldManager().GetActor;
script.Globals["GetItemGamedata"] = (Func<uint, ItemData>)Server.GetItemGamedata;
script.Globals["GetGuildleveGamedata"] = (Func<uint, GuildleveData>)Server.GetGuildleveGamedata;
script.Globals["GetRecipeResolver"] = (Func<RecipeResolver>)Server.ResolveRecipe;
script.Globals["GetLuaInstance"] = (Func<LuaEngine>)LuaEngine.GetInstance;
script.Options.DebugPrint = s => { Program.Log.Debug(s); };

View File

@ -168,6 +168,8 @@
<Compile Include="Actors\StaticActors.cs" />
<Compile Include="Actors\World\WorldMaster.cs" />
<Compile Include="DataObjects\GuildleveData.cs" />
<Compile Include="DataObjects\Recipe.cs" />
<Compile Include="DataObjects\RecipeResolver.cs" />
<Compile Include="DataObjects\TradeTransaction.cs" />
<Compile Include="DataObjects\ZoneConnection.cs" />
<Compile Include="CommandProcessor.cs" />