using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Terraria;
using Terraria.ID;
using TShockAPI.DB.Queries;
namespace TShockAPI.DB
{
///
/// This class is used as the data interface for Journey mode research.
/// This information is maintained such that SSC characters will be properly set up with
/// the world's current research.
///
public class ResearchDatastore
{
private IDbConnection database;
///
/// In-memory cache of what items have been sacrificed.
/// The first call to GetSacrificedItems will load this with data from the database.
///
private Dictionary _itemsSacrificed;
///
/// Initializes a new instance of the class.
///
/// A valid connection to the TShock database
public ResearchDatastore(IDbConnection db)
{
database = db;
var table = new SqlTable("Research",
new SqlColumn("WorldId", MySqlDbType.Int32),
new SqlColumn("PlayerId", MySqlDbType.Int32),
new SqlColumn("ItemId", MySqlDbType.Int32),
new SqlColumn("AmountSacrificed", MySqlDbType.Int32),
new SqlColumn("TimeSacrificed", MySqlDbType.DateTime)
);
SqlTableCreator creator = new(db, db.GetSqlQueryBuilder());
try
{
creator.EnsureTableStructure(table);
}
catch (DllNotFoundException)
{
TShock.Log.ConsoleWarn(GetString("Possible problem with your database - is Sqlite3.dll present?"));
throw new Exception(GetString("Could not find a database library (probably Sqlite3.dll)"));
}
}
///
/// This call will return the memory-cached list of items sacrificed.
/// If the cache is not initialized, it will be initialized from the database.
///
///
public Dictionary GetSacrificedItems()
{
if (_itemsSacrificed == null)
{
_itemsSacrificed = ReadFromDatabase();
}
return _itemsSacrificed;
}
///
/// This function will return a Dictionary<ItemId, AmountSacrificed> representing
/// what the progress of research on items is for this world.
///
/// A dictionary of ItemID keys and Amount Sacrificed values.
private Dictionary ReadFromDatabase()
{
Dictionary sacrificedItems = new Dictionary();
var sql = @"select itemId, sum(AmountSacrificed) totalSacrificed
from Research
where WorldId = @0
group by itemId";
try
{
using var reader = database.QueryReader(sql, Main.worldID);
while (reader.Read())
{
var itemId = reader.Get("itemId");
var amount = reader.Get("totalSacrificed");
sacrificedItems[itemId] = amount;
}
}
catch (Exception ex)
{
TShock.Log.Error(ex.ToString());
}
return sacrificedItems;
}
///
/// This method will sacrifice an amount of an item for research.
///
/// The net ItemId that is being researched.
/// The amount of items being sacrificed.
/// The player who sacrificed the item for research.
/// The cumulative total sacrifices for this item.
public int SacrificeItem(int itemId, int amount, TSPlayer player)
{
var itemsSacrificed = GetSacrificedItems();
if (!(itemsSacrificed.ContainsKey(itemId)))
itemsSacrificed[itemId] = 0;
var sql = @"insert into Research (WorldId, PlayerId, ItemId, AmountSacrificed, TimeSacrificed) values (@0, @1, @2, @3, @4)";
var result = 0;
try
{
result = database.Query(sql, Main.worldID, player.Account.ID, itemId, amount, DateTime.Now);
}
catch (Exception ex)
{
TShock.Log.Error(ex.ToString());
}
if (result == 1)
{
itemsSacrificed[itemId] += amount;
}
return itemsSacrificed[itemId];
}
}
}