From b5e259b09f531cdd8d80cd3365a074632e8c9cf6 Mon Sep 17 00:00:00 2001 From: DoctorVanGogh Date: Sun, 17 Sep 2017 00:55:26 +0200 Subject: [PATCH] initial version --- .gitattributes | 2 + .gitignore | 304 ++++++++++++++ About/About.xml | 10 + Assemblies/0Harmony.dll | Bin 0 -> 65536 bytes Assemblies/ModSwitch.dll | Bin 0 -> 13824 bytes Assemblies/harmonycheck.dll | Bin 0 -> 7680 bytes LICENSE | 382 ++++++++++++++++++ README.md | 13 + Source/DEVELOPMENT-SETUP.md | 16 + Source/ModSwitch.sln | 22 + Source/ModSwitch/ModSwitch.cs | 34 ++ Source/ModSwitch/ModSwitch.csproj | 69 ++++ Source/ModSwitch/ModSwitch.csproj.DotSettings | 3 + Source/ModSwitch/Model/ModSet.cs | 73 ++++ Source/ModSwitch/Properties/AssemblyInfo.cs | 36 ++ Source/ModSwitch/Settings.cs | 100 +++++ Source/ModSwitch/Util.cs | 19 + Source/ModSwitch/[Patches]/Patches.cs | 18 + Source/RimworldInstall.props | 26 ++ TODO.md | 9 + 20 files changed, 1136 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 About/About.xml create mode 100644 Assemblies/0Harmony.dll create mode 100644 Assemblies/ModSwitch.dll create mode 100644 Assemblies/harmonycheck.dll create mode 100644 LICENSE create mode 100644 README.md create mode 100644 Source/DEVELOPMENT-SETUP.md create mode 100644 Source/ModSwitch.sln create mode 100644 Source/ModSwitch/ModSwitch.cs create mode 100644 Source/ModSwitch/ModSwitch.csproj create mode 100644 Source/ModSwitch/ModSwitch.csproj.DotSettings create mode 100644 Source/ModSwitch/Model/ModSet.cs create mode 100644 Source/ModSwitch/Properties/AssemblyInfo.cs create mode 100644 Source/ModSwitch/Settings.cs create mode 100644 Source/ModSwitch/Util.cs create mode 100644 Source/ModSwitch/[Patches]/Patches.cs create mode 100644 Source/RimworldInstall.props create mode 100644 TODO.md diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..12dde44 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +.git* export-ignore +Source/ export-ignore \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..702ea6c --- /dev/null +++ b/.gitignore @@ -0,0 +1,304 @@ + +# Created by https://www.gitignore.io/api/visualstudio,visualstudiocode + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +### VisualStudio ### +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ +**/Properties/launchSettings.json + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Typescript v1 declaration files +typings/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# End of https://www.gitignore.io/api/visualstudio,visualstudiocode + +Source\TODO.md +Assemblies\0Reloader.dll diff --git a/About/About.xml b/About/About.xml new file mode 100644 index 0000000..2ee59c5 --- /dev/null +++ b/About/About.xml @@ -0,0 +1,10 @@ + + + ModSwitch + DoctorVanGogh + 0.17.1557 + COMING SOON + DEVELOPMENT VERSION: alpha1 + +Allows loading & saving sets of active mods for Rimworld.]]> + diff --git a/Assemblies/0Harmony.dll b/Assemblies/0Harmony.dll new file mode 100644 index 0000000000000000000000000000000000000000..a95b6df8aa6f4472d514a983bf1b9178a7283bd6 GIT binary patch literal 65536 zcmce<2Y^#m7C(I7d&zsrOPR?`Cdm}005d$2nGqONP!yynBB&_BV5KQV;XyK>5@s9( zv4M&O5gWz6>WW<#MMM!56kTkn*z4-5D;9PYzu!6cC6j>efB*aK_l@Sfd&)ic+;e+* zj}a$cAv7U`3%}of6XH=k>2CnTe-GNh4pu!L6c2j0);y{V-&!+j%G6Z#%%nXzIevQe z#PKs`*e%r)POnbRo>4t@M)lxhj<23>PddFZ5HPzss*fEa#BfCuKi>a(b0)R-Mdxat z(nE+JLGeiHk6}fKYJ{ut6rzyBs zb!C+h!TB4Y2!AI0fAg%)n$EF2z=!6;eFf^Xk|QjQ^^I7}uCgB_{%7 z+hC*6f&9$uEEs^|YD}JfmJLC+6*jXE_GCpk0J(wr6d~Ruzv7QcGeUp*EDW%havTq{?p3BDZ$Vd%-PdJ6fW!gOf9AXP)qS&?5(5+sez7wK?It(QV|8t!x zMBXd#Gn{gJlAUEYLAdQ?7*N{~t!q08fjzoU5qhdO7`5%hv7jOmr!tQrE|8Fg#B|j{ zaVAW?K@G=ss}+>^KxWtnAS#6t@nKR@v*v+q_W?aVA!#ULW;@ufs!8qS(GqrmtXCS> zV<--VO*IW$U0RW_`yyhU-cX!62!RY;w+{vu_UW!7#qLKEMnj?IvQTt7h=zR#Xa?+- zI*}mj^f)>Xr5L2MKLXInbln~R%+YxmNl2YV8Jz<`Gf)>bF%7G!Gf`}mPcWK|T%yktZT5TZ5(qS` z-)Va5b+3&kVZNgq)u&(De9DQj$j#0)%9fjDnoCvS%%BIoT0 z1dunT>-JD!PTr0r38NvH8ioLS>nLLS-4^;EJz#i?RC_qdcp8c{mpg2sA?kj^>#;|G z>WQybQ%57vN+qPG(EpmP}WYqb63vMo5NIe$*^eS6fl-U3!{e#2Seh zKBHkkPJKKL46cu-BCtmfQGGlPVzuqWp%$0W_vis4j{@03{u6tt7?-c2s6z#DGAe?5 zseq5Eo}*FFuoco&`vmAW^~I$q=W_Q z67kp7Hss1>gKV}<$d855TTg+8Sj4elQo<^rSfkYjJv9*=)GkyT(<((1%<4jAFx$Y* zwV;G_p@^Z2I2L+~KhjlBx|VT~s2x6TqMB)=YMAwgYN5!@csQPPC`GDOjaUt)N&~VU z*`vfGaYvkx!&Ms<#%wTD8>MQ-qw#}sR70S#x*xjfc5+30n3_V#>aEBwdJ2@58Lw2S z2hih3%cq(qp4J*A@x5pmhn#tcCc2{>;jfU4<*GN54H#b%?&N`Zpzk9sx@MtJ%~p=L zmo9kK6~A}iG-XT|$B|)oE6cY1u`KiV(qHyF_QU)8&YR2ZFatVHB$i&Kz)WPNFJ$#WSz8I5W`IPHQk<#kUa-Lm!soXDk_#{VQ@^iER2_l_*}KN zL9eqS2uGKY#@dK>3q36uN)0|UcR`$xYU){OjRh=Ji$weY=tTJ?Bt~&u0$rLw3aDG1 zkbWDA!WC_9r$_QA@-l^ZK4{GapXZz=4`aHVdiqo&Icr}*o{YAl(o!WZ?qP^^NC(!3 zsucx#)HJb@SM3{7-`14r4(&7~eMa>n*bt3zXIdNS7@StuMz^6qkzMC%dme;K?N&g| zZUgii$+b{ly$K0x+@*S~-e`RGd0+;-rFJ`>kz!Y(+#5ocBc70Jg*_iM`+R^pq7}PB zF3)9Cd+juM9*i}jqVQls`| z;Fzj?IUd$A$e~o|Guo~Ih1D2sOA*xVD;b^)XwaNQH*!)!#mP;HP!t`fg$aT{y$S7; zhN*X?p|@QHy{dgR!)qudPDB6C(y%-7vkY-F`8oCv@^dX@IBPl=c4URU92CPkj&s$K z+uR(Yn&;+_Q0dEY`T6TeGe3XXG*w$>j}p_{u0z5y+qqf&y~JKmew$w(Ix0hS-|CI( zu>z{O{pi_6anhsZRjF+-UN(W>Zz1S!oEDPNH`*EO{94=fZ2Aq9N)GkL4k|ip>K51r zw^#{3(O>E&&}!8*`bSq=5`eqySqSXW6V$8TO#F7@SQr};_DU&VMDnS8`T7od;_NHm zk}r>uFQcD09r8S*uvd|_)EAz_mQsmR2DAoD@-U>Ug^DX1RNdL2hMuvUEL{!ZR?3&^ z${~>9syl}OuhK}CMk{fltIq5pFp5cyFIkOJk_%;(=D&LU49#8x-Rd44^LssY3&K_f zQmn(I0;`XpD~0y2Q3Q+JWb9Ej*?5`;(-iTsH~Dp@2=+&Gd%yVrz;G~tzy zW=(}gQ?Ku&TbR-&B0a;ph1r?zQ#B)n-pjH3Aho0wHs-90RFQxV^TinkHCZ zE}zyksn;*nsTO8-I;vu>8kEdFTlxNeZ|_11PoqqW5$ zr0HI0vi}TVNINyr7x7_hD0L{s*BX>Kb`v-v#u%EdaTr65%Rcj}}P^m+y0Wu9$jY~r_HeNtUImu#>$|j2uDw`~3R5{6J?LQH^ z=?~+}{V=BuBbD?Y1~d3?FvWTRjM{eM&~!OLdsT@xREJzaOx5(%Lo7%fnmQz`t^mj& z)v+lu8KKTT5It4Bo_d%vpGg&MB3Ier9jOv0C)G>x1u^f-q)MEeR6Cd~Tn zP8{e7x#fUmKL(llus7uHAU#e>5`kRW>W~|=5qHS##cbqhfF=E4O|dIdtS2HNS4cO! zA$>*E{tHD7>5$b!I>~+%DK-*^8g1F3%Lo}3`b~`d>mVy92i}me!a`>a;u9c3pRvMz zl0pVFAqHvsi)yb2sUde-5h?a0`glT~+`JSSZBI!hAd`|rq0zP>j}pQ@P%)yB+6_`| zeSw^!sA2nQiW4x}Hsa}^Do@|Gjmwlk6WGsy&E_ZkSdEL$ z$SE74@k=zRHlViMh{&2v+OWQUt^*nEi1<}b*%9G3@|x2|w34wyOoUNIXZV-w;X-MbkCgO3-TS z8_IZdyf%_N8I2M1ec57H*T#4keRXZAy4rdjN-WfGbg8w-vWsD}PfgB59HV3DV%-E8 zzwY5?*@_u9dhawntee3I=&3iLs1-%)3KzSKNY7fyRcZaDTPp#IF>VsStr7q`oo`Ym z&~YD0oy}W7>>U6yn*BC{#qL~0cNA(;OGvlQC8dVy@uvPkA&=XBhhljXMMYlgT?(2Z zPsp^t2N#r`pfr54Gg#!^6FCswjodtigxlT)38_Bhwopg)kgL8(5}Y<|p(5xZqdwq> z=`7}$SIYt=8!&-By<;9sZS*dJ!6*inIxT(Lvl==okL<>ZJ(2@oSz(t#);uAq;YqNO(SPH zihgq`str#;E=ORGehgKcFA%e~oj4X+a>D8c;CJzufuX|H=X*2@tWQ@^=Wox4a9bym z{Su-2LA2z&2nC?YwRt^=b0J16Avv&MSLJU&A{JVv-e(nbsk~t0BJ8sict&egR_j5z z8X9EZop85(1wF;48ZzB3UTNB2Q!0N4;QG-A6N0QVY9G?XF&a0YZR4^o3nkzDHx}=e zo=*+=+}zx9QbHpWROiVXG~y;`uq$cWFWXsEySTG(M5wpu!<14@_7=_o7Di0_Tj*%O z5QkvaYbdjXf^ie^nH|b?h{N=RbiF}~BorP5jF6|PKyCXD%0gcDb)pZNT5-tJ05X+8 zhFp^;rDhYh&PD-osbuyYFs}61_Wbr6suhm`gYZQE7D^pU{Ugp7u7s1Z?S2(K+^tvB zBj{?qhMtkuWq8p1e&k+V6Vc^*q7nK~<3g$99DV3QNgv!m`mS>n9G|Bk-j+NAu570| zn4Cu;D(d8A6rvggW9i%om6(1Z>efs%h3*RmQy+y%(GP&Womflgy6nF&PLGafC~G`O;V&@<3JDfY2$g)3{5H^C7vJz2B{Kbt>tpmc)au`asZ?B}C&cqtPr-4Qn@&Jw0BacsNA6 zs&Iy>%GG5n>~UqnH96tV>>S!Z>H|ArKuArKEH5c>dg5RSSQc%j)nL$_T0qACla%ZB zzwlt?ya&~xgVN~G!PvjoK_YwUAlo{0F!t|taAs)kejM^bf6f|P&fp`-&G4+2taM{! zsD|CnGT7CMBE>4Y6}_WNMO8&@#?#%3T8O9KiW=j>DiMV)_Y8G$0d&I@_=<>f5{Q9M zcF~Q7B*z`@dL)I7c^1vk+CalL6gtL4G%K$=n?>7Vf1oNHb*3HKYWo*x;C#gwY4sJ_ zZ1_*D56e`v7Q#3|J}78IF>)T$oV7G(EKS+6V2B>?`Rur8x?xqS?iN$rzX1Igv4#j1lC zsIsZE?qIGADTl3;2b89OU1)bY(sGWdy&aL3tb{2l4ip~zn2Yr5YFBq zh|9jmFIw8=wSk9al=`R|%~S(PS#3d80xMJJ#s*{L1Gku<3IPK{s%l*h<*k&aYAr#q z?=Y}r{Dxvx#g1_?RXPYKq!ioNP@Y_m)}p4V;CW!R&O#kY{R%KwQl$>*hj|gwpQgM! zLCP-&ts6L_3bPfFZLeeat(J(d1hYi)8)K6M`95Yr7^P`vr2O#BXeMtC3_N! zC*BzovkA%_9a&Z7rVgF4WeV^N4wB)y)@AWOw5~&9AL}|;m;a%4SsAv@C#^Gh2g|XJ zBzR{G2GO_>wN~JD?xZMOOuDH0aw_l-b0vDJRL1C}*D6+k1eT zsowyx?aR$lD0DXCvT>Ya8ny~Zr%F1^r%J4QEGWb#Mtyu6ER{PWUhctd4YKvc-mr|t zJ?yO{gHD^HX1Bs&z1+cDol(~G`^qZ3*)CgJC;RO@t!*wc(J`ve@9Qb@hFL7frd&#$ z7T4m9DH`wFsrO>vp?eZ2AFQ`Lvf5y$&y_9%yQC2m3MAasSHQ!jD~-)m?pPyB5KZy9 z(iM3GzbaK|y5X_gso1Ezbzal|f0D-h{~yvgKa++gro&e~;j7eWXU@3-+1J|8XUTQZ z^$6_IPoycQ8>Lm-P8QFBVzj(GXO*$nrw_T-Ev-EH6VkB(%N) zTBmv~WC(>u;~eHGbjKzXu}s8h^8uJe!ouw!Gx=wz<5Ou1_j}NaR2!Fc%$=rDuN!hw zoS74M5#IXzIdSj*qs{{8qA}kkK7bATQ=Z>9xf%PS*nFH~$ff$1sFC%0@@3fKGxX#e zWD_pXnY^{a*7>mO*u$kon-U>+o};$aJJO^kG_$=!?{Kv)n= zuR%siZgN13j)dy;^ zpS&K~ZU`AUC*d~kAfXe+1tZg6;Rs-Hs#X<_i^}~gkK8$v2hOyykm$mv-q`I~VOJv_ z2hbgub`7w)%qmpJ?&j-W*@iS4BdA`7Qm1kI)mm4Q*KOP`GHu)qNGWJJJ5EJv8*Y!7n5bgS zxfRUBQQEc{G*Pplwke{v;jV~@slEKOwvmXXZJV7H!7{%)L?Y9yH;9Kl-0g@d_g!QL zJZzi?myNF61|Le*$rDiARb8z(;$qoIb3-0`>f*!N4u)?V%v2Ei+9{0VMmpoe4b+Zd z+FC;dFz%#hFO^QP_#{xzIh5>2kt>ZW~O)6%WA)AqAnhtv&p zTzzyd^Q@5S(RgQfG+s_w>epmq_x?v>@_rDFO@=rZY13b>e>(5uA5CUnW*f)g=D&B9 zBcAIk933MPyULf`*pUa^E|LxcmmP$IM3wy@D;DkBqB+wqq#^sic0^@)EZJ_S3MgZ1 zbW4dm=un*siTJc$oPZ~Kg}wDy=o=9yPaQV_Nz!ce;#d=AbQ(4ex6Ov2F73{w#F!DL zgKjx@(!?mFhvxG~=~2C)%aoMujPks6eR=81^bD6wfyUUe(2vM}q(4`$i)YBbT=j+> zfPUP8&&z>_uYtPgV4kwUWBGA-!r1>Lo!kUmoIr=;oD6UR?o0wyE*Pfh3@MZv@AU1f z;E~MP@oI!sx@tk^)Dx(SzYl#!&N;P4wh7d%P--H_ceSEx%ErHi!p@QRt+~1;{jM&u zWdP|q-Ld7i99^hsu%$xUa>nn*CtD7q_>&!5&~IjKL06fz1@)vu*OcGUrSLxFKGW!)1R8^30ff&#B4kDZE-k{q1lZtI6=p=c(k~{Ma zND|kQ4gfE*0<$vbevz@-#-&lSLxvW>rr*PZL9*6^P18Q$2Q(X{jd@w(G#qqcVTZFU zBj)THwBhoE$uG04whlrN`|s|M-gXb{GpYvsAkPNyA$PkBb*=yF5*>2Xsa>K@D7;Mt=1Q*wr&!(6i2e?>Iy9M?W1lkbh$a?Z( z@Z<7kxT$X&ovGkWq2yKIs0?X-XU289DCtbsx+bqB?yW@eVGxf{z@|;tj>BL?K%vTQ ziKfBH+Yy0HR$GWn2j#LVZ$@B`ei0QZuIHeZ5XTw-NAO9VH2_3j_dp?9u4BO=nWHGR zg^2cHka9c|O+JFO;4X*tEPJMuFDgq{VB{SL`S@M3M9QV3wZ)u4i0hmluX`|~9Ymtb zq-Z1~8YWBTLUTrHG5JW2Bj`8yPey6VTAC?NO*ZU~BX*ZXiRKg&mPdSLLas6YH~Ow- z18F?{-{>1mZsBngJxWe~`}_y_?eO$onZ{KnGk(8xTt%+0rHi;GIv#h~xT?hcHRb8Q zuwgnC;qN#e7n|tp;J?yo|AEe-|1Wf={y^tnsX+frJ9*{xJ9)=Fi~m~ZDSu$+YZ*KL zH}&qyY(4%j%Dm+dY#f%!_y5MmqevaMjsK0lOR{9;lj&*DthdHE{ZD-X3lO0>L6{mas95wa|q2PqSmKmLYkO3N5vSA znR~Rkl>+)wo_EkZ3R5xc53{V?x5Rpwqi_rzyO+lyF-L*sM33)KW4Y>Cc4=SJ7F8!%x|A~@ZwXx=n6bATepg>*o<1B*K;OPDvWVg6%h-2@^s?40GkMw6o_N(2Vsr7nzx=+y zkyPC>?*?F!O=tU<+tLF?LFY#*?avFyVSUL0X=0=>2gc#VJfc|5P+8t&=wbfC04gzQ z+)3j3LF4sLc6cMaOs}p7bL;6DB#dgsgm5gsHaDk9hP< z)a%&5qr9}h$nwjkHkX~)Y$hUlC19am259OrKo^|{$h{bscn>kr$Ax(QkJAv8|5I}Ow=Qs02L?sV>gc-otvttztz&P+l^mDxBlG1sW_HHM9;p@AW`X!^z`e=uhB_KokhaqUBR-r(;M*88(;4vvNJ_q=-_#Ma*RIlulsY>Da>J&V&rm{}OlVntS7h4=n zGVfz?e4HAchL`w>UIqFwlz%hgOW=a~QorhPwBuGePMqN7FZk}3)NyP^$0)Tdql0vh z%+OCzDx(H(TGd=*2G7!?KrYowtH7ADgj+M>?GQyGg~QD zc|PU$)K_?H?97=B9*>PJII|x9=G~uGlmeu%(*~YqV@r*AnvJb9vlU(kZ#~j(04;Sf z7P_slo-Azxu@$o=T$AR*omOmN6OQ zvTmgskIQqv09DyphK=nuwDD{dCrHEXWm9`SpjtnZ)6rzn25x~*kvjTF%CS8aG0nue zsE*SR@);fdB-~(n&<#|2&=q%6WD_a zxmCP+aW%{5y?61k5t7|E5X(qhp7-z@f3E20!TKu|ltG+%K+I6*eBMS5-GQ=+*6D zG}gv7wFN_qGLixpX98uJK$lDa9f_2w<^c7HYmf~57}7dQ-qd-Fn-A4pG@Sfm1icTx zO&G}Bp!G+L^MKRy13ZgC4}d-d&x`QehB#w^-+>=yv|>E)J_kWq3(KKeR!{pwxC!@% zvbDC%II-DpETPpUpQ=W2s+uF}X}&3Ql4|t&So3oIi#r1ELD%GBw}uMWp|F|viSpzq z&0<{(p)pZqG%)P6POiXrs%B)zvxQfA~1}f_&!e!!N3{cY)kuJ$fqiSeY?#9<)Tqnp&h+ z80A32q;BKLz)aJ~+jCH6+cS9`rWM$<*PQL>SaJgsaLseCI8s1f@~o%1NyMl769*U` zV{GiC=75y_~JzNMYi8F z^=b_GqAAh_CuO>1s%dM&DB5@%io@lEX^x?aC6LBiJk$n7F1sB`nu!XG^z#v-8SnXc zYVNk??!D!FLdCe+n3iFhBRmP2lVNu?>a|!xnQN!KRaMC_<$l{VQ2A)EDrS#IS<;mJ zc->gxe4vdY`SIzS3y_^y;{gcK3NqRhW-kF<1k`g2i6vs}Plv|Ki_;`0JE^}tbs@yt z$&K4kFfw5aM<^!W$7|aP#vXks%`4u5EqqEApCBhA8Xp&Fd`!eIv #{m2@Ill<|% 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 U0GYv2w*MD0*FXLHYe#|q3mf->X8-^I literal 0 HcmV?d00001 diff --git a/Assemblies/ModSwitch.dll b/Assemblies/ModSwitch.dll new file mode 100644 index 0000000000000000000000000000000000000000..be2135d70e4e5bab99daa3e5fddb17605c7bcb4b GIT binary patch literal 13824 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 literal 0 HcmV?d00001 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..1852d7f --- /dev/null +++ b/LICENSE @@ -0,0 +1,382 @@ +Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International +Public License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution-NonCommercial-ShareAlike 4.0 International Public License +("Public License"). To the extent this Public License may be +interpreted as a contract, You are granted the Licensed Rights in +consideration of Your acceptance of these terms and conditions, and the +Licensor grants You such rights in consideration of benefits the +Licensor receives from making the Licensed Material available under +these terms and conditions. + + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + + c. BY-NC-SA Compatible License means a license listed at + creativecommons.org/compatiblelicenses, approved by Creative + Commons as essentially the equivalent of this Public License. + + d. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + + e. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + f. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + g. License Elements means the license attributes listed in the name + of a Creative Commons Public License. The License Elements of this + Public License are Attribution, NonCommercial, and ShareAlike. + + h. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + i. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + j. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + k. NonCommercial means not primarily intended for or directed towards + commercial advantage or monetary compensation. For purposes of + this Public License, the exchange of the Licensed Material for + other material subject to Copyright and Similar Rights by digital + file-sharing or similar means is NonCommercial provided there is + no payment of monetary compensation in connection with the + exchange. + + l. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + m. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + n. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part, for NonCommercial purposes only; and + + b. produce, reproduce, and Share Adapted Material for + NonCommercial purposes only. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. Additional offer from the Licensor -- Adapted Material. + Every recipient of Adapted Material from You + automatically receives an offer from the Licensor to + exercise the Licensed Rights in the Adapted Material + under the conditions of the Adapter's License You apply. + + c. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties, including when + the Licensed Material is used other than for NonCommercial + purposes. + + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified + form), You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + b. ShareAlike. + + In addition to the conditions in Section 3(a), if You Share + Adapted Material You produce, the following conditions also apply. + + 1. The Adapter's License You apply must be a Creative Commons + license with the same License Elements, this version or + later, or a BY-NC-SA Compatible License. + + 2. You must include the text of, or the URI or hyperlink to, the + Adapter's License You apply. You may satisfy this condition + in any reasonable manner based on the medium, means, and + context in which You Share Adapted Material. + + 3. You may not offer or impose any additional or different terms + or conditions on, or apply any Effective Technological + Measures to, Adapted Material that restrict exercise of the + rights granted under the Adapter's License You apply. + + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database for NonCommercial purposes + only; + + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material, + including for purposes of Section 3(b); and + + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + +======================================================================= + +Creative Commons is not a party to its public +licenses. Notwithstanding, Creative Commons may elect to apply one of +its public licenses to material it publishes and in those instances +will be considered the “Licensor.” The text of the Creative Commons +public licenses is dedicated to the public domain under the CC0 Public +Domain Dedication. Except for the limited purpose of indicating that +material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the +public licenses. + +Creative Commons may be contacted at creativecommons.org. + diff --git a/README.md b/README.md new file mode 100644 index 0000000..a6b4c76 --- /dev/null +++ b/README.md @@ -0,0 +1,13 @@ +[![RimWorld Alpha 17](https://img.shields.io/badge/RimWorld-Alpha%2017-brightgreen.svg)](http://rimworldgame.com/) [![License: CC BY-NC-SA 4.0](https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-lightgrey.svg)](https://creativecommons.org/licenses/by-nc-sa/4.0/) + +# ModSwitch + +_A Rimworld mod manager *(in the making)*_ + +## Powered by ![Harmony](https://github.com/pardeike/Harmony) + +

