Split ACSE into Core & WinForms projects

This will help code maintainability, and allow for cross platform support if another UI system is created.

Code refactoring will come at some point in the future.
This commit is contained in:
Cuyler36 2018-10-31 19:01:03 -04:00
parent d7a384cdcd
commit b8f8f866fd
1929 changed files with 7703 additions and 1503 deletions

View file

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Costura.Fody" Version="3.1.6" />
<PackageReference Include="Fody" Version="3.2.16">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.CSharp" Version="4.5.0" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="System.Drawing.Common" Version="4.5.1" />
</ItemGroup>
</Project>

View file

@ -1,7 +1,11 @@
using System; using System;
using System.IO; using System.IO;
using ACSE.Core.Debug;
using ACSE.Core.Items;
using ACSE.Core.Saves;
using ACSE.Core.Utilities;
namespace ACSE namespace ACSE.Core.Acres
{ {
public class Acre public class Acre
{ {
@ -28,7 +32,9 @@ public class WorldAcre : Acre
{ {
public WorldItem[] AcreItems = new WorldItem[16 * 16]; public WorldItem[] AcreItems = new WorldItem[16 * 16];
public WorldAcre(ushort acreId, int position, ushort[] items = null, byte[] buriedItemData = null, SaveType saveType = SaveType.AnimalCrossing, uint[] nlItems = null, int townPosition = -1) : base(acreId, position) public WorldAcre(ushort acreId, int position, ushort[] items = null, byte[] buriedItemData = null,
SaveType saveType = SaveType.AnimalCrossing, uint[] nlItems = null, int townPosition = -1) : base(acreId,
position)
{ {
if (items != null) if (items != null)
{ {
@ -36,7 +42,7 @@ public WorldAcre(ushort acreId, int position, ushort[] items = null, byte[] buri
{ {
AcreItems[i] = new WorldItem(items[i], i); AcreItems[i] = new WorldItem(items[i], i);
if (buriedItemData != null) if (buriedItemData != null)
SetBuried(AcreItems[i], townPosition == -1 ? position : townPosition, buriedItemData, saveType); //Broken in original save editor lol.. needs a position - 1 to function properly SetBuried(AcreItems[i], townPosition == -1 ? position : townPosition, buriedItemData, saveType);
} }
} }
else if (nlItems != null) else if (nlItems != null)
@ -54,13 +60,15 @@ public WorldAcre(ushort acreId, int position) : base(acreId, position) { }
public WorldAcre(ushort acreId, int position, uint[] items = null, byte[] buriedItemData = null, SaveType saveType = SaveType.AnimalCrossing) public WorldAcre(ushort acreId, int position, uint[] items = null, byte[] buriedItemData = null, SaveType saveType = SaveType.AnimalCrossing)
: this(acreId, position, null, null, saveType, items) { } : this(acreId, position, null, null, saveType, items) { }
public WorldAcre(ushort acreId, int position, WorldItem[] items, byte[] buriedItemData = null, SaveType saveType = SaveType.AnimalCrossing, int townPosition = -1) : base(acreId, position) public WorldAcre(ushort acreId, int position, WorldItem[] items, byte[] buriedItemData = null,
SaveType saveType = SaveType.AnimalCrossing, int townPosition = -1) : base(acreId, position)
{ {
AcreItems = items; AcreItems = items;
if (buriedItemData == null || townPosition <= -1) return; if (buriedItemData == null || townPosition <= -1) return;
for (var i = 0; i < 256; i++) for (var i = 0; i < 256; i++)
SetBuried(AcreItems[i], townPosition, buriedItemData, saveType); SetBuried(AcreItems[i], townPosition, buriedItemData, saveType);
} }
//TODO: Change BuriedData from byte[] to ushort[] and use updated code //TODO: Change BuriedData from byte[] to ushort[] and use updated code
private static int GetBuriedDataLocation(WorldItem item, int acre, SaveType saveType) private static int GetBuriedDataLocation(WorldItem item, int acre, SaveType saveType)
{ {
@ -68,11 +76,12 @@ private static int GetBuriedDataLocation(WorldItem item, int acre, SaveType save
var worldPosition = 0; var worldPosition = 0;
switch (saveType) switch (saveType)
{ {
//15 - item.Location.X because it's stored as a ushort in memory w/ reversed endianess
case SaveType.AnimalCrossing: case SaveType.AnimalCrossing:
case SaveType.DoubutsuNoMoriEPlus: case SaveType.DoubutsuNoMoriEPlus:
case SaveType.AnimalForestEPlus: case SaveType.AnimalForestEPlus:
case SaveType.CityFolk: case SaveType.CityFolk:
worldPosition = (acre * 256) + (15 - item.Location.X) + item.Location.Y * 16; //15 - item.Location.X because it's stored as a ushort in memory w/ reversed endianess worldPosition = (acre * 256) + (15 - item.Location.X) + item.Location.Y * 16;
break; break;
case SaveType.WildWorld: case SaveType.WildWorld:
worldPosition = (acre * 256) + item.Index; worldPosition = (acre * 256) + item.Index;
@ -110,7 +119,7 @@ private static void SetBuried(WorldItem item, int acre, byte[] buriedItemData, S
/// <returns>bool ItemsWereLoaded</returns> /// <returns>bool ItemsWereLoaded</returns>
public bool LoadDefaultItems(Save saveFile) public bool LoadDefaultItems(Save saveFile)
{ {
var defaultAcreDataFolder = MainForm.AssemblyLocation + Path.DirectorySeparatorChar + "Resources" + Path.DirectorySeparatorChar + "Default Acre Items"; var defaultAcreDataFolder = Path.Combine(PathUtility.GetExeDirectory(), "Resources", "Default Acre Items");
switch (saveFile.SaveGeneration) switch (saveFile.SaveGeneration)
{ {
@ -140,7 +149,7 @@ public bool LoadDefaultItems(Save saveFile)
} }
catch catch
{ {
MainForm.DebugManager.WriteLine( DebugUtility.DebugManagerInstance.WriteLine(
$"Unable to open default acre data for Acre Id 0x{BaseAcreId:X4}", DebugLevel.Error); $"Unable to open default acre data for Acre Id 0x{BaseAcreId:X4}", DebugLevel.Error);
} }

View file

@ -1,6 +1,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using ACSE.Core.Players;
using ACSE.Core.Saves;
namespace ACSE namespace ACSE.Core.BitFields.Catalog
{ {
public static class Catalog public static class Catalog
{ {

View file

@ -1,6 +1,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using ACSE.Core.Players;
using ACSE.Core.Saves;
namespace ACSE namespace ACSE.Core.BitFields.Encyclopedia
{ {
public static class Encyclopedia public static class Encyclopedia
{ {
@ -280,8 +282,6 @@ private static Dictionary<int, byte> GetBitMap(SaveType saveType)
case SaveType.WelcomeAmiibo: case SaveType.WelcomeAmiibo:
return WelcomeAmiiboEncyclopediaBitMap; return WelcomeAmiiboEncyclopediaBitMap;
default: default:
System.Windows.Forms.MessageBox.Show("Encylopedia data for this game has not been implemented yet!", "Unimplemented Notification",
System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Information);
return null; return null;
} }
} }

View file

@ -1,4 +1,7 @@
namespace ACSE using ACSE.Core.Players;
using ACSE.Core.Saves;
namespace ACSE.Core.BitFields.Museum
{ {
public static class Museum public static class Museum
{ {

View file

@ -1,6 +1,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using ACSE.Core.Players;
using ACSE.Core.Saves;
namespace ACSE namespace ACSE.Core.BitFields.SongLibrary
{ {
public static class SongLibrary public static class SongLibrary
{ {
@ -110,8 +112,6 @@ private static Dictionary<int, byte> GetBitMap(SaveType saveType)
case SaveType.WelcomeAmiibo: case SaveType.WelcomeAmiibo:
return WelcomeAmiiboSongLibraryBitMap; return WelcomeAmiiboSongLibraryBitMap;
default: default:
System.Windows.Forms.MessageBox.Show("Songs for this game have not been implemented yet!", "Unimplemented Notification",
System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Information);
return null; return null;
} }
} }

View file

@ -1,7 +1,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using ACSE.Core.Saves;
namespace ACSE namespace ACSE.Core.Buildings
{ {
/// <summary> /// <summary>
/// Building class for editing buildings in City Folk & New Leaf. /// Building class for editing buildings in City Folk & New Leaf.
@ -496,7 +497,7 @@ public static Building[] GetBuildings(Save save, bool islandBuildings = false)
if (islandBuildings == false) if (islandBuildings == false)
for (var i = 0; i < 58; i++) for (var i = 0; i < 58; i++)
{ {
var dataOffset = save.SaveDataStartOffset + MainForm.CurrentSaveInfo.SaveOffsets.Buildings + var dataOffset = save.SaveDataStartOffset + Save.SaveInstance.SaveInfo.SaveOffsets.Buildings +
i * 4; i * 4;
buildings.Add(new Building(save.ReadByte(dataOffset), save.ReadByte(dataOffset + 2), buildings.Add(new Building(save.ReadByte(dataOffset), save.ReadByte(dataOffset + 2),
save.ReadByte(dataOffset + 3), save.SaveType)); save.ReadByte(dataOffset + 3), save.SaveType));
@ -506,7 +507,7 @@ public static Building[] GetBuildings(Save save, bool islandBuildings = false)
for (var i = 0; i < 2; i++) for (var i = 0; i < 2; i++)
{ {
var dataOffset = save.SaveDataStartOffset + var dataOffset = save.SaveDataStartOffset +
MainForm.CurrentSaveInfo.SaveOffsets.IslandBuildings + i * 4; Save.SaveInstance.SaveInfo.SaveOffsets.IslandBuildings + i * 4;
buildings.Add(new Building(save.ReadByte(dataOffset), save.ReadByte(dataOffset + 2), buildings.Add(new Building(save.ReadByte(dataOffset), save.ReadByte(dataOffset + 2),
save.ReadByte(dataOffset + 3), save.SaveType)); save.ReadByte(dataOffset + 3), save.SaveType));
} }

View file

@ -1,7 +1,8 @@
using System; using System;
using System.IO; using System.IO;
using ACSE.Core.Saves;
namespace ACSE namespace ACSE.Core.Debug
{ {
public enum DebugLevel public enum DebugLevel
{ {
@ -17,13 +18,18 @@ public class DebugManager
private FileStream _logFile; private FileStream _logFile;
private StreamWriter _logWriter; private StreamWriter _logWriter;
private const int MaxLogSize = 5000000; // 5MB Max Size private const int MaxLogSize = 5000000; // 5MB Max Size
public bool Enabled; public Save SaveFile;
public DebugManager() public bool Enabled;
public DebugLevel Level;
public DebugManager(Save saveFile, DebugLevel level = DebugLevel.Info)
{ {
SaveFile = saveFile;
Level = level;
CheckAndDeleteLogFile(); CheckAndDeleteLogFile();
if (Properties.Settings.Default.DebugLevel > 0) if (level > 0)
{ {
InitializeDebugLogWriter(); InitializeDebugLogWriter();
Enabled = true; Enabled = true;
@ -86,7 +92,7 @@ public static string GetLogFilePath() =>
public void WriteLine(string contents, DebugLevel level = DebugLevel.Info) public void WriteLine(string contents, DebugLevel level = DebugLevel.Info)
{ {
if (_logWriter == null || level > Properties.Settings.Default.DebugLevel) return; if (_logWriter == null || level > Level) return;
if (!CheckLogSizeOk()) if (!CheckLogSizeOk())
{ {
CloseDebugLogWriter(); CloseDebugLogWriter();
@ -95,7 +101,7 @@ public void WriteLine(string contents, DebugLevel level = DebugLevel.Info)
} }
_logWriter.WriteLine( _logWriter.WriteLine(
$"[{level}] - ({(MainForm.SaveFile != null ? MainForm.SaveFile.SaveType.ToString().Replace("_", " ") : "No Save")}) - {DateTime.Now} => {contents}"); $"[{level}] - ({(SaveFile != null ? SaveFile.SaveType.ToString().Replace("_", " ") : "No Save")}) - {DateTime.Now} => {contents}");
_logWriter.Flush(); _logWriter.Flush();
} }
} }

View file

@ -1,4 +1,7 @@
namespace ACSE using ACSE.Core.Players;
using ACSE.Core.Saves;
namespace ACSE.Core.Emotions
{ {
public static class Emotion public static class Emotion
{ {

View file

@ -1,9 +1,10 @@
using System; using System;
using ACSE.Core.Utilities;
namespace ACSE namespace ACSE.Core.Encryption
{ {
/* /*
* Animal Crossing: New Leaf (and Welcome Amiibo) Interger Encryption Documentation * Animal Crossing: New Leaf (and Welcome Amiibo) Integer Encryption Documentation
* *
* Animal Crossing: New Leaf uses a combination of methods to obfuscate their integer values in the save file. * Animal Crossing: New Leaf uses a combination of methods to obfuscate their integer values in the save file.
* The encryption consists of two integer values. The first integer is the encrypted integer. The second integer contains the checksum of the encryption and * The encryption consists of two integer values. The first integer is the encrypted integer. The second integer contains the checksum of the encryption and
@ -52,7 +53,7 @@ public NewLeafInt32(uint intA, uint intB)
if (intChecksum != computedChecksum) if (intChecksum != computedChecksum)
{ {
MainForm.DebugManager.WriteLine( DebugUtility.DebugManagerInstance.WriteLine(
$"Encrypted Int had an invalid Checksum! Checksum: 0x{intChecksum:X2} | Calculated Checksum: 0x{computedChecksum:X2}"); $"Encrypted Int had an invalid Checksum! Checksum: 0x{intChecksum:X2} | Calculated Checksum: 0x{computedChecksum:X2}");
Int1 = 0; Int1 = 0;
Int2 = 0; Int2 = 0;
@ -71,7 +72,7 @@ public NewLeafInt32(uint intA, uint intB)
} }
else else
{ {
MainForm.DebugManager.WriteLine("Invalid Shift Count was detected!", DebugLevel.Info); DebugUtility.DebugManagerInstance.WriteLine("Invalid Shift Count was detected!");
Value = (intA << rightShiftCount) - (adjustValue + 0x8F187432); Value = (intA << rightShiftCount) - (adjustValue + 0x8F187432);
Valid = true; // Is this right? Valid = true; // Is this right?
} }

View file

@ -1,6 +1,6 @@
namespace ACSE namespace ACSE.Core.Enums
{ {
// TODO: Move all enums to this file // TODO: Split all enums into their own files.
public enum AnimalCrossingGrassType : byte public enum AnimalCrossingGrassType : byte
{ {
Triangle = 0, Triangle = 0,

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Weavers>
<Costura />
</Weavers>

View file

@ -1,9 +1,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace ACSE.Generators namespace ACSE.Core.Generators
{ {
public class GCNGenerator : IGenerator public sealed class GCNGenerator : IGenerator
{ {
private int _randomSeed = Environment.TickCount; private int _randomSeed = Environment.TickCount;

View file

@ -1,4 +1,6 @@
namespace ACSE.Generators using ACSE.Core.Saves;
namespace ACSE.Core.Generators
{ {
public static class Generator public static class Generator
{ {

View file

@ -1,4 +1,4 @@
namespace ACSE.Generators namespace ACSE.Core.Generators
{ {
public interface IGenerator public interface IGenerator
{ {

View file

@ -1,7 +1,11 @@
using ACSE.Utilities; using System.Reflection;
using System.Reflection; using ACSE.Core.Encryption;
using ACSE.Core.Items;
using ACSE.Core.Players;
using ACSE.Core.Saves;
using ACSE.Core.Utilities;
namespace ACSE namespace ACSE.Core.Housing
{ {
public class House public class House
{ {
@ -17,20 +21,20 @@ public House(int index, int offset, int roomCount = -1, int roomStart = -1)
Index = index; Index = index;
Offset = offset; Offset = offset;
var houseSize = HouseInfo.GetHouseSize(offset, MainForm.SaveFile.SaveType); var houseSize = HouseInfo.GetHouseSize(offset, Save.SaveInstance.SaveType);
var basement = false; var basement = false;
//Console.WriteLine("House Index: " + Index); //Console.WriteLine("House Index: " + Index);
//Console.WriteLine("House Offset: 0x" + Offset.ToString("X")); //Console.WriteLine("House Offset: 0x" + Offset.ToString("X"));
//Console.WriteLine("House Size: " + HouseSize.ToString()); //Console.WriteLine("House Size: " + HouseSize.ToString());
if (MainForm.SaveFile.SaveGeneration == SaveGeneration.N64 || MainForm.SaveFile.SaveGeneration == SaveGeneration.GCN) if (Save.SaveInstance.SaveGeneration == SaveGeneration.N64 || Save.SaveInstance.SaveGeneration == SaveGeneration.GCN)
{ {
basement = HouseInfo.HasBasement(offset, MainForm.SaveFile.SaveType); basement = HouseInfo.HasBasement(offset, Save.SaveInstance.SaveType);
//Console.WriteLine("Basement: " + Basement.ToString()); //Console.WriteLine("Basement: " + Basement.ToString());
} }
// Load House Data // Load House Data
var offsets = HouseInfo.GetHouseOffsets(MainForm.SaveFile.SaveType); var offsets = HouseInfo.GetHouseOffsets(Save.SaveInstance.SaveType);
var saveData = MainForm.SaveFile; var saveData = Save.SaveInstance;
var playerDataType = typeof(HouseData); var playerDataType = typeof(HouseData);
var playerSaveInfoType = typeof(HouseOffsets); var playerSaveInfoType = typeof(HouseOffsets);
object boxedData = new HouseData(); object boxedData = new HouseData();
@ -156,7 +160,7 @@ public House(int index, int offset, int roomCount = -1, int roomStart = -1)
public virtual void Write() public virtual void Write()
{ {
var saveData = MainForm.SaveFile; var saveData = Save.SaveInstance;
var offsets = HouseInfo.GetHouseOffsets(saveData.SaveType); var offsets = HouseInfo.GetHouseOffsets(saveData.SaveType);
// Set House TownID & Name // Set House TownID & Name
@ -165,15 +169,15 @@ public virtual void Write()
if (offsets.OwningPlayerName != -1 && offsets.TownId != -1) if (offsets.OwningPlayerName != -1 && offsets.TownId != -1)
{ {
Data.TownId = Data.TownId =
saveData.ReadUInt16(saveData.SaveDataStartOffset + MainForm.CurrentSaveInfo.SaveOffsets.TownId, saveData.ReadUInt16(saveData.SaveDataStartOffset + Save.SaveInstance.SaveInfo.SaveOffsets.TownId,
saveData.IsBigEndian); // Might not be UInt16 in all games saveData.IsBigEndian); // Might not be UInt16 in all games
} }
if (offsets.OwningPlayerName != -1 && offsets.TownName != -1) if (offsets.OwningPlayerName != -1 && offsets.TownName != -1)
{ {
Data.TownName = saveData.ReadString( Data.TownName = saveData.ReadString(
saveData.SaveDataStartOffset + MainForm.CurrentSaveInfo.SaveOffsets.TownName, saveData.SaveDataStartOffset + Save.SaveInstance.SaveInfo.SaveOffsets.TownName,
MainForm.CurrentSaveInfo.SaveOffsets.TownNameSize); Save.SaveInstance.SaveInfo.SaveOffsets.TownNameSize);
} }
if (offsets.OwningPlayerName != -1) if (offsets.OwningPlayerName != -1)

View file

@ -1,8 +1,10 @@
using System; using System;
using System.Reflection; using ACSE.Core.Items;
using ACSE.Utilities; using ACSE.Core.Patterns;
using ACSE.Core.Players;
using ACSE.Core.Saves;
namespace ACSE namespace ACSE.Core.Housing
{ {
public struct HouseOffsets public struct HouseOffsets
{ {
@ -69,7 +71,7 @@ public class Layer
public void Write() public void Write()
{ {
if (Items == null || Index <= -1) return; if (Items == null || Index <= -1) return;
var saveFile = MainForm.SaveFile; var saveFile = Save.SaveInstance;
if (saveFile.SaveGeneration == SaveGeneration.N3DS) if (saveFile.SaveGeneration == SaveGeneration.N3DS)
{ {
for (var i = 0; i < Items.Length; i++) for (var i = 0; i < Items.Length; i++)
@ -105,7 +107,7 @@ public class Room
public void Write() public void Write()
{ {
var saveFile = MainForm.SaveFile; var saveFile = Save.SaveInstance;
foreach (var l in Layers) foreach (var l in Layers)
{ {
@ -473,13 +475,13 @@ public static int GetHouseSize(int offset, SaveType saveType)
switch (saveType) switch (saveType)
{ {
case SaveType.AnimalCrossing: // NOTE: N64 & GameCube titles don't include Basement in the size case SaveType.AnimalCrossing: // NOTE: N64 & GameCube titles don't include Basement in the size
return (MainForm.SaveFile.SaveData[offset + 0x2A] >> 5) & 7; return (Save.SaveInstance.SaveData[offset + 0x2A] >> 5) & 7;
case SaveType.DoubutsuNoMoriPlus: case SaveType.DoubutsuNoMoriPlus:
case SaveType.DoubutsuNoMoriEPlus: case SaveType.DoubutsuNoMoriEPlus:
case SaveType.AnimalForestEPlus: case SaveType.AnimalForestEPlus:
return (MainForm.SaveFile.SaveData[offset + 0x26] >> 5) & 7; return (Save.SaveInstance.SaveData[offset + 0x26] >> 5) & 7;
case SaveType.WildWorld: case SaveType.WildWorld:
return MainForm.SaveFile.ReadByte(MainForm.SaveFile.SaveDataStartOffset + 0xFAF8) & 7; // Not sure about this return Save.SaveInstance.ReadByte(Save.SaveInstance.SaveDataStartOffset + 0xFAF8) & 7; // Not sure about this
default: default:
return 0; return 0;
} }
@ -490,18 +492,18 @@ public static void SetHouseSize(int offset, SaveType saveType, int value)
switch (saveType) switch (saveType)
{ {
case SaveType.AnimalCrossing: // NOTE: N64 & GameCube titles don't include Basement in the size case SaveType.AnimalCrossing: // NOTE: N64 & GameCube titles don't include Basement in the size
MainForm.SaveFile.Write(offset + 0x2A, Save.SaveInstance.Write(offset + 0x2A,
(byte) (MainForm.SaveFile.ReadByte(offset + 0x2A) & ~(7 << 5) | ((value & 7) << 5))); (byte) (Save.SaveInstance.ReadByte(offset + 0x2A) & ~(7 << 5) | ((value & 7) << 5)));
break; break;
case SaveType.DoubutsuNoMoriPlus: case SaveType.DoubutsuNoMoriPlus:
case SaveType.DoubutsuNoMoriEPlus: case SaveType.DoubutsuNoMoriEPlus:
case SaveType.AnimalForestEPlus: case SaveType.AnimalForestEPlus:
MainForm.SaveFile.Write(offset + 0x26, Save.SaveInstance.Write(offset + 0x26,
(byte) (MainForm.SaveFile.ReadByte(offset + 0x26) & ~(7 << 5) | ((value & 7) << 5))); (byte) (Save.SaveInstance.ReadByte(offset + 0x26) & ~(7 << 5) | ((value & 7) << 5)));
break; break;
case SaveType.WildWorld: case SaveType.WildWorld:
offset = MainForm.SaveFile.SaveDataStartOffset + 0xFAF8; offset = Save.SaveInstance.SaveDataStartOffset + 0xFAF8;
MainForm.SaveFile.Write(offset, (byte) ((MainForm.SaveFile.ReadByte(offset) & ~7) | (value & 7))); // Not sure about this Save.SaveInstance.Write(offset, (byte) ((Save.SaveInstance.ReadByte(offset) & ~7) | (value & 7))); // Not sure about this
break; break;
} }
} }
@ -511,12 +513,12 @@ public static bool HasStatue(int offset, SaveType saveType)
switch (saveType) switch (saveType)
{ {
case SaveType.DoubutsuNoMoriPlus: case SaveType.DoubutsuNoMoriPlus:
return ((MainForm.SaveFile.ReadByte(offset + 0x26) >> 2) & 7) == 4; return ((Save.SaveInstance.ReadByte(offset + 0x26) >> 2) & 7) == 4;
case SaveType.AnimalCrossing: case SaveType.AnimalCrossing:
return ((MainForm.SaveFile.ReadByte(offset + 0x2A) >> 2) & 7) == 4; return ((Save.SaveInstance.ReadByte(offset + 0x2A) >> 2) & 7) == 4;
case SaveType.DoubutsuNoMoriEPlus: case SaveType.DoubutsuNoMoriEPlus:
case SaveType.AnimalForestEPlus: case SaveType.AnimalForestEPlus:
return ((MainForm.SaveFile.ReadByte(offset + 0x26) >> 2) & 7) == 5; return ((Save.SaveInstance.ReadByte(offset + 0x26) >> 2) & 7) == 5;
default: default:
return false; return false;
} }
@ -529,16 +531,16 @@ public static void SetStatueEnabled(int offset, SaveType saveType, bool enabled)
{ {
case SaveType.DoubutsuNoMoriPlus: case SaveType.DoubutsuNoMoriPlus:
writeValue = enabled ? (4 << 2) : (5 << 2); writeValue = enabled ? (4 << 2) : (5 << 2);
MainForm.SaveFile.Write(offset + 0x26, (byte)((MainForm.SaveFile.ReadByte(offset + 0x26) & ~(7 << 2) | writeValue))); Save.SaveInstance.Write(offset + 0x26, (byte)((Save.SaveInstance.ReadByte(offset + 0x26) & ~(7 << 2) | writeValue)));
break; break;
case SaveType.AnimalCrossing: case SaveType.AnimalCrossing:
writeValue = enabled ? (4 << 2) : (5 << 2); writeValue = enabled ? (4 << 2) : (5 << 2);
MainForm.SaveFile.Write(offset + 0x2A, (byte)((MainForm.SaveFile.ReadByte(offset + 0x2A) & ~(7 << 2) | writeValue))); Save.SaveInstance.Write(offset + 0x2A, (byte)((Save.SaveInstance.ReadByte(offset + 0x2A) & ~(7 << 2) | writeValue)));
break; break;
case SaveType.DoubutsuNoMoriEPlus: case SaveType.DoubutsuNoMoriEPlus:
case SaveType.AnimalForestEPlus: case SaveType.AnimalForestEPlus:
writeValue = enabled ? (5 << 2) : (6 << 2); writeValue = enabled ? (5 << 2) : (6 << 2);
MainForm.SaveFile.Write(offset + 0x26, (byte)((MainForm.SaveFile.ReadByte(offset + 0x26) & ~(7 << 2) | writeValue))); Save.SaveInstance.Write(offset + 0x26, (byte)((Save.SaveInstance.ReadByte(offset + 0x26) & ~(7 << 2) | writeValue)));
break; break;
} }
} }
@ -549,7 +551,7 @@ public static int GetHouseUpgradeSize(int offset, SaveType saveType)
{ {
case SaveType.DoubutsuNoMoriEPlus: case SaveType.DoubutsuNoMoriEPlus:
case SaveType.AnimalForestEPlus: case SaveType.AnimalForestEPlus:
return (MainForm.SaveFile.SaveData[offset + 0x26] >> 2) & 7; return (Save.SaveInstance.SaveData[offset + 0x26] >> 2) & 7;
default: default:
return 0; return 0;
} }
@ -557,7 +559,7 @@ public static int GetHouseUpgradeSize(int offset, SaveType saveType)
public static int GetRoomSize(int offset) // NL/WA only public static int GetRoomSize(int offset) // NL/WA only
{ {
return Math.Min(8, MainForm.SaveFile.ReadByte(offset - 0x44) * 2); return Math.Min(8, Save.SaveInstance.ReadByte(offset - 0x44) * 2);
} }
public static bool HasBasement(int offset, SaveType saveType) public static bool HasBasement(int offset, SaveType saveType)
@ -565,10 +567,10 @@ public static bool HasBasement(int offset, SaveType saveType)
switch (saveType) switch (saveType)
{ {
case SaveType.AnimalCrossing: case SaveType.AnimalCrossing:
return (MainForm.SaveFile.SaveData[offset + 0x24] & 0x10) == 0x10; return (Save.SaveInstance.SaveData[offset + 0x24] & 0x10) == 0x10;
case SaveType.DoubutsuNoMoriEPlus: case SaveType.DoubutsuNoMoriEPlus:
case SaveType.AnimalForestEPlus: case SaveType.AnimalForestEPlus:
return (MainForm.SaveFile.SaveData[offset + 0x20] & 0x10) == 0x10; return (Save.SaveInstance.SaveData[offset + 0x20] & 0x10) == 0x10;
default: default:
return false; return false;
} }
@ -576,7 +578,7 @@ public static bool HasBasement(int offset, SaveType saveType)
public static void SetHasBasement(bool enabled, House selectedHouse) public static void SetHasBasement(bool enabled, House selectedHouse)
{ {
var saveFile = MainForm.SaveFile; var saveFile = Save.SaveInstance;
if (saveFile.SaveGeneration != SaveGeneration.N64 && saveFile.SaveGeneration != SaveGeneration.GCN && if (saveFile.SaveGeneration != SaveGeneration.N64 && saveFile.SaveGeneration != SaveGeneration.GCN &&
saveFile.SaveGeneration != SaveGeneration.iQue) return; saveFile.SaveGeneration != SaveGeneration.iQue) return;
var basementFlagOffset = selectedHouse.Offset; var basementFlagOffset = selectedHouse.Offset;

View file

@ -0,0 +1,65 @@
using System.Linq;
using System.IO;
using System.Drawing;
using System.Drawing.Drawing2D;
using ACSE.Core.Debug;
using ACSE.Core.Utilities;
namespace ACSE.Core.Imaging
{
public static class ImageGeneration
{
public static Bitmap DrawGrid2(Image img, int cellSize, Size imageSize, Pen gridPen = null, bool resize = true,
bool drawVertical = true, bool skipFirstLine = false)
{
if (gridPen == null)
gridPen = Pens.Black;
var gridBitmap = resize ? new Bitmap(imageSize.Width, imageSize.Height) : new Bitmap(img);
using (var gridGraphics = Graphics.FromImage(gridBitmap))
{
gridGraphics.InterpolationMode = InterpolationMode.NearestNeighbor;
if (resize)
gridGraphics.DrawImage(img, new Rectangle(0, 0, imageSize.Width, imageSize.Height),
new RectangleF((float) -0.5, (float) -0.5, 32, 32), GraphicsUnit.Pixel);
if (drawVertical)
for (var x = 0; x < gridBitmap.Width; x += cellSize)
{
gridGraphics.DrawLine(gridPen, x, 0, x, gridBitmap.Height);
}
for (var y = skipFirstLine ? cellSize : 0; y < gridBitmap.Height; y += cellSize)
{
gridGraphics.DrawLine(gridPen, 0, y, gridBitmap.Width, y);
}
}
return gridBitmap;
}
public static Image GetTpcImage(byte[] tpcBytes)
{
if (tpcBytes.Length != 0x1400)
{
return null;
}
for (var i = tpcBytes.Length - 1; i > 0; i--)
{
if (i > 0 && tpcBytes[i - 1] == 0xFF && tpcBytes[i] == 0xD9)
{
using (var ms = new MemoryStream(tpcBytes.Take(i).ToArray()))
{
return Image.FromStream(ms);
}
}
}
DebugUtility.DebugManagerInstance.WriteLine("Unable to find JPEG End-of-File marker. No TPC?",
DebugLevel.Error);
return null;
}
}
}

View file

@ -1,7 +1,13 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using ACSE.Core.Housing;
using ACSE.Core.Items;
using ACSE.Core.Patterns;
using ACSE.Core.Players;
using ACSE.Core.Saves;
using ACSE.Core.Villagers;
namespace ACSE namespace ACSE.Core.Island
{ {
/// <summary> /// <summary>
/// Island class for Doubutsu no Mori e+ /// Island class for Doubutsu no Mori e+

View file

@ -2,8 +2,11 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using ACSE.Core.Players;
using ACSE.Core.Saves;
using ACSE.Core.Utilities;
namespace ACSE namespace ACSE.Core.Items
{ {
public class Inventory public class Inventory
{ {
@ -60,7 +63,8 @@ public static Image GetItemPic(int itemsize, int itemsPerRow, Item[] items, Save
var dataPosition = (y * itemsize + x2 % itemsize) * width * 4 + (x * itemsize + x2 / itemsize) * 4; var dataPosition = (y * itemsize + x2 % itemsize) * width * 4 + (x * itemsize + x2 / itemsize) * 4;
if (dataPosition >= bmpData.Length) if (dataPosition >= bmpData.Length)
{ {
System.Windows.Forms.MessageBox.Show("Item Bitmap generation received more items than allocated space. Skipping " + (items.Length - i) + " Item(s)."); DebugUtility.DebugManagerInstance.WriteLine(
$"Item Bitmap generation received more items than allocated space. Skipping {items.Length - i} item(s).");
break; break;
} }
Buffer.BlockCopy(BitConverter.GetBytes(itemColor), 0, bmpData, dataPosition, 4); Buffer.BlockCopy(BitConverter.GetBytes(itemColor), 0, bmpData, dataPosition, 4);

View file

@ -1,8 +1,8 @@
using System; using System;
using System.Drawing; using System.Drawing;
using System.Runtime.Remoting.Messaging; using ACSE.Core.Saves;
namespace ACSE namespace ACSE.Core.Items
{ {
public class Item : IEquatable<Item>, IEquatable<ushort> public class Item : IEquatable<Item>, IEquatable<ushort>
{ {
@ -16,7 +16,7 @@ public class Item : IEquatable<Item>, IEquatable<ushort>
public Item() public Item()
{ {
var saveType = MainForm.SaveFile == null ? SaveType.AnimalCrossing : MainForm.SaveFile.SaveType; var saveType = Save.SaveInstance == null ? SaveType.AnimalCrossing : Save.SaveInstance.SaveType;
switch (saveType) switch (saveType)
{ {
case SaveType.WildWorld: case SaveType.WildWorld:
@ -29,14 +29,14 @@ public Item()
break; break;
} }
Name = ItemData.GetItemName(ItemId); Name = ItemData.GetItemName(ItemId);
Type = ItemData.GetItemType(ItemId, MainForm.SaveFile?.SaveType ?? SaveType.AnimalCrossing); Type = ItemData.GetItemType(ItemId, Save.SaveInstance?.SaveType ?? SaveType.AnimalCrossing);
} }
public Item(ushort itemId) public Item(ushort itemId)
{ {
ItemId = itemId; ItemId = itemId;
Name = ItemData.GetItemName(ItemId); Name = ItemData.GetItemName(ItemId);
Type = ItemData.GetItemType(ItemId, MainForm.SaveFile?.SaveType ?? SaveType.AnimalCrossing); Type = ItemData.GetItemType(ItemId, Save.SaveInstance?.SaveType ?? SaveType.AnimalCrossing);
} }
public Item(uint itemId) public Item(uint itemId)
@ -45,7 +45,7 @@ public Item(uint itemId)
Flag1 = (byte)(itemId >> 24); Flag1 = (byte)(itemId >> 24);
Flag2 = (byte)(itemId >> 16); Flag2 = (byte)(itemId >> 16);
Name = ItemData.GetItemName(ItemId); Name = ItemData.GetItemName(ItemId);
Type = ItemData.GetItemType(ItemId, MainForm.SaveFile?.SaveType ?? SaveType.AnimalCrossing); Type = ItemData.GetItemType(ItemId, Save.SaveInstance?.SaveType ?? SaveType.AnimalCrossing);
} }
public Item(Item cloningItem) public Item(Item cloningItem)
@ -63,7 +63,7 @@ public Item(ushort itemId, byte flag1, byte flag2)
Flag1 = flag1; Flag1 = flag1;
Flag2 = flag2; Flag2 = flag2;
Name = ItemData.GetItemName(ItemId); Name = ItemData.GetItemName(ItemId);
Type = ItemData.GetItemType(ItemId, MainForm.SaveFile?.SaveType ?? SaveType.AnimalCrossing); Type = ItemData.GetItemType(ItemId, Save.SaveInstance?.SaveType ?? SaveType.AnimalCrossing);
} }
public uint ToUInt32() public uint ToUInt32()
@ -199,7 +199,7 @@ public class Furniture : Item, IEquatable<Furniture>
public Furniture(ushort itemId) : base(itemId) public Furniture(ushort itemId) : base(itemId)
{ {
if (MainForm.SaveFile.SaveGeneration == SaveGeneration.N3DS) if (Save.SaveInstance.SaveGeneration == SaveGeneration.N3DS)
{ {
BaseItemId = itemId; BaseItemId = itemId;
Rotation = 0; Rotation = 0;
@ -207,8 +207,8 @@ public Furniture(ushort itemId) : base(itemId)
else else
{ {
BaseItemId = (ushort)(ItemId & 0xFFFC); BaseItemId = (ushort)(ItemId & 0xFFFC);
if (ItemData.GetItemType(itemId, MainForm.SaveFile.SaveType) == ItemType.Furniture || if (ItemData.GetItemType(itemId, Save.SaveInstance.SaveType) == ItemType.Furniture ||
ItemData.GetItemType(itemId, MainForm.SaveFile.SaveType) == ItemType.Gyroid) ItemData.GetItemType(itemId, Save.SaveInstance.SaveType) == ItemType.Gyroid)
{ {
Rotation = ItemId & 3; Rotation = ItemId & 3;
} }
@ -223,7 +223,7 @@ public Furniture(uint item) : base(item)
public Furniture(ushort item, byte flag1, byte flag2) : base(item, flag1, flag2) public Furniture(ushort item, byte flag1, byte flag2) : base(item, flag1, flag2)
{ {
if (MainForm.SaveFile.SaveGeneration == SaveGeneration.N3DS) if (Save.SaveInstance.SaveGeneration == SaveGeneration.N3DS)
{ {
BaseItemId = ItemId; BaseItemId = ItemId;
Rotation = (Flag1 >> 4) / 4; Rotation = (Flag1 >> 4) / 4;
@ -231,8 +231,8 @@ public Furniture(ushort item, byte flag1, byte flag2) : base(item, flag1, flag2)
else else
{ {
BaseItemId = (ushort)(ItemId & 0xFFFC); BaseItemId = (ushort)(ItemId & 0xFFFC);
if (ItemData.GetItemType(ItemId, MainForm.SaveFile.SaveType) == ItemType.Furniture || if (ItemData.GetItemType(ItemId, Save.SaveInstance.SaveType) == ItemType.Furniture ||
ItemData.GetItemType(ItemId, MainForm.SaveFile.SaveType) == ItemType.Gyroid) ItemData.GetItemType(ItemId, Save.SaveInstance.SaveType) == ItemType.Gyroid)
{ {
Rotation = ItemId & 3; Rotation = ItemId & 3;
} }
@ -241,7 +241,7 @@ public Furniture(ushort item, byte flag1, byte flag2) : base(item, flag1, flag2)
public Furniture(Item item) : base (item) public Furniture(Item item) : base (item)
{ {
if (MainForm.SaveFile.SaveGeneration == SaveGeneration.N3DS) if (Save.SaveInstance.SaveGeneration == SaveGeneration.N3DS)
{ {
BaseItemId = ItemId; BaseItemId = ItemId;
Rotation = (Flag1 >> 4) / 4; Rotation = (Flag1 >> 4) / 4;
@ -249,8 +249,8 @@ public Furniture(Item item) : base (item)
else else
{ {
BaseItemId = (ushort)(ItemId & 0xFFFC); BaseItemId = (ushort)(ItemId & 0xFFFC);
if (ItemData.GetItemType(ItemId, MainForm.SaveFile.SaveType) == ItemType.Furniture || if (ItemData.GetItemType(ItemId, Save.SaveInstance.SaveType) == ItemType.Furniture ||
ItemData.GetItemType(ItemId, MainForm.SaveFile.SaveType) == ItemType.Gyroid) ItemData.GetItemType(ItemId, Save.SaveInstance.SaveType) == ItemType.Gyroid)
{ {
Rotation = ItemId & 3; Rotation = ItemId & 3;
} }

View file

@ -1,4 +1,4 @@
namespace ACSE namespace ACSE.Core.Items
{ {
public class ItemChange public class ItemChange
{ {

View file

@ -1,4 +1,4 @@
namespace ACSE namespace ACSE.Core.Items
{ {
public class ItemChangedEventArgs public class ItemChangedEventArgs
{ {

View file

@ -1,10 +1,13 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using ACSE.Core.Buildings;
using ACSE.Core.Debug;
using ACSE.Core.Saves;
using ACSE.Core.Utilities;
namespace ACSE namespace ACSE.Core.Items
{ {
public enum ItemType public enum ItemType
{ {
@ -46,9 +49,14 @@ public enum ItemType
public class ItemData public class ItemData
{ {
/// <summary>
/// A dictionary containing string-uint pairs for item colors.
/// </summary>
public static Dictionary<string, uint> ItemColorsSettings;
public static List<KeyValuePair<ushort, string>> ItemDatabase = new List<KeyValuePair<ushort, string>>(); public static List<KeyValuePair<ushort, string>> ItemDatabase = new List<KeyValuePair<ushort, string>>();
internal static readonly string[] ItemTypeNames = public static readonly string[] ItemTypeNames =
{ {
"Empty", "Empty",
"Furniture", "Furniture",
@ -441,81 +449,80 @@ public static ItemType GetItemType(ushort id, SaveType saveType)
} }
public static uint GetItemColor(ItemType itemType) public static uint GetItemColor(ItemType itemType)
{ {
var settings = ItemColorSettings.Default;
switch (itemType) switch (itemType)
{ {
case ItemType.Furniture: case ItemType.Furniture:
return settings.FurnitureColor; return ItemColorsSettings["FurnitureColor"];
case ItemType.Flower: case ItemType.Flower:
return settings.FlowerColor; return ItemColorsSettings["FlowerColor"];
case ItemType.Pattern: case ItemType.Pattern:
return settings.PatternColor; return ItemColorsSettings["PatternColor"];
case ItemType.ParchedFlower: case ItemType.ParchedFlower:
return settings.ParchedFlowerColor; return ItemColorsSettings["ParchedFlowerColor"];
case ItemType.WiltedFlower: case ItemType.WiltedFlower:
return settings.WiltedFlowerColor; return ItemColorsSettings["WiltedFlowerColor"];
case ItemType.WateredFlower: case ItemType.WateredFlower:
return settings.WateredFlowerColor; return ItemColorsSettings["WateredFlowerColor"];
case ItemType.Money: case ItemType.Money:
return settings.MoneyColor; return ItemColorsSettings["MoneyColor"];
case ItemType.Rock: case ItemType.Rock:
return settings.RockColor; return ItemColorsSettings["RockColor"];
case ItemType.MoneyRock: case ItemType.MoneyRock:
return settings.MoneyRockColor; return ItemColorsSettings["MoneyRockColor"];
case ItemType.Signboard: case ItemType.Signboard:
return settings.SignboardColor; return ItemColorsSettings["SignboardColor"];
case ItemType.Song: case ItemType.Song:
return settings.SongColor; return ItemColorsSettings["SongColor"];
case ItemType.Paper: case ItemType.Paper:
return settings.PaperColor; return ItemColorsSettings["PaperColor"];
case ItemType.Turnip: case ItemType.Turnip:
return settings.TurnipColor; return ItemColorsSettings["TurnipColor"];
case ItemType.Catchable: case ItemType.Catchable:
return settings.CatchableColor; return ItemColorsSettings["CatchableColor"];
case ItemType.WallpaperCarpet: case ItemType.WallpaperCarpet:
return settings.WallpaperCarpetColor; return ItemColorsSettings["WallpaperCarpetColor"];
case ItemType.Clothes: case ItemType.Clothes:
return settings.ClothesColor; return ItemColorsSettings["ClothesColor"];
case ItemType.Gyroid: case ItemType.Gyroid:
return settings.GyroidColor; return ItemColorsSettings["GyroidColor"];
case ItemType.Fossil: case ItemType.Fossil:
return settings.FossilColor; return ItemColorsSettings["FossilColor"];
case ItemType.Tool: case ItemType.Tool:
return settings.ToolColor; return ItemColorsSettings["ToolColor"];
case ItemType.Item: case ItemType.Item:
return settings.ItemColor; return ItemColorsSettings["ItemColor"];
case ItemType.Fruit: case ItemType.Fruit:
return settings.FruitColor; return ItemColorsSettings["FruitColor"];
case ItemType.Trash: case ItemType.Trash:
return settings.TrashColor; return ItemColorsSettings["TrashColor"];
case ItemType.QuestItem: case ItemType.QuestItem:
return settings.QuestItemColor; return ItemColorsSettings["QuestItemColor"];
case ItemType.RaffleTicket: case ItemType.RaffleTicket:
return settings.RaffleTicketColor; return ItemColorsSettings["RaffleTicketColor"];
case ItemType.Tree: case ItemType.Tree:
return settings.TreeColor; return ItemColorsSettings["TreeColor"];
case ItemType.Weed: case ItemType.Weed:
return settings.WeedColor; return ItemColorsSettings["WeedColor"];
case ItemType.Shell: case ItemType.Shell:
return settings.ShellColor; return ItemColorsSettings["ShellColor"];
case ItemType.Empty: case ItemType.Empty:
return 0x00FFFFFF; // No setting for empty since we always want it transparent return 0x00FFFFFF; // No setting for empty since we always want it transparent
case ItemType.Occupied: case ItemType.Occupied:
return settings.OccupiedColor; return ItemColorsSettings["OccupiedColor"];
case ItemType.Building: case ItemType.Building:
return settings.BuildingColor; return ItemColorsSettings["BuildingColor"];
case ItemType.Diary: case ItemType.Diary:
return settings.DiaryColor; return ItemColorsSettings["DiaryColor"];
case ItemType.HouseObject: case ItemType.HouseObject:
return settings.HouseObjectColor; return ItemColorsSettings["HouseObjectColor"];
default: default:
return settings.InvalidColor; return ItemColorsSettings["InvalidColor"];
} }
} }
public static string GetItemFlag1Type(Item item, byte itemFlag) public static string GetItemFlag1Type(Item item, byte itemFlag)
{ {
var itemType = GetItemType(item.ItemId, MainForm.SaveFile.SaveType); var itemType = GetItemType(item.ItemId, Save.SaveInstance.SaveType);
switch (itemType) switch (itemType)
{ {
case ItemType.Fruit: case ItemType.Fruit:
@ -641,12 +648,12 @@ public static string GetFurnitureItemFlag2Type(byte itemFlag) //Our Flag 2, but
public static string GetItemName(ushort itemId) public static string GetItemName(ushort itemId)
{ {
switch (MainForm.SaveFile.SaveGeneration) switch (Save.SaveInstance.SaveGeneration)
{ {
case SaveGeneration.N3DS: case SaveGeneration.N3DS:
return ItemDatabase.FirstOrDefault(o => o.Key == itemId).Value ?? "Unknown"; return ItemDatabase.FirstOrDefault(o => o.Key == itemId).Value ?? "Unknown";
default: default:
if (GetItemType(itemId, MainForm.SaveFile.SaveType) == ItemType.Furniture) if (GetItemType(itemId, Save.SaveInstance.SaveType) == ItemType.Furniture)
{ {
return ItemDatabase.FirstOrDefault(o => o.Key == (ushort)(itemId & 0xFFFC)).Value ?? "Unknown"; return ItemDatabase.FirstOrDefault(o => o.Key == (ushort)(itemId & 0xFFFC)).Value ?? "Unknown";
} }
@ -675,7 +682,7 @@ public static Dictionary<ushort, string> LoadItemDatabase(StreamReader reader)
} }
catch catch
{ {
Debug.WriteLine($"Error in loading item: {line}"); DebugUtility.DebugManagerInstance.WriteLine($"Error in loading item: {line}", DebugLevel.Error);
} }
} }

View file

@ -1,6 +1,7 @@
using System; using System;
using ACSE.Core.Items;
namespace ACSE.Messages.Mail namespace ACSE.Core.Messages.Mail
{ {
public sealed class GCNAnimalMail public sealed class GCNAnimalMail
{ {

View file

@ -1,4 +1,8 @@
namespace ACSE.Messages.Mail using ACSE.Core.Items;
using ACSE.Core.Players;
using ACSE.Core.Saves;
namespace ACSE.Core.Messages.Mail
{ {
public sealed class GcnPlayerMail : PlayerMailBase public sealed class GcnPlayerMail : PlayerMailBase
{ {

View file

@ -1,10 +1,7 @@
using System; using ACSE.Core.Items;
using System.Collections.Generic; using ACSE.Core.Saves;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ACSE.Messages.Mail namespace ACSE.Core.Messages.Mail
{ {
/// <summary> /// <summary>
/// N64/GameCube/iQue letter type/state /// N64/GameCube/iQue letter type/state

View file

@ -1,4 +1,4 @@
namespace ACSE.Messages.Mail namespace ACSE.Core.Messages.Mail
{ {
public class PlayerMailBase : MailBase public class PlayerMailBase : MailBase
{ {

View file

@ -1,6 +1,6 @@
using ACSE.Utilities; using ACSE.Core.Utilities;
namespace ACSE.Messages namespace ACSE.Core.Messages
{ {
public abstract class MessageBase public abstract class MessageBase
{ {

View file

@ -1,4 +1,4 @@
namespace ACSE.Messages namespace ACSE.Core.Messages
{ {
public class MessageBoardPost : MessageBase public class MessageBoardPost : MessageBase
{ {

View file

@ -1,9 +1,9 @@
namespace ACSE namespace ACSE.Core.Modifiable
{ {
/// <summary> /// <summary>
/// Interface for all modifiable things that implement a modified stack. /// Interface for all modifiable things that implement a modified stack.
/// </summary> /// </summary>
internal interface IModifiable public interface IModifiable
{ {
void Undo(); void Undo();
void Redo(); void Redo();

View file

@ -1,9 +1,9 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
namespace ACSE namespace ACSE.Core.Modifiable
{ {
internal class ModifiedHandler : IModifiable public class ModifiedHandler : IModifiable
{ {
public readonly Stack<IModifiable> UndoStack; public readonly Stack<IModifiable> UndoStack;
public readonly Stack<IModifiable> RedoStack; public readonly Stack<IModifiable> RedoStack;

View file

@ -1,10 +1,10 @@
using System; using System;
using System.Drawing; using System.Drawing;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using System.Windows.Forms; using ACSE.Core.Saves;
using ACSE.Utilities; using ACSE.Core.Utilities;
namespace ACSE namespace ACSE.Core.Patterns
{ {
/// <summary> /// <summary>
/// GameCube Pattern Data Write-up /// GameCube Pattern Data Write-up
@ -19,7 +19,7 @@ namespace ACSE
/// [Byte Array] Alignment Bytes?: 0xF bytes /// [Byte Array] Alignment Bytes?: 0xF bytes
/// [Byte Array] Pattern Data: 0x200 bytes /// [Byte Array] Pattern Data: 0x200 bytes
/// </summary> /// </summary>
class PatternData public static class PatternData
{ {
#region Palettes #region Palettes
@ -324,7 +324,7 @@ public static byte ClosestColorRgb(uint color, uint[] paletteData, bool gen1 = f
} }
} }
public class Pattern public sealed class Pattern
{ {
private readonly Save _saveFile; private readonly Save _saveFile;
private readonly int _offset; private readonly int _offset;
@ -351,7 +351,6 @@ public uint[][] GetPaletteArray(SaveGeneration saveGeneration)
{ {
switch (saveGeneration) switch (saveGeneration)
{ {
case SaveGeneration.GCN:
default: default:
return PatternData.AcPaletteData; return PatternData.AcPaletteData;
case SaveGeneration.NDS: case SaveGeneration.NDS:
@ -364,15 +363,20 @@ public uint[][] GetPaletteArray(SaveGeneration saveGeneration)
// AC / CF // AC / CF
public void GeneratePatternBitmap(byte[] importData = null, bool decode = true) public void GeneratePatternBitmap(byte[] importData = null, bool decode = true)
{ {
var patternRawData = importData ?? (_saveFile.SaveType == SaveType.CityFolk ? _saveFile.ReadByteArray(_offset, 0x200) : _saveFile.ReadByteArray(_offset + 0x20, 0x200)); var patternRawData = importData ?? (_saveFile.SaveType == SaveType.CityFolk
var paletteData = _saveFile.SaveType == SaveType.CityFolk ? PatternData.CfPaletteData : PatternData.AcPaletteData; ? _saveFile.ReadByteArray(_offset, 0x200)
: _saveFile.ReadByteArray(_offset + 0x20, 0x200));
var paletteData = _saveFile.SaveType == SaveType.CityFolk
? PatternData.CfPaletteData
: PatternData.AcPaletteData;
if (decode) if (decode)
{ {
DecodedData = PatternUtility.DecodeC4(patternRawData); DecodedData = PatternUtility.DecodeC4(patternRawData);
} }
PatternBitmap = PatternUtility.C4PaletteMapToBitmap(DecodedData, paletteData[Palette], 32, 32); PatternBitmap = PatternUtility.C4PaletteMapToBitmap(DecodedData, paletteData[Palette]);
} }
public void GenerateWwPatternBitmap(byte[] importData = null, bool decode = true) public void GenerateWwPatternBitmap(byte[] importData = null, bool decode = true)
@ -482,9 +486,6 @@ public void Read(int index)
//No specific palette in NL/WA //No specific palette in NL/WA
GenerateNlPatternBitmap(); GenerateNlPatternBitmap();
break; break;
default:
MessageBox.Show("Patterns: Unknown Save Type");
break;
} }
} }
@ -495,7 +496,7 @@ public void RedrawBitmap()
case SaveGeneration.GCN: case SaveGeneration.GCN:
case SaveGeneration.Wii: case SaveGeneration.Wii:
GeneratePatternBitmap(DecodedData, false); GeneratePatternBitmap(DecodedData, false);
Write(PatternUtility.EncodeC4(DecodedData, 32, 32)); Write(PatternUtility.EncodeC4(DecodedData));
break; break;
case SaveGeneration.NDS: case SaveGeneration.NDS:
GenerateWwPatternBitmap(DecodedData, false); GenerateWwPatternBitmap(DecodedData, false);

View file

@ -1,9 +1,15 @@
using System; using System;
using System.Reflection; using System.Reflection;
using ACSE.Utilities; using ACSE.Core.Encryption;
using ACSE.Messages.Mail; using ACSE.Core.Housing;
using ACSE.Core.Imaging;
using ACSE.Core.Items;
using ACSE.Core.Messages.Mail;
using ACSE.Core.Patterns;
using ACSE.Core.Saves;
using ACSE.Core.Utilities;
namespace ACSE namespace ACSE.Core.Players
{ {
public sealed class Player public sealed class Player
{ {
@ -262,9 +268,13 @@ public void Write()
_saveData.Write(dataOffset, (byte)playerDataType.GetField(field.Name).GetValue(Data)); _saveData.Write(dataOffset, (byte)playerDataType.GetField(field.Name).GetValue(Data));
} }
} }
else if (fieldType == typeof(ushort) || fieldType == typeof(uint)) else if (fieldType == typeof(ushort))
{ {
_saveData.Write(dataOffset, (dynamic)playerDataType.GetField(field.Name).GetValue(Data), _saveData.IsBigEndian); _saveData.Write(dataOffset, (ushort)playerDataType.GetField(field.Name).GetValue(Data), _saveData.IsBigEndian);
}
else if (fieldType == typeof(uint))
{
_saveData.Write(dataOffset, (uint)playerDataType.GetField(field.Name).GetValue(Data), _saveData.IsBigEndian);
} }
else if (fieldType == typeof(Inventory)) else if (fieldType == typeof(Inventory))
{ {

View file

@ -1,8 +1,12 @@
using ACSE.Utilities; using System;
using System;
using System.Drawing; using System.Drawing;
using ACSE.Core.Encryption;
using ACSE.Core.Items;
using ACSE.Core.Patterns;
using ACSE.Core.Saves;
using ACSE.Core.Utilities;
namespace ACSE namespace ACSE.Core.Players
{ {
public struct PlayerSaveInfo public struct PlayerSaveInfo
{ {

View file

@ -1,12 +1,12 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace ACSE.Checksums namespace ACSE.Core.Saves.Checksums
{ {
/// <inheritdoc /> /// <inheritdoc />
/// <summary> /// <summary>
/// Generic CRC32 checksum used in Animal Crossing: City Folk. /// Generic CRC32 checksum used in Animal Crossing: City Folk.
/// </summary> /// </summary>
internal class CRC32 : IChecksum<uint> public sealed class CRC32 : IChecksum<uint>
{ {
private static readonly uint[] Crc32Table = { private static readonly uint[] Crc32Table = {
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419,

View file

@ -1,6 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace ACSE.Checksums namespace ACSE.Core.Saves.Checksums
{ {
/// <summary> /// <summary>
/// Interface for all checksum calculating objects. /// Interface for all checksum calculating objects.

View file

@ -1,9 +1,9 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
namespace ACSE.Checksums namespace ACSE.Core.Saves.Checksums
{ {
internal class NewLeafCRC32Type1 : IChecksum<uint> public sealed class NewLeafCRC32Type1 : IChecksum<uint>
{ {
public static uint[] NewLeafCrcTableType1 = { public static uint[] NewLeafCrcTableType1 = {
0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 0xC79A971F, 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 0xC79A971F,

View file

@ -1,9 +1,9 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
namespace ACSE.Checksums namespace ACSE.Core.Saves.Checksums
{ {
internal class NewLeafCRC32Type2 : IChecksum<uint> public sealed class NewLeafCRC32Type2 : IChecksum<uint>
{ {
private static readonly uint[] NewLeafCrcTableType2 = { private static readonly uint[] NewLeafCrcTableType2 = {
0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC,

View file

@ -1,12 +1,12 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace ACSE.Checksums namespace ACSE.Core.Saves.Checksums
{ {
/// <summary> /// <summary>
/// 16-bit big-endian checksum implementation used by N64, GCN, & iQue games. /// 16-bit big-endian checksum implementation used by N64, GCN, & iQue games.
/// </summary> /// </summary>
internal class UInt16BEChecksum : IChecksum<ushort> public sealed class UInt16BEChecksum : IChecksum<ushort>
{ {
/// <inheritdoc /> /// <inheritdoc />
/// <summary> /// <summary>

View file

@ -1,12 +1,12 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace ACSE.Checksums namespace ACSE.Core.Saves.Checksums
{ {
/// <summary> /// <summary>
/// 16-bit little-endian checksum implementation used by Animal Crossing: Wild World. /// 16-bit little-endian checksum implementation used by Animal Crossing: Wild World.
/// </summary> /// </summary>
internal class UInt16LEChecksum : IChecksum<ushort> public sealed class UInt16LEChecksum : IChecksum<ushort>
{ {
/// <inheritdoc /> /// <inheritdoc />
/// <summary> /// <summary>

View file

@ -1,12 +1,12 @@
using System; using System;
using System.Linq; using System.Linq;
using System.IO; using System.IO;
using System.Windows.Forms;
using System.Text; using System.Text;
using ACSE.Checksums; using ACSE.Core.Debug;
using ACSE.Utilities; using ACSE.Core.Saves.Checksums;
using ACSE.Core.Utilities;
namespace ACSE namespace ACSE.Core.Saves
{ {
public enum SaveType : byte public enum SaveType : byte
{ {
@ -48,6 +48,8 @@ public enum Region : byte
public class Save public class Save
{ {
public static Save SaveInstance { get; private set; }
public readonly SaveType SaveType; public readonly SaveType SaveType;
public readonly SaveGeneration SaveGeneration; public readonly SaveGeneration SaveGeneration;
public readonly SaveInfo SaveInfo; public readonly SaveInfo SaveInfo;
@ -64,10 +66,9 @@ public class Save
private FileStream _saveFile; private FileStream _saveFile;
private readonly BinaryReader _saveReader; private readonly BinaryReader _saveReader;
private BinaryWriter _saveWriter; private BinaryWriter _saveWriter;
private readonly Backup _backup;
private readonly bool _byteswap = false; private readonly bool _byteswap = false;
public Save(string filePath) public Save(string filePath, bool createBackup = false)
{ {
if (File.Exists(filePath)) if (File.Exists(filePath))
{ {
@ -79,9 +80,9 @@ public Save(string filePath)
try { _saveFile = new FileStream(filePath, FileMode.Open); } catch { SuccessfullyLoaded = false; } try { _saveFile = new FileStream(filePath, FileMode.Open); } catch { SuccessfullyLoaded = false; }
if (_saveFile == null || !SuccessfullyLoaded || !_saveFile.CanWrite) if (_saveFile == null || !SuccessfullyLoaded || !_saveFile.CanWrite)
{ {
MessageBox.Show( DebugUtility.DebugManagerInstance.WriteLine(
$"Error: File {Path.GetFileName(filePath)} is being used by another process. Please close any process using it before editing!", $"Error: File {Path.GetFileName(filePath)} is being used by another process. Please close any process using it before editing!",
"File Opening Error", MessageBoxButtons.OK, MessageBoxIcon.Error); DebugLevel.Error);
try try
{ {
_saveFile?.Close(); _saveFile?.Close();
@ -119,12 +120,12 @@ public Save(string filePath)
_saveReader.Dispose(); _saveReader.Dispose();
_saveFile.Dispose(); _saveFile.Dispose();
// Create a Backup SaveInstance = this;
if (Properties.Settings.Default.BackupFiles)
_backup = new Backup(this);
} }
else else
MessageBox.Show("File doesn't exist!"); {
DebugUtility.DebugManagerInstance.WriteLine("File doesn't exist!", DebugLevel.Error);
}
} }
public void Flush() public void Flush()

View file

@ -3,9 +3,11 @@
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Text; using System.Text;
using System.Windows.Forms; using ACSE.Core.Debug;
using ACSE.Core.Items;
using ACSE.Core.Utilities;
namespace ACSE namespace ACSE.Core.Saves
{ {
public struct Offsets public struct Offsets
{ {
@ -796,34 +798,42 @@ public static SaveInfo GetSaveInfo(SaveType saveType)
public static Dictionary<ushort, string> GetItemInfo(SaveType saveType, string language = "en") public static Dictionary<ushort, string> GetItemInfo(SaveType saveType, string language = "en")
{ {
var itemDbLocation = MainForm.AssemblyLocation + "\\Resources\\"; var itemDbLocation = "";
switch (saveType) switch (saveType)
{ {
case SaveType.DoubutsuNoMori: case SaveType.DoubutsuNoMori:
case SaveType.DongwuSenlin: case SaveType.DongwuSenlin:
itemDbLocation += "DnM_Items_" + language + ".txt"; itemDbLocation = Path.Combine(PathUtility.GetExeDirectory(), "Resources",
$"DnM_Items_{language}.txt");
break; break;
case SaveType.DoubutsuNoMoriPlus: case SaveType.DoubutsuNoMoriPlus:
itemDbLocation += "DBNM_Plus_Items_" + language + ".txt"; itemDbLocation = Path.Combine(PathUtility.GetExeDirectory(), "Resources",
$"DBNM_Plus_Items_{language}.txt");
break; break;
case SaveType.AnimalCrossing: case SaveType.AnimalCrossing:
itemDbLocation += "AC_Items_" + language + ".txt"; itemDbLocation = Path.Combine(PathUtility.GetExeDirectory(), "Resources",
$"AC_Items_{language}.txt");
break; break;
case SaveType.DoubutsuNoMoriEPlus: case SaveType.DoubutsuNoMoriEPlus:
case SaveType.AnimalForestEPlus: case SaveType.AnimalForestEPlus:
itemDbLocation += "DBNM_e_Plus_Items_" + language + ".txt"; itemDbLocation = Path.Combine(PathUtility.GetExeDirectory(), "Resources",
$"DBNM_e_Plus_Items_{language}.txt");
break; break;
case SaveType.WildWorld: case SaveType.WildWorld:
itemDbLocation += "WW_Items_" + language + ".txt"; itemDbLocation = Path.Combine(PathUtility.GetExeDirectory(), "Resources",
$"WW_Items_{language}.txt");
break; break;
case SaveType.CityFolk: case SaveType.CityFolk:
itemDbLocation += "CF_Items_" + language + ".txt"; itemDbLocation = Path.Combine(PathUtility.GetExeDirectory(), "Resources",
$"CF_Items_{language}.txt");
break; break;
case SaveType.NewLeaf: case SaveType.NewLeaf:
itemDbLocation += "NL_Items_" + language + ".txt"; itemDbLocation = Path.Combine(PathUtility.GetExeDirectory(), "Resources",
$"NL_Items_{language}.txt");
break; break;
case SaveType.WelcomeAmiibo: case SaveType.WelcomeAmiibo:
itemDbLocation += "WA_Items_" + language + ".txt"; itemDbLocation = Path.Combine(PathUtility.GetExeDirectory(), "Resources",
$"WA_Items_{language}.txt");
break; break;
} }
@ -836,7 +846,7 @@ public static Dictionary<ushort, string> GetItemInfo(SaveType saveType, string l
} }
catch (Exception e) catch (Exception e)
{ {
MainForm.DebugManager.WriteLine( DebugUtility.DebugManagerInstance.WriteLine(
$"An error occured opening item database file:\n\"{itemDbLocation}\"\nError Info:\n{e.Message}", DebugLevel.Error); $"An error occured opening item database file:\n\"{itemDbLocation}\"\nError Info:\n{e.Message}", DebugLevel.Error);
return null; return null;
} }
@ -844,108 +854,86 @@ public static Dictionary<ushort, string> GetItemInfo(SaveType saveType, string l
public static Dictionary<byte, string> GetAcreInfo(SaveType saveType, string language = "en") public static Dictionary<byte, string> GetAcreInfo(SaveType saveType, string language = "en")
{ {
StreamReader contents; if (saveType != SaveType.WildWorld) return null;
var acreDbLocation = MainForm.AssemblyLocation + "\\Resources\\";
if (saveType == SaveType.WildWorld) var (result, database) =
acreDbLocation += "WW_Acres_" + language + ".txt"; DatabaseUtility.LoadDatabaseByte(Path.Combine(PathUtility.GetExeDirectory(),
try { contents = File.OpenText(acreDbLocation); } $"WW_Acres_{language}.txt"));
catch (Exception e)
switch (result)
{ {
MainForm.DebugManager.WriteLine( case DatabaseUtility.DatabaseReturnCode.FailedToOpen:
$"An error occured opening acre database file:\n\"{acreDbLocation}\"\nError Info:\n{e.Message}", DebugLevel.Error); DebugUtility.DebugManagerInstance.WriteLine(
return null; "Failed to open the Wild World acre database file.", DebugLevel.Error);
} break;
var acreDictionary = new Dictionary<byte, string>();
string line; case DatabaseUtility.DatabaseReturnCode.FailedToRead:
while ((line = contents.ReadLine()) != null) DebugUtility.DebugManagerInstance.WriteLine(
{ "Failed to read the Wild World acre database file.", DebugLevel.Error);
if (!Properties.Settings.Default.DebuggingEnabled && line.Contains("//")) break;
MessageBox.Show("Now loading Acre type: " + line.Replace("//", ""));
else if (line.Contains("0x"))
{
string acreIdString = line.Substring(0, 4), acreName = line.Substring(5);
if (byte.TryParse(acreIdString.Replace("0x", ""), NumberStyles.AllowHexSpecifier, null, out var acreId))
acreDictionary.Add(acreId, acreName);
else
MainForm.DebugManager.WriteLine("Unable to add Acre: " + acreIdString + " | " + acreName, DebugLevel.Error);
}
} }
contents.Close(); return database;
contents.Dispose();
return acreDictionary;
} }
public static Dictionary<ushort, string> GetAcreInfoUInt16(SaveType saveType, string language = "en") public static Dictionary<ushort, string> GetAcreInfoUInt16(SaveType saveType, string language = "en")
{ {;
StreamReader contents; var databaseName = "";
var acreDbLocation = MainForm.AssemblyLocation + "\\Resources\\";
switch (saveType) switch (saveType)
{ {
case SaveType.DoubutsuNoMori: case SaveType.DoubutsuNoMori:
case SaveType.DongwuSenlin: case SaveType.DongwuSenlin:
case SaveType.AnimalCrossing: // TODO: DnM needs to have a custom list, since the docks/islands don't exist case SaveType.AnimalCrossing: // TODO: DnM needs to have a custom list, since the docks/islands don't exist
acreDbLocation += "AC_Acres_" + language + ".txt"; databaseName = $"AC_Acres_{language}.txt";
break; break;
case SaveType.DoubutsuNoMoriPlus: case SaveType.DoubutsuNoMoriPlus:
acreDbLocation += "DBNM_Plus_Acres_" + language + ".txt"; databaseName = $"DBNM_Plus_Acres_{language}.txt";
break; break;
case SaveType.DoubutsuNoMoriEPlus: case SaveType.DoubutsuNoMoriEPlus:
case SaveType.AnimalForestEPlus: case SaveType.AnimalForestEPlus:
acreDbLocation += "DBNM_e_Plus_Acres_" + language + ".txt"; databaseName = $"DBNM_e_Plus_Acres_{language}.txt";
break; break;
case SaveType.CityFolk: case SaveType.CityFolk:
acreDbLocation += "CF_Acres_" + language + ".txt"; databaseName = $"CF_Acres_{language}.txt";
break; break;
case SaveType.NewLeaf: case SaveType.NewLeaf:
acreDbLocation += "NL_Acres_" + language + ".txt"; databaseName = $"NL_Acres_{language}.txt";
break; break;
case SaveType.WelcomeAmiibo: case SaveType.WelcomeAmiibo:
acreDbLocation += "WA_Acres_" + language + ".txt"; databaseName = $"WA_Acres_{language}.txt";
break; break;
} }
try { contents = File.OpenText(acreDbLocation); } var (result, database) =
catch (Exception e) DatabaseUtility.LoadDatabase(Path.Combine(PathUtility.GetExeDirectory(), databaseName));
switch (result)
{ {
MainForm.DebugManager.WriteLine( case DatabaseUtility.DatabaseReturnCode.FailedToOpen:
$"An error occured opening acre database file:\n\"{acreDbLocation}\"\nError Info:\n{e.Message}", DebugLevel.Error); DebugUtility.DebugManagerInstance.WriteLine(
return null; "Failed to open the acre database file.", DebugLevel.Error);
} break;
var acreDictionary = new Dictionary<ushort, string>();
string line; case DatabaseUtility.DatabaseReturnCode.FailedToRead:
while ((line = contents.ReadLine()) != null) DebugUtility.DebugManagerInstance.WriteLine(
{ "Failed to read the acre database file.", DebugLevel.Error);
if (!Properties.Settings.Default.DebuggingEnabled && line.Contains("//")) break;
MessageBox.Show("Now loading Acre type: " + line.Replace("//", ""));
else if (line.Contains("0x"))
{
string acreIdString = line.Substring(0, 6), acreName = line.Substring(7);
if (ushort.TryParse(acreIdString.Replace("0x", ""), NumberStyles.AllowHexSpecifier, null, out var acreId))
acreDictionary.Add(acreId, acreName);
else
MainForm.DebugManager.WriteLine("Unable to add Acre: " + acreIdString + " | " + acreName, DebugLevel.Error);
}
} }
contents.Close(); return database;
contents.Dispose();
return acreDictionary;
} }
public static Dictionary<string, List<byte>> GetFiledAcreData(SaveType saveType, string language = "en") public static Dictionary<string, List<byte>> GetFiledAcreData(SaveType saveType, string language = "en")
{ {
StreamReader contents; StreamReader contents;
var acreDbLocation = MainForm.AssemblyLocation + "\\Resources\\"; var acreDbLocation = PathUtility.GetExeDirectory();
if (saveType == SaveType.WildWorld) if (saveType == SaveType.WildWorld)
acreDbLocation += "WW_Acres_" + language + ".txt"; acreDbLocation += "WW_Acres_" + language + ".txt";
try { contents = File.OpenText(acreDbLocation); } try { contents = File.OpenText(acreDbLocation); }
catch (Exception e) catch (Exception e)
{ {
MainForm.DebugManager.WriteLine( DebugUtility.DebugManagerInstance.WriteLine(
$"An error occured opening acre database file:\n\"{acreDbLocation}\"\nError Info:\n{e.Message}", DebugLevel.Error); $"An error occured opening acre database file:\n\"{acreDbLocation}\"\nError Info:\n{e.Message}", DebugLevel.Error);
return null; return null;
} }
@ -968,10 +956,12 @@ public static Dictionary<string, List<byte>> GetFiledAcreData(SaveType saveType,
if (!filedList.ContainsKey(currentAcreType)) if (!filedList.ContainsKey(currentAcreType))
filedList.Add(currentAcreType, new List<byte>()); filedList.Add(currentAcreType, new List<byte>());
string acreIdString = line.Substring(0, 4), acreName = line.Substring(5); string acreIdString = line.Substring(0, 4), acreName = line.Substring(5);
if (byte.TryParse(acreIdString.Replace("0x", ""), NumberStyles.AllowHexSpecifier, null, out var acreId)) if (byte.TryParse(acreIdString.Replace("0x", ""), NumberStyles.AllowHexSpecifier, null,
out var acreId))
filedList[currentAcreType].Add(acreId); filedList[currentAcreType].Add(acreId);
else else
MainForm.DebugManager.WriteLine("Unable to add Acre: " + acreIdString + " | " + acreName, DebugLevel.Error); DebugUtility.DebugManagerInstance.WriteLine(
"Unable to add Acre: " + acreIdString + " | " + acreName, DebugLevel.Error);
} }
} }
@ -984,7 +974,7 @@ public static Dictionary<string, List<byte>> GetFiledAcreData(SaveType saveType,
public static Dictionary<string, Dictionary<ushort, string>> GetFiledAcreDataUInt16(SaveType saveType, string language = "en") public static Dictionary<string, Dictionary<ushort, string>> GetFiledAcreDataUInt16(SaveType saveType, string language = "en")
{ {
StreamReader contents; StreamReader contents;
var acreDbLocation = MainForm.AssemblyLocation + "\\Resources\\"; var acreDbLocation = PathUtility.GetExeDirectory();
switch (saveType) switch (saveType)
{ {
case SaveType.DoubutsuNoMori: case SaveType.DoubutsuNoMori:
@ -1013,7 +1003,7 @@ public static Dictionary<string, Dictionary<ushort, string>> GetFiledAcreDataUIn
try { contents = File.OpenText(acreDbLocation); } try { contents = File.OpenText(acreDbLocation); }
catch (Exception e) catch (Exception e)
{ {
MainForm.DebugManager.WriteLine( DebugUtility.DebugManagerInstance.WriteLine(
$"An error occured opening acre database file:\n\"{acreDbLocation}\"\nError Info:\n{e.Message}", DebugLevel.Error); $"An error occured opening acre database file:\n\"{acreDbLocation}\"\nError Info:\n{e.Message}", DebugLevel.Error);
return null; return null;
} }
@ -1036,10 +1026,12 @@ public static Dictionary<string, Dictionary<ushort, string>> GetFiledAcreDataUIn
if (!filedList.ContainsKey(currentAcreType)) if (!filedList.ContainsKey(currentAcreType))
filedList.Add(currentAcreType, new Dictionary<ushort, string>()); filedList.Add(currentAcreType, new Dictionary<ushort, string>());
string acreIdString = line.Substring(0, 6), acreName = line.Substring(7); string acreIdString = line.Substring(0, 6), acreName = line.Substring(7);
if (ushort.TryParse(acreIdString.Replace("0x", ""), NumberStyles.AllowHexSpecifier, null, out var acreId)) if (ushort.TryParse(acreIdString.Replace("0x", ""), NumberStyles.AllowHexSpecifier, null,
out var acreId))
filedList[currentAcreType].Add(acreId, line.Substring(7)); filedList[currentAcreType].Add(acreId, line.Substring(7));
else else
MainForm.DebugManager.WriteLine("Unable to add Acre: " + acreIdString + " | " + acreName, DebugLevel.Error); DebugUtility.DebugManagerInstance.WriteLine(
"Unable to add Acre: " + acreIdString + " | " + acreName, DebugLevel.Error);
} }
} }

View file

@ -1,4 +1,8 @@
namespace ACSE using ACSE.Core.Items;
using ACSE.Core.Patterns;
using ACSE.Core.Saves;
namespace ACSE.Core.Shops
{ {
public class ShopOffsets public class ShopOffsets
{ {
@ -139,7 +143,7 @@ public FurnitureShop(Save saveFile, int offset) : base(saveFile, offset)
public byte GetSize(SaveGeneration generation) public byte GetSize(SaveGeneration generation)
{ {
var saveFile = MainForm.SaveFile; var saveFile = Save.SaveInstance;
var shopOffsets = ShopInfo.GetShopOffsets(saveFile.SaveType); var shopOffsets = ShopInfo.GetShopOffsets(saveFile.SaveType);
if (shopOffsets == null) return 0; if (shopOffsets == null) return 0;
switch (generation) switch (generation)
@ -156,7 +160,7 @@ public byte GetSize(SaveGeneration generation)
public void SetSize(byte size) public void SetSize(byte size)
{ {
var saveFile = MainForm.SaveFile; var saveFile = Save.SaveInstance;
var shopOffsets = ShopInfo.GetShopOffsets(saveFile.SaveType); var shopOffsets = ShopInfo.GetShopOffsets(saveFile.SaveType);
if (shopOffsets == null) return; if (shopOffsets == null) return;
switch (saveFile.SaveGeneration) switch (saveFile.SaveGeneration)

View file

@ -1,7 +1,10 @@
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using ACSE.Core.Debug;
using ACSE.Core.Saves;
using ACSE.Core.Utilities;
namespace ACSE namespace ACSE.Core.TownBuildings
{ {
public static class TrainStation public static class TrainStation
{ {
@ -11,7 +14,9 @@ public static bool HasModifiableTrainStation(SaveGeneration generation)
public static Image GetStationImage(int station) public static Image GetStationImage(int station)
{ {
Image stationImg = null; Image stationImg = null;
var stationFile = MainForm.AssemblyLocation + "\\Resources\\Images\\Icons\\Stations\\" + (station + 1).ToString() + ".png"; var stationFile = Path.Combine(PathUtility.GetResourcesDirectory(), "Images", "Icons",
$"Stations{station + 1}.png");
if (!File.Exists(stationFile)) return null; if (!File.Exists(stationFile)) return null;
try try
{ {
@ -19,7 +24,8 @@ public static Image GetStationImage(int station)
} }
catch catch
{ {
MainForm.DebugManager.WriteLine("Unable to load station image #" + (station + 1), DebugLevel.Error); DebugUtility.DebugManagerInstance.WriteLine("Unable to load station image #" + (station + 1),
DebugLevel.Error);
} }
return stationImg; return stationImg;
} }

View file

@ -2,11 +2,12 @@
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Reflection; using System.Reflection;
using ACSE.Core.Utilities;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
namespace ACSE namespace ACSE.Core.Updater
{ {
internal sealed class Updater public sealed class Updater
{ {
private int _versionMajor; private int _versionMajor;
private int _versionMinor; private int _versionMinor;
@ -16,7 +17,7 @@ internal sealed class Updater
private void SetCurrentVersionInfo() private void SetCurrentVersionInfo()
{ {
var versionInfo = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location); var versionInfo = FileVersionInfo.GetVersionInfo(PathUtility.GetExeLocation());
_versionMajor = versionInfo.FileMajorPart; _versionMajor = versionInfo.FileMajorPart;
_versionMinor = versionInfo.FileMinorPart; _versionMinor = versionInfo.FileMinorPart;
_versionRevision = versionInfo.ProductBuildPart; _versionRevision = versionInfo.ProductBuildPart;

View file

@ -0,0 +1,98 @@
using System.Collections.Generic;
using System.Globalization;
using System.IO;
namespace ACSE.Core.Utilities
{
public static class DatabaseUtility
{
public enum DatabaseReturnCode
{
FailedToRead = -2,
FailedToOpen = -1,
Success = 0
}
/// <summary>
/// Loads a specified database with the key type as bytes.
/// </summary>
/// <param name="databasePath">The path to the database to load.</param>
/// <returns>The result of the method <see cref="DatabaseReturnCode"/>, and the loaded database if execution was successful.</returns>
public static (DatabaseReturnCode, Dictionary<byte, string>) LoadDatabaseByte(string databasePath)
{
StreamReader databaseReader;
try
{
databaseReader = File.OpenText(databasePath);
}
catch
{
return (DatabaseReturnCode.FailedToOpen, null);
}
try
{
using (databaseReader)
{
var database = new Dictionary<byte, string>();
string line;
while ((line = databaseReader.ReadLine()) != null)
{
if (line.Contains("//")) continue;
database.Add(byte.Parse(line.Substring(0, 4).Replace("0x", ""), NumberStyles.HexNumber),
line.Substring(5));
}
return (DatabaseReturnCode.Success, database);
}
}
catch
{
return (DatabaseReturnCode.FailedToRead, null);
}
}
/// <summary>
/// Loads a specified database with the key type as ushorts.
/// </summary>
/// <param name="databasePath">The path to the database to load.</param>
/// <returns>The result of the method <see cref="DatabaseReturnCode"/>, and the loaded database if execution was successful.</returns>
public static (DatabaseReturnCode, Dictionary<ushort, string>) LoadDatabase(string databasePath)
{
StreamReader databaseReader;
try
{
databaseReader = File.OpenText(databasePath);
}
catch
{
return (DatabaseReturnCode.FailedToOpen, null);
}
try
{
using (databaseReader)
{
var database = new Dictionary<ushort, string>();
string line;
while ((line = databaseReader.ReadLine()) != null)
{
if (line.Contains("//")) continue;
database.Add(ushort.Parse(line.Substring(0, 6).Replace("0x", ""), NumberStyles.HexNumber),
line.Substring(7));
}
return (DatabaseReturnCode.Success, database);
}
}
catch
{
return (DatabaseReturnCode.FailedToRead, null);
}
}
}
}

View file

@ -1,6 +1,7 @@
using System; using System;
using ACSE.Core.Saves;
namespace ACSE.Utilities namespace ACSE.Core.Utilities
{ {
public class AcDate public class AcDate
{ {
@ -38,7 +39,7 @@ public AcDate()
public AcDate(byte[] dateData) public AcDate(byte[] dateData)
{ {
switch (MainForm.SaveFile.SaveType) switch (Save.SaveInstance.SaveType)
{ {
case SaveType.DoubutsuNoMori: case SaveType.DoubutsuNoMori:
case SaveType.DoubutsuNoMoriPlus: case SaveType.DoubutsuNoMoriPlus:
@ -125,7 +126,7 @@ public string Format(string formatString)
public byte[] ToFullDateData() public byte[] ToFullDateData()
{ {
switch (MainForm.SaveFile.SaveGeneration) switch (Save.SaveInstance.SaveGeneration)
{ {
case SaveGeneration.N64: case SaveGeneration.N64:
case SaveGeneration.GCN: case SaveGeneration.GCN:
@ -147,7 +148,7 @@ public byte[] ToFullDateData()
public byte[] ToYearMonthDayDateData() public byte[] ToYearMonthDayDateData()
{ {
switch (MainForm.SaveFile.SaveGeneration) switch (Save.SaveInstance.SaveGeneration)
{ {
case SaveGeneration.N64: case SaveGeneration.N64:
case SaveGeneration.GCN: case SaveGeneration.GCN:
@ -173,7 +174,7 @@ public byte[] ToYearMonthDayDateData()
public byte[] ToMonthDayDateData() public byte[] ToMonthDayDateData()
{ {
switch (MainForm.SaveFile.SaveGeneration) switch (Save.SaveInstance.SaveGeneration)
{ {
case SaveGeneration.N64: case SaveGeneration.N64:
case SaveGeneration.GCN: case SaveGeneration.GCN:

View file

@ -0,0 +1,22 @@
using ACSE.Core.Debug;
using ACSE.Core.Saves;
namespace ACSE.Core.Utilities
{
public static class DebugUtility
{
/// <summary>
/// The current DebugManager instance.
/// </summary>
public static DebugManager DebugManagerInstance { get; private set; }
/// <summary>
/// Initializes the DebugManager and returns the instance. If it is already initialized, it will return that instance.
/// </summary>
/// <param name="saveFile">The current save file to initialize the debug manager with.</param>
/// <param name="debugLevel">The debug level to initialize the manager with.</param>
/// <returns>The <see cref="DebugManager"/> object that is now initialized.</returns>
public static DebugManager InitializeDebugManager(Save saveFile, DebugLevel debugLevel = DebugLevel.Info) =>
DebugManagerInstance ?? (DebugManagerInstance = new DebugManager(saveFile, debugLevel));
}
}

View file

@ -0,0 +1,26 @@
using System.IO;
using System.Reflection;
namespace ACSE.Core.Utilities
{
public static class PathUtility
{
/// <summary>
/// Gets the path to the current executable.
/// </summary>
/// <returns>The path string of the current executable.</returns>
public static string GetExeLocation() => Assembly.GetEntryAssembly().Location;
/// <summary>
/// Gets the directory of the executable folder.
/// </summary>
/// <returns>The path string of the folder the executable was launched in.</returns>
public static string GetExeDirectory() => Path.GetDirectoryName(GetExeLocation());
/// <summary>
/// Gets the directory of the Resources folder.
/// </summary>
/// <returns>The path string of the Resources folder.</returns>
public static string GetResourcesDirectory() => Path.Combine(GetExeDirectory(), "Resources");
}
}

View file

@ -2,8 +2,9 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using ACSE.Core.Imaging;
namespace ACSE.Utilities namespace ACSE.Core.Utilities
{ {
public static class PatternUtility public static class PatternUtility
{ {

View file

@ -3,8 +3,10 @@
using System.Text; using System.Text;
using System.Globalization; using System.Globalization;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using ACSE.Core.Debug;
using ACSE.Core.Saves;
namespace ACSE.Utilities namespace ACSE.Core.Utilities
{ {
internal static class CharacterSets internal static class CharacterSets
{ {
@ -472,9 +474,6 @@ public AcString(byte[] stringBuffer, SaveType saveType)
if (result >= CharacterSets.DongwuSenlinCharacterSet.Length) if (result >= CharacterSets.DongwuSenlinCharacterSet.Length)
{ {
System.Windows.Forms.MessageBox.Show(
$"Unknown Dongwu Senlin character encountered: {result:X4}");
String += "?"; String += "?";
} }
else else
@ -617,10 +616,6 @@ public static byte[] GetBytes(string String, int maxSize = 0)
Array.Resize(ref stringBuffer, maxSize); Array.Resize(ref stringBuffer, maxSize);
return stringBuffer; return stringBuffer;
} }
case SaveType.Unknown:
MainForm.DebugManager.WriteLine(
$"StringUtil was passed an unknown SaveType enum. Received Type: {_saveType.ToString()}", DebugLevel.Error);
return null;
default: default:
return null; return null;
} }

View file

@ -4,8 +4,13 @@
using System.Drawing.Imaging; using System.Drawing.Imaging;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using ACSE.Core.Acres;
using ACSE.Core.Encryption;
using ACSE.Core.Items;
using ACSE.Core.Saves;
using ACSE.Core.Villagers;
namespace ACSE.Utilities namespace ACSE.Core.Utilities
{ {
public static class Utility public static class Utility
{ {
@ -57,41 +62,11 @@ public static int[] FindLargestMatch(ref List<byte> dictionary, int[] matchesFou
return bestMatch; return bestMatch;
} }
public static void Scan_For_NL_Int32() public static Tuple<byte[], bool> FindVillagerHouse(ushort villagerId, WorldAcre[] townAcres) // TODO: Apply to WW
{ {
if (MainForm.SaveFile == null || MainForm.SaveFile.SaveGeneration != SaveGeneration.N3DS) return; if (Save.SaveInstance == null) return new Tuple<byte[], bool>(new byte[] {0xFF, 0xFF, 0xFF, 0xFF}, false);
using (var int32Stream = File.CreateText(MainForm.AssemblyLocation + "\\" +
(MainForm.SaveFile.SaveType == SaveType.WelcomeAmiibo ? "WA_" : "") + "NL_Int32_Database.txt"))
for (var i = 0; i < MainForm.SaveFile.SaveData.Length - 4; i += 4)
{
var possibleNlInt32 = new NewLeafInt32(MainForm.SaveFile.ReadUInt32(i), MainForm.SaveFile.ReadUInt32(i + 4));
if (possibleNlInt32.Valid)
int32Stream.WriteLine(
$"Found Valid NewLeafInt32 at offset 0x{i:X} | Value: {possibleNlInt32.Value}");
}
}
public static Image Set_Image_Color(Image grayscaleImage, ColorMatrix transformMatrix)
{
using (var attributes = new ImageAttributes())
{
attributes.SetColorMatrix(transformMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
var transformedImage = new Bitmap(grayscaleImage.Width, grayscaleImage.Height);
using (var g = Graphics.FromImage(transformedImage))
{
g.DrawImage(grayscaleImage, 0, 0);
g.DrawImage(transformedImage, new Rectangle(0, 0, grayscaleImage.Size.Width, grayscaleImage.Size.Height),
0, 0, grayscaleImage.Size.Width, grayscaleImage.Size.Height, GraphicsUnit.Pixel, attributes);
return transformedImage;
}
}
}
public static Tuple<byte[], bool> Find_Villager_House(ushort villagerId) // TODO: Apply to WW
{
if (MainForm.SaveFile == null) return new Tuple<byte[], bool>(new byte[] {0xFF, 0xFF, 0xFF, 0xFF}, false);
var villagerHouseId = (ushort)(0x5000 + (villagerId & 0xFF)); var villagerHouseId = (ushort)(0x5000 + (villagerId & 0xFF));
foreach (var acre in MainForm.TownAcres) foreach (var acre in townAcres)
{ {
var villagerHouse = acre.AcreItems.FirstOrDefault(o => o.ItemId == villagerHouseId); var villagerHouse = acre.AcreItems.FirstOrDefault(o => o.ItemId == villagerHouseId);
if (villagerHouse != null) if (villagerHouse != null)
@ -104,12 +79,12 @@ public static Tuple<byte[], bool> Find_Villager_House(ushort villagerId) // TODO
return new Tuple<byte[], bool>(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF }, false); return new Tuple<byte[], bool>(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF }, false);
} }
public static (byte[], bool) FindVillagerHouseWildWorld(int villagerIndex) public static (byte[], bool) FindVillagerHouseWildWorld(int villagerIndex, WorldAcre[] townAcres)
{ {
if (MainForm.SaveFile == null) return (new byte[] {0xFF, 0xFF}, false); if (Save.SaveInstance == null) return (new byte[] {0xFF, 0xFF}, false);
var houseId = 0x5001 + villagerIndex; var houseId = 0x5001 + villagerIndex;
foreach (var acre in MainForm.TownAcres) foreach (var acre in townAcres)
{ {
var villagerHouse = acre.AcreItems.FirstOrDefault(o => o.ItemId == houseId); var villagerHouse = acre.AcreItems.FirstOrDefault(o => o.ItemId == houseId);
if (villagerHouse != null) if (villagerHouse != null)
@ -133,14 +108,14 @@ public static Villager GetVillagerFromHouse(ushort houseId, Villager[] villagers
} }
public static bool[] Check_Perfect_Town_Requirements(WorldAcre[] acres, bool makePerfect = false) public static bool[] CheckPerfectTownRequirements(WorldAcre[] acres, bool makePerfect = false)
{ {
var acreResults = new bool[acres.Length]; var acreResults = new bool[acres.Length];
var points = 0; var points = 0;
for (var i = 0; i < acreResults.Length; i++) for (var i = 0; i < acreResults.Length; i++)
{ {
var acre = acres[i]; var acre = acres[i];
switch (MainForm.SaveFile.SaveGeneration) switch (Save.SaveInstance.SaveGeneration)
{ {
case SaveGeneration.N64: case SaveGeneration.N64:
case SaveGeneration.GCN: case SaveGeneration.GCN:
@ -159,7 +134,7 @@ public static bool[] Check_Perfect_Town_Requirements(WorldAcre[] acres, bool mak
acre.AcreItems[o] = new WorldItem(0, o); acre.AcreItems[o] = new WorldItem(0, o);
} }
} }
else if (ItemData.GetItemType(item.ItemId, MainForm.SaveFile.SaveType) == ItemType.Tree) else if (ItemData.GetItemType(item.ItemId, Save.SaveInstance.SaveType) == ItemType.Tree)
{ {
treeCount++; treeCount++;
} }
@ -173,7 +148,7 @@ public static bool[] Check_Perfect_Town_Requirements(WorldAcre[] acres, bool mak
for (var x = 0; x < 256; x++) for (var x = 0; x < 256; x++)
{ {
if (ItemData.GetItemType(acre.AcreItems[x].ItemId, if (ItemData.GetItemType(acre.AcreItems[x].ItemId,
MainForm.SaveFile.SaveType) != ItemType.Tree) continue; Save.SaveInstance.SaveType) != ItemType.Tree) continue;
acre.AcreItems[x] = new WorldItem(0, x); acre.AcreItems[x] = new WorldItem(0, x);
break; break;
} }
@ -215,10 +190,10 @@ public static bool[] Check_Perfect_Town_Requirements(WorldAcre[] acres, bool mak
return acreResults; return acreResults;
} }
public static void Place_Structure(WorldAcre acre, int startIndex, List<ushort[]> structureInfo) public static void PlaceStructure(WorldAcre acre, int startIndex, List<ushort[]> structureInfo)
{ {
if (startIndex <= -1 || startIndex >= 256) return; if (startIndex <= -1 || startIndex >= 256) return;
if (MainForm.SaveFile.SaveGeneration != SaveGeneration.GCN) return; if (Save.SaveInstance.SaveGeneration != SaveGeneration.GCN) return;
for (var y = 0; y < structureInfo.Count; y++) for (var y = 0; y < structureInfo.Count; y++)
{ {
for (var x = 0; x < structureInfo[y].Length; x++) for (var x = 0; x < structureInfo[y].Length; x++)
@ -269,7 +244,7 @@ public static void FloodFillItemArray(ref Item[] items, int itemsPerRow, int sta
var i = items[idx]; var i = items[idx];
if (i.Equals(originalItem)) if (i.Equals(originalItem))
{ {
MainForm.SaveFile.ChangesMade = true; Save.SaveInstance.ChangesMade = true;
items[idx] = new Item(newItem); items[idx] = new Item(newItem);
if (p.X - 1 > -1) if (p.X - 1 > -1)
locationStack.Push(new Point(p.X - 1, p.Y)); locationStack.Push(new Point(p.X - 1, p.Y));
@ -308,7 +283,7 @@ public static void FloodFillWorldItemArray(ref WorldItem[] items, int itemsPerRo
var i = items[idx]; var i = items[idx];
if (i.Equals(originalItem)) if (i.Equals(originalItem))
{ {
MainForm.SaveFile.ChangesMade = true; Save.SaveInstance.ChangesMade = true;
items[idx] = new WorldItem(newItem.ItemId, newItem.Flag1, newItem.Flag2, i.Index); items[idx] = new WorldItem(newItem.ItemId, newItem.Flag1, newItem.Flag2, i.Index);
if (p.X - 1 > -1) if (p.X - 1 > -1)
locationStack.Push(new Point(p.X - 1, p.Y)); locationStack.Push(new Point(p.X - 1, p.Y));
@ -347,7 +322,7 @@ public static void FloodFillFurnitureArray(ref Furniture[] items, int itemsPerRo
var i = items[idx]; var i = items[idx];
if (i.Equals(originalItem)) if (i.Equals(originalItem))
{ {
MainForm.SaveFile.ChangesMade = true; Save.SaveInstance.ChangesMade = true;
items[idx] = new Furniture(newItem); items[idx] = new Furniture(newItem);
if (p.X - 1 > -1) if (p.X - 1 > -1)
locationStack.Push(new Point(p.X - 1, p.Y)); locationStack.Push(new Point(p.X - 1, p.Y));
@ -362,176 +337,5 @@ public static void FloodFillFurnitureArray(ref Furniture[] items, int itemsPerRo
previousPoints[idx] = 1; previousPoints[idx] = 1;
} }
} }
// Export/Import Methods
public static void ExportAcres(WorldAcre[] acres, SaveGeneration saveGeneration, string saveFileName)
{
using (var saveDialog = new System.Windows.Forms.SaveFileDialog())
{
saveDialog.Filter = "ACSE Acre Save (*.aas)|*.aas";
saveDialog.FileName = saveFileName + " Acre Data.aas";
if (saveDialog.ShowDialog() != System.Windows.Forms.DialogResult.OK) return;
try
{
using (var stream = new FileStream(saveDialog.FileName, FileMode.Create))
{
using (var writer = new BinaryWriter(stream))
{
writer.Write(new byte[] { 0x41, 0x41, 0x53 }); // "AAS" Identifier
writer.Write((byte)acres.Length); // Total Acre Count
writer.Write((byte)saveGeneration); // Save Generation
writer.Write(new byte[] { 0, 0, 0 }); // Padding
foreach (var t in acres)
{
writer.Write(BitConverter.GetBytes(t.AcreId));
}
writer.Flush();
}
}
}
catch
{
System.Windows.Forms.MessageBox.Show("Acre exportation failed!", "Acre Export Error", System.Windows.Forms.MessageBoxButtons.OK,
System.Windows.Forms.MessageBoxIcon.Error);
}
}
}
public static void ImportAcres(ref WorldAcre[] acres, SaveGeneration saveGeneration)
{
using (var openDialog = new System.Windows.Forms.OpenFileDialog())
{
openDialog.Filter = "ACSE Acre Save (*.aas)|*.aas";
openDialog.FileName = "";
if (openDialog.ShowDialog() != System.Windows.Forms.DialogResult.OK) return;
try
{
using (var stream = new FileStream(openDialog.FileName, FileMode.Open))
{
using (var reader = new BinaryReader(stream))
{
if (!System.Text.Encoding.ASCII.GetString(reader.ReadBytes(3)).Equals("AAS") ||
reader.ReadByte() != acres.Length ||
(SaveGeneration) reader.ReadByte() != saveGeneration) return;
reader.BaseStream.Seek(8, SeekOrigin.Begin);
foreach (var t in acres)
{
t.AcreId = reader.ReadUInt16();
t.BaseAcreId = (ushort)(t.AcreId & 0xFFFC);
}
}
}
}
catch
{
System.Windows.Forms.MessageBox.Show("Acre importation failed!", "Acre Import Error", System.Windows.Forms.MessageBoxButtons.OK,
System.Windows.Forms.MessageBoxIcon.Error);
}
}
}
public static void ExportTown(WorldAcre[] acres, SaveGeneration saveGeneration, string saveFileName)
{
using (var saveDialog = new System.Windows.Forms.SaveFileDialog())
{
saveDialog.Filter = "ACSE Town Save (*.ats)|*.ats";
saveDialog.FileName = saveFileName + " Town Data.ats";
if (saveDialog.ShowDialog() != System.Windows.Forms.DialogResult.OK) return;
try
{
using (var stream = new FileStream(saveDialog.FileName, FileMode.Create))
{
using (var writer = new BinaryWriter(stream))
{
writer.Write(new byte[] { 0x41, 0x54, 0x53 }); // "ATS" Identifier
writer.Write((byte)acres.Length); // Total Acre Count
writer.Write((byte)saveGeneration); // Save Generation
writer.Write(new byte[] { 0, 0, 0 }); // Padding
if (saveGeneration == SaveGeneration.N3DS)
{
foreach (var acre in acres)
{
foreach (var item in acre.AcreItems)
{
writer.Write(BitConverter.GetBytes(item.ToUInt32()));
}
}
}
else
{
foreach (var acre in acres)
{
foreach (var item in acre.AcreItems)
{
writer.Write(BitConverter.GetBytes(item.ItemId));
}
}
}
writer.Flush();
}
}
}
catch
{
System.Windows.Forms.MessageBox.Show("Town exportation failed!", "Town Export Error", System.Windows.Forms.MessageBoxButtons.OK,
System.Windows.Forms.MessageBoxIcon.Error);
}
}
}
public static void ImportTown(ref WorldAcre[] acres, SaveGeneration saveGeneration)
{
using (var openDialog = new System.Windows.Forms.OpenFileDialog())
{
openDialog.Filter = "ACSE Town Save (*.ats)|*.ats";
openDialog.FileName = "";
if (openDialog.ShowDialog() != System.Windows.Forms.DialogResult.OK) return;
try
{
using (var stream = new FileStream(openDialog.FileName, FileMode.Open))
{
using (var reader = new BinaryReader(stream))
{
if (!System.Text.Encoding.ASCII.GetString(reader.ReadBytes(3)).Equals("ATS") ||
reader.ReadByte() != acres.Length ||
(SaveGeneration) reader.ReadByte() != saveGeneration) return;
reader.BaseStream.Seek(8, SeekOrigin.Begin);
if (saveGeneration == SaveGeneration.N3DS)
{
foreach (var acre in acres)
{
for (var x = 0; x < acre.AcreItems.Length; x++)
{
acre.AcreItems[x] = new WorldItem(reader.ReadUInt32(), acre.AcreItems[x].Index);
}
}
}
else
{
foreach (var acre in acres)
{
for (var x = 0; x < acre.AcreItems.Length; x++)
{
acre.AcreItems[x] = new WorldItem(reader.ReadUInt16(), acre.AcreItems[x].Index);
}
}
}
}
}
}
catch
{
System.Windows.Forms.MessageBox.Show("Acre importation failed!", "Acre Import Error", System.Windows.Forms.MessageBoxButtons.OK,
System.Windows.Forms.MessageBoxIcon.Error);
}
}
}
} }
} }

View file

@ -1,9 +1,11 @@
using ACSE.Utilities; using ACSE.Core.Messages.Mail;
using ACSE.Messages.Mail; using ACSE.Core.Players;
using ACSE.Core.Saves;
using ACSE.Core.Utilities;
namespace ACSE namespace ACSE.Core.Villagers.AnimalMemories
{ {
public abstract class PlayerRelation public abstract class AnimalMemory
{ {
public bool Exists; public bool Exists;
@ -28,13 +30,13 @@ public abstract class PlayerRelation
public abstract void Write(); public abstract void Write();
} }
public class AcPlayerRelation : PlayerRelation public class AnimalCrossingAnimalMemory : AnimalMemory
{ {
public byte[] Unknown1; public byte[] Unknown1;
public byte[] Unknown2; public byte[] Unknown2;
public byte[] Unknown3; public byte[] Unknown3;
public AcPlayerRelation(Save saveFile, Villager villager, int dataOffset) public AnimalCrossingAnimalMemory(Save saveFile, Villager villager, int dataOffset)
{ {
SaveFile = saveFile; SaveFile = saveFile;
Villager = villager; Villager = villager;

View file

@ -1,6 +1,7 @@
using System; using System;
using ACSE.Core.Saves;
namespace ACSE.Quests namespace ACSE.Core.Villagers.Quests
{ {
public enum QuestCategory public enum QuestCategory
{ {

View file

@ -1,4 +1,6 @@
namespace ACSE using ACSE.Core.Items;
namespace ACSE.Core.Villagers
{ {
public class SimpleVillager public class SimpleVillager
{ {

View file

@ -2,15 +2,19 @@
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
using ACSE.Utilities; using ACSE.Core.Items;
using ACSE.Core.Players;
using ACSE.Core.Saves;
using ACSE.Core.Utilities;
using ACSE.Core.Villagers.AnimalMemories;
namespace ACSE namespace ACSE.Core.Villagers
{ {
public class Villager public class Villager
{ {
public VillagerOffsets Offsets; public VillagerOffsets Offsets;
public VillagerDataStruct Data; public VillagerDataStruct Data;
public PlayerRelation[] PlayerRelations; public AnimalMemory[] AnimalMemories;
public readonly int Index; public readonly int Index;
public readonly int Offset; public readonly int Offset;
public string Name; public string Name;
@ -107,10 +111,10 @@ public Villager(int offset, int idx, Save save)
// Create Player Relations; // Create Player Relations;
if (save.SaveType != SaveType.AnimalCrossing) return; if (save.SaveType != SaveType.AnimalCrossing) return;
{ {
PlayerRelations = new PlayerRelation[7]; AnimalMemories = new AnimalMemory[7];
for (var i = 0; i < 7; i++) for (var i = 0; i < 7; i++)
{ {
PlayerRelations[i] = new AcPlayerRelation(save, this, Offset + 0x10 + i * 0x138); AnimalMemories[i] = new AnimalCrossingAnimalMemory(save, this, Offset + 0x10 + i * 0x138);
} }
} }
} }
@ -130,9 +134,9 @@ public override string ToString()
return Name ?? "Unknown"; return Name ?? "Unknown";
} }
public PlayerRelation GetPlayerRelation(Player player) public AnimalMemory GetAnimalMemory(Player player)
{ {
return PlayerRelations?.First(o => o.PlayerId == player.Data.Identifier && o.PlayerName.Equals(player.Data.Name)); return AnimalMemories?.First(o => o.PlayerId == player.Data.Identifier && o.PlayerName.Equals(player.Data.Name));
} }
public void SetDlcVillager(int dlcIndex) public void SetDlcVillager(int dlcIndex)
@ -165,7 +169,10 @@ public void Write(string townName)
{ {
if (Offsets.TownId != -1) if (Offsets.TownId != -1)
{ {
Data.TownId = _saveData.ReadUInt16(_saveData.SaveDataStartOffset + MainForm.CurrentSaveInfo.SaveOffsets.TownId, _saveData.IsBigEndian); // Might not be UInt16 in all games Data.TownId =
_saveData.ReadUInt16(
_saveData.SaveDataStartOffset + Save.SaveInstance.SaveInfo.SaveOffsets.TownId,
_saveData.IsBigEndian); // Might not be UInt16 in all games
} }
if (!string.IsNullOrWhiteSpace(townName) && Offsets.TownName != -1) if (!string.IsNullOrWhiteSpace(townName) && Offsets.TownName != -1)
{ {
@ -200,7 +207,9 @@ public void Write(string townName)
default: default:
if (fieldType == typeof(string)) if (fieldType == typeof(string))
{ {
_saveData.Write(dataOffset, AcString.GetBytes(dataObject, (int)villagerOffsetData.GetField(field.Name + "Size").GetValue(Offsets))); _saveData.Write(dataOffset,
AcString.GetBytes(dataObject,
(int) villagerOffsetData.GetField(field.Name + "Size").GetValue(Offsets)));
} }
else if (fieldType == typeof(byte[])) else if (fieldType == typeof(byte[]))
{ {
@ -244,10 +253,10 @@ public void Write(string townName)
} }
} }
// Write PlayerRelations // Write AnimalMemories
if (Exists && PlayerRelations != null) if (Exists && AnimalMemories != null)
{ {
foreach (var relation in PlayerRelations) foreach (var relation in AnimalMemories)
{ {
if (relation.Exists) if (relation.Exists)
{ {

View file

@ -2,12 +2,15 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.Globalization; using System.Globalization;
using ACSE.Core.Debug;
using ACSE.Core.Items;
using ACSE.Core.Saves;
using ACSE.Core.Utilities;
namespace ACSE namespace ACSE.Core.Villagers
{ {
internal class VillagerData public static class VillagerData
{ {
public static readonly Dictionary<ushort, string> WaSpecialVillagers = new Dictionary<ushort, string> public static readonly Dictionary<ushort, string> WaSpecialVillagers = new Dictionary<ushort, string>
{ {
@ -45,10 +48,11 @@ internal class VillagerData
{0x2010, "Isabelle (2)"} {0x2010, "Isabelle (2)"}
}; };
public static BindingSource GetCaravanBindingSource() public static Dictionary<ushort, SimpleVillager> GetCaravanBindingSource()
{ {
var waDatabase = VillagerInfo.GetVillagerDatabase(SaveType.WelcomeAmiibo); var waDatabase = VillagerInfo.GetVillagerDatabase(SaveType.WelcomeAmiibo);
if (waDatabase == null) return new BindingSource(WaSpecialVillagers, null); if (waDatabase == null) return null;
foreach (var v in WaSpecialVillagers) foreach (var v in WaSpecialVillagers)
{ {
var specialVillager = new SimpleVillager var specialVillager = new SimpleVillager
@ -59,7 +63,7 @@ public static BindingSource GetCaravanBindingSource()
waDatabase.Add(v.Key, specialVillager); waDatabase.Add(v.Key, specialVillager);
} }
return new BindingSource(waDatabase, null); return waDatabase;
} }
} }
@ -325,7 +329,7 @@ public static Dictionary<ushort, SimpleVillager> GetVillagerDatabase(SaveType sa
{ {
var database = new Dictionary<ushort, SimpleVillager>(); var database = new Dictionary<ushort, SimpleVillager>();
StreamReader contents; StreamReader contents;
var databaseFilename = MainForm.AssemblyLocation + "\\Resources\\{0}_Villagers_" + language + ".txt"; var databaseFilename = "{0}_Villagers_" + language + ".txt";
switch (saveType) switch (saveType)
{ {
case SaveType.DoubutsuNoMori: case SaveType.DoubutsuNoMori:
@ -357,14 +361,17 @@ public static Dictionary<ushort, SimpleVillager> GetVillagerDatabase(SaveType sa
throw new ArgumentOutOfRangeException(nameof(saveType), saveType, null); throw new ArgumentOutOfRangeException(nameof(saveType), saveType, null);
} }
databaseFilename = Path.Combine(PathUtility.GetResourcesDirectory(), databaseFilename);
try try
{ {
contents = File.OpenText(databaseFilename); contents = File.OpenText(databaseFilename);
} }
catch (Exception e) catch (Exception e)
{ {
MessageBox.Show( DebugUtility.DebugManagerInstance.WriteLine(
$"An error occured opening villager database file:\n\"{databaseFilename}\"\nError Info:\n{e.Message}"); $"An error occured opening villager database file:\n\"{databaseFilename}\"\nError Info:\n{e.Message}",
DebugLevel.Error);
return null; return null;
} }

View file

@ -1,4 +1,6 @@
namespace ACSE using ACSE.Core.Saves;
namespace ACSE.Core.Weather
{ {
public static class Weather public static class Weather
{ {
@ -36,7 +38,9 @@ public static byte ToWeatherByte(byte index, SaveGeneration generation)
{ {
case SaveGeneration.N64: case SaveGeneration.N64:
case SaveGeneration.GCN: case SaveGeneration.GCN:
return (byte)((MainForm.SaveFile.ReadByte(MainForm.SaveFile.SaveDataStartOffset + MainForm.SaveFile.SaveInfo.SaveOffsets.Weather) & 0x0F) | (index << 4)); return (byte) ((Save.SaveInstance.ReadByte(
Save.SaveInstance.SaveDataStartOffset +
Save.SaveInstance.SaveInfo.SaveOffsets.Weather) & 0x0F) | (index << 4));
default: default:
return index; return index;
} }
@ -46,13 +50,6 @@ public static bool UpdateWeather(Save saveFile, byte index)
{ {
if (saveFile.SaveGeneration != SaveGeneration.N64 && saveFile.SaveGeneration != SaveGeneration.GCN) if (saveFile.SaveGeneration != SaveGeneration.N64 && saveFile.SaveGeneration != SaveGeneration.GCN)
return false; return false;
if (saveFile.SaveType != SaveType.DoubutsuNoMoriEPlus && saveFile.SaveType != SaveType.AnimalForestEPlus
&& index == 4 && System.Windows.Forms.MessageBox.Show(
"Setting the Weather to Fall Leaves will cause glitches, and will crash your game if you run."
+ "Are you sure you want to change the weather to it?", "Weather Warning",
System.Windows.Forms.MessageBoxButtons.YesNo,
System.Windows.Forms.MessageBoxIcon.Question) !=
System.Windows.Forms.DialogResult.Yes) return false;
saveFile.Write(saveFile.SaveDataStartOffset + saveFile.SaveInfo.SaveOffsets.Weather, ToWeatherByte(index, saveFile.SaveGeneration)); saveFile.Write(saveFile.SaveDataStartOffset + saveFile.SaveInfo.SaveOffsets.Weather, ToWeatherByte(index, saveFile.SaveGeneration));
return true; return true;
} }

View file

@ -1,9 +1,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using ACSE.Utilities; using ACSE.Core.Utilities;
namespace ACSE namespace ACSE.Core
{ {
public static class Yaz0 public static class Yaz0
{ {

File diff suppressed because it is too large Load diff

View file

Before

Width:  |  Height:  |  Size: 361 KiB

After

Width:  |  Height:  |  Size: 361 KiB

View file

@ -1,4 +1,4 @@
namespace ACSE namespace ACSE.WinForms
{ {
partial class AboutBox partial class AboutBox
{ {

View file

@ -2,9 +2,9 @@
using System.Reflection; using System.Reflection;
using System.Windows.Forms; using System.Windows.Forms;
namespace ACSE namespace ACSE.WinForms
{ {
partial class AboutBox : Form public partial class AboutBox : Form
{ {
public AboutBox() public AboutBox()
{ {

42
ACSE.WinForms/App.config Normal file
View file

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="ACSE.WinForms.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7" />
</startup>
<userSettings>
<ACSE.WinForms.Properties.Settings>
<setting name="DebuggingEnabled" serializeAs="String">
<value>True</value>
</setting>
<setting name="ImageResizeMode" serializeAs="String">
<value>5</value>
</setting>
<setting name="DebugLevel" serializeAs="String">
<value>2</value>
</setting>
<setting name="TownMapSize" serializeAs="String">
<value>256</value>
</setting>
<setting name="AcreMapSize" serializeAs="String">
<value>96</value>
</setting>
<setting name="ShowDumpAcreWarning" serializeAs="String">
<value>True</value>
</setting>
<setting name="ShowBetaAcreWarning" serializeAs="String">
<value>True</value>
</setting>
<setting name="BackupFiles" serializeAs="String">
<value>True</value>
</setting>
<setting name="BackupLocation" serializeAs="String">
<value />
</setting>
</ACSE.WinForms.Properties.Settings>
</userSettings>
</configuration>

View file

@ -3,10 +3,13 @@
using System.Linq; using System.Linq;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
using ACSE.Core.Debug;
using ACSE.Core.Saves;
using ACSE.Core.Utilities;
namespace ACSE namespace ACSE.WinForms.Backups
{ {
public class Backup public sealed class Backup
{ {
private readonly Save _save; private readonly Save _save;
@ -35,7 +38,7 @@ private static string GetBackupLocation()
} }
catch catch
{ {
MainForm.DebugManager.WriteLine( DebugUtility.DebugManagerInstance.WriteLine(
$"The requested backup path {Properties.Settings.Default.BackupLocation} couldn't be accessed!\n" + $"The requested backup path {Properties.Settings.Default.BackupLocation} couldn't be accessed!\n" +
"The backup folder was reset to the default in ApplicationData/ACSE/Backups/!"); "The backup folder was reset to the default in ApplicationData/ACSE/Backups/!");
Properties.Settings.Default.BackupLocation = ""; Properties.Settings.Default.BackupLocation = "";
@ -97,13 +100,13 @@ public bool CreateBackup()
using (var backupFile = File.Create(saveLocation)) using (var backupFile = File.Create(saveLocation))
{ {
backupFile.Write(_save.SaveData, 0, _save.SaveData.Length); backupFile.Write(_save.SaveData, 0, _save.SaveData.Length);
MainForm.DebugManager.WriteLine( DebugUtility.DebugManagerInstance.WriteLine(
$"Save File {_save.SaveName} was backuped to {backupLocation}"); $"Save File {_save.SaveName} was backuped to {backupLocation}");
} }
} }
catch catch
{ {
MainForm.DebugManager.WriteLine( DebugUtility.DebugManagerInstance.WriteLine(
$"Failed to create backup for save {_save.SaveName} at {backupLocation}", DebugLevel.Error); $"Failed to create backup for save {_save.SaveName} at {backupLocation}", DebugLevel.Error);
return false; return false;
} }

View file

@ -1,10 +1,12 @@
using System; using System;
using System.Drawing; using System.Drawing;
using System.Windows.Forms; using System.Windows.Forms;
using ACSE.Core.Encryption;
using ACSE.Core.Saves;
namespace ACSE namespace ACSE.WinForms.Controls
{ {
public class BadgeControl : OffsetablePictureBox public sealed class BadgeControl : OffsetablePictureBox
{ {
private static readonly Bitmap BadgeImage = Properties.Resources.Animal_Crossing_NL_Badges_28x28; private static readonly Bitmap BadgeImage = Properties.Resources.Animal_Crossing_NL_Badges_28x28;
private static readonly Bitmap NoBadgeImage = Properties.Resources.Animal_Crossing_NL_NoBadge_28x28; private static readonly Bitmap NoBadgeImage = Properties.Resources.Animal_Crossing_NL_NoBadge_28x28;

View file

@ -2,8 +2,11 @@
using System.Drawing; using System.Drawing;
using System.Linq; using System.Linq;
using System.Windows.Forms; using System.Windows.Forms;
using ACSE.Core.Items;
using ACSE.Core.Utilities;
using ACSE.WinForms.Imaging;
namespace ACSE namespace ACSE.WinForms.Controls
{ {
internal sealed class FurnitureItemEditor : ItemEditor internal sealed class FurnitureItemEditor : ItemEditor
{ {
@ -70,7 +73,7 @@ protected override void OnEditorMouseDown(object sender, MouseEventArgs e)
break; break;
case MouseButtons.Middle: case MouseButtons.Middle:
var tempItems = (Furniture[]) Items; var tempItems = (Furniture[]) Items;
Utilities.Utility.FloodFillFurnitureArray(ref tempItems, ItemsPerRow, index, Utility.FloodFillFurnitureArray(ref tempItems, ItemsPerRow, index,
(Furniture) Items[index], new Furniture(MainFormReference.GetCurrentItem())); (Furniture) Items[index], new Furniture(MainFormReference.GetCurrentItem()));
Items = tempItems; Items = tempItems;
break; break;

View file

@ -1,12 +1,15 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Windows.Forms; using System.Windows.Forms;
using ACSE.Core.Housing;
using ACSE.Core.Saves;
using ItemChangedEventArgs = ACSE.Core.Items.ItemChangedEventArgs;
namespace ACSE namespace ACSE.WinForms.Controls
{ {
/// <inheritdoc/> /// <inheritdoc/>
/// <summary> /// <summary>
/// An all-in-one Control for editing <see cref="ACSE.House"/> objects. /// An all-in-one Control for editing <see cref="Core.Housing.House"/> objects.
/// </summary> /// </summary>
internal sealed class HouseControl : FlowLayoutPanel internal sealed class HouseControl : FlowLayoutPanel
{ {

View file

@ -3,8 +3,11 @@
using System.Drawing; using System.Drawing;
using System.Linq; using System.Linq;
using System.Windows.Forms; using System.Windows.Forms;
using ACSE.Core.Items;
using ACSE.Core.Modifiable;
using ACSE.Core.Utilities;
namespace ACSE namespace ACSE.WinForms.Controls
{ {
/// <inheritdoc cref="IModifiable" /> /// <inheritdoc cref="IModifiable" />
/// <summary> /// <summary>
@ -185,7 +188,7 @@ protected virtual void OnEditorMouseDown(object sender, MouseEventArgs e)
MainFormReference.SetCurrentItem(selectedItem); MainFormReference.SetCurrentItem(selectedItem);
break; break;
case MouseButtons.Middle: case MouseButtons.Middle:
Utilities.Utility.FloodFillItemArray(ref _items, ItemsPerRow, index, _items[index], Utility.FloodFillItemArray(ref _items, ItemsPerRow, index, _items[index],
MainFormReference.GetCurrentItem()); MainFormReference.GetCurrentItem());
SetItemPicture(); SetItemPicture();
break; break;

View file

@ -2,7 +2,7 @@
using System.Drawing.Drawing2D; using System.Drawing.Drawing2D;
using System.Windows.Forms; using System.Windows.Forms;
namespace ACSE namespace ACSE.WinForms.Controls
{ {
public enum MaskingType public enum MaskingType
{ {

View file

@ -1,7 +1,7 @@
using System.Drawing.Drawing2D; using System.Drawing.Drawing2D;
using System.Windows.Forms; using System.Windows.Forms;
namespace ACSE namespace ACSE.WinForms.Controls
{ {
/// <inheritdoc /> /// <inheritdoc />
/// <summary> /// <summary>

View file

@ -1,8 +1,9 @@
using System.Windows.Forms; using System.Windows.Forms;
using ACSE.Core.Items;
namespace ACSE namespace ACSE.WinForms.Controls
{ {
class ShopEditorControl : Panel public class ShopEditorControl : Panel
{ {
protected ItemEditor ShopEditor; protected ItemEditor ShopEditor;
protected Label ShopLabel; protected Label ShopLabel;

View file

@ -1,4 +1,4 @@
namespace ACSE namespace ACSE.WinForms.Controls
{ {
partial class SingleItemEditor partial class SingleItemEditor
{ {

View file

@ -3,8 +3,11 @@
using System.Drawing; using System.Drawing;
using System.Linq; using System.Linq;
using System.Windows.Forms; using System.Windows.Forms;
using ACSE.Core.Items;
using ACSE.Core.Modifiable;
using ItemChangedEventArgs = ACSE.Core.Items.ItemChangedEventArgs;
namespace ACSE namespace ACSE.WinForms.Controls
{ {
/// <inheritdoc cref="IModifiable" /> /// <inheritdoc cref="IModifiable" />
/// <summary> /// <summary>

View file

@ -2,8 +2,10 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Windows.Forms; using System.Windows.Forms;
using ACSE.Core.Encryption;
using ACSE.Core.Saves;
namespace ACSE namespace ACSE.WinForms.Controls
{ {
internal sealed class StalkMarketEditor : FlowLayoutPanel internal sealed class StalkMarketEditor : FlowLayoutPanel
{ {

View file

@ -3,9 +3,14 @@
using System.Drawing; using System.Drawing;
using System.Linq; using System.Linq;
using System.Windows.Forms; using System.Windows.Forms;
using ACSE.Utilities; using ACSE.Core;
using ACSE.Core.Items;
using ACSE.Core.Saves;
using ACSE.Core.Utilities;
using ACSE.Core.Villagers;
using ItemChangedEventArgs = ACSE.Core.Items.ItemChangedEventArgs;
namespace ACSE.Controls namespace ACSE.WinForms.Controls
{ {
/// <inheritdoc/> /// <inheritdoc/>
/// <summary> /// <summary>
@ -261,9 +266,11 @@ private void VillagerSelectionBoxChanged()
else else
{ {
// TODO: Update islander house location. In e+, update all four islander house locations. // TODO: Update islander house location. In e+, update all four islander house locations.
// TODO: Remove the static reference to MainForm.TownAcres.
if (_saveFile.SaveGeneration != SaveGeneration.GCN || _villager.Index < 15) if (_saveFile.SaveGeneration != SaveGeneration.GCN || _villager.Index < 15)
{ {
var houseCoordinatesInfo = Utility.Find_Villager_House(_villager.Data.VillagerId); var houseCoordinatesInfo =
Utility.FindVillagerHouse(_villager.Data.VillagerId, MainForm.TownAcres);
_villager.Data.HouseCoordinates = houseCoordinatesInfo.Item1; _villager.Data.HouseCoordinates = houseCoordinatesInfo.Item1;
if (!houseCoordinatesInfo.Item2) if (!houseCoordinatesInfo.Item2)
{ {
@ -281,7 +288,8 @@ private void VillagerSelectionBoxChanged()
} }
else else
{ {
var (houseCoordinates, found) = Utility.FindVillagerHouseWildWorld(_villager.Index); var (houseCoordinates, found) =
Utility.FindVillagerHouseWildWorld(_villager.Index, MainForm.TownAcres);
_villager.Data.HouseCoordinates = houseCoordinates; _villager.Data.HouseCoordinates = houseCoordinates;
if (!found) if (!found)
{ {

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Weavers>
<Costura />
</Weavers>

View file

@ -6,8 +6,15 @@
using System.Drawing.Imaging; using System.Drawing.Imaging;
using System.Windows.Forms; using System.Windows.Forms;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using ACSE.Core.Buildings;
using ACSE.Core.Debug;
using ACSE.Core.Items;
using ACSE.Core.Players;
using ACSE.Core.Saves;
using ACSE.Core.Villagers;
using ACSE.WinForms.Controls;
namespace ACSE namespace ACSE.WinForms.Imaging
{ {
public static class ImageGeneration public static class ImageGeneration
{ {
@ -51,6 +58,22 @@ private static void ReplaceGrayscaleColor(ref Bitmap editingImage, Color replaci
} }
} }
public static Image SetImageColor(Image grayscaleImage, ColorMatrix transformMatrix)
{
using (var attributes = new ImageAttributes())
{
attributes.SetColorMatrix(transformMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
var transformedImage = new Bitmap(grayscaleImage.Width, grayscaleImage.Height);
using (var g = Graphics.FromImage(transformedImage))
{
g.DrawImage(grayscaleImage, 0, 0);
g.DrawImage(transformedImage, new Rectangle(0, 0, grayscaleImage.Size.Width, grayscaleImage.Size.Height),
0, 0, grayscaleImage.Size.Width, grayscaleImage.Size.Height, GraphicsUnit.Pixel, attributes);
return transformedImage;
}
}
}
public static void DrawBuriedIcons(Bitmap map, WorldItem[] items, int itemSize) public static void DrawBuriedIcons(Bitmap map, WorldItem[] items, int itemSize)
{ {
using (var bitmapGraphics = Graphics.FromImage(map)) using (var bitmapGraphics = Graphics.FromImage(map))

View file

@ -1,4 +1,4 @@
namespace ACSE namespace ACSE.WinForms
{ {
partial class ItemColorEditor partial class ItemColorEditor
{ {

View file

@ -1,8 +1,10 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Configuration;
using System.Drawing; using System.Drawing;
using System.Windows.Forms; using System.Windows.Forms;
using ACSE.Core.Items;
namespace ACSE namespace ACSE.WinForms
{ {
public partial class ItemColorEditor : Form public partial class ItemColorEditor : Form
{ {
@ -11,6 +13,7 @@ public partial class ItemColorEditor : Form
public ItemColorEditor() public ItemColorEditor()
{ {
InitializeComponent(); InitializeComponent();
UpdateItemColors(); // Initialize at the start
CreateEditorControls(); CreateEditorControls();
} }
@ -109,9 +112,23 @@ private static void SetColor(Control colorPreview, uint newColor)
colorPreview.BackColor = Color.FromArgb((int)newColor); colorPreview.BackColor = Color.FromArgb((int)newColor);
} }
// TODO: I don't like this at all. Come up with a better way. Possibly expose the colors from ACSE.Core instead.
public static void UpdateItemColors()
{
var database = new Dictionary<string, uint>();
foreach (SettingsProperty prop in ItemColorSettings.Default.Properties)
{
database.Add(prop.Name, (uint) ItemColorSettings.Default[prop.Name]);
}
ItemData.ItemColorsSettings = database;
}
private void Done() private void Done()
{ {
ItemColorSettings.Default.Save(); ItemColorSettings.Default.Save();
UpdateItemColors();
Close(); Close();
Dispose(); Dispose();
} }

View file

@ -0,0 +1,410 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace ACSE {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.7.0.0")]
internal sealed partial class ItemColorSettings : global::System.Configuration.ApplicationSettingsBase {
private static ItemColorSettings defaultInstance = ((ItemColorSettings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new ItemColorSettings())));
public static ItemColorSettings Default {
get {
return defaultInstance;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3359432240")]
public uint FurnitureColor {
get {
return ((uint)(this["FurnitureColor"]));
}
set {
this["FurnitureColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3369370404")]
public uint GyroidColor {
get {
return ((uint)(this["GyroidColor"]));
}
set {
this["GyroidColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3372155007")]
public uint DiaryColor {
get {
return ((uint)(this["DiaryColor"]));
}
set {
this["DiaryColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3358094506")]
public uint ClothesColor {
get {
return ((uint)(this["ClothesColor"]));
}
set {
this["ClothesColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3366251704")]
public uint SongColor {
get {
return ((uint)(this["SongColor"]));
}
set {
this["SongColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3366251752")]
public uint PaperColor {
get {
return ((uint)(this["PaperColor"]));
}
set {
this["PaperColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3361041199")]
public uint TrashColor {
get {
return ((uint)(this["TrashColor"]));
}
set {
this["TrashColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3372204235")]
public uint ShellColor {
get {
return ((uint)(this["ShellColor"]));
}
set {
this["ShellColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3369967837")]
public uint FruitColor {
get {
return ((uint)(this["FruitColor"]));
}
set {
this["FruitColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3367742621")]
public uint TurnipColor {
get {
return ((uint)(this["TurnipColor"]));
}
set {
this["TurnipColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3367691070")]
public uint CatchableColor {
get {
return ((uint)(this["CatchableColor"]));
}
set {
this["CatchableColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3367876459")]
public uint QuestItemColor {
get {
return ((uint)(this["QuestItemColor"]));
}
set {
this["QuestItemColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3372197120")]
public uint ItemColor {
get {
return ((uint)(this["ItemColor"]));
}
set {
this["ItemColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3357446399")]
public uint RaffleTicketColor {
get {
return ((uint)(this["RaffleTicketColor"]));
}
set {
this["RaffleTicketColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3365486656")]
public uint WallpaperCarpetColor {
get {
return ((uint)(this["WallpaperCarpetColor"]));
}
set {
this["WallpaperCarpetColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3360767279")]
public uint FossilColor {
get {
return ((uint)(this["FossilColor"]));
}
set {
this["FossilColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3363930497")]
public uint ToolColor {
get {
return ((uint)(this["ToolColor"]));
}
set {
this["ToolColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3364570387")]
public uint TreeColor {
get {
return ((uint)(this["TreeColor"]));
}
set {
this["TreeColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3355475968")]
public uint WeedColor {
get {
return ((uint)(this["WeedColor"]));
}
set {
this["WeedColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3370936248")]
public uint FlowerColor {
get {
return ((uint)(this["FlowerColor"]));
}
set {
this["FlowerColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3355443200")]
public uint RockColor {
get {
return ((uint)(this["RockColor"]));
}
set {
this["RockColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3366137647")]
public uint MoneyRockColor {
get {
return ((uint)(this["MoneyRockColor"]));
}
set {
this["MoneyRockColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3362140928")]
public uint SignboardColor {
get {
return ((uint)(this["SignboardColor"]));
}
set {
this["SignboardColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3372220160")]
public uint MoneyColor {
get {
return ((uint)(this["MoneyColor"]));
}
set {
this["MoneyColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3366295701")]
public uint HouseObjectColor {
get {
return ((uint)(this["HouseObjectColor"]));
}
set {
this["HouseObjectColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("4286019447")]
public uint BuildingColor {
get {
return ((uint)(this["BuildingColor"]));
}
set {
this["BuildingColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3366151936")]
public uint ParchedFlowerColor {
get {
return ((uint)(this["ParchedFlowerColor"]));
}
set {
this["ParchedFlowerColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3355484320")]
public uint WateredFlowerColor {
get {
return ((uint)(this["WateredFlowerColor"]));
}
set {
this["WateredFlowerColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3365509631")]
public uint PatternColor {
get {
return ((uint)(this["PatternColor"]));
}
set {
this["PatternColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3360509235")]
public uint WiltedFlowerColor {
get {
return ((uint)(this["WiltedFlowerColor"]));
}
set {
this["WiltedFlowerColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3717831065")]
public uint OccupiedColor {
get {
return ((uint)(this["OccupiedColor"]));
}
set {
this["OccupiedColor"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3372154880")]
public uint InvalidColor {
get {
return ((uint)(this["InvalidColor"]));
}
set {
this["InvalidColor"] = value;
}
}
}
}

View file

@ -0,0 +1,102 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="ACSE" GeneratedClassName="ItemColorSettings">
<Profiles />
<Settings>
<Setting Name="FurnitureColor" Type="System.UInt32" Scope="User">
<Value Profile="(Default)">3359432240</Value>
</Setting>
<Setting Name="GyroidColor" Type="System.UInt32" Scope="User">
<Value Profile="(Default)">3369370404</Value>
</Setting>
<Setting Name="DiaryColor" Type="System.UInt32" Scope="User">
<Value Profile="(Default)">3372155007</Value>
</Setting>
<Setting Name="ClothesColor" Type="System.UInt32" Scope="User">
<Value Profile="(Default)">3358094506</Value>
</Setting>
<Setting Name="SongColor" Type="System.UInt32" Scope="User">
<Value Profile="(Default)">3366251704</Value>
</Setting>
<Setting Name="PaperColor" Type="System.UInt32" Scope="User">
<Value Profile="(Default)">3366251752</Value>
</Setting>
<Setting Name="TrashColor" Type="System.UInt32" Scope="User">
<Value Profile="(Default)">3361041199</Value>
</Setting>
<Setting Name="ShellColor" Type="System.UInt32" Scope="User">
<Value Profile="(Default)">3372204235</Value>
</Setting>
<Setting Name="FruitColor" Type="System.UInt32" Scope="User">
<Value Profile="(Default)">3369967837</Value>
</Setting>
<Setting Name="TurnipColor" Type="System.UInt32" Scope="User">
<Value Profile="(Default)">3367742621</Value>
</Setting>
<Setting Name="CatchableColor" Type="System.UInt32" Scope="User">
<Value Profile="(Default)">3367691070</Value>
</Setting>
<Setting Name="QuestItemColor" Type="System.UInt32" Scope="User">
<Value Profile="(Default)">3367876459</Value>
</Setting>
<Setting Name="ItemColor" Type="System.UInt32" Scope="User">
<Value Profile="(Default)">3372197120</Value>
</Setting>
<Setting Name="RaffleTicketColor" Type="System.UInt32" Scope="User">
<Value Profile="(Default)">3357446399</Value>
</Setting>
<Setting Name="WallpaperCarpetColor" Type="System.UInt32" Scope="User">
<Value Profile="(Default)">3365486656</Value>
</Setting>
<Setting Name="FossilColor" Type="System.UInt32" Scope="User">
<Value Profile="(Default)">3360767279</Value>
</Setting>
<Setting Name="ToolColor" Type="System.UInt32" Scope="User">
<Value Profile="(Default)">3363930497</Value>
</Setting>
<Setting Name="TreeColor" Type="System.UInt32" Scope="User">
<Value Profile="(Default)">3364570387</Value>
</Setting>
<Setting Name="WeedColor" Type="System.UInt32" Scope="User">
<Value Profile="(Default)">3355475968</Value>
</Setting>
<Setting Name="FlowerColor" Type="System.UInt32" Scope="User">
<Value Profile="(Default)">3370936248</Value>
</Setting>
<Setting Name="RockColor" Type="System.UInt32" Scope="User">
<Value Profile="(Default)">3355443200</Value>
</Setting>
<Setting Name="MoneyRockColor" Type="System.UInt32" Scope="User">
<Value Profile="(Default)">3366137647</Value>
</Setting>
<Setting Name="SignboardColor" Type="System.UInt32" Scope="User">
<Value Profile="(Default)">3362140928</Value>
</Setting>
<Setting Name="MoneyColor" Type="System.UInt32" Scope="User">
<Value Profile="(Default)">3372220160</Value>
</Setting>
<Setting Name="HouseObjectColor" Type="System.UInt32" Scope="User">
<Value Profile="(Default)">3366295701</Value>
</Setting>
<Setting Name="BuildingColor" Type="System.UInt32" Scope="User">
<Value Profile="(Default)">4286019447</Value>
</Setting>
<Setting Name="ParchedFlowerColor" Type="System.UInt32" Scope="User">
<Value Profile="(Default)">3366151936</Value>
</Setting>
<Setting Name="WateredFlowerColor" Type="System.UInt32" Scope="User">
<Value Profile="(Default)">3355484320</Value>
</Setting>
<Setting Name="PatternColor" Type="System.UInt32" Scope="User">
<Value Profile="(Default)">3365509631</Value>
</Setting>
<Setting Name="WiltedFlowerColor" Type="System.UInt32" Scope="User">
<Value Profile="(Default)">3360509235</Value>
</Setting>
<Setting Name="OccupiedColor" Type="System.UInt32" Scope="User">
<Value Profile="(Default)">3717831065</Value>
</Setting>
<Setting Name="InvalidColor" Type="System.UInt32" Scope="User">
<Value Profile="(Default)">3372154880</Value>
</Setting>
</Settings>
</SettingsFile>

View file

@ -1,4 +1,6 @@
namespace ACSE using ACSE.WinForms.Controls;
namespace ACSE.WinForms
{ {
sealed partial class MainForm sealed partial class MainForm
{ {
@ -37,7 +39,7 @@ private void InitializeComponent()
this.palettePreviousButton = new System.Windows.Forms.Button(); this.palettePreviousButton = new System.Windows.Forms.Button();
this.paletteNextButton = new System.Windows.Forms.Button(); this.paletteNextButton = new System.Windows.Forms.Button();
this.patternEditorPanel = new System.Windows.Forms.Panel(); this.patternEditorPanel = new System.Windows.Forms.Panel();
this.patternEditorPictureBox = new ACSE.PictureBoxWithInterpolationMode(); this.patternEditorPictureBox = new PictureBoxWithInterpolationMode();
this.patternEditorPreviewPanel = new System.Windows.Forms.Panel(); this.patternEditorPreviewPanel = new System.Windows.Forms.Panel();
this.patternGroupTabControl = new System.Windows.Forms.TabControl(); this.patternGroupTabControl = new System.Windows.Forms.TabControl();
this.player1Tab = new System.Windows.Forms.TabPage(); this.player1Tab = new System.Windows.Forms.TabPage();
@ -344,7 +346,7 @@ private void InitializeComponent()
// paletteColorSelectedPictureBox // paletteColorSelectedPictureBox
// //
this.paletteColorSelectedPictureBox.Anchor = System.Windows.Forms.AnchorStyles.None; this.paletteColorSelectedPictureBox.Anchor = System.Windows.Forms.AnchorStyles.None;
this.paletteColorSelectedPictureBox.Image = global::ACSE.Properties.Resources.PaletteArrow; this.paletteColorSelectedPictureBox.Image = global::ACSE.WinForms.Properties.Resources.PaletteArrow;
this.paletteColorSelectedPictureBox.Location = new System.Drawing.Point(114, 21); this.paletteColorSelectedPictureBox.Location = new System.Drawing.Point(114, 21);
this.paletteColorSelectedPictureBox.Name = "paletteColorSelectedPictureBox"; this.paletteColorSelectedPictureBox.Name = "paletteColorSelectedPictureBox";
this.paletteColorSelectedPictureBox.Size = new System.Drawing.Size(16, 32); this.paletteColorSelectedPictureBox.Size = new System.Drawing.Size(16, 32);
@ -975,7 +977,7 @@ private void InitializeComponent()
this.clearEncylopediaButton.TabIndex = 5; this.clearEncylopediaButton.TabIndex = 5;
this.clearEncylopediaButton.Text = "Clear Encyclopedia"; this.clearEncylopediaButton.Text = "Clear Encyclopedia";
this.clearEncylopediaButton.UseVisualStyleBackColor = true; this.clearEncylopediaButton.UseVisualStyleBackColor = true;
this.clearEncylopediaButton.Click += new System.EventHandler(this.ClearEncylopediaButtonClick); this.clearEncylopediaButton.Click += new System.EventHandler(this.ClearEncyclopediaButtonClick);
// //
// fillEncyclopediaButton // fillEncyclopediaButton
// //

File diff suppressed because it is too large Load diff

View file

@ -1,13 +1,15 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Drawing; using System.Drawing;
using System.Globalization; using System.Globalization;
using System.IO;
using System.Linq;
using ACSE.Core.Saves;
using ACSE.Core.Utilities;
using ACSE.WinForms.Controls;
namespace ACSE namespace ACSE.WinForms.Managers
{ {
// TODO: Check if any references to the Image exist, and if not, dispose of them. public static class AcreImageManager
public static class AcreData
{ {
private static Dictionary<ushort, Image> _loadedImageDictionary = new Dictionary<ushort, Image>(); private static Dictionary<ushort, Image> _loadedImageDictionary = new Dictionary<ushort, Image>();
private static Dictionary<byte, Image> _loadedAnimalCrossingMapIcons = new Dictionary<byte, Image>(); private static Dictionary<byte, Image> _loadedAnimalCrossingMapIcons = new Dictionary<byte, Image>();
@ -34,7 +36,7 @@ public static Image FetchAcreImage(SaveType saveType, ushort acreId)
Image result = null; Image result = null;
var imageDir = MainForm.AssemblyLocation + "\\Resources\\Images\\"; var imageDir = Path.Combine(PathUtility.GetResourcesDirectory(), "Images");
switch (saveType) switch (saveType)
{ {
case SaveType.DoubutsuNoMori: case SaveType.DoubutsuNoMori:
@ -44,19 +46,19 @@ public static Image FetchAcreImage(SaveType saveType, ushort acreId)
case SaveType.AnimalForestEPlus: case SaveType.AnimalForestEPlus:
// TODO: DnM needs its own set? // TODO: DnM needs its own set?
case SaveType.DongwuSenlin: case SaveType.DongwuSenlin:
imageDir += "Acre_Images"; imageDir = Path.Combine(imageDir, "Acre_Images");
break; break;
case SaveType.WildWorld: case SaveType.WildWorld:
imageDir += "WW_Acre_Images"; imageDir = Path.Combine(imageDir, "WW_Acre_Images");
break; break;
case SaveType.CityFolk: case SaveType.CityFolk:
imageDir += "CF_Acre_Images"; imageDir = Path.Combine(imageDir, "CF_Acre_Images");
break; break;
case SaveType.NewLeaf: case SaveType.NewLeaf:
imageDir += "NL_Acre_Images"; imageDir = Path.Combine(imageDir, "NL_Acre_Images");
break; break;
case SaveType.WelcomeAmiibo: case SaveType.WelcomeAmiibo:
imageDir += "WA_Acre_Images"; imageDir = Path.Combine(imageDir, "WA_Acre_Images");
break; break;
default: default:
return null; return null;
@ -110,7 +112,7 @@ public static Image FetchAcMapIcon(byte index)
Image result = null; Image result = null;
var iconDirectory = MainForm.AssemblyLocation + "\\Resources\\Images\\AC_Map_Icons"; var iconDirectory = Path.Combine(PathUtility.GetResourcesDirectory(), "Images", "AC_Map_Icons");
if (Directory.Exists(iconDirectory)) if (Directory.Exists(iconDirectory))
{ {
foreach (var iconFile in Directory.GetFiles(iconDirectory)) foreach (var iconFile in Directory.GetFiles(iconDirectory))
@ -134,10 +136,12 @@ public static Image FetchAcMapIcon(byte index)
return result; return result;
} }
public static void CheckReferencesAndDispose(Image referencedImage, PictureBoxWithInterpolationMode[] pictureBoxes, PictureBoxWithInterpolationMode selectedAcreBox) public static void CheckReferencesAndDispose(Image referencedImage,
PictureBoxWithInterpolationMode[] pictureBoxes, PictureBoxWithInterpolationMode selectedAcreBox)
{ {
if (referencedImage == null || selectedAcreBox.Image == referencedImage if (referencedImage == null || selectedAcreBox.Image == referencedImage
|| pictureBoxes.Any(box => box != null && box.BackgroundImage == referencedImage)) return; || pictureBoxes.Any(
box => box != null && box.BackgroundImage == referencedImage)) return;
foreach (var pair in _loadedImageDictionary) foreach (var pair in _loadedImageDictionary)
if (pair.Value == referencedImage) if (pair.Value == referencedImage)
@ -172,20 +176,20 @@ public static void DisposeLoadedImages()
_loadedAnimalCrossingMapIcons = new Dictionary<byte, Image>(); _loadedAnimalCrossingMapIcons = new Dictionary<byte, Image>();
} }
public static Dictionary<ushort, byte> Load_AC_Map_Index(SaveType saveType) public static Dictionary<ushort, byte> LoadAcMapIndex(SaveType saveType)
{ {
var indexFile = MainForm.AssemblyLocation; var indexFile = PathUtility.GetResourcesDirectory();
switch (saveType) switch (saveType)
{ {
case SaveType.DoubutsuNoMori: case SaveType.DoubutsuNoMori:
case SaveType.DoubutsuNoMoriPlus: case SaveType.DoubutsuNoMoriPlus:
case SaveType.DongwuSenlin: case SaveType.DongwuSenlin:
indexFile += "\\Resources\\DnM_Map_Icon_Index.txt"; indexFile = Path.Combine(indexFile, "DnM_Map_Icon_Index.txt");
break; break;
case SaveType.AnimalCrossing: case SaveType.AnimalCrossing:
case SaveType.DoubutsuNoMoriEPlus: case SaveType.DoubutsuNoMoriEPlus:
case SaveType.AnimalForestEPlus: case SaveType.AnimalForestEPlus:
indexFile += "\\Resources\\AC_Map_Icon_Index.txt"; indexFile = Path.Combine(indexFile, "AC_Map_Icon_Index.txt");
break; break;
} }
@ -200,7 +204,9 @@ public static Dictionary<ushort, byte> Load_AC_Map_Index(SaveType saveType)
{ {
if (!line.Contains("0x")) continue; if (!line.Contains("0x")) continue;
string acreIdStr = line.Substring(0, 6).Replace("0x", ""), indexStr = line.Substring(7).Trim(); string acreIdStr = line.Substring(0, 6).Replace("0x", ""), indexStr = line.Substring(7).Trim();
if (ushort.TryParse(acreIdStr, NumberStyles.AllowHexSpecifier, null, out var acreId) && byte.TryParse(indexStr, out var index))
if (ushort.TryParse(acreIdStr, NumberStyles.AllowHexSpecifier, null, out var acreId) &&
byte.TryParse(indexStr, out var index))
{ {
iconIndex.Add(acreId, index); iconIndex.Add(acreId, index);
} }

View file

@ -1,7 +1,10 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
namespace ACSE namespace ACSE.WinForms
{ {
static class Program static class Program
{ {
@ -13,8 +16,7 @@ static void Main()
{ {
Application.EnableVisualStyles(); Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false); Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm()); Application.Run(new MainForm());
} }
} }
} }

View file

@ -2,7 +2,7 @@
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following // General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information // set of attributes. Change these attribute values to modify the information
// associated with an assembly. // associated with an assembly.
[assembly: AssemblyTitle("ACSE")] [assembly: AssemblyTitle("ACSE")]
@ -14,25 +14,23 @@
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible // Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from // to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type. // COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)] [assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM // The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("52b2adb4-812e-4b42-9955-9e8f1f14dbea")] [assembly: Guid("b4a73545-0177-4159-8602-648aa3058650")]
// Version information for an assembly consists of the following four values: // Version information for an assembly consists of the following four values:
// //
// Major Version // Major Version
// Minor Version // Minor Version
// Build Number // Build Number
// Revision // Revision
// //
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.4.1.0")] [assembly: AssemblyVersion("0.4.1.0")]
[assembly: AssemblyFileVersion("0.4.1.0")] [assembly: AssemblyFileVersion("0.4.1.0")]
[assembly: InternalsVisibleTo("ACSE.Tests")]

Some files were not shown because too many files have changed in this diff Show more