diff --git a/PortableTerrariaCommon/PortableTerrariaCommon.sln b/PortableTerrariaCommon/PortableTerrariaCommon.sln
new file mode 100644
index 0000000..f6cb3aa
--- /dev/null
+++ b/PortableTerrariaCommon/PortableTerrariaCommon.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.32228.343
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PortableTerrariaCommon", "PortableTerrariaCommon\PortableTerrariaCommon.csproj", "{AFB76C63-9158-4CE9-8CFB-21DF06EE8FB9}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {AFB76C63-9158-4CE9-8CFB-21DF06EE8FB9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AFB76C63-9158-4CE9-8CFB-21DF06EE8FB9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AFB76C63-9158-4CE9-8CFB-21DF06EE8FB9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AFB76C63-9158-4CE9-8CFB-21DF06EE8FB9}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {80AFC25F-AA34-428B-99E1-4C59C70D4FA5}
+ EndGlobalSection
+EndGlobal
diff --git a/PortableTerrariaCommon/PortableTerrariaCommon/App.config b/PortableTerrariaCommon/PortableTerrariaCommon/App.config
new file mode 100644
index 0000000..56efbc7
--- /dev/null
+++ b/PortableTerrariaCommon/PortableTerrariaCommon/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/PortableTerrariaCommon/PortableTerrariaCommon/AtomicObj.cs b/PortableTerrariaCommon/PortableTerrariaCommon/AtomicObj.cs
new file mode 100644
index 0000000..32944b9
--- /dev/null
+++ b/PortableTerrariaCommon/PortableTerrariaCommon/AtomicObj.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Sahlaysta.PortableTerrariaCommon
+{
+ //thread safe atomic obj
+ class AtomicObj
+ {
+ //constructor
+ public AtomicObj(T obj = default)
+ {
+ val = obj;
+ }
+
+ //public operations
+ public T Value
+ {
+ get
+ {
+ lock (objLock)
+ {
+ return (T)val;
+ }
+ }
+ set
+ {
+ lock (objLock)
+ {
+ val = value;
+ }
+ }
+ }
+
+ volatile object val;
+ readonly object objLock = new object();
+ }
+}
diff --git a/PortableTerrariaCommon/PortableTerrariaCommon/DotNetZip.dll b/PortableTerrariaCommon/PortableTerrariaCommon/DotNetZip.dll
new file mode 100644
index 0000000..e4dd8a2
Binary files /dev/null and b/PortableTerrariaCommon/PortableTerrariaCommon/DotNetZip.dll differ
diff --git a/PortableTerrariaCommon/PortableTerrariaCommon/DotNetZipAssembly.cs b/PortableTerrariaCommon/PortableTerrariaCommon/DotNetZipAssembly.cs
new file mode 100644
index 0000000..4cb9f76
--- /dev/null
+++ b/PortableTerrariaCommon/PortableTerrariaCommon/DotNetZipAssembly.cs
@@ -0,0 +1,265 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Sahlaysta.PortableTerrariaCommon
+{
+ // DotNetZip assembly reflection class
+ static class DotNetZipAssembly
+ {
+ //reflection ZipFile
+ public class ZipFile : IEnumerable, IDisposable
+ {
+ //reflection enumerator
+ class ZipEntryEnumerator : IEnumerator
+ {
+ //reflection constructor
+ public ZipEntryEnumerator(IEnumerator enumerator)
+ {
+ ie = enumerator;
+ }
+
+ //interface operations
+ ZipEntry IEnumerator.Current => getCurrent();
+ object IEnumerator.Current => getCurrent();
+ void IDisposable.Dispose() => ((IDisposable)ie).Dispose();
+ bool IEnumerator.MoveNext()
+ {
+ bool result = ie.MoveNext();
+ if (result)
+ current = null;
+ return result;
+ }
+ void IEnumerator.Reset()
+ {
+ ie.Reset();
+ current = null;
+ }
+
+ ZipEntry getCurrent()
+ {
+ return current ?? (current = new ZipEntry(ie.Current));
+ }
+
+ readonly IEnumerator ie;
+ ZipEntry current;
+ }
+
+ //reflection constructor
+ public ZipFile() : this(
+ (IDisposable)rZipFileConstr.Invoke(null)) { }
+ ZipFile(IDisposable instance)
+ {
+ this.instance = instance;
+ addSaveProgressEventHandler(invokeSaveProgress);
+ }
+ public static ZipFile Read(Stream arg0)
+ {
+ return new ZipFile(
+ (IDisposable)rRead.Invoke(null, new object[] { arg0 }));
+ }
+
+ //reflection event
+ public event EventHandler SaveProgress;
+
+ //public reflection operations
+ public int Count
+ {
+ get => (int)rCount.GetValue(instance);
+ }
+ public void AddFile(string arg0)
+ {
+ rAddFile.Invoke(instance, new object[] { arg0 });
+ }
+ public void AddFile(string arg0, string arg1)
+ {
+ rAddFile2.Invoke(instance, new object[] { arg0, arg1 });
+ }
+ public void AddDirectory(string arg0)
+ {
+ rAddDirectory.Invoke(instance, new object[] { arg0 });
+ }
+ public void AddDirectory(string arg0, string arg1)
+ {
+ rAddDirectory2.Invoke(instance, new object[] { arg0, arg1 });
+ }
+ public void Save(Stream arg0)
+ {
+ rSave.Invoke(instance, new object[] { arg0 });
+ }
+ public IEnumerator GetEnumerator()
+ {
+ return getEnumerator();
+ }
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return getEnumerator();
+ }
+ public void Dispose()
+ {
+ instance.Dispose();
+ }
+
+ //reflection SaveProgress event
+ void addSaveProgressEventHandler(EventHandler eh)
+ {
+ var d = (Delegate)
+ rSaveProgressConstr.Invoke(new object[]
+ {
+ eh.Target,
+ eh.Method.MethodHandle.GetFunctionPointer()
+ });
+ rSaveProgress.AddEventHandler(instance, d);
+ }
+ void invokeSaveProgress(object sender, EventArgs e)
+ {
+ var eh = SaveProgress;
+ if (eh == null || eh.GetInvocationList().Length == 0)
+ return;
+
+ eh.Invoke(sender, new SaveProgressEventArgs(e));
+ }
+
+ IEnumerator getEnumerator()
+ {
+ IEnumerator ie = (IEnumerator)
+ rEnumerator.Invoke(instance, null);
+ return new ZipEntryEnumerator(ie);
+ }
+
+ readonly IDisposable instance;
+ }
+
+ //reflection ZipEntry
+ public class ZipEntry
+ {
+ //reflection constructor
+ internal ZipEntry(object instance)
+ {
+ this.instance = instance;
+ }
+
+ //public reflection operations
+ public string FileName
+ {
+ get => (string)rFileName.GetValue(instance);
+ }
+ public void Extract(Stream arg0)
+ {
+ rExtract.Invoke(instance, new object[] { arg0 });
+ }
+
+ readonly object instance;
+ }
+
+ //reflection SaveProgressEventArgs
+ public class SaveProgressEventArgs : EventArgs
+ {
+ //reflection constructor
+ internal SaveProgressEventArgs(EventArgs e)
+ {
+ this.e = e;
+ }
+
+ //public reflection operations
+ public bool Cancel
+ {
+ get => (bool)rCancel.GetValue(e);
+ set => rCancel.SetValue(e, value);
+ }
+ public bool EventTypeIsSaving_AfterWriteEntry
+ {
+ get => rEventType.GetValue(e)
+ .Equals(rSaving_AfterWriteEntry);
+ }
+ public int EntriesSaved
+ {
+ get => (int)rEntriesSaved.GetValue(e);
+ }
+ public int EntriesTotal
+ {
+ get => (int)rEntriesTotal.GetValue(e);
+ }
+
+ readonly EventArgs e;
+ }
+
+ //assembly
+ static readonly Assembly assembly =
+ Assembly.Load(GuiHelper.GetResourceBytes(
+ "DotNetZip.dll"));
+
+ //reflection fields
+ static readonly Type rZipFile =
+ assembly.GetType(
+ "Ionic.Zip.ZipFile");
+ static readonly ConstructorInfo rZipFileConstr =
+ rZipFile.GetConstructors()
+ .First(c => c.GetParameters().Length == 0);
+ static readonly PropertyInfo rCount =
+ rZipFile.GetProperty(
+ "Count");
+ static readonly MethodInfo rRead =
+ rZipFile.GetMethod(
+ "Read",
+ new Type[] { typeof(Stream) });
+ static readonly MethodInfo rAddFile =
+ rZipFile.GetMethod(
+ "AddFile",
+ new Type[] { typeof(string) });
+ static readonly MethodInfo rAddFile2 =
+ rZipFile.GetMethod(
+ "AddFile",
+ new Type[] { typeof(string), typeof(string) });
+ static readonly MethodInfo rAddDirectory =
+ rZipFile.GetMethod(
+ "AddDirectory",
+ new Type[] { typeof(string) });
+ static readonly MethodInfo rAddDirectory2 =
+ rZipFile.GetMethod(
+ "AddDirectory",
+ new Type[] { typeof(string), typeof(string) });
+ static readonly MethodInfo rSave =
+ rZipFile.GetMethod(
+ "Save",
+ new Type[] { typeof(Stream) });
+ static readonly EventInfo rSaveProgress =
+ rZipFile.GetEvent(
+ "SaveProgress");
+ static readonly ConstructorInfo rSaveProgressConstr =
+ rSaveProgress.EventHandlerType.GetConstructor(
+ new Type[] { typeof(object), typeof(IntPtr) });
+ static readonly Type rEnumType =
+ assembly.GetType("Ionic.Zip.ZipProgressEventType");
+ static readonly Type rEventArgsType =
+ assembly.GetType("Ionic.Zip.SaveProgressEventArgs");
+ static readonly object rSaving_AfterWriteEntry =
+ Enum.GetValues(rEnumType).Cast