Merge pull request #1909 from Olink/fix-1907

Add initial support for Journey mode in SSC.
This commit is contained in:
Lucas Nicodemus 2020-05-25 00:16:57 -07:00 committed by GitHub
commit 5d35c4f2c5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 179 additions and 1 deletions

View file

@ -2,6 +2,9 @@
This is the rolling changelog for TShock for Terraria. Use past tense when adding new entries; sign your name off when you add or change something. This should primarily be things like user changes, not necessarily codebase changes unless it's really relevant or large. This is the rolling changelog for TShock for Terraria. Use past tense when adding new entries; sign your name off when you add or change something. This should primarily be things like user changes, not necessarily codebase changes unless it's really relevant or large.
## Upcoming Release
* Initial support for Journey mode in SSC worlds. (@Olink)
## TShock 4.4.0 (Pre-release 8) ## TShock 4.4.0 (Pre-release 8)
* Update for OTAPI 2.0.0.36 and Terraria 1.4.0.4. (@hakusaro, @Patrikkk, @DeathCradle) * Update for OTAPI 2.0.0.36 and Terraria 1.4.0.4. (@hakusaro, @Patrikkk, @DeathCradle)
* Fixed /wind command. (@AxeelAnder) * Fixed /wind command. (@AxeelAnder)

View file

@ -0,0 +1,138 @@
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;
namespace TShockAPI.DB
{
/// <summary>
/// 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.
/// </summary>
public class ResearchDatastore
{
private IDbConnection database;
/// <summary>
/// In-memory cache of what items have been sacrificed.
/// The first call to GetSacrificedItems will load this with data from the database.
/// </summary>
private Dictionary<int, int> _itemsSacrificed;
/// <summary>
/// Initializes a new instance of the <see cref="TShockAPI.DB.ResearchDatastore"/> class.
/// </summary>
/// <param name="db">A valid connection to the TShock database</param>
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)
);
var creator = new SqlTableCreator(db,
db.GetSqlType() == SqlType.Sqlite
? (IQueryBuilder)new SqliteQueryCreator()
: new MysqlQueryCreator());
try
{
creator.EnsureTableStructure(table);
}
catch (DllNotFoundException)
{
Console.WriteLine("Possible problem with your database - is Sqlite3.dll present?");
throw new Exception("Could not find a database library (probably Sqlite3.dll)");
}
}
/// <summary>
/// This call will return the memory-cached list of items sacrificed.
/// If the cache is not initialized, it will be initialized from the database.
/// </summary>
/// <returns></returns>
public Dictionary<int, int> GetSacrificedItems()
{
if (_itemsSacrificed == null)
{
_itemsSacrificed = ReadFromDatabase();
}
return _itemsSacrificed;
}
/// <summary>
/// This function will return a Dictionary&lt;ItemId, AmountSacrificed&gt; representing
/// what the progress of research on items is for this world.
/// </summary>
/// <returns>A dictionary of ItemID keys and Amount Sacrificed values.</returns>
private Dictionary<int, int> ReadFromDatabase()
{
Dictionary<int, int> sacrificedItems = new Dictionary<int, int>();
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<Int32>("itemId");
var amount = reader.Get<Int32>("totalSacrificed");
sacrificedItems[itemId] = amount;
}
}
}
catch (Exception ex)
{
TShock.Log.Error(ex.ToString());
}
return sacrificedItems;
}
/// <summary>
/// This method will sacrifice an amount of an item for research.
/// </summary>
/// <param name="itemId">The net ItemId that is being researched.</param>
/// <param name="amount">The amount of items being sacrificed.</param>
/// <param name="player">The player who sacrificed the item for research.</param>
/// <returns>The cumulative total sacrifices for this item.</returns>
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];
}
}
}

View file

@ -39,6 +39,8 @@ using TShockAPI.Localization;
using TShockAPI.Models; using TShockAPI.Models;
using TShockAPI.Models.PlayerUpdate; using TShockAPI.Models.PlayerUpdate;
using TShockAPI.Models.Projectiles; using TShockAPI.Models.Projectiles;
using Terraria.Net;
using Terraria.GameContent.NetModules;
namespace TShockAPI namespace TShockAPI
{ {
@ -3238,6 +3240,20 @@ namespace TShockAPI
return true; return true;
} }
} }
} else if (moduleId == (int)NetModulesTypes.CreativeUnlocksPlayerReport)
{
var unknownField = args.Data.ReadByte();
if (unknownField == 0) //this is required or something???
{
var itemId = args.Data.ReadUInt16();
var amount = args.Data.ReadUInt16();
var totalSacrificed = TShock.ResearchDatastore.SacrificeItem(itemId, amount, args.Player);
var response = NetCreativeUnlocksModule.SerializeItemSacrifice(itemId, totalSacrificed);
NetManager.Instance.Broadcast(response);
}
} }
// As of 1.4.x.x, this is now used for more things: // As of 1.4.x.x, this is now used for more things:

