mhsec-g/MHSEC-G/MHSEC-G/Item.cs

146 lines
5.2 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Windows;
using MHSEC_G.Annotations;
namespace MHSEC_G
{
public class Item : INotifyPropertyChanged
{
private static readonly uint OFFSETA_ITEM_BOX = 0x10;
private static readonly uint SIZE_ITEM = 0x8;
private static readonly uint OFFSETR_ITEM_ID = 0x0;
private static readonly uint OFFSETR_ITEM_COUNT = 0x2;
private static readonly uint OFFSETA_ITEM_BOX_END = 0x2EE7;
public static readonly uint OFFSETA_FIRST_KEY_ITEM = 0x17B0;
private static readonly Dictionary<uint, uint> OFFSET_ID_MAPPING = new Dictionary<uint, uint>();
private static readonly Dictionary<uint, string> OFFSET_NAME_MAPPING = new Dictionary<uint, string>();
private readonly uint _offset;
public uint offset
{
get { return _offset; }
}
private readonly Model _model;
public string name
{
get {
string name = _offset >= OFFSETA_FIRST_KEY_ITEM ? "Key Item [" + id.ToString("X4") + "]" : "Unknown";
if (OFFSET_NAME_MAPPING.ContainsKey(_offset))
{
name = OFFSET_NAME_MAPPING[_offset];
}
return name;
}
}
public uint count
{
get { return Model.byte_to_uint16_le(_model.save_file, _offset + OFFSETR_ITEM_COUNT); }
set
{
if (value <= 999)
{
Model.write_uint16_le(_model.save_file, _offset + OFFSETR_ITEM_COUNT, value);
}
else
{
MessageBox.Show("Quantity must be less than 999.","Error",MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(count));
}
}
public uint id
{
get { return Model.byte_to_uint16_le(_model.save_file, _offset + OFFSETR_ITEM_ID); }
}
public Item(uint offset, Model model)
{
_offset = offset;
_model = model;
}
public static List<Item> read_all_items(Model model)
{
byte[] buffer = model.save_file;
List<Item> ret = new List<Item>();
for (uint offset = OFFSETA_ITEM_BOX; offset < OFFSETA_ITEM_BOX_END; offset += SIZE_ITEM)
{
uint item_id = Model.byte_to_uint16_le(buffer, offset + OFFSETR_ITEM_ID);
if (item_id == 0)
{
// if not obtained yet
if (!OFFSET_ID_MAPPING.ContainsKey(offset))
{
// well we dont know the id to this offset either. just ignore!
// continue
continue;
}
// if we know the id to the offset, just set it
Model.write_uint16_le(model.save_file, offset + OFFSETR_ITEM_ID, OFFSET_ID_MAPPING[offset]);
}
else
{
// already obtained
// validate
if (OFFSET_ID_MAPPING.ContainsKey(offset))
{
if (item_id != OFFSET_ID_MAPPING[offset])
{
// correct to the correct id
// don't bug_check since too many people's files are broken
// TODO: BugCheck.bug_check(BugCheck.ErrorCode.ITEM_NO_CORRESPONDENCE, "Item offset " + offset.ToString("X") + " and item ID " + item_id.ToString("X") + " do not correspond.");
Model.write_uint16_le(model.save_file, offset + OFFSETR_ITEM_ID, OFFSET_ID_MAPPING[offset]);
}
}
}
// valid offset
ret.Add(new Item(offset, model));
}
return ret;
}
public static void read_item_mappings()
{
string line;
StringReader file = new StringReader(Properties.Resources.idmap);
while ((line = file.ReadLine()) != null)
{
if (line.Length == 0)
continue;
string[] eachline = line.Split('\t');
if (eachline.Length != 3)
{
BugCheck.bug_check(BugCheck.ErrorCode.ITEM_MAPPING_CORRUPTED, "Invalid mapping file line:\n" + line);
}
OFFSET_ID_MAPPING.Add(uint.Parse(eachline[0], System.Globalization.NumberStyles.HexNumber), uint.Parse(eachline[1], System.Globalization.NumberStyles.HexNumber));
OFFSET_NAME_MAPPING.Add(uint.Parse(eachline[0], System.Globalization.NumberStyles.HexNumber), eachline[2]);
}
file.Close();
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}