+Powered by Harmony +

+ +Harmony is lisenced under a [MIT license](https://raw.githubusercontent.com/pardeike/Harmony/master/LICENSE). \ No newline at end of file diff --git a/Source/DEVELOPMENT-SETUP.md b/Source/DEVELOPMENT-SETUP.md new file mode 100644 index 0000000..732652c --- /dev/null +++ b/Source/DEVELOPMENT-SETUP.md @@ -0,0 +1,16 @@ +# How to setup local developement + +Your local path to the Rimworld game & assemblies is probably not what anybody else is using. + +To keep multiple developers from playing ping-pong with the project file(s) and the respective assembly HintPath entries that setting has been externalized. + +After cloning the repository just edit `Source\RimworldInstall.props` (it's a plain XML file) and make sure the `RimworldManagedDir`entry resolves to the correct directory for _your_ local Rimworld assemblies. If you're developing on a running Rimworld install, then you can simply edit the `RimworldInstallDir` entry (other variables derive from there by default). +If you're keeping just a copy of the managed assemblies simply make sure the `RimworldManagedDir` resolves correctly to those assemblies. For relative paths starting with `$(SolutionDir)` is a good idea, as well as making sure you end in a `\`. + +If you want to be a particularly conscientious developer, run + +```bash +git update-index --skip-worktree Source\Rimworldinstall.props +``` + +after setting up your local version of the file. Then git will never upload your modified version. diff --git a/Source/ModSwitch.sln b/Source/ModSwitch.sln new file mode 100644 index 0000000..68b40be --- /dev/null +++ b/Source/ModSwitch.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModSwitch", "ModSwitch\ModSwitch.csproj", "{AB2E8E89-3D1D-4E36-A0AE-489B6EBC84A6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {AB2E8E89-3D1D-4E36-A0AE-489B6EBC84A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AB2E8E89-3D1D-4E36-A0AE-489B6EBC84A6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AB2E8E89-3D1D-4E36-A0AE-489B6EBC84A6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AB2E8E89-3D1D-4E36-A0AE-489B6EBC84A6}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Source/ModSwitch/ModSwitch.cs b/Source/ModSwitch/ModSwitch.cs new file mode 100644 index 0000000..bd17ea5 --- /dev/null +++ b/Source/ModSwitch/ModSwitch.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Harmony; +using UnityEngine; +using Verse; + +namespace DoctorVanGogh.ModSwitch { + class ModSwitch : Mod { + private Settings _settings; + + public ModSwitch(ModContentPack content) : base(content) { + var harmony = HarmonyInstance.Create("DoctorVanGogh.ModSwitch"); + harmony.PatchAll(typeof(ModSwitch).Assembly); + + Log.Message("Initialized ModSwitch patches..."); + + _settings = GetSettings(); + } + + public override string SettingsCategory() { + return "ModSwitch"; + } + + public override void DoSettingsWindowContents(Rect inRect) { + _settings.DoWindowContents(inRect); + } + + public void DoModsConfigWindowContents(Rect bottom) { + _settings.DoModsConfigWindowContents(bottom); + } + } +} diff --git a/Source/ModSwitch/ModSwitch.csproj b/Source/ModSwitch/ModSwitch.csproj new file mode 100644 index 0000000..8f2a507 --- /dev/null +++ b/Source/ModSwitch/ModSwitch.csproj @@ -0,0 +1,69 @@ + + + + + + Debug + AnyCPU + {AB2E8E89-3D1D-4E36-A0AE-489B6EBC84A6} + Library + Properties + DoctorVanGogh.ModSwitch + ModSwitch + v3.5 + 512 + + + + false + none + false + ..\..\Assemblies\ + DEBUG;TRACE + prompt + 4 + + + none + true + ..\..\Assemblies\ + + + prompt + 4 + + + + False + ..\..\Assemblies\0Harmony.dll + False + + + $(RimworldManagedDir)\Assembly-CSharp.dll + False + + + + + + $(RimworldManagedDir)\UnityEngine.dll + False + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/ModSwitch/ModSwitch.csproj.DotSettings b/Source/ModSwitch/ModSwitch.csproj.DotSettings new file mode 100644 index 0000000..d425c61 --- /dev/null +++ b/Source/ModSwitch/ModSwitch.csproj.DotSettings @@ -0,0 +1,3 @@ + + True + True \ No newline at end of file diff --git a/Source/ModSwitch/Model/ModSet.cs b/Source/ModSwitch/Model/ModSet.cs new file mode 100644 index 0000000..cfd6fed --- /dev/null +++ b/Source/ModSwitch/Model/ModSet.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using Harmony; +using RimWorld; +using UnityEngine; +using Verse; + +namespace DoctorVanGogh.ModSwitch { + class ModSet : IExposable { + + private static readonly FieldInfo fiModsConfig_data; + private static readonly FieldInfo fiModsConfigData_activeMods; + + static ModSet() { + var tModsConfig = typeof(ModsConfig); + var tModsConfigData = AccessTools.Inner(tModsConfig, "ModsConfigData"); + fiModsConfigData_activeMods = AccessTools.Field(tModsConfigData, "activeMods"); + fiModsConfig_data = AccessTools.Field(tModsConfig, "data"); + } + + public List Mods = new List(); + + public string Name = String.Empty; + private TipSignal? _tip; + + public void ExposeData() { + Scribe_Collections.Look(ref Mods, false, "mods"); + Scribe_Values.Look(ref Name, "name"); + } + + private TipSignal Tip { + get { return (_tip ?? (_tip = new TipSignal(ToString()))).Value; } + } + + public override string ToString() { + return Mods.Aggregate(new StringBuilder(), (sb, m) => sb.Length == 0 ? sb.Append(m) : sb.AppendFormat(", {0}", m), sb => sb.ToString()); + } + + public void DoWindowContents(Rect rect) { + GUI.Label(rect, Name); + TooltipHandler.TipRegion(rect, Tip); + } + + public void Apply() { + // TODO: improve performance, dont do multiple joins over same data... + + // join set with installed mods while perserving order from set + List installedMods = Mods + .Select((m, idx) => new {id = m, Index = idx}) + .Join(ModLister.AllInstalledMods, t => t.id, md => md.Identifier, (t, md) => new {Id = t.id, Index = t.Index}) + .OrderBy(t => t.Index) + .Select(t => t.Id) + .ToList(); + + fiModsConfigData_activeMods.SetValue(fiModsConfig_data.GetValue(null), new List(installedMods)); + + if (installedMods.Count != Mods.Count) { + var missingMods = Mods.Where(m => !installedMods.Contains(m)); + StringBuilder sb = new StringBuilder($"Some mods from {Name} are not currently installed:"); + sb.AppendLine(); + sb.AppendLine(); + foreach (var item in missingMods) { + sb.AppendLine($" - {item}"); + } + + Find.WindowStack.Add(new Dialog_MessageBox(sb.ToString(), title: "Missing mods")); + } + } + } +} diff --git a/Source/ModSwitch/Properties/AssemblyInfo.cs b/Source/ModSwitch/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..cb00015 --- /dev/null +++ b/Source/ModSwitch/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ModSwitch")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ModSwitch")] +[assembly: AssemblyCopyright("Copyright © DoctorVanGogh 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 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 +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("ab2e8e89-3d1d-4e36-a0ae-489b6ebc84a6")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("0.0.1.0")] +[assembly: AssemblyFileVersion("0.0.1.0")] diff --git a/Source/ModSwitch/Settings.cs b/Source/ModSwitch/Settings.cs new file mode 100644 index 0000000..fad2254 --- /dev/null +++ b/Source/ModSwitch/Settings.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Xml; +using UnityEngine; +using Verse; + +namespace DoctorVanGogh.ModSwitch { + class Settings : ModSettings{ + private List Sets = new List(); + + private Vector2 _scrollPosition = new Vector2(); + + + public override void ExposeData() { + Scribe_Collections.Look(ref Sets, false, "sets"); + } + + public void DoWindowContents(Rect rect) { + Listing_Standard list = new Listing_Standard(GameFont.Small) { + ColumnWidth = rect.width + }; + list.Begin(rect); + + if (list.ButtonTextLabeled("Import", "ModListBackup")) { + Find.WindowStack.Add(Dialog_MessageBox.CreateConfirmation("Importing from ModListBackup will overwrite all existing sets.", ImportModListBackupo, true, "Confirm import")); + } + +#if DEBUG + if (list.ButtonTextLabeled("Debug", "ListExisting")) { + foreach (var modSet in Sets) { + Log.Message($"ModSet '{modSet.Name}': {modSet}"); + } + } +#endif + + const float scrollbarSize = 16f; + const float sliderHeight = 30f; + const float gapSize = 4f; + + var r = list.GetRect(rect.height - list.CurHeight); + + int count = Sets.Count; + + Widgets.BeginScrollView(r, ref _scrollPosition, new Rect(0, 0, r.width - scrollbarSize, count * (sliderHeight + gapSize))); + Vector2 position = new Vector2(); + + // render each row + foreach (var entry in Sets) { + position.y = position.y + gapSize; + + Rect line = new Rect(0, position.y, r.width - scrollbarSize, sliderHeight); + + entry.DoWindowContents(line); + position.y += sliderHeight; + } + + Widgets.EndScrollView(); + + list.End(); + } + + private void ImportModListBackupo() { + Sets.Clear(); + + string parent = Path.Combine(GenFilePaths.SaveDataFolderPath, "ModListBackup"); + Util.Trace($"Looking at {parent}"); + if (Directory.Exists(parent)) { + var existing = Directory.GetFiles(parent, "*.rws"); + + foreach (var mlbSet in existing) { + Util.Trace($"Reading {mlbSet}"); + + XmlDocument doc = new XmlDocument(); + doc.Load(mlbSet); + + var set = new ModSet { + Name = $"MLB '{Path.GetFileNameWithoutExtension(mlbSet)}'", + Mods = doc.DocumentElement.SelectNodes(@"//activeMods/li/text()").Cast().Select(n => n.Value).ToList() + }; + Util.Trace($"Imported {set.Name}: {set}"); + Sets.Add(set); + } + } + + LoadedModManager.GetMod().WriteSettings(); + } + + + + public void DoModsConfigWindowContents(Rect target) { + if (Widgets.ButtonText(new Rect(target.x, target.y, 120f, 30f), "[MS] Load set")) { + Find.WindowStack.Add(new FloatMenu(Sets.Select(ms => new FloatMenuOption(ms.Name, ms.Apply)).ToList())); + } + } + } +} diff --git a/Source/ModSwitch/Util.cs b/Source/ModSwitch/Util.cs new file mode 100644 index 0000000..fb4634c --- /dev/null +++ b/Source/ModSwitch/Util.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using Verse; + +namespace DoctorVanGogh.ModSwitch { + class Util { + [Conditional("TRACE")] + public static void Trace(string s) { + Log.Message($"[ModSwitch]: {s}"); + } + + public static void Warning(string s) { + Log.Warning($"[ModSwitch]: {s}"); + } + } +} diff --git a/Source/ModSwitch/[Patches]/Patches.cs b/Source/ModSwitch/[Patches]/Patches.cs new file mode 100644 index 0000000..0450738 --- /dev/null +++ b/Source/ModSwitch/[Patches]/Patches.cs @@ -0,0 +1,18 @@ +using Harmony; +using RimWorld; +using UnityEngine; +using Verse; + +namespace DoctorVanGogh.ModSwitch { + class Patches { + + [HarmonyPatch(typeof(Page_ModsConfig), nameof(Page_ModsConfig.DoWindowContents))] + public class ModsConfig_DoWindowContents { + + public static void Postfix(Rect rect) { + const float bottomHeight = 52f; + LoadedModManager.GetMod()?.DoModsConfigWindowContents(new Rect(0, rect.height - bottomHeight + 8f, 350f, bottomHeight - 8f)); + } + } + } +} diff --git a/Source/RimworldInstall.props b/Source/RimworldInstall.props new file mode 100644 index 0000000..11af416 --- /dev/null +++ b/Source/RimworldInstall.props @@ -0,0 +1,26 @@ + + + + C:\Program Files (x86)\Steam\steamapps\common\RimWorld\ + + + $(RimworldInstallDir)\RimWorldWin_Data\ + + + $(RimworldDataDir)\Managed\ + + + + \ No newline at end of file diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..b7ba722 --- /dev/null +++ b/TODO.md @@ -0,0 +1,9 @@ +# Things to do + +- Implement saving current mod set +- Subscribing to items that are 'new' +- Renaming sets +- Deleting sets +- Auto-creating/picking sets at mod load +- 'copy local' for Steam mods ??? +- fancy UI (colors etc)