From 97ff2c89e4a9ba17a7fb0282f75b343cebb13721 Mon Sep 17 00:00:00 2001 From: shnakamura Date: Sun, 10 Mar 2024 22:23:55 -0300 Subject: [PATCH] Initial commit --- .github/ISSUE_TEMPLATE/BUG_REPORT.yml | 37 + .github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml | 22 + .github/ISSUE_TEMPLATE/config.yml | 5 + .github/README.md | 38 + .gitignore | 10 + .gitmodules | 3 + LICENSE | 661 ++++++++++++++++++ catalyst/.gitignore | 6 + catalyst/LICENSE | 661 ++++++++++++++++++ catalyst/Library.Build.targets | 11 + catalyst/Mod.Build.targets | 21 + catalyst/README.md | 2 + .../TeamCatalyst.Catalyst.DotNetPath.targets | 23 + ...TeamCatalyst.Catalyst.ErrorChecker.targets | 10 + .../TeamCatalyst.Catalyst.ModLoader.targets | 14 + ...Catalyst.Catalyst.ModifyReferences.targets | 29 + catalyst/build/TeamCatalyst.Catalyst.targets | 16 + .../AssemblyRewritingContext.cs | 20 + .../AssemblyRewriting/IAssemblyRewriter.cs | 14 + .../Engines/EngineRegistry.cs | 16 + .../Engines/IEngine.cs | 7 + .../Hashing/Hasher.cs | 45 ++ .../PublicReferenceManifest.cs | 13 + .../PublicReferenceRecord.cs | 19 + .../PublicReferenceType.cs | 25 + .../TeamCatalyst.Catalyst.Abstractions.csproj | 16 + .../AnnotationsProvider.cs | 25 + .../FNA/Attributes.xml | 4 + .../TeamCatalyst.Catalyst.Annotations.csproj | 14 + .../tModLoader/Attributes.xml | 15 + .../JavaScriptEngine.cs | 34 + .../JsReferenceManifest.cs | 42 ++ .../JsReferenceRecord.cs | 37 + .../ReferenceModification/JsReferenceType.cs | 60 ++ ...mCatalyst.Catalyst.Build.JavaScript.csproj | 19 + .../JsonEngine.cs | 10 + .../TeamCatalyst.Catalyst.Build.Json.csproj | 19 + .../LuaEngine.cs | 10 + .../TeamCatalyst.Catalyst.Build.Lua.csproj | 15 + .../AnnotationProviderAssemblyRewriter.cs | 31 + .../PublicizerAssemblyRewriter.cs | 195 ++++++ .../SummaryProviderAssemblyRewriter.cs | 36 + .../EngineInitializer.cs | 17 + .../ProjectBuilding/AbstractTask.cs | 19 + .../ModifyReferencesTask.cs | 160 +++++ .../TeamCatalyst.Catalyst.Build.csproj | 32 + generate-symlinks.js | 16 + mods.json | 1 + scripts/gen-lib.js | 23 + scripts/gen-mod.js | 105 +++ scripts/gen-sln.js | 38 + scripts/setup.sh | 25 + src/Silicate/.editorconfig | 41 ++ src/Silicate/Assets/Textures/UI/Panel.png | Bin 0 -> 180 bytes .../Assets/Textures/UI/Panel_Left.png | Bin 0 -> 124 bytes .../Assets/Textures/UI/Panel_Right.png | Bin 0 -> 139 bytes src/Silicate/Assets/Textures/UI/Progress.png | Bin 0 -> 91 bytes src/Silicate/Assets/Textures/UI/Unknown.png | Bin 0 -> 147 bytes src/Silicate/Common/UI/UIManager.cs | 60 ++ src/Silicate/Common/UI/UITileDisplay.cs | 203 ++++++ .../Localization/en-US_Mods.Silicate.hjson | 1 + src/Silicate/Properties/launchSettings.json | 16 + src/Silicate/Silicate.cs | 11 + src/Silicate/Silicate.csproj | 13 + src/Silicate/build.txt | 11 + src/Silicate/description.txt | 1 + src/Silicate/icon.png | Bin 0 -> 3210 bytes src/TeamCatalyst.Silicate.sln | 30 + tModLoader.targets | 3 + 69 files changed, 3136 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/BUG_REPORT.yml create mode 100644 .github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/README.md create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 LICENSE create mode 100644 catalyst/.gitignore create mode 100644 catalyst/LICENSE create mode 100644 catalyst/Library.Build.targets create mode 100644 catalyst/Mod.Build.targets create mode 100644 catalyst/README.md create mode 100644 catalyst/build/TeamCatalyst.Catalyst.DotNetPath.targets create mode 100644 catalyst/build/TeamCatalyst.Catalyst.ErrorChecker.targets create mode 100644 catalyst/build/TeamCatalyst.Catalyst.ModLoader.targets create mode 100644 catalyst/build/TeamCatalyst.Catalyst.ModifyReferences.targets create mode 100644 catalyst/build/TeamCatalyst.Catalyst.targets create mode 100644 catalyst/src/TeamCatalyst.Catalyst.Abstractions/AssemblyRewriting/AssemblyRewritingContext.cs create mode 100644 catalyst/src/TeamCatalyst.Catalyst.Abstractions/AssemblyRewriting/IAssemblyRewriter.cs create mode 100644 catalyst/src/TeamCatalyst.Catalyst.Abstractions/Engines/EngineRegistry.cs create mode 100644 catalyst/src/TeamCatalyst.Catalyst.Abstractions/Engines/IEngine.cs create mode 100644 catalyst/src/TeamCatalyst.Catalyst.Abstractions/Hashing/Hasher.cs create mode 100644 catalyst/src/TeamCatalyst.Catalyst.Abstractions/ReferenceModification/PublicReferenceManifest.cs create mode 100644 catalyst/src/TeamCatalyst.Catalyst.Abstractions/ReferenceModification/PublicReferenceRecord.cs create mode 100644 catalyst/src/TeamCatalyst.Catalyst.Abstractions/ReferenceModification/PublicReferenceType.cs create mode 100644 catalyst/src/TeamCatalyst.Catalyst.Abstractions/TeamCatalyst.Catalyst.Abstractions.csproj create mode 100644 catalyst/src/TeamCatalyst.Catalyst.Annotations/AnnotationsProvider.cs create mode 100644 catalyst/src/TeamCatalyst.Catalyst.Annotations/FNA/Attributes.xml create mode 100644 catalyst/src/TeamCatalyst.Catalyst.Annotations/TeamCatalyst.Catalyst.Annotations.csproj create mode 100644 catalyst/src/TeamCatalyst.Catalyst.Annotations/tModLoader/Attributes.xml create mode 100644 catalyst/src/TeamCatalyst.Catalyst.Build.JavaScript/JavaScriptEngine.cs create mode 100644 catalyst/src/TeamCatalyst.Catalyst.Build.JavaScript/ReferenceModification/JsReferenceManifest.cs create mode 100644 catalyst/src/TeamCatalyst.Catalyst.Build.JavaScript/ReferenceModification/JsReferenceRecord.cs create mode 100644 catalyst/src/TeamCatalyst.Catalyst.Build.JavaScript/ReferenceModification/JsReferenceType.cs create mode 100644 catalyst/src/TeamCatalyst.Catalyst.Build.JavaScript/TeamCatalyst.Catalyst.Build.JavaScript.csproj create mode 100644 catalyst/src/TeamCatalyst.Catalyst.Build.Json/JsonEngine.cs create mode 100644 catalyst/src/TeamCatalyst.Catalyst.Build.Json/TeamCatalyst.Catalyst.Build.Json.csproj create mode 100644 catalyst/src/TeamCatalyst.Catalyst.Build.Lua/LuaEngine.cs create mode 100644 catalyst/src/TeamCatalyst.Catalyst.Build.Lua/TeamCatalyst.Catalyst.Build.Lua.csproj create mode 100644 catalyst/src/TeamCatalyst.Catalyst.Build/AssemblyRewriting/AnnotationProviderAssemblyRewriter.cs create mode 100644 catalyst/src/TeamCatalyst.Catalyst.Build/AssemblyRewriting/PublicizerAssemblyRewriter.cs create mode 100644 catalyst/src/TeamCatalyst.Catalyst.Build/AssemblyRewriting/SummaryProviderAssemblyRewriter.cs create mode 100644 catalyst/src/TeamCatalyst.Catalyst.Build/EngineInitializer.cs create mode 100644 catalyst/src/TeamCatalyst.Catalyst.Build/ProjectBuilding/AbstractTask.cs create mode 100644 catalyst/src/TeamCatalyst.Catalyst.Build/ProjectBuilding/Tasks/ReferenceModification/ModifyReferencesTask.cs create mode 100644 catalyst/src/TeamCatalyst.Catalyst.Build/TeamCatalyst.Catalyst.Build.csproj create mode 100644 generate-symlinks.js create mode 100644 mods.json create mode 100644 scripts/gen-lib.js create mode 100644 scripts/gen-mod.js create mode 100644 scripts/gen-sln.js create mode 100644 scripts/setup.sh create mode 100644 src/Silicate/.editorconfig create mode 100644 src/Silicate/Assets/Textures/UI/Panel.png create mode 100644 src/Silicate/Assets/Textures/UI/Panel_Left.png create mode 100644 src/Silicate/Assets/Textures/UI/Panel_Right.png create mode 100644 src/Silicate/Assets/Textures/UI/Progress.png create mode 100644 src/Silicate/Assets/Textures/UI/Unknown.png create mode 100644 src/Silicate/Common/UI/UIManager.cs create mode 100644 src/Silicate/Common/UI/UITileDisplay.cs create mode 100644 src/Silicate/Localization/en-US_Mods.Silicate.hjson create mode 100644 src/Silicate/Properties/launchSettings.json create mode 100644 src/Silicate/Silicate.cs create mode 100644 src/Silicate/Silicate.csproj create mode 100644 src/Silicate/build.txt create mode 100644 src/Silicate/description.txt create mode 100644 src/Silicate/icon.png create mode 100644 src/TeamCatalyst.Silicate.sln create mode 100644 tModLoader.targets diff --git a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml new file mode 100644 index 0000000..ab58a5d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml @@ -0,0 +1,37 @@ +name: "🐛 Bug Report" +description: Create an issue for a bug report. +title: "" +labels: [ + "Bug", + "New Issue" +] +body: + - type: textarea + id: description + attributes: + label: "Description" + description: Please enter an explicit description of your issue. + validations: + required: true + - type: textarea + id: reprod + attributes: + label: "Reproduction steps" + description: Please demonstrate the steps to replicate your issue, if known about. + validations: + required: false + - type: textarea + id: screenshot + attributes: + label: "Screenshots" + description: Please attach screenshots to help further demonstrate your issue. + validations: + required: false + - type: textarea + id: logs + attributes: + label: "Logs" + description: Please copy and paste any relevant log output, if any. + render: bash + validations: + required: false \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml b/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml new file mode 100644 index 0000000..b801d4a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml @@ -0,0 +1,22 @@ +name: "⭐ Feature Request" +description: Create an issue for a feature request. +title: "<title>" +labels: [ + "Feature", + "New Issue" +] +body: + - type: textarea + id: summary + attributes: + label: "Summary" + description: Please provide a brief explanation of the request. + validations: + required: true + - type: textarea + id: reasonings + attributes: + label: "Reasonings" + description: Please provide reasons why your request should be taken into account. + validations: + required: true \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..86dde27 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: true +contact_links: + - name: Discord Server + url: https://www.discord.gg/vPTUZcvXjg + about: Need extra assistance? Get in touch with developers through our Discord Server. \ No newline at end of file diff --git a/.github/README.md b/.github/README.md new file mode 100644 index 0000000..99aa13a --- /dev/null +++ b/.github/README.md @@ -0,0 +1,38 @@ +> [!NOTE] +> This is the `.github/README.md` file. We choose to leave it outside of the root directory. You can move it to the root directory or edit it in `.github/`. + +# template-mod + +This is the Team Catalyst Template Mod, a template repository for quick-starting development with [terraria-catalyst/catalyst](https://github.com/terraria-catalyst/catalyst). + +Catalyst is a build toolchain and extension to the tModLoader ecosystem that facilitates monolithic/multi-project repositories that may contain multiple projects, including multiple mods. + +## About Catalyst + +Catalyst is a set of projects and MSBuild targets/props that make mod development quicker and easier. It provides features like access transformers, allows for non-standard project organization, features source generators, and more. + +This template is specifically designed to integrate with it, so it isn't optional. + +## Cloning + +The repository should be cloned into the `tModLoader/ModSources/` directory, such that the path looks like: `tModLoader/ModSources/template-mod`. This requirement may change in the future as Catalyst develops. + +## Building + +Once cloned, one should run the `scripts/setup.sh` script. This script generates symlinks, initializes and updates submodules, and builds Catalyst. + +After running the setup script, you can build any mod project with `dotnet build` and it will produce binaries in the `bin/` directory and a built `.tmod` archive in `tModLoader/Mods`, just like regular tModLoader. + +## Symbolic Linking + +As mentioned in [Building](#building), symbolic links are used. These are used to mimic the expected tModLoader mod directory setup. Your cloned repository is included in `ModSources/` but isn't actually a mod. Normally, any mods within `src/` would go unrecognized. To fix this, symbolic links are generated that lie within `ModSources/` and point to the projects in `src/`. The allows for tML to detect your mods, reference assets like icons for publishing, and properly update and hot reload localization files. + +Generating symbolic links may require administrator/root permissions. + +## Generating Projects + +You can generate projects with the `gen-mod.js` and `gen-library.js` scripts, which will create a new mod or library project respectively. + +When generating a mod, you should pass in both the namespace and internal mod name (assembly name) as arguments. When generating a library, you should just pass in the namespace (assembly name). + +To generate the solution file, run `gen-sln.js` with the name as input. **Generating mods and libraries will not automatically add them to the solution.** diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ff8d8f8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +.vs/ +.vscode/ +.idea/ +.catalyst/ + +bin/ +obj/ + +*.user + diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..5bf181f --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "catalyst"] + path = catalyst + url = https://github.com/terraria-catalyst/catalyst.git diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0ad25db --- /dev/null +++ b/LICENSE @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +<https://www.gnu.org/licenses/>. diff --git a/catalyst/.gitignore b/catalyst/.gitignore new file mode 100644 index 0000000..1bf5a88 --- /dev/null +++ b/catalyst/.gitignore @@ -0,0 +1,6 @@ +.vs/ +.vscode/ +.idea/ + +bin/ +obj/ diff --git a/catalyst/LICENSE b/catalyst/LICENSE new file mode 100644 index 0000000..0ad25db --- /dev/null +++ b/catalyst/LICENSE @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +<https://www.gnu.org/licenses/>. diff --git a/catalyst/Library.Build.targets b/catalyst/Library.Build.targets new file mode 100644 index 0000000..e4e3c62 --- /dev/null +++ b/catalyst/Library.Build.targets @@ -0,0 +1,11 @@ +<Project> + + <!-- Set defaults for libraries. --> + <PropertyGroup> + <OverrideTMLBuildTask>true</OverrideTMLBuildTask> + </PropertyGroup> + + <!-- Import Mod.Build.Targets as normal. --> + <Import Project="Mod.Build.targets"/> + +</Project> \ No newline at end of file diff --git a/catalyst/Mod.Build.targets b/catalyst/Mod.Build.targets new file mode 100644 index 0000000..2223237 --- /dev/null +++ b/catalyst/Mod.Build.targets @@ -0,0 +1,21 @@ +<Project> + + <!-- Define defaults for project properties. --> + <PropertyGroup> + <ImportModLoader Condition=" '$(ImportModLoader)' == '' ">enable</ImportModLoader> + <CodeAssist Condition=" '$(CodeAssist)' == '' ">enable</CodeAssist> + <PreferDotNetNameToDotNetPath Condition=" '$(PreferDotNetNameToDotNetPath)' == '' ">false</PreferDotNetNameToDotNetPath> + <OverrideTMLBuildTask Condition=" '$(OverrideTMLBuildTask)' == '' ">false</OverrideTMLBuildTask> + + <!--suppress CheckTagEmptyBody --> + <AssemblyPublicizerPaths Condition=" '$(AssemblyPublicizerPaths)' == '' "></AssemblyPublicizerPaths> + + <CatalystDir Condition=" '$(CatalystDir)' == '' ">$(MSBuildProjectDirectory)/.catalyst/</CatalystDir> + + <PathToModLoaderTargetsDir Condition=" $(PathToModLoaderTargetsDir) == '' ">$(MSBuildThisFileDirectory)/../../</PathToModLoaderTargetsDir> + </PropertyGroup> + + <!-- Import general Catalst build targets. --> + <Import Project="build/TeamCatalyst.Catalyst.targets"/> + +</Project> \ No newline at end of file diff --git a/catalyst/README.md b/catalyst/README.md new file mode 100644 index 0000000..f2ff20b --- /dev/null +++ b/catalyst/README.md @@ -0,0 +1,2 @@ +# catalyst +Auxiliary helpers for the tModLoader build toolchain. diff --git a/catalyst/build/TeamCatalyst.Catalyst.DotNetPath.targets b/catalyst/build/TeamCatalyst.Catalyst.DotNetPath.targets new file mode 100644 index 0000000..1a92007 --- /dev/null +++ b/catalyst/build/TeamCatalyst.Catalyst.DotNetPath.targets @@ -0,0 +1,23 @@ +<Project> + + <!-- Set the correct dotnet path to use based on platform. On Windows, it's + dotnet.exe. On Linux, it's dotnet. Depends on what's on the PATH. + Normally, Windows applications would be fine with omitting the + extension, but IDEs such as Rider are special. --> + <PropertyGroup> + <!-- If there ever arises a situation in which we would have to split up + Unix logic into Linux and macOS logic, we should instead use + $([MSBuild]::IsOSPlatform('OSX')). --> + <DotNetPath Condition=" '$(DotNetPath)' == '' AND '$(OS)' == 'Windows_NT' ">dotnet.exe</DotNetPath> + <DotNetPath Condition=" '$(DotNetPath)' == '' AND '$(OS)' == 'Unix' ">dotnet</DotNetPath> + + <!-- Fallback value if we can't detect the platform. --> + <DotNetPath Condition=" '$(DotNetPath)' == '' ">dotnet</DotNetPath> + + <!-- Use the DotNetName property introduced in TML-3944, which as of + writing is determined by the logic above because someone else PR'd + this into tML specifically. --> + <DotNetPath Condition=" '$(PreferDotNetNameToDotNetPath)' == 'true' AND '$(DotNetName)' != '' ">$(DotNetName)</DotNetPath> + </PropertyGroup> + +</Project> \ No newline at end of file diff --git a/catalyst/build/TeamCatalyst.Catalyst.ErrorChecker.targets b/catalyst/build/TeamCatalyst.Catalyst.ErrorChecker.targets new file mode 100644 index 0000000..7c83465 --- /dev/null +++ b/catalyst/build/TeamCatalyst.Catalyst.ErrorChecker.targets @@ -0,0 +1,10 @@ +<Project> + + <Target Name="DisplayErrors" BeforeTargets="Build"> + <Error Text="Invalid option '$(ImportModLoader)' for ImportModLoader; must be 'enable' or 'disable'" Condition=" '$(ImportModLoader)' != 'enable' AND '$(ImportModLoader)' != 'disable' "/> + <Error Text="Invalid option '$(CodeAssist)' for CodeAssist; must be 'enable' or 'disable'" Condition=" '$(CodeAssist)' != 'enable' AND '$(CodeAssist)' != 'disable' "/> + <Error Text="Invalid option '$(PreferDotNetNameToDotNetPath)' for PreferDotNetNameToDotNetPath; must be 'true' or 'false'" Condition=" '$(PreferDotNetNameToDotNetPath)' != 'true' AND '$(PreferDotNetNameToDotNetPath)' != 'false' "/> + <Error Text="Invalid option '$(OverrideTMLBuildTask)' for OverrideTMLBuildTask; must be 'true' or 'false'" Condition=" '$(OverrideTMLBuildTask)' != 'true' AND '$(OverrideTMLBuildTask)' != 'false' "/> + </Target> + +</Project> \ No newline at end of file diff --git a/catalyst/build/TeamCatalyst.Catalyst.ModLoader.targets b/catalyst/build/TeamCatalyst.Catalyst.ModLoader.targets new file mode 100644 index 0000000..18fa0a5 --- /dev/null +++ b/catalyst/build/TeamCatalyst.Catalyst.ModLoader.targets @@ -0,0 +1,14 @@ +<Project> + + <Import Condition=" '$(ImportModLoader)' == 'enable' " Project="$(PathToModLoaderTargetsDir)tModLoader.targets"/> + + <!-- Add tModLoader CodeAssist when enabled. --> + <ItemGroup> + <PackageReference Condition=" '$(CodeAssist)' == 'enable' " Include="tModLoader.CodeAssist" Version="0.1.*"/> + </ItemGroup> + + <!-- Redefine the build task and only run if enabled. --> + <Target Condition=" '$(OverrideTMLBuildTask)' == 'true' " Name="BuildMod" AfterTargets="Build"> + <Exec Command="dotnet $(tMLServerPath) -build $(ProjectDir) -eac $(TargetPath) -define "$(DefineConstants)" -unsafe $(AllowUnsafeBlocks) $(ExtraBuildModFlags)" WorkingDirectory="$(tMLSteamPath)"/> + </Target> +</Project> \ No newline at end of file diff --git a/catalyst/build/TeamCatalyst.Catalyst.ModifyReferences.targets b/catalyst/build/TeamCatalyst.Catalyst.ModifyReferences.targets new file mode 100644 index 0000000..ae1bb03 --- /dev/null +++ b/catalyst/build/TeamCatalyst.Catalyst.ModifyReferences.targets @@ -0,0 +1,29 @@ +<Project> + + <UsingTask TaskName="ModifyReferencesTask" AssemblyFile="../src/TeamCatalyst.Catalyst.Build/bin/TeamCatalyst.Catalyst.Build.dll"/> + + <Target Name="ModifyReferences" DependsOnTargets="ResolveAssemblyReferences" BeforeTargets="ResolveReferences"> + <ModifyReferencesTask ReferencePaths="@(ReferencePath)" Publicizers="$(AssemblyPublicizerPaths)" OutputDirectory="$(CatalystDir)assemblies"> + <Output TaskParameter="ReferencesToAdd" ItemName="_ReferencesToAdd"/> + <Output TaskParameter="ReferencesToRemove" ItemName="_ReferencesToRemove"/> + </ModifyReferencesTask> + + <ItemGroup> + <ReferencePath Remove="@(_ReferencesToRemove)"/> + <ReferencePath Include="@(_ReferencesToAdd)"/> + </ItemGroup> + + <!-- Handle flags for allowing accessing at runtime. --> + + <ItemGroup> + <AssemblyAttribute Include="System.Runtime.CompilerServices.IgnoresAccessChecksToAttribute"> + <_Parameter1>%(_ReferencesToAdd.Filename)</_Parameter1> + </AssemblyAttribute> + </ItemGroup> + + <PropertyGroup> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + </PropertyGroup> + </Target> + +</Project> \ No newline at end of file diff --git a/catalyst/build/TeamCatalyst.Catalyst.targets b/catalyst/build/TeamCatalyst.Catalyst.targets new file mode 100644 index 0000000..6a384fb --- /dev/null +++ b/catalyst/build/TeamCatalyst.Catalyst.targets @@ -0,0 +1,16 @@ +<Project> + + <Import Project="TeamCatalyst.Catalyst.DotNetPath.targets"/> + <Import Project="TeamCatalyst.Catalyst.ModLoader.targets"/> + <Import Project="TeamCatalyst.Catalyst.ModifyReferences.targets"/> + <Import Project="TeamCatalyst.Catalyst.ErrorChecker.targets"/> + + <ItemGroup> + <PackageReference Include="JetBrains.Annotations" Version="2023.3.0"/> + </ItemGroup> + + <ItemGroup> + <ProjectReference Include="$(MSBuildThisFileDirectory)/../src/TeamCatalyst.Catalyst.Build/TeamCatalyst.Catalyst.Build.csproj" Private="true" PrivateAssets="all" ReferenceOutputAssembly="false" OutputItemType="Analyzer"/> + </ItemGroup> + +</Project> \ No newline at end of file diff --git a/catalyst/src/TeamCatalyst.Catalyst.Abstractions/AssemblyRewriting/AssemblyRewritingContext.cs b/catalyst/src/TeamCatalyst.Catalyst.Abstractions/AssemblyRewriting/AssemblyRewritingContext.cs new file mode 100644 index 0000000..6b8007b --- /dev/null +++ b/catalyst/src/TeamCatalyst.Catalyst.Abstractions/AssemblyRewriting/AssemblyRewritingContext.cs @@ -0,0 +1,20 @@ +using AsmResolver.DotNet; + +namespace TeamCatalyst.Catalyst.Abstractions.AssemblyRewriting; + +public readonly record struct AssemblyRewritingContext { + public string AssemblyName { get; } + + public string AssemblyPath { get; } + + public AssemblyDefinition Assembly { get; } + + public ModuleDefinition Module { get; } + + public AssemblyRewritingContext(string assemblyName, string assemblyPath, AssemblyDefinition assembly, ModuleDefinition module) { + AssemblyName = assemblyName; + AssemblyPath = assemblyPath; + Assembly = assembly; + Module = module; + } +} diff --git a/catalyst/src/TeamCatalyst.Catalyst.Abstractions/AssemblyRewriting/IAssemblyRewriter.cs b/catalyst/src/TeamCatalyst.Catalyst.Abstractions/AssemblyRewriting/IAssemblyRewriter.cs new file mode 100644 index 0000000..18e93f3 --- /dev/null +++ b/catalyst/src/TeamCatalyst.Catalyst.Abstractions/AssemblyRewriting/IAssemblyRewriter.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; +using System.Security.Cryptography; + +namespace TeamCatalyst.Catalyst.Abstractions.AssemblyRewriting; + +public interface IAssemblyRewriter { + AssemblyRewritingContext Context { get; } + + bool ProcessAssembly(); + + IEnumerable<(string name, byte[] data)> GetAuxiliaryFiles(); + + void Hash(ICryptoTransform hash); +} diff --git a/catalyst/src/TeamCatalyst.Catalyst.Abstractions/Engines/EngineRegistry.cs b/catalyst/src/TeamCatalyst.Catalyst.Abstractions/Engines/EngineRegistry.cs new file mode 100644 index 0000000..0f3d3b5 --- /dev/null +++ b/catalyst/src/TeamCatalyst.Catalyst.Abstractions/Engines/EngineRegistry.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; + +namespace TeamCatalyst.Catalyst.Abstractions.Engines; + +public static class EngineRegistry { + private static readonly Dictionary<string, IEngine> engines = new(); + + public static bool TryGetEngineFromExtension(string extension, out IEngine? engine) { + return engines.TryGetValue(extension, out engine); + } + + public static void RegisterEngineWithExtensions(IEngine engine, params string[] extensions) { + foreach (var extension in extensions) + engines[extension] = engine; + } +} diff --git a/catalyst/src/TeamCatalyst.Catalyst.Abstractions/Engines/IEngine.cs b/catalyst/src/TeamCatalyst.Catalyst.Abstractions/Engines/IEngine.cs new file mode 100644 index 0000000..b146be8 --- /dev/null +++ b/catalyst/src/TeamCatalyst.Catalyst.Abstractions/Engines/IEngine.cs @@ -0,0 +1,7 @@ +using TeamCatalyst.Catalyst.Abstractions.ReferenceModification; + +namespace TeamCatalyst.Catalyst.Abstractions.Engines; + +public interface IEngine { + PublicReferenceManifest ProcessAssemblyPublicizer(string filePath); +} diff --git a/catalyst/src/TeamCatalyst.Catalyst.Abstractions/Hashing/Hasher.cs b/catalyst/src/TeamCatalyst.Catalyst.Abstractions/Hashing/Hasher.cs new file mode 100644 index 0000000..335df60 --- /dev/null +++ b/catalyst/src/TeamCatalyst.Catalyst.Abstractions/Hashing/Hasher.cs @@ -0,0 +1,45 @@ +using System; +using System.Security.Cryptography; +using System.Text; +using TeamCatalyst.Catalyst.Abstractions.AssemblyRewriting; + +namespace TeamCatalyst.Catalyst.Abstractions.Hashing; + +public static class Hasher { + public static void HashBuffer(this ICryptoTransform hash, byte[] buffer) { + hash.TransformBlock(buffer, 0, buffer.Length, buffer, 0); + } + + public static void HashString(this ICryptoTransform hash, string value) { + HashBuffer(hash, Encoding.UTF8.GetBytes(value)); + } + + public static void HashInt32(this ICryptoTransform hash, int value) { + HashBuffer(hash, BitConverter.GetBytes(value)); + } + + public static void HashBoolean(this ICryptoTransform hash, bool value) { + HashBuffer(hash, BitConverter.GetBytes(value)); + } + + public static string ComputeHash(byte[] bytes, params IAssemblyRewriter[] hashers) { + using var md5 = MD5.Create(); + + // TODO: Hash versions here. + + foreach (var hasher in hashers) + hasher.Hash(md5); + + md5.TransformFinalBlock(bytes, 0, bytes.Length); + return ByteArrayToString(md5.Hash); + } + + private static string ByteArrayToString(byte[] data) { + var sb = new StringBuilder(data.Length * 2); + + foreach (var datum in data) + sb.Append(datum.ToString("x2")); + + return sb.ToString(); + } +} diff --git a/catalyst/src/TeamCatalyst.Catalyst.Abstractions/ReferenceModification/PublicReferenceManifest.cs b/catalyst/src/TeamCatalyst.Catalyst.Abstractions/ReferenceModification/PublicReferenceManifest.cs new file mode 100644 index 0000000..a6eec61 --- /dev/null +++ b/catalyst/src/TeamCatalyst.Catalyst.Abstractions/ReferenceModification/PublicReferenceManifest.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; + +namespace TeamCatalyst.Catalyst.Abstractions.ReferenceModification; + +public sealed class PublicReferenceManifest { + public string Name { get; } + + public Dictionary<string, PublicReferenceRecord> Assemblies { get; } = new(); + + public PublicReferenceManifest(string name) { + Name = name; + } +} diff --git a/catalyst/src/TeamCatalyst.Catalyst.Abstractions/ReferenceModification/PublicReferenceRecord.cs b/catalyst/src/TeamCatalyst.Catalyst.Abstractions/ReferenceModification/PublicReferenceRecord.cs new file mode 100644 index 0000000..e48364d --- /dev/null +++ b/catalyst/src/TeamCatalyst.Catalyst.Abstractions/ReferenceModification/PublicReferenceRecord.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; + +namespace TeamCatalyst.Catalyst.Abstractions.ReferenceModification; + +public sealed class PublicReferenceRecord { + public string AssemblyName { get; } + + public bool PublicizeAllMembersAndTypes { get; set; } + + public bool AllowVirtualMembers { get; set; } + + public List<PublicReferenceType> Types { get; } = new(); + + public PublicReferenceRecord(string assemblyName, bool publicizeAllMembersAndTypes, bool allowVirtualMembers) { + AssemblyName = assemblyName; + PublicizeAllMembersAndTypes = publicizeAllMembersAndTypes; + AllowVirtualMembers = allowVirtualMembers; + } +} diff --git a/catalyst/src/TeamCatalyst.Catalyst.Abstractions/ReferenceModification/PublicReferenceType.cs b/catalyst/src/TeamCatalyst.Catalyst.Abstractions/ReferenceModification/PublicReferenceType.cs new file mode 100644 index 0000000..03a9dc5 --- /dev/null +++ b/catalyst/src/TeamCatalyst.Catalyst.Abstractions/ReferenceModification/PublicReferenceType.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; + +namespace TeamCatalyst.Catalyst.Abstractions.ReferenceModification; + +public sealed class PublicReferenceType { + public string TypeName { get; } + + public bool PublicizeSelf { get; set; } + + public bool PublicizeAllMembers { get; set; } + + public List<string> Fields { get; } = new(); + + public List<string> Properties { get; } = new(); + + public List<string> Events { get; } = new(); + + public List<string> Methods { get; } = new(); + + public PublicReferenceType(string typeName, bool publicizeSelf, bool publicizeAllMembers) { + TypeName = typeName; + PublicizeSelf = publicizeSelf; + PublicizeAllMembers = publicizeAllMembers; + } +} diff --git a/catalyst/src/TeamCatalyst.Catalyst.Abstractions/TeamCatalyst.Catalyst.Abstractions.csproj b/catalyst/src/TeamCatalyst.Catalyst.Abstractions/TeamCatalyst.Catalyst.Abstractions.csproj new file mode 100644 index 0000000..92a647f --- /dev/null +++ b/catalyst/src/TeamCatalyst.Catalyst.Abstractions/TeamCatalyst.Catalyst.Abstractions.csproj @@ -0,0 +1,16 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFramework>netstandard2.0</TargetFramework> + <LangVersion>latest</LangVersion> + <Nullable>enable</Nullable> + + <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> + </PropertyGroup> + + <ItemGroup> + <PackageReference Include="AsmResolver.DotNet" Version="5.5.0"/> + <PackageReference Include="JetBrains.Annotations" Version="2023.3.0"/> + </ItemGroup> + +</Project> \ No newline at end of file diff --git a/catalyst/src/TeamCatalyst.Catalyst.Annotations/AnnotationsProvider.cs b/catalyst/src/TeamCatalyst.Catalyst.Annotations/AnnotationsProvider.cs new file mode 100644 index 0000000..1d9c94a --- /dev/null +++ b/catalyst/src/TeamCatalyst.Catalyst.Annotations/AnnotationsProvider.cs @@ -0,0 +1,25 @@ +using System.IO; + +namespace TeamCatalyst.Catalyst.Annotations; + +public static class AnnotationsProvider { + public static bool TryGetAnnotationsForAssembly(string assemblyName, out string? annotations) { + var asm = typeof(AnnotationsProvider).Assembly; + var resourceName = $"{asm.GetName().Name}.{assemblyName}.Attributes.xml"; + try { + using var stream = asm.GetManifestResourceStream(resourceName); + if (stream == null) { + annotations = null; + return false; + } + + using var reader = new StreamReader(stream); + annotations = reader.ReadToEnd(); + return true; + } + catch { + annotations = null; + return false; + } + } +} diff --git a/catalyst/src/TeamCatalyst.Catalyst.Annotations/FNA/Attributes.xml b/catalyst/src/TeamCatalyst.Catalyst.Annotations/FNA/Attributes.xml new file mode 100644 index 0000000..8019dfb --- /dev/null +++ b/catalyst/src/TeamCatalyst.Catalyst.Annotations/FNA/Attributes.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<assembly name="FNA"> + +</assembly> \ No newline at end of file diff --git a/catalyst/src/TeamCatalyst.Catalyst.Annotations/TeamCatalyst.Catalyst.Annotations.csproj b/catalyst/src/TeamCatalyst.Catalyst.Annotations/TeamCatalyst.Catalyst.Annotations.csproj new file mode 100644 index 0000000..6e14f06 --- /dev/null +++ b/catalyst/src/TeamCatalyst.Catalyst.Annotations/TeamCatalyst.Catalyst.Annotations.csproj @@ -0,0 +1,14 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFramework>netstandard2.0</TargetFramework> + <LangVersion>latest</LangVersion> + <Nullable>enable</Nullable> + </PropertyGroup> + + <ItemGroup> + <None Remove="**\*.xml"/> + <EmbeddedResource Include="**\*.xml"/> + </ItemGroup> + +</Project> \ No newline at end of file diff --git a/catalyst/src/TeamCatalyst.Catalyst.Annotations/tModLoader/Attributes.xml b/catalyst/src/TeamCatalyst.Catalyst.Annotations/tModLoader/Attributes.xml new file mode 100644 index 0000000..50ea5d2 --- /dev/null +++ b/catalyst/src/TeamCatalyst.Catalyst.Annotations/tModLoader/Attributes.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<assembly name="tModLoader"> + <member name="T:Terraria.ModLoader.ILoadable"> + <attribute ctor="M:JetBrains.Annotations.UsedImplicitlyAttribute.#ctor(JetBrains.Annotations.ImplicitUseKindFlags,JetBrains.Annotations.ImplicitUseTargetFlags)"> + <argument>4</argument> + <argument>4</argument> + </attribute> + </member> + <member name="T:Terraria.ModLoader.Mod"> + <attribute ctor="M:JetBrains.Annotations.UsedImplicitlyAttribute.#ctor(JetBrains.Annotations.ImplicitUseKindFlags,JetBrains.Annotations.ImplicitUseTargetFlags)"> + <argument>4</argument> + <argument>4</argument> + </attribute> + </member> +</assembly> \ No newline at end of file diff --git a/catalyst/src/TeamCatalyst.Catalyst.Build.JavaScript/JavaScriptEngine.cs b/catalyst/src/TeamCatalyst.Catalyst.Build.JavaScript/JavaScriptEngine.cs new file mode 100644 index 0000000..675fdc1 --- /dev/null +++ b/catalyst/src/TeamCatalyst.Catalyst.Build.JavaScript/JavaScriptEngine.cs @@ -0,0 +1,34 @@ +using System; +using System.IO; +using Jint; +using Jint.Native; +using Jint.Runtime.Interop; +using TeamCatalyst.Catalyst.Abstractions.Engines; +using TeamCatalyst.Catalyst.Abstractions.ReferenceModification; +using TeamCatalyst.Catalyst.Build.JavaScript.ReferenceModification; + +namespace TeamCatalyst.Catalyst.Build.JavaScript; + +public sealed class JavaScriptEngine : IEngine { + public PublicReferenceManifest ProcessAssemblyPublicizer(string filePath) { + using var engine = new Engine(); + + engine.Modules.Add( + "publicizer", + builder => { + builder.ExportFunction("createPublicizer", createPublicizer); + } + ); + + engine.Modules.Add("publicizerModule", File.ReadAllText(filePath)); + var publicizerModule = engine.Modules.Import("publicizerModule"); + return ((JsReferenceManifest)((ObjectWrapper)publicizerModule.Get("publicizer").AsObject()).Target).ToManifest(); + + JsValue createPublicizer(JsValue[] arguments) { + var name = arguments[0].AsString(); + + // ReSharper disable once AccessToDisposedClosure + return JsValue.FromObject(engine, new JsReferenceManifest(name)); + } + } +} diff --git a/catalyst/src/TeamCatalyst.Catalyst.Build.JavaScript/ReferenceModification/JsReferenceManifest.cs b/catalyst/src/TeamCatalyst.Catalyst.Build.JavaScript/ReferenceModification/JsReferenceManifest.cs new file mode 100644 index 0000000..86297c9 --- /dev/null +++ b/catalyst/src/TeamCatalyst.Catalyst.Build.JavaScript/ReferenceModification/JsReferenceManifest.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; +using JetBrains.Annotations; +using TeamCatalyst.Catalyst.Abstractions.ReferenceModification; + +namespace TeamCatalyst.Catalyst.Build.JavaScript.ReferenceModification; + +internal sealed class JsReferenceManifest { + public string Name { get; } + + public List<JsReferenceRecord> Assemblies { get; } = new(); + + public JsReferenceManifest(string name) { + Name = name; + } + + [UsedImplicitly(ImplicitUseKindFlags.Access)] + public JsReferenceRecord CreateAssembly(string name) { + var record = new JsReferenceRecord(name); + Assemblies.Add(record); + return record; + } + + public PublicReferenceManifest ToManifest() { + var manifest = new PublicReferenceManifest(Name); + + foreach (var asm in Assemblies) { + var record = manifest.Assemblies[asm.AssemblyName] = new PublicReferenceRecord(asm.AssemblyName, asm.PublicizeAllMembersAndTypes, asm.AllowVirtualsForEntireAssembly); + + foreach (var type in asm.Types) { + var pubType = new PublicReferenceType(type.FullName, type.PublicizeThisType, type.PublicizeAllMembers); + record.Types.Add(pubType); + + pubType.Fields.AddRange(type.FieldsToPublicize); + pubType.Properties.AddRange(type.PropertiesToPublicize); + pubType.Events.AddRange(type.EventsToPublicize); + pubType.Methods.AddRange(type.Methods); + } + } + + return manifest; + } +} diff --git a/catalyst/src/TeamCatalyst.Catalyst.Build.JavaScript/ReferenceModification/JsReferenceRecord.cs b/catalyst/src/TeamCatalyst.Catalyst.Build.JavaScript/ReferenceModification/JsReferenceRecord.cs new file mode 100644 index 0000000..2248f99 --- /dev/null +++ b/catalyst/src/TeamCatalyst.Catalyst.Build.JavaScript/ReferenceModification/JsReferenceRecord.cs @@ -0,0 +1,37 @@ +using System.Collections.Generic; +using JetBrains.Annotations; + +namespace TeamCatalyst.Catalyst.Build.JavaScript.ReferenceModification; + +internal sealed class JsReferenceRecord { + public string AssemblyName { get; } + + public bool PublicizeAllMembersAndTypes { get; set; } + + public bool AllowVirtualsForEntireAssembly { get; set; } + + public List<JsReferenceType> Types { get; } = new(); + + public JsReferenceRecord(string assemblyName) { + AssemblyName = assemblyName; + } + + [UsedImplicitly(ImplicitUseKindFlags.Access)] + public JsReferenceRecord AllowVirtuals() { + AllowVirtualsForEntireAssembly = true; + return this; + } + + [UsedImplicitly(ImplicitUseKindFlags.Access)] + public JsReferenceRecord PublicizeAll() { + PublicizeAllMembersAndTypes = true; + return this; + } + + [UsedImplicitly(ImplicitUseKindFlags.Access)] + public JsReferenceType CreateType(string name) { + var type = new JsReferenceType(name); + Types.Add(type); + return type; + } +} diff --git a/catalyst/src/TeamCatalyst.Catalyst.Build.JavaScript/ReferenceModification/JsReferenceType.cs b/catalyst/src/TeamCatalyst.Catalyst.Build.JavaScript/ReferenceModification/JsReferenceType.cs new file mode 100644 index 0000000..c37c676 --- /dev/null +++ b/catalyst/src/TeamCatalyst.Catalyst.Build.JavaScript/ReferenceModification/JsReferenceType.cs @@ -0,0 +1,60 @@ +using System.Collections.Generic; +using JetBrains.Annotations; + +namespace TeamCatalyst.Catalyst.Build.JavaScript.ReferenceModification; + +internal sealed class JsReferenceType { + public string FullName { get; } + + public bool PublicizeThisType { get; set; } + + public bool PublicizeAllMembers { get; set; } + + public List<string> FieldsToPublicize { get; } = new(); + + public List<string> PropertiesToPublicize { get; } = new(); + + public List<string> EventsToPublicize { get; } = new(); + + public List<string> Methods { get; } = new(); + + public JsReferenceType(string fullName) { + FullName = fullName; + } + + [UsedImplicitly(ImplicitUseKindFlags.Access)] + public JsReferenceType PublicizeType() { + PublicizeThisType = true; + return this; + } + + [UsedImplicitly(ImplicitUseKindFlags.Access)] + public JsReferenceType PublicizeMembers() { + PublicizeAllMembers = true; + return this; + } + + [UsedImplicitly(ImplicitUseKindFlags.Access)] + public JsReferenceType PublicizeField(string name) { + FieldsToPublicize.Add(name); + return this; + } + + [UsedImplicitly(ImplicitUseKindFlags.Access)] + public JsReferenceType PublicizeProperty(string name) { + PropertiesToPublicize.Add(name); + return this; + } + + [UsedImplicitly(ImplicitUseKindFlags.Access)] + public JsReferenceType PublicizeEvent(string name) { + EventsToPublicize.Add(name); + return this; + } + + [UsedImplicitly(ImplicitUseKindFlags.Access)] + public JsReferenceType PublicizeMethod(string name) { + Methods.Add(name); + return this; + } +} diff --git a/catalyst/src/TeamCatalyst.Catalyst.Build.JavaScript/TeamCatalyst.Catalyst.Build.JavaScript.csproj b/catalyst/src/TeamCatalyst.Catalyst.Build.JavaScript/TeamCatalyst.Catalyst.Build.JavaScript.csproj new file mode 100644 index 0000000..0561165 --- /dev/null +++ b/catalyst/src/TeamCatalyst.Catalyst.Build.JavaScript/TeamCatalyst.Catalyst.Build.JavaScript.csproj @@ -0,0 +1,19 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFramework>netstandard2.0</TargetFramework> + <LangVersion>latest</LangVersion> + <Nullable>enable</Nullable> + + <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> + </PropertyGroup> + + <ItemGroup> + <ProjectReference Include="..\TeamCatalyst.Catalyst.Abstractions\TeamCatalyst.Catalyst.Abstractions.csproj"/> + </ItemGroup> + + <ItemGroup> + <PackageReference Include="Jint" Version="3.0.0-beta-2059"/> + </ItemGroup> + +</Project> \ No newline at end of file diff --git a/catalyst/src/TeamCatalyst.Catalyst.Build.Json/JsonEngine.cs b/catalyst/src/TeamCatalyst.Catalyst.Build.Json/JsonEngine.cs new file mode 100644 index 0000000..c67e3d7 --- /dev/null +++ b/catalyst/src/TeamCatalyst.Catalyst.Build.Json/JsonEngine.cs @@ -0,0 +1,10 @@ +using TeamCatalyst.Catalyst.Abstractions.Engines; +using TeamCatalyst.Catalyst.Abstractions.ReferenceModification; + +namespace TeamCatalyst.Catalyst.Build.Json; + +public sealed class JsonEngine : IEngine { + public PublicReferenceManifest ProcessAssemblyPublicizer(string filePath) { + throw new System.NotImplementedException(); + } +} diff --git a/catalyst/src/TeamCatalyst.Catalyst.Build.Json/TeamCatalyst.Catalyst.Build.Json.csproj b/catalyst/src/TeamCatalyst.Catalyst.Build.Json/TeamCatalyst.Catalyst.Build.Json.csproj new file mode 100644 index 0000000..a1bfc0f --- /dev/null +++ b/catalyst/src/TeamCatalyst.Catalyst.Build.Json/TeamCatalyst.Catalyst.Build.Json.csproj @@ -0,0 +1,19 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFramework>netstandard2.0</TargetFramework> + <LangVersion>latest</LangVersion> + <Nullable>enable</Nullable> + + <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> + </PropertyGroup> + + <ItemGroup> + <ProjectReference Include="..\TeamCatalyst.Catalyst.Abstractions\TeamCatalyst.Catalyst.Abstractions.csproj"/> + </ItemGroup> + + <ItemGroup> + <PackageReference Include="Newtonsoft.Json" Version="13.0.3"/> + </ItemGroup> + +</Project> \ No newline at end of file diff --git a/catalyst/src/TeamCatalyst.Catalyst.Build.Lua/LuaEngine.cs b/catalyst/src/TeamCatalyst.Catalyst.Build.Lua/LuaEngine.cs new file mode 100644 index 0000000..0232dfd --- /dev/null +++ b/catalyst/src/TeamCatalyst.Catalyst.Build.Lua/LuaEngine.cs @@ -0,0 +1,10 @@ +using TeamCatalyst.Catalyst.Abstractions.Engines; +using TeamCatalyst.Catalyst.Abstractions.ReferenceModification; + +namespace TeamCatalyst.Catalyst.Build.Lua; + +public sealed class LuaEngine : IEngine { + public PublicReferenceManifest ProcessAssemblyPublicizer(string filePath) { + throw new System.NotImplementedException(); + } +} diff --git a/catalyst/src/TeamCatalyst.Catalyst.Build.Lua/TeamCatalyst.Catalyst.Build.Lua.csproj b/catalyst/src/TeamCatalyst.Catalyst.Build.Lua/TeamCatalyst.Catalyst.Build.Lua.csproj new file mode 100644 index 0000000..a93ecad --- /dev/null +++ b/catalyst/src/TeamCatalyst.Catalyst.Build.Lua/TeamCatalyst.Catalyst.Build.Lua.csproj @@ -0,0 +1,15 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFramework>netstandard2.0</TargetFramework> + <LangVersion>latest</LangVersion> + <Nullable>enable</Nullable> + + <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> + </PropertyGroup> + + <ItemGroup> + <ProjectReference Include="..\TeamCatalyst.Catalyst.Abstractions\TeamCatalyst.Catalyst.Abstractions.csproj"/> + </ItemGroup> + +</Project> diff --git a/catalyst/src/TeamCatalyst.Catalyst.Build/AssemblyRewriting/AnnotationProviderAssemblyRewriter.cs b/catalyst/src/TeamCatalyst.Catalyst.Build/AssemblyRewriting/AnnotationProviderAssemblyRewriter.cs new file mode 100644 index 0000000..55d420b --- /dev/null +++ b/catalyst/src/TeamCatalyst.Catalyst.Build/AssemblyRewriting/AnnotationProviderAssemblyRewriter.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; +using System.Security.Cryptography; +using System.Text; +using TeamCatalyst.Catalyst.Abstractions.AssemblyRewriting; +using TeamCatalyst.Catalyst.Abstractions.Hashing; +using TeamCatalyst.Catalyst.Annotations; + +namespace TeamCatalyst.Catalyst.Build.AssemblyRewriting; + +public sealed class AnnotationProviderAssemblyRewriter : IAssemblyRewriter { + public AssemblyRewritingContext Context { get; } + + private readonly string? attributes; + + public AnnotationProviderAssemblyRewriter(AssemblyRewritingContext context) { + Context = context; + AnnotationsProvider.TryGetAnnotationsForAssembly(context.AssemblyName, out attributes); + } + + bool IAssemblyRewriter.ProcessAssembly() { + return attributes is not null; + } + + IEnumerable<(string name, byte[] data)> IAssemblyRewriter.GetAuxiliaryFiles() { + yield return ($"{Context.AssemblyName}.ExternalAnnotations.xml", Encoding.UTF8.GetBytes(attributes!)); + } + + void IAssemblyRewriter.Hash(ICryptoTransform hash) { + hash.HashString(attributes ?? ""); + } +} diff --git a/catalyst/src/TeamCatalyst.Catalyst.Build/AssemblyRewriting/PublicizerAssemblyRewriter.cs b/catalyst/src/TeamCatalyst.Catalyst.Build/AssemblyRewriting/PublicizerAssemblyRewriter.cs new file mode 100644 index 0000000..861e144 --- /dev/null +++ b/catalyst/src/TeamCatalyst.Catalyst.Build/AssemblyRewriting/PublicizerAssemblyRewriter.cs @@ -0,0 +1,195 @@ +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using AsmResolver.DotNet; +using AsmResolver.PE.DotNet.Metadata.Tables.Rows; +using TeamCatalyst.Catalyst.Abstractions.AssemblyRewriting; +using TeamCatalyst.Catalyst.Abstractions.Hashing; +using TeamCatalyst.Catalyst.Abstractions.ReferenceModification; + +namespace TeamCatalyst.Catalyst.Build.AssemblyRewriting; + +internal sealed class PublicizerAssemblyRewriter : IAssemblyRewriter { + public PublicReferenceManifest Manifest { get; } + + public AssemblyRewritingContext Context { get; } + + public PublicizerAssemblyRewriter(AssemblyRewritingContext context, PublicReferenceManifest manifest) { + Context = context; + Manifest = manifest; + } + + bool IAssemblyRewriter.ProcessAssembly() { + foreach (var manifestAssembly in Manifest.Assemblies) { + if (manifestAssembly.Key != Context.Assembly.Name) + continue; + + var publicizeAll = manifestAssembly.Value.PublicizeAllMembersAndTypes; + var includeVirtuals = manifestAssembly.Value.AllowVirtualMembers; + + var types = Context.Assembly.Modules.SelectMany(x => x.GetAllTypes()).ToList(); + + if (publicizeAll) + PublicizeAllTypesAndMembers(types, includeVirtuals); + else { + foreach (var manifestType in manifestAssembly.Value.Types) { + // Fall back to just checking the type name minus the + // namespace, which is iffy but user-friendly. + var type = types.FirstOrDefault(x => x.FullName == manifestType.TypeName) ?? types.FirstOrDefault(x => x.Name == manifestType.TypeName); + + // TODO: Log? + if (type is null) + continue; + + PublicizeType(type, includeVirtuals, manifestType.PublicizeAllMembers, manifestType.PublicizeSelf); + + if (manifestType.PublicizeAllMembers) + continue; + + foreach (var requestedField in manifestType.Fields) { + var field = type.Fields.FirstOrDefault(x => x.Name == requestedField); + + // TODO: Log? + if (field is not null) + PublicizeField(field); + } + + foreach (var requestedProperty in manifestType.Properties) { + var property = type.Properties.FirstOrDefault(x => x.Name == requestedProperty); + + // TODO: Log? + if (property is not null) + PublicizeProperty(property, includeVirtuals); + } + + foreach (var requestedEvent in manifestType.Events) { + var @event = type.Events.FirstOrDefault(x => x.Name == requestedEvent); + + // TODO: Log? + if (@event is not null) + PublicizeEvent(@event, includeVirtuals); + } + + foreach (var requestedMethod in manifestType.Methods) { + var fullSig = requestedMethod.Contains('('); + + var methods = new List<MethodDefinition>(); + + // Check the full name and expect only one result. + if (fullSig) { + methods.Add(type.Methods.FirstOrDefault(x => x.FullName == requestedMethod)); + } + else { + // Otherwise expect multiple results to account for + // overloads. + methods.AddRange(type.Methods.Where(x => x.Name == requestedMethod)); + } + + // TODO: Log when methods.Length == 0? + + foreach (var method in methods) + PublicizeMethod(method, includeVirtuals); + } + } + } + + return true; + } + + return false; + } + + IEnumerable<(string name, byte[] data)> IAssemblyRewriter.GetAuxiliaryFiles() { + yield break; + } + + void IAssemblyRewriter.Hash(ICryptoTransform hash) { + hash.HashString( Manifest.Name); + + foreach (var asm in Manifest.Assemblies) { + hash.HashString( asm.Key); + hash.HashString( asm.Value.AssemblyName); + hash.HashBoolean( asm.Value.PublicizeAllMembersAndTypes); + hash.HashBoolean( asm.Value.AllowVirtualMembers); + + foreach (var type in asm.Value.Types) { + hash.HashString( type.TypeName); + hash.HashBoolean( type.PublicizeSelf); + hash.HashBoolean( type.PublicizeAllMembers); + + foreach (var field in type.Fields) + hash.HashString( field); + + foreach (var property in type.Properties) + hash.HashString( property); + + foreach (var @event in type.Events) + hash.HashString( @event); + + foreach (var method in type.Methods) + hash.HashString( method); + } + } + } + + private static void PublicizeAllTypesAndMembers(List<TypeDefinition> types, bool includeVirtuals) { + foreach (var type in types) + PublicizeType(type, includeVirtuals, true, true); + } + + private static void PublicizeType(TypeDefinition typeDefinition, bool includeVirtuals, bool publicizeAllMembers, bool publicizeSelf) { + if (publicizeSelf) { + typeDefinition.Attributes &= ~TypeAttributes.VisibilityMask; + typeDefinition.Attributes |= typeDefinition.IsNested ? TypeAttributes.NestedPublic : TypeAttributes.Public; + } + + if (!publicizeAllMembers) + return; + + foreach (var field in typeDefinition.Fields) { + // Filter out fields that share names with events. + if (typeDefinition.Events.Any(x => x.Name == field.Name)) + continue; + + PublicizeField(field); + } + + foreach (var property in typeDefinition.Properties) + PublicizeProperty(property, includeVirtuals); + + foreach (var @event in typeDefinition.Events) + PublicizeEvent(@event, includeVirtuals); + + foreach (var method in typeDefinition.Methods) + PublicizeMethod(method, includeVirtuals); + } + + private static void PublicizeField(FieldDefinition fieldDefinition) { + fieldDefinition.Attributes &= ~FieldAttributes.FieldAccessMask; + fieldDefinition.Attributes |= FieldAttributes.Public; + } + + private static void PublicizeProperty(PropertyDefinition propertyDefinition, bool includeVirtuals) { + if (propertyDefinition.GetMethod is not null) + PublicizeMethod(propertyDefinition.GetMethod, includeVirtuals); + + if (propertyDefinition.SetMethod is not null) + PublicizeMethod(propertyDefinition.SetMethod, includeVirtuals); + } + + private static void PublicizeEvent(EventDefinition eventDefinition, bool includeVirtuals) { + if (eventDefinition.AddMethod is not null) + PublicizeMethod(eventDefinition.AddMethod, includeVirtuals); + + if (eventDefinition.RemoveMethod is not null) + PublicizeMethod(eventDefinition.RemoveMethod, includeVirtuals); + } + + private static void PublicizeMethod(MethodDefinition methodDefinition, bool includeVirtuals) { + if (methodDefinition.IsVirtual && !includeVirtuals) + return; + + methodDefinition.Attributes &= ~MethodAttributes.MemberAccessMask; + methodDefinition.Attributes |= MethodAttributes.Public; + } +} diff --git a/catalyst/src/TeamCatalyst.Catalyst.Build/AssemblyRewriting/SummaryProviderAssemblyRewriter.cs b/catalyst/src/TeamCatalyst.Catalyst.Build/AssemblyRewriting/SummaryProviderAssemblyRewriter.cs new file mode 100644 index 0000000..c661ce2 --- /dev/null +++ b/catalyst/src/TeamCatalyst.Catalyst.Build/AssemblyRewriting/SummaryProviderAssemblyRewriter.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using System.IO; +using System.Security.Cryptography; +using TeamCatalyst.Catalyst.Abstractions.AssemblyRewriting; +using TeamCatalyst.Catalyst.Abstractions.Hashing; + +namespace TeamCatalyst.Catalyst.Build.AssemblyRewriting; + +public sealed class SummaryProviderAssemblyRewriter : IAssemblyRewriter { + public AssemblyRewritingContext Context { get; } + + private readonly string? summaryPath; + + public SummaryProviderAssemblyRewriter(AssemblyRewritingContext context) { + Context = context; + + var documentationPath = Path.Combine(Path.GetDirectoryName(Context.AssemblyPath)!, Context.AssemblyName + ".xml"); + if (File.Exists(documentationPath)) + summaryPath = documentationPath; + } + + bool IAssemblyRewriter.ProcessAssembly() { + return false; + } + + IEnumerable<(string name, byte[] data)> IAssemblyRewriter.GetAuxiliaryFiles() { + if (summaryPath is null) + yield break; + + yield return (Path.GetFileName(summaryPath), File.ReadAllBytes(summaryPath)); + } + + void IAssemblyRewriter.Hash(ICryptoTransform hash) { + hash.HashBoolean(summaryPath is not null); + } +} diff --git a/catalyst/src/TeamCatalyst.Catalyst.Build/EngineInitializer.cs b/catalyst/src/TeamCatalyst.Catalyst.Build/EngineInitializer.cs new file mode 100644 index 0000000..299720b --- /dev/null +++ b/catalyst/src/TeamCatalyst.Catalyst.Build/EngineInitializer.cs @@ -0,0 +1,17 @@ +using System.Runtime.CompilerServices; +using TeamCatalyst.Catalyst.Abstractions.Engines; +using TeamCatalyst.Catalyst.Build.JavaScript; +using TeamCatalyst.Catalyst.Build.Json; +using TeamCatalyst.Catalyst.Build.Lua; + +namespace TeamCatalyst.Catalyst.Build; + +internal static class EngineInitializer { + [ModuleInitializer] + internal static void Initialize() { + EngineRegistry.RegisterEngineWithExtensions(new LuaEngine(), ".lua"); + EngineRegistry.RegisterEngineWithExtensions(new JsonEngine(), ".json", ".jsonc", ".json5"); + // TODO: What does Jint actually support? + EngineRegistry.RegisterEngineWithExtensions(new JavaScriptEngine(), ".js", ".mjs", ".cjs"); + } +} diff --git a/catalyst/src/TeamCatalyst.Catalyst.Build/ProjectBuilding/AbstractTask.cs b/catalyst/src/TeamCatalyst.Catalyst.Build/ProjectBuilding/AbstractTask.cs new file mode 100644 index 0000000..d86b78d --- /dev/null +++ b/catalyst/src/TeamCatalyst.Catalyst.Build/ProjectBuilding/AbstractTask.cs @@ -0,0 +1,19 @@ +using System; +using Microsoft.Build.Utilities; + +namespace TeamCatalyst.Catalyst.Build.ProjectBuilding; + +public abstract class AbstractTask : Task { + public sealed override bool Execute() { + try { + return Run(); + } + catch (Exception e) { + Log.LogError("Unhandled exception in task {0}", GetType().Name); + Log.LogErrorFromException(e); + return false; + } + } + + protected abstract bool Run(); +} diff --git a/catalyst/src/TeamCatalyst.Catalyst.Build/ProjectBuilding/Tasks/ReferenceModification/ModifyReferencesTask.cs b/catalyst/src/TeamCatalyst.Catalyst.Build/ProjectBuilding/Tasks/ReferenceModification/ModifyReferencesTask.cs new file mode 100644 index 0000000..1966e78 --- /dev/null +++ b/catalyst/src/TeamCatalyst.Catalyst.Build/ProjectBuilding/Tasks/ReferenceModification/ModifyReferencesTask.cs @@ -0,0 +1,160 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using AsmResolver.DotNet; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; +using TeamCatalyst.Catalyst.Abstractions.AssemblyRewriting; +using TeamCatalyst.Catalyst.Abstractions.Engines; +using TeamCatalyst.Catalyst.Abstractions.Hashing; +using TeamCatalyst.Catalyst.Abstractions.ReferenceModification; +using TeamCatalyst.Catalyst.Build.AssemblyRewriting; + +namespace TeamCatalyst.Catalyst.Build.ProjectBuilding.Tasks.ReferenceModification; + +public sealed class ModifyReferencesTask : AbstractTask { + public ITaskItem[] ReferencePaths { get; set; } = null!; + + public ITaskItem[] Publicizers { get; set; } = null!; + + [Required] + public string OutputDirectory { get; set; } = null!; + + [Output] + public ITaskItem[]? ReferencesToAdd { get; set; } + + [Output] + public ITaskItem[]? ReferencesToRemove { get; set; } + + protected override bool Run() { + if (Publicizers is null || Publicizers.Length == 0) + return true; + + Directory.CreateDirectory(OutputDirectory); + ReferencesToAdd ??= Array.Empty<ITaskItem>(); + ReferencesToRemove ??= Array.Empty<ITaskItem>(); + + var publicManifest = HandlePublicizers(); + + var toAdd = new List<ITaskItem>(); + var toRemove = new List<ITaskItem>(); + + foreach (var reference in ReferencePaths) { + var assemblyName = reference.GetMetadata("Filename"); + var assemblyPath = reference.GetMetadata("FullPath"); + var assemblyBytes = File.ReadAllBytes(assemblyPath); + var assemblyDefinition = AssemblyDefinition.FromBytes(assemblyBytes); + + var context = new AssemblyRewritingContext(assemblyName, assemblyPath, assemblyDefinition, assemblyDefinition.ManifestModule!); + var rewriters = new IAssemblyRewriter[] { + new SummaryProviderAssemblyRewriter(context), + new PublicizerAssemblyRewriter(context, publicManifest), + new AnnotationProviderAssemblyRewriter(context), + }; + + var hash = Hasher.ComputeHash(assemblyBytes, rewriters); + var outputDir = Path.Combine(OutputDirectory, $"{assemblyName}-{hash}"); + var outputPath = Path.Combine(outputDir, $"{assemblyName}.dll"); + Directory.CreateDirectory(outputDir); + + if (File.Exists(outputPath)) { + Log.LogMessage("Skipping reference '{0}' because it already exists in the output directory", assemblyName); + goto ModifyReferences; + } + + if (!RewriteAssembly(rewriters)) + continue; + + Log.LogMessage("Writing modified reference '{0}' to '{1}'", assemblyName, outputPath); + assemblyDefinition.Write(outputPath); + + Log.LogMessage("Writing auxiliary files"); + foreach (var (name, data) in rewriters.SelectMany(x => x.GetAuxiliaryFiles())) + File.WriteAllBytes(Path.Combine(outputDir, name), data); + + ModifyReferences: + var newRef = new TaskItem(outputPath); + reference.CopyMetadataTo(newRef); + toRemove.Add(reference); + toAdd.Add(newRef); + } + + ReferencesToAdd = toAdd.ToArray(); + ReferencesToRemove = toRemove.ToArray(); + return true; + } + + private PublicReferenceManifest HandlePublicizers() { + var publicizerFiles = Publicizers.Select(x => x.ToString()).ToArray(); + Log.LogMessage("Publicizer running with inputs: {0}", string.Join(", ", publicizerFiles)); + + var manifests = new List<PublicReferenceManifest>(); + + foreach (var publicizerFile in publicizerFiles) { + if (!File.Exists(publicizerFile)) { + Log.LogWarning("Publicizer file '{0}' does not exist", publicizerFile); + continue; + } + + if (!EngineRegistry.TryGetEngineFromExtension(Path.GetExtension(publicizerFile), out var engine)) { + Log.LogWarning("Publicizer file '{0}' could not be processed because it does not have a supported extension!"); + continue; + } + + try { + manifests.Add(engine!.ProcessAssemblyPublicizer(publicizerFile)); + } + catch (Exception e) { + Log.LogWarning("Failed to run publicizer file '{0}': {1}", publicizerFile, e.Message); + } + } + + Log.LogMessage("Parsed into {0} manifests", manifests.Count); + return CombineManifests(manifests); + } + + private static PublicReferenceManifest CombineManifests(List<PublicReferenceManifest> manifests) { + var combined = new PublicReferenceManifest("Combined"); + + foreach (var manifest in manifests) { + foreach (var asm in manifest.Assemblies.Values) { + var asmName = asm.AssemblyName; + if (asmName.EndsWith(".dll")) + asmName = asmName[..^".dll".Length]; + + if (!combined.Assemblies.TryGetValue(asmName, out var combinedAsm)) + combined.Assemblies[asmName] = combinedAsm = new PublicReferenceRecord(asmName, false, false); + + if (asm.PublicizeAllMembersAndTypes) + combinedAsm.PublicizeAllMembersAndTypes = true; + + if (asm.AllowVirtualMembers) + combinedAsm.AllowVirtualMembers = true; + + foreach (var type in asm.Types) { + var combinedType = combinedAsm.Types.FirstOrDefault(x => x.TypeName == type.TypeName); + if (combinedType is null) + combinedAsm.Types.Add(combinedType = new PublicReferenceType(type.TypeName, false, false)); + + if (type.PublicizeSelf) + combinedType.PublicizeSelf = true; + + if (type.PublicizeAllMembers) + combinedType.PublicizeAllMembers = true; + + combinedType.Fields.AddRange(type.Fields); + combinedType.Properties.AddRange(type.Properties); + combinedType.Events.AddRange(type.Events); + combinedType.Methods.AddRange(type.Methods); + } + } + } + + return combined; + } + + private static bool RewriteAssembly(params IAssemblyRewriter[] rewriters) { + return rewriters.Aggregate(false, (current, rewriter) => current | rewriter.ProcessAssembly()); + } +} diff --git a/catalyst/src/TeamCatalyst.Catalyst.Build/TeamCatalyst.Catalyst.Build.csproj b/catalyst/src/TeamCatalyst.Catalyst.Build/TeamCatalyst.Catalyst.Build.csproj new file mode 100644 index 0000000..f260b44 --- /dev/null +++ b/catalyst/src/TeamCatalyst.Catalyst.Build/TeamCatalyst.Catalyst.Build.csproj @@ -0,0 +1,32 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFramework>netstandard2.0</TargetFramework> + <LangVersion>latest</LangVersion> + <Nullable>enable</Nullable> + <IsPackable>false</IsPackable> + <EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules> + + <OutDir>$(MSBuildThisFileDirectory)bin\</OutDir> + <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> + </PropertyGroup> + + <ItemGroup> + <PackageReference Include="Microsoft.Build.Utilities.Core" Version="17.8.3"/> + <PackageReference Include="MoonSharp" Version="2.0.0"/> + <PackageReference Include="Newtonsoft.Json" Version="13.0.3"/> + <PackageReference Include="Polyfill" Version="1.34.0"> + <PrivateAssets>all</PrivateAssets> + <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> + </PackageReference> + </ItemGroup> + + <ItemGroup> + <ProjectReference Include="..\TeamCatalyst.Catalyst.Abstractions\TeamCatalyst.Catalyst.Abstractions.csproj"/> + <ProjectReference Include="..\TeamCatalyst.Catalyst.Annotations\TeamCatalyst.Catalyst.Annotations.csproj"/> + <ProjectReference Include="..\TeamCatalyst.Catalyst.Build.JavaScript\TeamCatalyst.Catalyst.Build.JavaScript.csproj"/> + <ProjectReference Include="..\TeamCatalyst.Catalyst.Build.Json\TeamCatalyst.Catalyst.Build.Json.csproj"/> + <ProjectReference Include="..\TeamCatalyst.Catalyst.Build.Lua\TeamCatalyst.Catalyst.Build.Lua.csproj"/> + </ItemGroup> + +</Project> \ No newline at end of file diff --git a/generate-symlinks.js b/generate-symlinks.js new file mode 100644 index 0000000..d256d93 --- /dev/null +++ b/generate-symlinks.js @@ -0,0 +1,16 @@ +const path = require("path"); +const fs = require("fs"); + +const dirs = require("./mods.json"); + +const sourceDirs = dirs.map((dir) => path.join(__dirname, "src", dir)); +const targetDirs = dirs.map((dir) => path.join(__dirname, "..", dir)); + +for (let i = 0; i < sourceDirs.length; i++) { + const sourceDir = sourceDirs[i]; + const targetDir = targetDirs[i]; + + if (!fs.existsSync(targetDir)) { + fs.symlinkSync(sourceDir, targetDir, "dir"); + } +} diff --git a/mods.json b/mods.json new file mode 100644 index 0000000..94dba79 --- /dev/null +++ b/mods.json @@ -0,0 +1 @@ +["Silicate"] diff --git a/scripts/gen-lib.js b/scripts/gen-lib.js new file mode 100644 index 0000000..d73eb8c --- /dev/null +++ b/scripts/gen-lib.js @@ -0,0 +1,23 @@ +const fs = require("fs"); + +const ns = process.argv[2]; +const csprojText = ` +<Project Sdk="Microsoft.NET.Sdk"> + + <Import Project="../../catalyst/Library.Build.targets" /> + + <PropertyGroup> + <TargetFramework>net6.0</TargetFramework> + <LangVersion>latest</LangVersion> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + <Nullable>enable</Nullable> + </PropertyGroup> + +</Project> +`.trim(); + +try { + fs.mkdirSync(`../src/` + ns, { recursive: true }); +} catch (e) {} + +fs.writeFileSync(`../src/${ns}/${ns}.csproj`, csprojText); diff --git a/scripts/gen-mod.js b/scripts/gen-mod.js new file mode 100644 index 0000000..d24dea2 --- /dev/null +++ b/scripts/gen-mod.js @@ -0,0 +1,105 @@ +const fs = require("fs"); + +const ns = process.argv[2]; +const internalName = process.argv[3]; +const csprojText = ` +<Project Sdk="Microsoft.NET.Sdk"> + + <Import Project="../../catalyst/Mod.Build.targets" /> + + <PropertyGroup> + <TargetFramework>net6.0</TargetFramework> + <LangVersion>latest</LangVersion> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + <Nullable>enable</Nullable> + <RootNamespace>{NAMESPACE}</RootNamespace> + + <AssemblyPublicizerPaths>$(AssemblyPublicizerPaths);$(MSBuildThisFileDirectory){NAME_LOWER}.publicizer.js</AssemblyPublicizerPaths> + </PropertyGroup> + +</Project> +` + .trim() + .replace(/{NAMESPACE}/g, ns) + .replace(/{NAME_LOWER}/g, internalName.toLowerCase()); +const buildText = ` +displayName = {NAME} +author = Me +version = 1.0.0 +` + .trim() + .replace(/{NAME}/g, internalName); + +const descriptionText = "TODO"; +const workshopText = "TODO"; +const publicizerText = ` +import {createPublicizer} from "publicizer"; + +export const publicizer = createPublicizer("{NAME}"); + +publicizer.createAssembly("tModLoader").publicizeAll(); +` + .trim() + .replace(/{NAME}/g, internalName); + +const launchSettingsText = ` + { + "profiles": { + "Terraria (Client) (dotnet)": { + "commandName": "Executable", + "executablePath": "dotnet", + "commandLineArgs": "$(tMLPath) -unsafe true", + "workingDirectory": "$(tMLSteamPath)" + }, + "Terraria (Server) (dotnet)": { + "commandName": "Executable", + "executablePath": "dotnet", + "commandLineArgs": "$(tMLServerPath) -unsafe true", + "workingDirectory": "$(tMLSteamPath)" + }, + "Terraria (Client) (dotnet.exe)": { + "commandName": "Executable", + "executablePath": "dotnet.exe", + "commandLineArgs": "$(tMLPath) -unsafe true", + "workingDirectory": "$(tMLSteamPath)" + }, + "Terraria (Server) (dotnet.exe)": { + "commandName": "Executable", + "executablePath": "dotnet.exe", + "commandLineArgs": "$(tMLServerPath) -unsafe true", + "workingDirectory": "$(tMLSteamPath)" + } + } + } +`.trim(); + +try { + fs.mkdirSync(`../src/` + internalName, { recursive: true }); + fs.mkdirSync(`../src/${internalName}/Properties/`, { recursive: true }); +} catch (e) {} + +fs.writeFileSync(`../src/${internalName}/${internalName}.csproj`, csprojText); +fs.writeFileSync(`../src/${internalName}/build.txt`, buildText); +fs.writeFileSync(`../src/${internalName}/description.txt`, descriptionText); +fs.writeFileSync( + `../src/${internalName}/description_workshop.txt`, + workshopText +); +fs.writeFileSync( + `../src/${internalName}/${internalName.toLowerCase()}.publicizer.js`, + publicizerText +); +fs.writeFileSync( + `../src/${internalName}/Properties/launchSettings.json`, + launchSettingsText +); +fs.copyFileSync( + `assets/icon_workshop.png`, + `../src/${internalName}/icon_workshop.png` +); +fs.copyFileSync(`assets/icon.png`, `../src/${internalName}/icon.png`); + +// add to mods.json +const modsJson = require("../mods.json"); +modsJson.push(internalName); +fs.writeFileSync("../mods.json", JSON.stringify(modsJson, null, 4)); diff --git a/scripts/gen-sln.js b/scripts/gen-sln.js new file mode 100644 index 0000000..7c1bdde --- /dev/null +++ b/scripts/gen-sln.js @@ -0,0 +1,38 @@ +const fs = require("fs"); +const crypto = require("crypto"); + +const name = process.argv[2]; +const guid0 = crypto.randomUUID(); +const guid1 = crypto.randomUUID(); +const slnText = ` +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {{GUID_0}}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {{GUID_0}}.Debug|Any CPU.Build.0 = Debug|Any CPU + {{GUID_0}}.Release|Any CPU.ActiveCfg = Release|Any CPU + {{GUID_0}}.Release|Any CPU.Build.0 = Release|Any CPU + {{GUID_1}}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {{GUID_1}}.Debug|Any CPU.Build.0 = Debug|Any CPU + {{GUID_1}}.Release|Any CPU.ActiveCfg = Release|Any CPU + {{GUID_1}}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal +` + .replace(/{GUID_0}/g, guid0) + .replace(/{GUID_1}/g, guid1); + +try { + fs.mkdirSync(`../src/`, { recursive: true }); +} catch (e) {} +fs.writeFileSync(`../src/${name}.sln`, slnText); diff --git a/scripts/setup.sh b/scripts/setup.sh new file mode 100644 index 0000000..78f8971 --- /dev/null +++ b/scripts/setup.sh @@ -0,0 +1,25 @@ +#!/bin/sh +echo "Step 1: Generating Symbolic Links..." +if ! node ../generate-symlinks.js; then + echo "Error: Failed to generate symbolic links." + exit 1 +fi + +echo "Step 2: Updating Submodules..." +if ! git submodule update --init --recursive; then + echo "Error: Failed to update submodules." + exit 1 +fi + +echo "Step 3: Building Catalyst Build Tools..." +if ! dotnet restore ../catalyst/src/TeamCatalyst.Catalyst.Build; then + echo "Error: Failed to restore Catalyst Tools dependencies." + exit 1 +fi + +if ! dotnet build ../catalyst/src/TeamCatalyst.Catalyst.Build -c Release; then + echo "Error: Failed to build Catalyst Tools." + exit 1 +fi + +echo "Setup complete!" \ No newline at end of file diff --git a/src/Silicate/.editorconfig b/src/Silicate/.editorconfig new file mode 100644 index 0000000..8fbf40e --- /dev/null +++ b/src/Silicate/.editorconfig @@ -0,0 +1,41 @@ +[*] + +# Standard properties +insert_final_newline = false + +# Microsoft .NET properties +csharp_indent_braces = false +csharp_new_line_before_open_brace = anonymous_methods, anonymous_types, control_blocks, lambdas, local_functions, methods, object_collection_array_initalizers, types +csharp_preferred_modifier_order = private, public, protected, internal, file, new, static, abstract, virtual, sealed, override, unsafe, extern, readonly, volatile, async, required:suggestion +csharp_style_var_elsewhere = false:suggestion +csharp_style_var_for_built_in_types = false:suggestion +csharp_style_var_when_type_is_apparent = false:suggestion +dotnet_sort_system_directives_first = false + +# ReSharper properties +resharper_blank_lines_after_multiline_statements = 1 +resharper_blank_lines_before_control_transfer_statements = 1 +resharper_blank_lines_before_multiline_statements = 1 +resharper_braces_for_for = required +resharper_braces_for_foreach = required +resharper_braces_for_ifelse = required +resharper_csharp_blank_lines_around_single_line_invocable = 1 +resharper_csharp_case_block_braces = end_of_line +resharper_csharp_empty_block_style = multiline +resharper_csharp_max_line_length = 300 +resharper_instance_members_qualify_declared_in = +resharper_method_or_operator_body = expression_body +resharper_parentheses_redundancy_style = remove +resharper_place_expr_method_on_single_line = true +resharper_place_simple_anonymousmethod_on_single_line = false +resharper_place_simple_initializer_on_single_line = false +resharper_simple_block_style = line_break +resharper_toplevel_function_definition_return_type_style = on_single_line +resharper_wrap_after_invocation_lpar = false +resharper_wrap_arguments_style = wrap_if_long +resharper_wrap_array_initializer_style = chop_if_long +resharper_wrap_before_binary_opsign = false +resharper_wrap_before_expression_rbrace = false +resharper_wrap_before_invocation_rpar = false +resharper_wrap_chained_binary_expressions = chop_if_long +resharper_wrap_chained_method_calls = wrap_if_long diff --git a/src/Silicate/Assets/Textures/UI/Panel.png b/src/Silicate/Assets/Textures/UI/Panel.png new file mode 100644 index 0000000000000000000000000000000000000000..be60fdc31586329631e5fb0773c7ca5b9099054a GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^8bEBo!3HFgt1V^&DaPU;cPEB*=VV?2IeDHgjv*1P zZ!c}+J)j`K;+P!Ba8UWz`}2&lH)J0qH2+Un-gNb4l*^v*#PYHO^X;CW%CpegpYXYP vLgN%7V2Hf(Ch5Lc`a8Z)zFQDdcaXoth)t$&#*Ljon;AS^{an^LB{Ts5yz@sK literal 0 HcmV?d00001 diff --git a/src/Silicate/Assets/Textures/UI/Panel_Left.png b/src/Silicate/Assets/Textures/UI/Panel_Left.png new file mode 100644 index 0000000000000000000000000000000000000000..d0cf1478204f1436a731ca828ca7607a6c28940f GIT binary patch literal 124 zcmeAS@N?(olHy`uVBq!ia0vp^EI@3)!3HGFq;4MtQjEnx?oJHr&dIz4iFvv>hG<Mo zPHA8g6rA{<2MBz4G8zQcl(n?ZHH02ralnCN!vTr?_5Wo<_@oap^%$_7yTicX>CW!@ TYiHaApa~3~u6{1-oD!M<1F0fl literal 0 HcmV?d00001 diff --git a/src/Silicate/Assets/Textures/UI/Panel_Right.png b/src/Silicate/Assets/Textures/UI/Panel_Right.png new file mode 100644 index 0000000000000000000000000000000000000000..cdf99841c8b2aff7b208e98736258d3fb19f1f88 GIT binary patch literal 139 zcmeAS@N?(olHy`uVBq!ia0vp^EI@3)!3HGFq;4MtQjEnx?oJHr&dIz4a$G%K978lF zCW{CP{ycx+zySdXv6Cl&^noJ{Y!arXTmKsy7#QrS`#Xtobyr|xqd>yXzrWun6dW%Q lO8EKVAulsC^SnC@3?{#MXXWo+1!OTWc)I$ztaD0e0stG4FrWYc literal 0 HcmV?d00001 diff --git a/src/Silicate/Assets/Textures/UI/Progress.png b/src/Silicate/Assets/Textures/UI/Progress.png new file mode 100644 index 0000000000000000000000000000000000000000..003686db9b5dcb8f58f853d35efedd8c954c9414 GIT binary patch literal 91 zcmeAS@N?(olHy`uVBq!ia0vp^Od!m`1|*BN@u~nR#^NA%Cx&(BWL^R}qMj~}AsjQ4 l|NQ^|zn%>U)Yvo_7;JyAFx;$Za04n}@O1TaS?83{1OPUa6@CB! literal 0 HcmV?d00001 diff --git a/src/Silicate/Assets/Textures/UI/Unknown.png b/src/Silicate/Assets/Textures/UI/Unknown.png new file mode 100644 index 0000000000000000000000000000000000000000..09f5cd137ef8a49f1c1fd5bdbeee917bfe769337 GIT binary patch literal 147 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|d_7$pLo9le zea@arO#lLmP4)Nd*@O;!eH|_-DIp;-!{cHLuR&H;*8g;%Y{lPSs-9A=u16(TJZcJL qcH@<hVKX=+vBAbsXF*gR3xo1v{#pOJW1j*IX7F_Nb6Mw<&;$VGb1r%S literal 0 HcmV?d00001 diff --git a/src/Silicate/Common/UI/UIManager.cs b/src/Silicate/Common/UI/UIManager.cs new file mode 100644 index 0000000..163284c --- /dev/null +++ b/src/Silicate/Common/UI/UIManager.cs @@ -0,0 +1,60 @@ +using Microsoft.Xna.Framework; +using System.Collections.Generic; +using Terraria; +using Terraria.ModLoader; +using Terraria.UI; + +namespace TeamCatalyst.Silicate.Common.UI; + +public sealed class UIManager : ModSystem +{ + // Keeps track of the last game time update, which isn't provided for rendering. + private static GameTime gameTime; + + public static UserInterface State { get; private set; } + + public override void Load() + { + base.Load(); + + State = new UserInterface(); + State.SetState(new UITileDisplay()); + } + + public override void Unload() + { + base.Unload(); + + State.CurrentState?.Deactivate(); + State.SetState(null); + State = null; + } + + public override void UpdateUI(GameTime gameTime) + { + base.UpdateUI(gameTime); + + State.Update(gameTime); + + UIManager.gameTime = gameTime; + } + + public override void ModifyInterfaceLayers(List<GameInterfaceLayer> layers) + { + base.ModifyInterfaceLayers(layers); + + int index = layers.FindIndex(l => l.Name == "Vanilla: Mouse Text"); + + if (index == -1) + { + return; + } + + layers.Insert(index + 1, new LegacyGameInterfaceLayer("Silicate:TileDisplay", static () => + { + State.Draw(Main.spriteBatch, gameTime); + + return true; + }, InterfaceScaleType.UI)); + } +} \ No newline at end of file diff --git a/src/Silicate/Common/UI/UITileDisplay.cs b/src/Silicate/Common/UI/UITileDisplay.cs new file mode 100644 index 0000000..67d71e2 --- /dev/null +++ b/src/Silicate/Common/UI/UITileDisplay.cs @@ -0,0 +1,203 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using ReLogic.Content; +using ReLogic.Graphics; +using System; +using System.Text.RegularExpressions; +using Terraria; +using Terraria.GameContent; +using Terraria.GameContent.UI.Elements; +using Terraria.ID; +using Terraria.ModLoader; +using Terraria.UI; + +namespace TeamCatalyst.Silicate.Common.UI; + +/// <summary> +/// Displays information about the tile currently being hovered at the player's cursor. +/// </summary> +public sealed class UITileDisplay : UIState +{ + // Splits PascalCase and numbers to look more presentable. + private static readonly Regex Pattern = new("(\\B[A-Z0-9])", RegexOptions.Compiled); + + private Player Player => Main.LocalPlayer; + + public UIImage Panel { get; private set; } + + public UIImage Bar { get; private set; } + + public UIImageFramed TileImage { get; private set; } + + public UIText TileName { get; private set; } + + public UIText ModName { get; private set; } + + public float Opacity { get; private set; } + + public override void OnInitialize() + { + base.OnInitialize(); + + // TODO: Central UIElement for the full area of the state. + // Will also avoid progress bar being cut out from the overflow. + + Panel = new UIImage(Silicate.Instance.Assets.Request<Texture2D>("Assets/Textures/UI/Panel")) + { + OverflowHidden = true, + ScaleToFit = true, + HAlign = 0.5f, + Top = StyleDimension.FromPixels(24f), + Height = StyleDimension.FromPixels(48f), + OverrideSamplerState = SamplerState.PointClamp + }; + + Append(Panel); + + TileImage = new UIImageFramed(TextureAssets.Tile[0], new Rectangle(9 * 18, 3 * 18, 16, 16)) + { + MarginLeft = 8f, + VAlign = 0.5f, + OverrideSamplerState = SamplerState.PointClamp + }; + + Panel.Append(TileImage); + + TileName = new UIText(string.Empty, 0.8f) + { + MarginTop = 8f, + MarginLeft = 32f, + OverrideSamplerState = SamplerState.PointClamp + }; + + Panel.Append(TileName); + + ModName = new UIText(string.Empty, 0.6f) + { + MarginBottom = 8f, + MarginLeft = 32f, + VAlign = 1f, + OverrideSamplerState = SamplerState.PointClamp + }; + + Panel.Append(ModName); + + Bar = new UIImage(Silicate.Instance.Assets.Request<Texture2D>("Assets/Textures/UI/Progress")) + { + ScaleToFit = true, + VAlign = 1f, + Left = StyleDimension.FromPixels(-2f), + Height = StyleDimension.FromPixels(2f), + OverrideSamplerState = SamplerState.PointClamp + }; + + Panel.Append(Bar); + } + + public override void Update(GameTime gameTime) + { + base.Update(gameTime); + + UpdateColors(); + + UpdatePanel(); + UpdateProgress(); + } + + public override void Draw(SpriteBatch spriteBatch) + { + base.Draw(spriteBatch); + + // Panel borders are drawn separately to ensure a smoother resizing. Avoids texture stretching. + spriteBatch.Draw( + Silicate.Instance.Assets.Request<Texture2D>("Assets/Textures/UI/Panel_Left").Value, + Panel.GetDimensions().Position() - new Vector2(4f, 0f), + Color.White * Opacity + ); + + spriteBatch.Draw( + Silicate.Instance.Assets.Request<Texture2D>("Assets/Textures/UI/Panel_Right").Value, + Panel.GetDimensions().Position() + new Vector2(Panel.Width.Pixels, 0f), + Color.White * Opacity + ); + } + + private void UpdateColors() + { + Panel.Color = Color.White * Opacity; + + TileImage.Color = Color.White * Opacity; + + TileName.TextColor = Color.White * Opacity; + ModName.TextColor = new Color(88, 88, 173) * Opacity; + + Bar.Color = Color.Lerp(Color.Black, Color.White, Bar.Width.Pixels / (Panel.Width.Pixels + 2f)) * Opacity; + } + + private void UpdatePanel() + { + Tile tile = Framing.GetTileSafely(Player.tileTargetX, Player.tileTargetY); + + if (tile.HasTile && TileID.Search.TryGetName(tile.TileType, out string? name)) + { + DynamicSpriteFont? font = FontAssets.MouseText.Value; + + string tileName = Pattern.Replace(name, " $1"); + Vector2 tileNameSize = font.MeasureString(tileName); + + TileName.SetText(tileName); + + Mod? mod = TileLoader.GetTile(tile.TileType)?.Mod; + string? modName = mod == null ? "Terraria" : mod.DisplayName; + Vector2 modNameSize = font.MeasureString(modName); + + ModName.SetText(modName); + + Asset<Texture2D>? texture = TextureAssets.Tile[tile.TileType]; + Rectangle frame = Main.tileFrameImportant[tile.TileType] ? new Rectangle(9 * 18, 3 * 18, 16, 16) : new Rectangle(tile.TileFrameX, tile.TileFrameY, 16, 16); + + TileImage.SetImage(texture, frame); + + float desiredWidth = MathF.Max(tileNameSize.X, modNameSize.X); + float width = MathHelper.Lerp(Panel.Width.Pixels, desiredWidth, 0.2f) + frame.Width; + + Panel.Width.Set(MathF.Ceiling(width), 0f); + + Recalculate(); + + Opacity = MathHelper.Lerp(Opacity, 1f, 0.2f); + } + else + { + Asset<Texture2D>? texture = Silicate.Instance.Assets.Request<Texture2D>("Assets/Textures/UI/Unknown"); + + TileImage.SetImage(texture, texture.Frame()); + + TileName.SetText(string.Empty); + ModName.SetText(string.Empty); + + Opacity = MathHelper.Lerp(Opacity, 0f, 0.2f); + } + } + + private void UpdateProgress() + { + float progress = 0f; + int index = Player.hitTile.TryFinding(Player.tileTargetX, Player.tileTargetY, 1); + + if (index != -1) + { + HitTile.HitTileObject? data = Player.hitTile.data[index]; + + if (data == null) + { + return; + } + + // TODO: Find a way to make the progress bar fill up after the tile is mined. + progress = (Panel.Width.Pixels + 2f) * data.damage / 100f; + } + + Bar.Width.Set(MathHelper.Lerp(Bar.Width.Pixels, progress, 0.2f), 0f); + } +} \ No newline at end of file diff --git a/src/Silicate/Localization/en-US_Mods.Silicate.hjson b/src/Silicate/Localization/en-US_Mods.Silicate.hjson new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/Silicate/Localization/en-US_Mods.Silicate.hjson @@ -0,0 +1 @@ + diff --git a/src/Silicate/Properties/launchSettings.json b/src/Silicate/Properties/launchSettings.json new file mode 100644 index 0000000..1011447 --- /dev/null +++ b/src/Silicate/Properties/launchSettings.json @@ -0,0 +1,16 @@ +{ + "profiles": { + "Terraria": { + "commandName": "Executable", + "executablePath": "$(DotNetName)", + "commandLineArgs": "$(tMLPath)", + "workingDirectory": "$(tMLSteamPath)" + }, + "TerrariaServer": { + "commandName": "Executable", + "executablePath": "$(DotNetName)", + "commandLineArgs": "$(tMLServerPath)", + "workingDirectory": "$(tMLSteamPath)" + } + } +} \ No newline at end of file diff --git a/src/Silicate/Silicate.cs b/src/Silicate/Silicate.cs new file mode 100644 index 0000000..dc566bc --- /dev/null +++ b/src/Silicate/Silicate.cs @@ -0,0 +1,11 @@ +using Terraria.ModLoader; + +namespace TeamCatalyst.Silicate; + +/// <summary> +/// The main <see cref="Mod" /> implementation of Silicate. +/// </summary> +public sealed class Silicate : Mod +{ + public static Silicate Instance => ModContent.GetInstance<Silicate>(); +} \ No newline at end of file diff --git a/src/Silicate/Silicate.csproj b/src/Silicate/Silicate.csproj new file mode 100644 index 0000000..f5675ca --- /dev/null +++ b/src/Silicate/Silicate.csproj @@ -0,0 +1,13 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <Import Project="../../catalyst/Library.Build.targets"/> + + <PropertyGroup> + <TargetFramework>net6.0</TargetFramework> + <LangVersion>latest</LangVersion> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + <Nullable>enable</Nullable> + <RootNamespace>TeamCatalyst.Silicate</RootNamespace> + </PropertyGroup> + +</Project> \ No newline at end of file diff --git a/src/Silicate/build.txt b/src/Silicate/build.txt new file mode 100644 index 0000000..b7a2b9d --- /dev/null +++ b/src/Silicate/build.txt @@ -0,0 +1,11 @@ +displayName = Silicate +author = naka +version = 0.1 + +hideCode = false +hideResources = false + +includePDB = true +includeSource = true + +side = Client \ No newline at end of file diff --git a/src/Silicate/description.txt b/src/Silicate/description.txt new file mode 100644 index 0000000..59f0b70 --- /dev/null +++ b/src/Silicate/description.txt @@ -0,0 +1 @@ +Silicate is a pretty cool mod, it does...this. Modify this file with a description of your mod. \ No newline at end of file diff --git a/src/Silicate/icon.png b/src/Silicate/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..707e83545d1815eee17ac0f636d82fae3c9b7710 GIT binary patch literal 3210 zcmaKuS2P^@7RLXB=smg+o#<V3X7pZTghUHNM3hLhkU?~Z=q-dKdM_CnEu;65A?hg6 zgM$+#M7=p{-G}>hANKFtFMF@OzqKEBoSBI(6*(I@0DwwgPs`$un*AH3#DADXcTf!g zxv2*XW@hH@?eG1}-P?yt9|q&{@$+``c;X5`;9R~X!pd@sN%ds$2x=IMOgHqlU?k<T zfF>XrQUrv#$!HB?xr=5Q%{%F|wTajV3S$YAl8}jv=AxAG<TE5|-0zbjKg7lloiB%c z@SJKp*%-b0G_AH-b(r5cMuH)w%+!-HmqSvPLpkZbNA~yhEw71dgp>3609w+<N8HaY zc_H95OhrY62Sd^UAb}GUqyS@_hmpJ$b4{}i&9R3dUqdkdDR&J?kqkg1I0;$;G;|=y z{A>YBP)GzEhh3akfteU^6nwQY0g(BpIUx{Wm(I-yDNF%eH(g`3fV(oN8oL*-4d9Z1 z!OgHo5zL4INqrkPJy6#SFj!iO20%&)B+X-^?f{|?;5fj`8wg(K00x}{8<n3THME<; zf1Ju`P(kx4YKPmAiusb**oboqVfC3s804J@oN_h9yMl69rNd=uz8{VNP?*B_XWPTe zKrD3)7Av2GqIMA5{z81s<Ltb8wLVtqqXEFOe;DpcRHBg$sZ5OYx_ZyQN96vHqVV}i zf?ETP#wSp?HD`0^^RGABMQ_lvv+HYXGX_0SJEtL=&?`ij1IFg^$?q_gi<9H;9V>j{ z(htIQiB7+FjT{*j-x^CLd+j{Gk*s^sOmTg|F~QTL?~H~EGpw4^`zC4SCLT%`^Ta_@ z@AUGIUq4z|5<MqWTap8HkJTU{DPm<0TnK*|3ev*;F)Jqk9JG3OeiI@kM7l>Vj|E)s zt6%CC@&lxseyT4354HHjt%e%a`$+-NDhwB{(_}yDWD&&>-|D<E-$`-dDE}JD*V6^1 zg_1u)-tu$2QxyRfiXN@w5O$RKrokbLF?Wwn^Pv{+vi?l1>O*tpL|V`()D})gq&Yx( z(}{a77UCQa=S?DI&WSqZ?$jfqPvGMkjAbzAF-(!uld_1n;<DD`I8gN?P>iwHX-QEY z0MZc`(QUd?>ER9Ls^2I-!O&$2Y_E0RQ+$2oFO{3jRG9bGuZc}HQNC#NYo$BQT(TOh zUlQ|!g+!+3iKKX6H?;n)C|R1za6L~IWn~{*-MuQp*0^JrvHAca`fzOwnLJSdl*@@z zQx9$gH<{5Z<GRHsOE*WRKt}l5yi1TLt<11VpoQ*t4~w(3R192Cly{0g`KAPINGz;J zfsZ~8CM}45L!e*((Q2H2Txa~L1@D$<d7i8u8*kd++#}Bh62){;E|Gz#wfwd2HJLT` zHSPmD@_c6v-;bx3D?%1Sj}2JYY1d`fiCwd$HLXA7S}c?mS<%TQ--lKgp)6|6W6EyI zKF?Jgjbzd{EUtc^F~R1}?0(`=`@_G5ZXtuyB<riq`0$qQkE|brM*);n(TtJ(u?Qj7 zJQflb1Zx0GZMIPf>qG);zm=qd)K2zh4o!}?HCz}a{E{(ch&;m}Lm-1)Si-8jqNHN6 zg2MXHde|zt{GnxNjgGa9<!U+Ex6DfGihQ#jOLj{{xpG-d1)|K`O8sM)?PVOXZMRXk zDeR+pVZFm@TOSvN3u|MbD7Pn7W%ToKxgLS~(b<<Tgj=&OIa(7`E6R%$VKN3XHjNgC z>2B&ItJ%J%Z~aZkHib&F4#VOX8TRk2++i<~H9||d+Iv=HW@W-F^(xIPb$8n3Yj#WX zOWL(tZO_B0HTw+&?FDra$=DnDo0hYd3#H_xOvb88$2H;=p2h4%ty%$Jo|f)q7j!&C z78rS#E(W!4p4|$SxU{<TIx9WarGyhVQt}bwDX}any>h<ZDjX91_@Cym2i+R5Vy6tJ ztmW4!Xq?K2Nu9rRXc9g8>{t0#z52ZRJ_ryCa0?h3ZyWFBS{S2C?vyASDI4{Vj*Pw^ zoyw8RQ<a*Q-pt#~o6cKmcDx^WUldh_`s}LTuy()1b`RC|H0r*hZ86;X{)0xH>ilZ{ zsn+V&Qo2&KNt#Jz!4#sq?k8#xRo={6w?0FRuR(dCLY)xK%!uaRn(n={_O#HJ(7!HK zNvL9GsVh0|bA&x>@?%iCr?i-heY>X~+Iy6_C4qpC(T>f?tfFoX-|6wlx6GT+MKB}K z&ms?F6XFabhQ+hg#Pitu76#ha4E&FMA1nutALr*a=5_6s;cNHg_dNDu=HHFTzPnRk zEA#AY_W<m>`8rOW;$4QM=TcReDa<q+@oAG+!bKv*rh2-rxj3NW#A%;d?U$P0yH&MS z6@^9VMO%jv1x)im^RQ{RcY#CH66_W4^`q<HYaA#=@<R}Wap9Wbb_D0A!7sVLB&jRm zU4J#q?rJ6$qBR*clOw7l);p`Y-3R`DQ_X#{nT<`sdQeB1h5eZNO5(KPl+YbUDHs(K zWfQHQ<P!^L!%1by1>ojk&z7{#v@*38^AJ*|inU?}a>8mA;*VA46k23k)ceHUY)2;H z`EdOwhPM>Og=^%WKIvGx*gcF{$zP#Z4Pnlf7<k|lRD|t1iYjF)7pE6h%G5B5HMyJq zk0z~f8B-$v!OZ~vB=VpxjxGd`1Wq0oI|H*9<}^9b6E+S`{X3;iE{LyJrdV_x{aUd6 zO`8#w(L$b50aNY^E-z_SrFN;v)RZ^A&<bwjG!$YRvElY&xXLxE;i~s(LbC*C2Fajj z<D04*wqoQcXvq(&`$E&gBn=2x8@Df`aYKrkl?5WByCaQ5_%{k~_upOb(s$7>r=p6Z z4Q<3Y;2Z5#j};qKe1q`htBf~9qVEw`seFz{342YNR_@wl)r7SR1RHyXKkOWe===on z+@Y{0UylminV;T$U<#M8UHas77M;(o#uyi0!+>YbVth3tG#|Lm9^*aqC1*apsl2iW z{b<Z>+-+-PQLMm@I<q2cBa8Ye)$Cjo)zZDD-Q!={c!{i0A$)5j3WomhMdfpwYv~|% zR9W5Xqt%hsnU(zB_`)Zr>C>mUJ@$~cU$TEs;_cc_F4YD*@YWD(<4Lzk*K_^z#uN3L zxQeaQ%yX{?)h1rPyZwaYgqI||)Tn9nw@Hq1RV$0+DUlsr>i*juSNZz^VpQ@})_=Y2 zTjBN53R>GbAzM1(q*9uDkr-07Ofqr%1qXsd;xRP$AXg{PGWXoh*{;QOL=88!y%>C< zi@#0tR#wF}$l%aw&|_{ZVj>N3FqW8~kslf+{(IgL{~i^x>4IH)Oyj-ZLhHXgu6>=b zsobWFwLkdmf6#zmziIQ?Cbw3}!E4)pTjeTk!nD8jZEJ1~+TIhr7u^0S#O-8@y+8rG zaMT|3lj(YDvOrOFq5Uw}`=s~ec!_Bt%unzVJKQ=OAh=iEX4>X(q_L|x3tNbpRJXgD zpV^;(^%xUSc!-<VJt2;Y9J@+6PNsp~NX|(fj;4y<DY&bqsJNo;ce!;@3LASgCQ!h9 z_5NzOhM7qs>~wNx8jH)u6=fY{rG4>wS$w&T*<r24_jUDgb_@o}NIg8dcfQ*hFdx9N z|6z&7bnPYAE1_%m-}T3qUrW!^Skuz3i3qa~FI;5A@P9r`E*CuuV*rBr0YF9q@ca6Y zZUOLI5`b+-0F<%;VD?UR=+yxLGNiAiX%#s4_k6ucml;d%Ps`gF636F0JW`Y;6!Db_ zoxLPniGBV)a=!AoUaE8Q&*-@y&bQe9N{g&a$fE(&&F^q?7KZFx%dawt-3c#JL%a<K ze`53464FhMmQkEYISBC>P3lKns6%Sg_>6x@6}mr|T`zS7Z<g9rzc{k!ZJze>>e}t- z>MqWymV*E;@*U?Yuh+DX=;++u^P`*`V{cv{r+@c?VCEl46{94}FX?5aX_sVvSbWPO zJXHzN{#KC|6OSC^A+Ue35>D9E+Zgf>fnz&zkTxj^1_S}>1^I>sC?%R#yJ&wxNc#N= zWLN8KYtlHWS`7)XE_C&`DFBgAA966x|K&O%eBFRZ13-vq{|hI=e=|NnK+1*ufB5bU z4g{b5PvL)C{G(fSHfS(yVoJn?d<L4>RHA(rkoQ9T0+t^Z1`4uEHeXTy89qIk5ks{g zmVCkF07M8%9>4Jtk_Z|1xtIJl#D*H<0kPz7+9K@ONipn8ayWu-&Ap5G`R$}`lfv#L lM3l^Z{p_PXsLHN|0O|Hr>M5t5uYWE8=xdv3)j%C1{sYV9=H>tZ literal 0 HcmV?d00001 diff --git a/src/TeamCatalyst.Silicate.sln b/src/TeamCatalyst.Silicate.sln new file mode 100644 index 0000000..da85141 --- /dev/null +++ b/src/TeamCatalyst.Silicate.sln @@ -0,0 +1,30 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Silicate", "Silicate\Silicate.csproj", "{3E68A440-6BF6-48B7-83DD-B0430D306510}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {01df345e-ef9f-46b3-b831-c78994c87f80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {01df345e-ef9f-46b3-b831-c78994c87f80}.Debug|Any CPU.Build.0 = Debug|Any CPU + {01df345e-ef9f-46b3-b831-c78994c87f80}.Release|Any CPU.ActiveCfg = Release|Any CPU + {01df345e-ef9f-46b3-b831-c78994c87f80}.Release|Any CPU.Build.0 = Release|Any CPU + {3aa099c9-58b7-4c42-a654-f06182f6a144}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3aa099c9-58b7-4c42-a654-f06182f6a144}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3aa099c9-58b7-4c42-a654-f06182f6a144}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3aa099c9-58b7-4c42-a654-f06182f6a144}.Release|Any CPU.Build.0 = Release|Any CPU + {3E68A440-6BF6-48B7-83DD-B0430D306510}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3E68A440-6BF6-48B7-83DD-B0430D306510}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3E68A440-6BF6-48B7-83DD-B0430D306510}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3E68A440-6BF6-48B7-83DD-B0430D306510}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/tModLoader.targets b/tModLoader.targets new file mode 100644 index 0000000..f6fba4d --- /dev/null +++ b/tModLoader.targets @@ -0,0 +1,3 @@ +<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="C:\Program Files (x86)\Steam\steamapps\common\tModLoader\tMLMod.targets" /> +</Project> \ No newline at end of file