View file

@ -20,6 +20,9 @@ using Microsoft.Xna.Framework;
using Terraria; using Terraria;
using TShockAPI; using TShockAPI;
using Terraria.Localization; using Terraria.Localization;
using Terraria.GameContent.NetModules;
using Terraria.Net;
using Terraria.ID;
namespace TShockAPI namespace TShockAPI
{ {
@ -480,6 +483,20 @@ namespace TShockAPI
NetMessage.SendData(76, -1, -1, NetworkText.Empty, player.Index); NetMessage.SendData(76, -1, -1, NetworkText.Empty, player.Index);
NetMessage.SendData(39, player.Index, -1, NetworkText.Empty, 400); NetMessage.SendData(39, player.Index, -1, NetworkText.Empty, 400);
var sacrificedItems = TShock.ResearchDatastore.GetSacrificedItems();
for(int i = 0; i < ItemID.Count; i++)
{
var amount = 0;
if (sacrificedItems.ContainsKey(i))
{
amount = sacrificedItems[i];
}
var response = NetCreativeUnlocksModule.SerializeItemSacrifice(i, amount);
NetManager.Instance.SendToClient(response, player.TPlayer.whoAmI);
}
} }
} }
} }

View file

@ -100,6 +100,8 @@ namespace TShockAPI
public static RememberedPosManager RememberedPos; public static RememberedPosManager RememberedPos;
/// <summary>CharacterDB - Static reference to the SSC character manager.</summary> /// <summary>CharacterDB - Static reference to the SSC character manager.</summary>
public static CharacterManager CharacterDB; public static CharacterManager CharacterDB;
/// <summary>Contains the information about what research has been performed in Journey mode.</summary>
public static ResearchDatastore ResearchDatastore;
/// <summary>Config - Static reference to the config system, for accessing values set in users' config files.</summary> /// <summary>Config - Static reference to the config system, for accessing values set in users' config files.</summary>
public static ConfigFile Config { get; set; } public static ConfigFile Config { get; set; }
/// <summary>ServerSideCharacterConfig - Static reference to the server side character config, for accessing values set by users to modify SSC.</summary> /// <summary>ServerSideCharacterConfig - Static reference to the server side character config, for accessing values set by users to modify SSC.</summary>
@ -324,6 +326,7 @@ namespace TShockAPI
TileBans = new TileManager(DB); TileBans = new TileManager(DB);
RememberedPos = new RememberedPosManager(DB); RememberedPos = new RememberedPosManager(DB);
CharacterDB = new CharacterManager(DB); CharacterDB = new CharacterManager(DB);
ResearchDatastore = new ResearchDatastore(DB);
RestApi = new SecureRest(Netplay.ServerIP, Config.RestApiPort); RestApi = new SecureRest(Netplay.ServerIP, Config.RestApiPort);
RestManager = new RestManager(RestApi); RestManager = new RestManager(RestApi);
RestManager.RegisterRestfulCommands(); RestManager.RegisterRestfulCommands();

View file

@ -85,6 +85,7 @@
<Compile Include="CLI\FlagSet.cs" /> <Compile Include="CLI\FlagSet.cs" />
<Compile Include="DB\ProjectileManager.cs" /> <Compile Include="DB\ProjectileManager.cs" />
<Compile Include="DB\RegionManager.cs" /> <Compile Include="DB\RegionManager.cs" />
<Compile Include="DB\ResearchDatastore.cs" />
<Compile Include="DB\TileManager.cs" /> <Compile Include="DB\TileManager.cs" />
<Compile Include="Extensions\ExceptionExt.cs" /> <Compile Include="Extensions\ExceptionExt.cs" />
<Compile Include="Hooks\AccountHooks.cs" /> <Compile Include="Hooks\AccountHooks.cs" />
@ -220,4 +221,4 @@
<Target Name="AfterBuild"> <Target Name="AfterBuild">
</Target> </Target>
--> -->
</Project> </Project>