├── .gitattributes
├── DalamudPackager
├── buildMultiTargeting
│ └── DalamudPackager.props
├── build
│ ├── DalamudPackager.props
│ └── DalamudPackager.targets
├── DalamudPackager.csproj
└── DalamudPackager.cs
├── DalamudPackager.sln
├── README.org
├── .gitignore
└── LICENCE
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text eol=lf
2 |
--------------------------------------------------------------------------------
/DalamudPackager/buildMultiTargeting/DalamudPackager.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/DalamudPackager/build/DalamudPackager.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | netstandard2.1
4 | net48
5 | $(MSBuildThisFileDirectory)..\tasks\$(DPTaskFolder)\DalamudPackager.dll
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/DalamudPackager.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DalamudPackager", "DalamudPackager\DalamudPackager.csproj", "{32D99B21-57F1-457B-8902-EF7325DA15A8}"
4 | EndProject
5 | Global
6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
7 | Debug|Any CPU = Debug|Any CPU
8 | Release|Any CPU = Release|Any CPU
9 | EndGlobalSection
10 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
11 | {32D99B21-57F1-457B-8902-EF7325DA15A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
12 | {32D99B21-57F1-457B-8902-EF7325DA15A8}.Debug|Any CPU.Build.0 = Debug|Any CPU
13 | {32D99B21-57F1-457B-8902-EF7325DA15A8}.Release|Any CPU.ActiveCfg = Release|Any CPU
14 | {32D99B21-57F1-457B-8902-EF7325DA15A8}.Release|Any CPU.Build.0 = Release|Any CPU
15 | EndGlobalSection
16 | EndGlobal
17 |
--------------------------------------------------------------------------------
/DalamudPackager/DalamudPackager.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | enable
5 | latest
6 | netstandard2.1;net48
7 |
8 | true
9 |
10 | true
11 |
12 | tasks
13 | true
14 | DalamudPackager
15 | An MSBuild task that simplifies making Dalamud plugins by generating a manifest and packing the build output into a release-ready zip.
16 | EUPL-1.2
17 | 14.0.1
18 | Anna Clemens, goatcorp contributors
19 | https://github.com/goatcorp/DalamudPackager
20 | https://github.com/goatcorp/DalamudPackager
21 |
22 |
23 |
24 |
25 | build\
26 |
27 |
28 | buildMultiTargeting\
29 |
30 |
31 |
32 | build\
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
53 |
54 | <_PackageFiles Include="bin\$(Configuration)\*\Newtonsoft.Json.dll;bin\$(Configuration)\*\YamlDotNet.dll">
55 | tasks\%(RecursiveDir)
56 | false
57 | Content
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/DalamudPackager/build/DalamudPackager.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $(ProjectDir)DalamudPackager.targets
5 |
6 |
7 |
8 |
9 |
12 |
37 |
38 |
39 |
42 |
67 |
68 |
--------------------------------------------------------------------------------
/README.org:
--------------------------------------------------------------------------------
1 | #+title: DalamudPackager
2 | #+options: ^:{}
3 | #+options: toc:nil
4 |
5 | This is an MSBuild task that is designed to simplify creating plugins
6 | for [[https://github.com/goatcorp/Dalamud][Dalamud]].
7 |
8 | Install the NuGet package ~DalamudPackager~. When you build in release
9 | mode, a folder will be placed in your output directory containing your
10 | plugin manifest and ~latest.zip~.
11 |
12 | * Table of contents :TOC:
13 | - [[#configuration][Configuration]]
14 | - [[#manifest-generation][Manifest generation]]
15 | - [[#yaml-manifests][YAML manifests]]
16 | - [[#zip-file-generation][~.zip~ file generation]]
17 | - [[#task-attributes][Task attributes]]
18 |
19 | * Configuration
20 |
21 | If you need to additionally configure the task, create a file called
22 | ~DalamudPackager.targets~ in your project and use the template below.
23 |
24 | #+begin_src xml
25 |
26 |
27 |
28 |
33 |
34 |
35 | #+end_src
36 |
37 | * Manifest generation
38 |
39 | DalamudPackager reduces the amount of keys you need to include in your
40 | manifest, filling in the rest from sane defaults or your assembly. You
41 | can, of course, specify everything manually.
42 |
43 | #+begin_src json5
44 | {
45 | "Name": "Test Plugin",
46 | "Author": "You",
47 | "Description": "This is a test plugin",
48 | "RepoUrl": "https://example.com/"
49 | }
50 | #+end_src
51 |
52 | Notice how keys like ~AssemblyVersion~ and ~DalamudApiLevel~ are
53 | missing. You can include these if you'd like, but DalamudPackager will
54 | automatically do it for you when you build your project. If you build
55 | a project with this manifest in Release mode, you will find the
56 | following JSON file in your output directory.
57 |
58 | #+begin_src json5
59 | {
60 | "Author": "You",
61 | "Name": "Test Plugin",
62 | // this will be set to your AssemblyName automatically
63 | "InternalName": "TestPlugin",
64 | // this will be set to your assembly's version automatically
65 | "AssemblyVersion": "1.0.0.0",
66 | "Description": "This is a test plugin - this first line is a summary.\n\nDown here is a more detailed explanation of what the plugin\ndoes, manually wrapped to make sure it stays visible in the\ninstaller.",
67 | // this will be set to "any" automatically
68 | "ApplicableVersion": "any",
69 | "RepoUrl": "https://example.com/",
70 | // this will be set to 2 automatically
71 | "DalamudApiLevel": 2,
72 | // this will be set to 0 automatically
73 | "LoadPriority": 0
74 | }
75 | #+end_src
76 |
77 | * YAML manifests
78 |
79 | In addition, DalamudPackager allows you to use YAML, a more
80 | human-friendly format, for your manifest instead of JSON. YAML uses
81 | *snake_case* for keys instead of PascalCase like JSON. All the
82 | features of DalamudPackager work with YAML manifests. Just end your
83 | manifest's file name with ~.yaml~ instead of ~.json~ to make use of
84 | it.
85 |
86 | #+begin_src yaml
87 | name: Test Plugin
88 | author: You
89 | description: |-
90 | This is a test plugin - this first line is a summary.
91 |
92 | Down here is a more detailed explanation of what the plugin
93 | does, manually wrapped to make sure it stays visible in the
94 | installer.
95 | repo_url: https://example.com/
96 | #+end_src
97 |
98 | * ~.zip~ file generation
99 |
100 | DalamudPackager will also create a folder with ~latest.zip~ for you if
101 | ~MakeZip~ is ~true~. Check your output directory for a folder with the
102 | name of your assembly. Inside will be your manifest and ~latest.zip~,
103 | ready for distribution or PRs.
104 |
105 | Note that the entire contents of your output directory will be zipped
106 | by default. Either turn off copy local for Dalamud references, set up
107 | a task to clean your output directory, or use ~Exclude~ or ~Include~
108 | if you want to change this.
109 |
110 | * Task attributes
111 |
112 | | Attribute | Description | Required | Default |
113 | |---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------+-----------------------------------|
114 | | ~ProjectDir~ | This is the path where your ~csproj~ is located. You must set this to ~$(ProjectDir)~. | *Yes* | /None/ - set to ~$(ProjectDir)~ |
115 | | ~OutputPath~ | This is the path that your assemblies are output to after build. You must set this to ~$(OutputPath)~. | *Yes* | /None/ - set to ~$(OutputPath)~ |
116 | | ~AssemblyName~ | This is the name of the assembly that Dalamud will be loading. You used to need to specify this in your manifest as ~InternalName~. | *Yes* | /None/ - set to ~$(AssemblyName)~ |
117 | | ~ManifestType~ | You can choose between ~auto~, ~json~, and ~yaml~ for your manifest file. ~auto~ will use ~json~ first, then fall back on ~yaml~. | No | ~auto~ |
118 | | ~VersionComponents~ | How many components of the assembly's version to include in the generated manifest. If you use semantic versioning, set this to ~3~. | No | ~4~ |
119 | | ~MakeZip~ | If this is ~true~, a folder will be created in your ~OutputPath~ that contains your generated manifest and ~latest.zip~, reading for PRing. | No | ~false~ |
120 | | ~Exclude~ | Files to exclude from the zip if ~MakeZip~ is ~true~. Mutually exclusive with ~Include~. Files should be separated by a semicolon (~;~) and be relative to ~OutputPath~. Files do not need to exist. | No | /None/ |
121 | | ~Include~ | Files to include in the zip if ~MakeZip~ is ~true~. Mutually exclusive with ~Exclude~. Files should be separated by a semicolon (~;~) and be relative to ~OutputPath~. Files must exist. | No | /None/ |
122 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Ww][Ii][Nn]32/
27 | [Aa][Rr][Mm]/
28 | [Aa][Rr][Mm]64/
29 | bld/
30 | [Bb]in/
31 | [Oo]bj/
32 | [Ll]og/
33 | [Ll]ogs/
34 |
35 | # Visual Studio 2015/2017 cache/options directory
36 | .vs/
37 | # Rider
38 | .idea/
39 | # Uncomment if you have tasks that create the project's static files in wwwroot
40 | #wwwroot/
41 |
42 | # Visual Studio 2017 auto generated files
43 | Generated\ Files/
44 |
45 | # MSTest test Results
46 | [Tt]est[Rr]esult*/
47 | [Bb]uild[Ll]og.*
48 |
49 | # NUnit
50 | *.VisualState.xml
51 | TestResult.xml
52 | nunit-*.xml
53 |
54 | # Build Results of an ATL Project
55 | [Dd]ebugPS/
56 | [Rr]eleasePS/
57 | dlldata.c
58 |
59 | # Benchmark Results
60 | BenchmarkDotNet.Artifacts/
61 |
62 | # .NET Core
63 | project.lock.json
64 | project.fragment.lock.json
65 | artifacts/
66 |
67 | # ASP.NET Scaffolding
68 | ScaffoldingReadMe.txt
69 |
70 | # StyleCop
71 | StyleCopReport.xml
72 |
73 | # Files built by Visual Studio
74 | *_i.c
75 | *_p.c
76 | *_h.h
77 | *.ilk
78 | *.meta
79 | *.obj
80 | *.iobj
81 | *.pch
82 | *.pdb
83 | *.ipdb
84 | *.pgc
85 | *.pgd
86 | *.rsp
87 | *.sbr
88 | *.tlb
89 | *.tli
90 | *.tlh
91 | *.tmp
92 | *.tmp_proj
93 | *_wpftmp.csproj
94 | *.log
95 | *.vspscc
96 | *.vssscc
97 | .builds
98 | *.pidb
99 | *.svclog
100 | *.scc
101 |
102 | # Chutzpah Test files
103 | _Chutzpah*
104 |
105 | # Visual C++ cache files
106 | ipch/
107 | *.aps
108 | *.ncb
109 | *.opendb
110 | *.opensdf
111 | *.sdf
112 | *.cachefile
113 | *.VC.db
114 | *.VC.VC.opendb
115 |
116 | # Visual Studio profiler
117 | *.psess
118 | *.vsp
119 | *.vspx
120 | *.sap
121 |
122 | # Visual Studio Trace Files
123 | *.e2e
124 |
125 | # TFS 2012 Local Workspace
126 | $tf/
127 |
128 | # Guidance Automation Toolkit
129 | *.gpState
130 |
131 | # ReSharper is a .NET coding add-in
132 | _ReSharper*/
133 | *.[Rr]e[Ss]harper
134 | *.DotSettings.user
135 |
136 | # TeamCity is a build add-in
137 | _TeamCity*
138 |
139 | # DotCover is a Code Coverage Tool
140 | *.dotCover
141 |
142 | # AxoCover is a Code Coverage Tool
143 | .axoCover/*
144 | !.axoCover/settings.json
145 |
146 | # Coverlet is a free, cross platform Code Coverage Tool
147 | coverage*.json
148 | coverage*.xml
149 | coverage*.info
150 |
151 | # Visual Studio code coverage results
152 | *.coverage
153 | *.coveragexml
154 |
155 | # NCrunch
156 | _NCrunch_*
157 | .*crunch*.local.xml
158 | nCrunchTemp_*
159 |
160 | # MightyMoose
161 | *.mm.*
162 | AutoTest.Net/
163 |
164 | # Web workbench (sass)
165 | .sass-cache/
166 |
167 | # Installshield output folder
168 | [Ee]xpress/
169 |
170 | # DocProject is a documentation generator add-in
171 | DocProject/buildhelp/
172 | DocProject/Help/*.HxT
173 | DocProject/Help/*.HxC
174 | DocProject/Help/*.hhc
175 | DocProject/Help/*.hhk
176 | DocProject/Help/*.hhp
177 | DocProject/Help/Html2
178 | DocProject/Help/html
179 |
180 | # Click-Once directory
181 | publish/
182 |
183 | # Publish Web Output
184 | *.[Pp]ublish.xml
185 | *.azurePubxml
186 | # Note: Comment the next line if you want to checkin your web deploy settings,
187 | # but database connection strings (with potential passwords) will be unencrypted
188 | *.pubxml
189 | *.publishproj
190 |
191 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
192 | # checkin your Azure Web App publish settings, but sensitive information contained
193 | # in these scripts will be unencrypted
194 | PublishScripts/
195 |
196 | # NuGet Packages
197 | *.nupkg
198 | # NuGet Symbol Packages
199 | *.snupkg
200 | # The packages folder can be ignored because of Package Restore
201 | **/[Pp]ackages/*
202 | # except build/, which is used as an MSBuild target.
203 | !**/[Pp]ackages/build/
204 | # Uncomment if necessary however generally it will be regenerated when needed
205 | #!**/[Pp]ackages/repositories.config
206 | # NuGet v3's project.json files produces more ignorable files
207 | *.nuget.props
208 | *.nuget.targets
209 |
210 | # Microsoft Azure Build Output
211 | csx/
212 | *.build.csdef
213 |
214 | # Microsoft Azure Emulator
215 | ecf/
216 | rcf/
217 |
218 | # Windows Store app package directories and files
219 | AppPackages/
220 | BundleArtifacts/
221 | Package.StoreAssociation.xml
222 | _pkginfo.txt
223 | *.appx
224 | *.appxbundle
225 | *.appxupload
226 |
227 | # Visual Studio cache files
228 | # files ending in .cache can be ignored
229 | *.[Cc]ache
230 | # but keep track of directories ending in .cache
231 | !?*.[Cc]ache/
232 |
233 | # Others
234 | ClientBin/
235 | ~$*
236 | *~
237 | *.dbmdl
238 | *.dbproj.schemaview
239 | *.jfm
240 | *.pfx
241 | *.publishsettings
242 | orleans.codegen.cs
243 |
244 | # Including strong name files can present a security risk
245 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
246 | #*.snk
247 |
248 | # Since there are multiple workflows, uncomment next line to ignore bower_components
249 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
250 | #bower_components/
251 |
252 | # RIA/Silverlight projects
253 | Generated_Code/
254 |
255 | # Backup & report files from converting an old project file
256 | # to a newer Visual Studio version. Backup files are not needed,
257 | # because we have git ;-)
258 | _UpgradeReport_Files/
259 | Backup*/
260 | UpgradeLog*.XML
261 | UpgradeLog*.htm
262 | ServiceFabricBackup/
263 | *.rptproj.bak
264 |
265 | # SQL Server files
266 | *.mdf
267 | *.ldf
268 | *.ndf
269 |
270 | # Business Intelligence projects
271 | *.rdl.data
272 | *.bim.layout
273 | *.bim_*.settings
274 | *.rptproj.rsuser
275 | *- [Bb]ackup.rdl
276 | *- [Bb]ackup ([0-9]).rdl
277 | *- [Bb]ackup ([0-9][0-9]).rdl
278 |
279 | # Microsoft Fakes
280 | FakesAssemblies/
281 |
282 | # GhostDoc plugin setting file
283 | *.GhostDoc.xml
284 |
285 | # Node.js Tools for Visual Studio
286 | .ntvs_analysis.dat
287 | node_modules/
288 |
289 | # Visual Studio 6 build log
290 | *.plg
291 |
292 | # Visual Studio 6 workspace options file
293 | *.opt
294 |
295 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
296 | *.vbw
297 |
298 | # Visual Studio LightSwitch build output
299 | **/*.HTMLClient/GeneratedArtifacts
300 | **/*.DesktopClient/GeneratedArtifacts
301 | **/*.DesktopClient/ModelManifest.xml
302 | **/*.Server/GeneratedArtifacts
303 | **/*.Server/ModelManifest.xml
304 | _Pvt_Extensions
305 |
306 | # Paket dependency manager
307 | .paket/paket.exe
308 | paket-files/
309 |
310 | # FAKE - F# Make
311 | .fake/
312 |
313 | # CodeRush personal settings
314 | .cr/personal
315 |
316 | # Python Tools for Visual Studio (PTVS)
317 | __pycache__/
318 | *.pyc
319 |
320 | # Cake - Uncomment if you are using it
321 | # tools/**
322 | # !tools/packages.config
323 |
324 | # Tabs Studio
325 | *.tss
326 |
327 | # Telerik's JustMock configuration file
328 | *.jmconfig
329 |
330 | # BizTalk build output
331 | *.btp.cs
332 | *.btm.cs
333 | *.odx.cs
334 | *.xsd.cs
335 |
336 | # OpenCover UI analysis results
337 | OpenCover/
338 |
339 | # Azure Stream Analytics local run output
340 | ASALocalRun/
341 |
342 | # MSBuild Binary and Structured Log
343 | *.binlog
344 |
345 | # NVidia Nsight GPU debugger configuration file
346 | *.nvuser
347 |
348 | # MFractors (Xamarin productivity tool) working folder
349 | .mfractor/
350 |
351 | # Local History for Visual Studio
352 | .localhistory/
353 |
354 | # BeatPulse healthcheck temp database
355 | healthchecksdb
356 |
357 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
358 | MigrationBackup/
359 |
360 | # Ionide (cross platform F# VS Code tools) working folder
361 | .ionide/
362 |
363 | # Fody - auto-generated XML schema
364 | FodyWeavers.xsd
365 |
--------------------------------------------------------------------------------
/LICENCE:
--------------------------------------------------------------------------------
1 | EUROPEAN UNION PUBLIC LICENCE v. 1.2
2 | EUPL © the European Union 2007, 2016
3 |
4 | This European Union Public Licence (the ‘EUPL’) applies to the Work (as defined
5 | below) which is provided under the terms of this Licence. Any use of the Work,
6 | other than as authorised under this Licence is prohibited (to the extent such
7 | use is covered by a right of the copyright holder of the Work).
8 |
9 | The Work is provided under the terms of this Licence when the Licensor (as
10 | defined below) has placed the following notice immediately following the
11 | copyright notice for the Work:
12 |
13 | Licensed under the EUPL
14 |
15 | or has expressed by any other means his willingness to license under the EUPL.
16 |
17 | 1. Definitions
18 |
19 | In this Licence, the following terms have the following meaning:
20 |
21 | - ‘The Licence’: this Licence.
22 |
23 | - ‘The Original Work’: the work or software distributed or communicated by the
24 | Licensor under this Licence, available as Source Code and also as Executable
25 | Code as the case may be.
26 |
27 | - ‘Derivative Works’: the works or software that could be created by the
28 | Licensee, based upon the Original Work or modifications thereof. This Licence
29 | does not define the extent of modification or dependence on the Original Work
30 | required in order to classify a work as a Derivative Work; this extent is
31 | determined by copyright law applicable in the country mentioned in Article 15.
32 |
33 | - ‘The Work’: the Original Work or its Derivative Works.
34 |
35 | - ‘The Source Code’: the human-readable form of the Work which is the most
36 | convenient for people to study and modify.
37 |
38 | - ‘The Executable Code’: any code which has generally been compiled and which is
39 | meant to be interpreted by a computer as a program.
40 |
41 | - ‘The Licensor’: the natural or legal person that distributes or communicates
42 | the Work under the Licence.
43 |
44 | - ‘Contributor(s)’: any natural or legal person who modifies the Work under the
45 | Licence, or otherwise contributes to the creation of a Derivative Work.
46 |
47 | - ‘The Licensee’ or ‘You’: any natural or legal person who makes any usage of
48 | the Work under the terms of the Licence.
49 |
50 | - ‘Distribution’ or ‘Communication’: any act of selling, giving, lending,
51 | renting, distributing, communicating, transmitting, or otherwise making
52 | available, online or offline, copies of the Work or providing access to its
53 | essential functionalities at the disposal of any other natural or legal
54 | person.
55 |
56 | 2. Scope of the rights granted by the Licence
57 |
58 | The Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
59 | sublicensable licence to do the following, for the duration of copyright vested
60 | in the Original Work:
61 |
62 | - use the Work in any circumstance and for all usage,
63 | - reproduce the Work,
64 | - modify the Work, and make Derivative Works based upon the Work,
65 | - communicate to the public, including the right to make available or display
66 | the Work or copies thereof to the public and perform publicly, as the case may
67 | be, the Work,
68 | - distribute the Work or copies thereof,
69 | - lend and rent the Work or copies thereof,
70 | - sublicense rights in the Work or copies thereof.
71 |
72 | Those rights can be exercised on any media, supports and formats, whether now
73 | known or later invented, as far as the applicable law permits so.
74 |
75 | In the countries where moral rights apply, the Licensor waives his right to
76 | exercise his moral right to the extent allowed by law in order to make effective
77 | the licence of the economic rights here above listed.
78 |
79 | The Licensor grants to the Licensee royalty-free, non-exclusive usage rights to
80 | any patents held by the Licensor, to the extent necessary to make use of the
81 | rights granted on the Work under this Licence.
82 |
83 | 3. Communication of the Source Code
84 |
85 | The Licensor may provide the Work either in its Source Code form, or as
86 | Executable Code. If the Work is provided as Executable Code, the Licensor
87 | provides in addition a machine-readable copy of the Source Code of the Work
88 | along with each copy of the Work that the Licensor distributes or indicates, in
89 | a notice following the copyright notice attached to the Work, a repository where
90 | the Source Code is easily and freely accessible for as long as the Licensor
91 | continues to distribute or communicate the Work.
92 |
93 | 4. Limitations on copyright
94 |
95 | Nothing in this Licence is intended to deprive the Licensee of the benefits from
96 | any exception or limitation to the exclusive rights of the rights owners in the
97 | Work, of the exhaustion of those rights or of other applicable limitations
98 | thereto.
99 |
100 | 5. Obligations of the Licensee
101 |
102 | The grant of the rights mentioned above is subject to some restrictions and
103 | obligations imposed on the Licensee. Those obligations are the following:
104 |
105 | Attribution right: The Licensee shall keep intact all copyright, patent or
106 | trademarks notices and all notices that refer to the Licence and to the
107 | disclaimer of warranties. The Licensee must include a copy of such notices and a
108 | copy of the Licence with every copy of the Work he/she distributes or
109 | communicates. The Licensee must cause any Derivative Work to carry prominent
110 | notices stating that the Work has been modified and the date of modification.
111 |
112 | Copyleft clause: If the Licensee distributes or communicates copies of the
113 | Original Works or Derivative Works, this Distribution or Communication will be
114 | done under the terms of this Licence or of a later version of this Licence
115 | unless the Original Work is expressly distributed only under this version of the
116 | Licence — for example by communicating ‘EUPL v. 1.2 only’. The Licensee
117 | (becoming Licensor) cannot offer or impose any additional terms or conditions on
118 | the Work or Derivative Work that alter or restrict the terms of the Licence.
119 |
120 | Compatibility clause: If the Licensee Distributes or Communicates Derivative
121 | Works or copies thereof based upon both the Work and another work licensed under
122 | a Compatible Licence, this Distribution or Communication can be done under the
123 | terms of this Compatible Licence. For the sake of this clause, ‘Compatible
124 | Licence’ refers to the licences listed in the appendix attached to this Licence.
125 | Should the Licensee's obligations under the Compatible Licence conflict with
126 | his/her obligations under this Licence, the obligations of the Compatible
127 | Licence shall prevail.
128 |
129 | Provision of Source Code: When distributing or communicating copies of the Work,
130 | the Licensee will provide a machine-readable copy of the Source Code or indicate
131 | a repository where this Source will be easily and freely available for as long
132 | as the Licensee continues to distribute or communicate the Work.
133 |
134 | Legal Protection: This Licence does not grant permission to use the trade names,
135 | trademarks, service marks, or names of the Licensor, except as required for
136 | reasonable and customary use in describing the origin of the Work and
137 | reproducing the content of the copyright notice.
138 |
139 | 6. Chain of Authorship
140 |
141 | The original Licensor warrants that the copyright in the Original Work granted
142 | hereunder is owned by him/her or licensed to him/her and that he/she has the
143 | power and authority to grant the Licence.
144 |
145 | Each Contributor warrants that the copyright in the modifications he/she brings
146 | to the Work are owned by him/her or licensed to him/her and that he/she has the
147 | power and authority to grant the Licence.
148 |
149 | Each time You accept the Licence, the original Licensor and subsequent
150 | Contributors grant You a licence to their contributions to the Work, under the
151 | terms of this Licence.
152 |
153 | 7. Disclaimer of Warranty
154 |
155 | The Work is a work in progress, which is continuously improved by numerous
156 | Contributors. It is not a finished work and may therefore contain defects or
157 | ‘bugs’ inherent to this type of development.
158 |
159 | For the above reason, the Work is provided under the Licence on an ‘as is’ basis
160 | and without warranties of any kind concerning the Work, including without
161 | limitation merchantability, fitness for a particular purpose, absence of defects
162 | or errors, accuracy, non-infringement of intellectual property rights other than
163 | copyright as stated in Article 6 of this Licence.
164 |
165 | This disclaimer of warranty is an essential part of the Licence and a condition
166 | for the grant of any rights to the Work.
167 |
168 | 8. Disclaimer of Liability
169 |
170 | Except in the cases of wilful misconduct or damages directly caused to natural
171 | persons, the Licensor will in no event be liable for any direct or indirect,
172 | material or moral, damages of any kind, arising out of the Licence or of the use
173 | of the Work, including without limitation, damages for loss of goodwill, work
174 | stoppage, computer failure or malfunction, loss of data or any commercial
175 | damage, even if the Licensor has been advised of the possibility of such damage.
176 | However, the Licensor will be liable under statutory product liability laws as
177 | far such laws apply to the Work.
178 |
179 | 9. Additional agreements
180 |
181 | While distributing the Work, You may choose to conclude an additional agreement,
182 | defining obligations or services consistent with this Licence. However, if
183 | accepting obligations, You may act only on your own behalf and on your sole
184 | responsibility, not on behalf of the original Licensor or any other Contributor,
185 | and only if You agree to indemnify, defend, and hold each Contributor harmless
186 | for any liability incurred by, or claims asserted against such Contributor by
187 | the fact You have accepted any warranty or additional liability.
188 |
189 | 10. Acceptance of the Licence
190 |
191 | The provisions of this Licence can be accepted by clicking on an icon ‘I agree’
192 | placed under the bottom of a window displaying the text of this Licence or by
193 | affirming consent in any other similar way, in accordance with the rules of
194 | applicable law. Clicking on that icon indicates your clear and irrevocable
195 | acceptance of this Licence and all of its terms and conditions.
196 |
197 | Similarly, you irrevocably accept this Licence and all of its terms and
198 | conditions by exercising any rights granted to You by Article 2 of this Licence,
199 | such as the use of the Work, the creation by You of a Derivative Work or the
200 | Distribution or Communication by You of the Work or copies thereof.
201 |
202 | 11. Information to the public
203 |
204 | In case of any Distribution or Communication of the Work by means of electronic
205 | communication by You (for example, by offering to download the Work from a
206 | remote location) the distribution channel or media (for example, a website) must
207 | at least provide to the public the information requested by the applicable law
208 | regarding the Licensor, the Licence and the way it may be accessible, concluded,
209 | stored and reproduced by the Licensee.
210 |
211 | 12. Termination of the Licence
212 |
213 | The Licence and the rights granted hereunder will terminate automatically upon
214 | any breach by the Licensee of the terms of the Licence.
215 |
216 | Such a termination will not terminate the licences of any person who has
217 | received the Work from the Licensee under the Licence, provided such persons
218 | remain in full compliance with the Licence.
219 |
220 | 13. Miscellaneous
221 |
222 | Without prejudice of Article 9 above, the Licence represents the complete
223 | agreement between the Parties as to the Work.
224 |
225 | If any provision of the Licence is invalid or unenforceable under applicable
226 | law, this will not affect the validity or enforceability of the Licence as a
227 | whole. Such provision will be construed or reformed so as necessary to make it
228 | valid and enforceable.
229 |
230 | The European Commission may publish other linguistic versions or new versions of
231 | this Licence or updated versions of the Appendix, so far this is required and
232 | reasonable, without reducing the scope of the rights granted by the Licence. New
233 | versions of the Licence will be published with a unique version number.
234 |
235 | All linguistic versions of this Licence, approved by the European Commission,
236 | have identical value. Parties can take advantage of the linguistic version of
237 | their choice.
238 |
239 | 14. Jurisdiction
240 |
241 | Without prejudice to specific agreement between parties,
242 |
243 | - any litigation resulting from the interpretation of this License, arising
244 | between the European Union institutions, bodies, offices or agencies, as a
245 | Licensor, and any Licensee, will be subject to the jurisdiction of the Court
246 | of Justice of the European Union, as laid down in article 272 of the Treaty on
247 | the Functioning of the European Union,
248 |
249 | - any litigation arising between other parties and resulting from the
250 | interpretation of this License, will be subject to the exclusive jurisdiction
251 | of the competent court where the Licensor resides or conducts its primary
252 | business.
253 |
254 | 15. Applicable Law
255 |
256 | Without prejudice to specific agreement between parties,
257 |
258 | - this Licence shall be governed by the law of the European Union Member State
259 | where the Licensor has his seat, resides or has his registered office,
260 |
261 | - this licence shall be governed by Belgian law if the Licensor has no seat,
262 | residence or registered office inside a European Union Member State.
263 |
264 | Appendix
265 |
266 | ‘Compatible Licences’ according to Article 5 EUPL are:
267 |
268 | - GNU General Public License (GPL) v. 2, v. 3
269 | - GNU Affero General Public License (AGPL) v. 3
270 | - Open Software License (OSL) v. 2.1, v. 3.0
271 | - Eclipse Public License (EPL) v. 1.0
272 | - CeCILL v. 2.0, v. 2.1
273 | - Mozilla Public Licence (MPL) v. 2
274 | - GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3
275 | - Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) for
276 | works other than software
277 | - European Union Public Licence (EUPL) v. 1.1, v. 1.2
278 | - Québec Free and Open-Source Licence — Reciprocity (LiLiQ-R) or Strong
279 | Reciprocity (LiLiQ-R+).
280 |
281 | The European Commission may update this Appendix to later versions of the above
282 | licences without producing a new version of the EUPL, as long as they provide
283 | the rights granted in Article 2 of this Licence and protect the covered Source
284 | Code from exclusive appropriation.
285 |
286 | All other changes or additions to this Appendix require the production of a new
287 | EUPL version.
288 |
--------------------------------------------------------------------------------
/DalamudPackager/DalamudPackager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics.CodeAnalysis;
4 | using System.IO;
5 | using System.IO.Compression;
6 | using System.Linq;
7 | using System.Reflection;
8 | using Microsoft.Build.Framework;
9 | using Microsoft.Build.Utilities;
10 | using Newtonsoft.Json;
11 | using YamlDotNet.Serialization;
12 | using YamlDotNet.Serialization.NamingConventions;
13 |
14 | namespace DalamudPackager {
15 | [SuppressMessage("ReSharper", "AutoPropertyCanBeMadeGetOnly.Global")]
16 | [SuppressMessage("ReSharper", "UnusedType.Global")]
17 | [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
18 | [SuppressMessage("ReSharper", "UnusedAutoPropertyAccessor.Global")]
19 | public class DalamudPackager : Task {
20 | private static readonly string[] ImagePaths = {
21 | "icon.png",
22 | "image1.png",
23 | "image2.png",
24 | "image3.png",
25 | "image4.png",
26 | "image5.png",
27 | };
28 |
29 | ///
30 | /// Set this to $(AssemblyName)
31 | ///
32 | [Required]
33 | public string AssemblyName { get; set; } = null!;
34 |
35 | ///
36 | /// Set this to $(ProjectDir)
37 | ///
38 | [Required]
39 | public string ProjectDir { get; set; } = null!;
40 |
41 | ///
42 | /// Set this to $(OutputPath)
43 | ///
44 | [Required]
45 | public string OutputPath { get; set; } = null!;
46 |
47 | ///
48 | /// This can be either "auto", "json", or "yaml"
49 | ///
50 | public string ManifestType { get; set; } = "auto";
51 |
52 | private ManifestKind RealManifestType => this.ManifestType switch {
53 | "auto" => ManifestKind.Auto,
54 | "json" => ManifestKind.Json,
55 | "yaml" => ManifestKind.Yaml,
56 | _ => throw new ArgumentException("Invalid manifest type: expected either 'auto', 'json', or 'yaml'", nameof(this.ManifestType)),
57 | };
58 |
59 | public byte VersionComponents { get; set; } = 4;
60 |
61 | public bool MakeZip { get; set; } = false;
62 |
63 | public bool HandleImages { get; set; } = true;
64 |
65 | ///
66 | /// Path to images relative to .
67 | ///
68 | public string ImagesPath { get; set; } = "images";
69 |
70 | public string? Exclude { get; set; }
71 |
72 | public string? Include { get; set; }
73 |
74 | #region Packager Manifest Properties
75 |
76 | public string? Author { get; set; }
77 |
78 | public string? Name { get; set; }
79 |
80 | public string? InternalName { get; set; }
81 |
82 | public string? AssemblyVersion { get; set; }
83 |
84 | public string? MinimumDalamudVersion { get; set; }
85 |
86 | public string? Description { get; set; }
87 |
88 | public string? ApplicableVersion { get; set; }
89 |
90 | public string? RepoUrl { get; set; }
91 |
92 | public string? Tags { get; set; }
93 |
94 | public string? CategoryTags { get; set; }
95 |
96 | public string? DalamudApiLevel { get; set; }
97 |
98 | public string? LoadRequiredState { get; set; }
99 |
100 | public string? LoadSync { get; set; }
101 |
102 | public string? CanUnloadAsync { get; set; }
103 |
104 | public string? LoadPriority { get; set; }
105 |
106 | public string? ImageUrls { get; set; }
107 |
108 | public string? IconUrl { get; set; }
109 |
110 | public string? Punchline { get; set; }
111 |
112 | public string? Changelog { get; set; }
113 |
114 | public string? AcceptsFeedback { get; set; }
115 |
116 | public string? FeedbackMessage { get; set; }
117 |
118 | #endregion
119 |
120 | private Lazy> ExcludeFiles => new(() => this.StringToList(this.Exclude));
121 |
122 | private Lazy> IncludeFiles => new(() => this.StringToList(this.Include));
123 |
124 | private void NormalizePaths() {
125 | this.ProjectDir = this.NormalizePath(this.ProjectDir);
126 | this.OutputPath = this.NormalizePath(this.OutputPath);
127 | this.ImagesPath = this.NormalizePath(this.ImagesPath);
128 | }
129 |
130 | private string NormalizePath(string path) {
131 | return path
132 | .Replace('/', Path.DirectorySeparatorChar)
133 | .Replace('\\', Path.DirectorySeparatorChar)
134 | .TrimEnd(Path.DirectorySeparatorChar);
135 | }
136 |
137 | public override bool Execute() {
138 | // normalise path attributes
139 | this.NormalizePaths();
140 |
141 | // load the manifest
142 | var manifest = this.LoadManifest();
143 |
144 | // verify required fields on the manifest
145 | if (manifest.LogMissing(this.Log)) {
146 | return false;
147 | }
148 |
149 | // set some things automatically from the assembly
150 | var assemblyName = this.LoadAssemblyInfo();
151 | manifest.SetProperties(assemblyName, this.VersionComponents);
152 |
153 | // save the json manifest in the output
154 | this.SaveManifest(manifest);
155 |
156 | // make a zip if specified
157 | return !this.MakeZip || this.CreateZip();
158 | }
159 |
160 | private bool CreateZip() {
161 | // get path of the folder called the assembly name where we'll have the manifest and latest.zip
162 | var zipOutput = Path.Combine(this.OutputPath, this.AssemblyName);
163 |
164 | // remove the output folder if it exists
165 | if (Directory.Exists(zipOutput)) {
166 | Directory.Delete(zipOutput, true);
167 | }
168 |
169 | // determine file names to zip
170 | var includeLen = this.IncludeFiles.Value.Count;
171 | var excludeLen = this.ExcludeFiles.Value.Count;
172 |
173 | if (includeLen > 0 && excludeLen > 0) {
174 | this.Log.LogError("Specify either Include or Exclude on your DalamudPackager task, not both.");
175 | return false;
176 | }
177 |
178 | // File names all using \ as separator
179 | string[] fileNames;
180 |
181 | if (includeLen == 0 && excludeLen == 0) {
182 | fileNames = Directory.EnumerateFiles(this.OutputPath, "*", SearchOption.AllDirectories)
183 | .Select(file => this.NormalizePath(file.Substring(this.OutputPath.Length + 1)))
184 | .ToArray();
185 | } else if (includeLen > 0) {
186 | fileNames = this.IncludeFiles.Value.ToArray();
187 | } else {
188 | fileNames = Directory.EnumerateFiles(this.OutputPath, "*", SearchOption.AllDirectories)
189 | .Select(file => this.NormalizePath(file.Substring(this.OutputPath.Length + 1)))
190 | .Where(file => !this.ExcludeFiles.Value.Contains(file))
191 | .ToArray();
192 | }
193 |
194 | // remove any images that will be handled
195 | if (this.HandleImages) {
196 | var badPaths = ImagePaths.Select(p => Path.Combine(this.ImagesPath, p)).ToArray();
197 |
198 | fileNames = fileNames
199 | .Where(file => !badPaths.Contains(file))
200 | .ToArray();
201 | }
202 |
203 | // create zip of files in the output path
204 | var zipPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
205 | using (var zipFile = File.Create(zipPath)) {
206 | using (var zip = new ZipArchive(zipFile, ZipArchiveMode.Create)) {
207 | foreach (var file in fileNames) {
208 | var filePath = Path.Combine(this.OutputPath, file);
209 | zip.CreateEntryFromFile(filePath, file);
210 | }
211 | }
212 | }
213 |
214 | // create the output folder
215 | Directory.CreateDirectory(zipOutput);
216 |
217 | // copy manifest to output
218 | File.Copy(
219 | Path.Combine(this.OutputPath, $"{this.AssemblyName}.json"),
220 | Path.Combine(zipOutput, $"{this.AssemblyName}.json")
221 | );
222 |
223 | // copy images to output
224 | if (this.HandleImages) {
225 | var outputImagesPath = Path.Combine(zipOutput, "images");
226 |
227 | foreach (var path in ImagePaths) {
228 | var actualPath = Path.Combine(this.OutputPath, this.ImagesPath, path);
229 | if (File.Exists(actualPath)) {
230 | if (!Directory.Exists(outputImagesPath)) {
231 | Directory.CreateDirectory(outputImagesPath);
232 | }
233 |
234 | File.Copy(
235 | actualPath,
236 | Path.Combine(outputImagesPath, path)
237 | );
238 | }
239 | }
240 | }
241 |
242 | // move zip to output
243 | File.Move(
244 | zipPath,
245 | Path.Combine(zipOutput, "latest.zip")
246 | );
247 |
248 | return true;
249 | }
250 |
251 | private AssemblyName LoadAssemblyInfo() {
252 | var assemblyPath = Path.Combine(this.OutputPath, $"{this.AssemblyName}.dll");
253 | var fullPath = Path.GetFullPath(assemblyPath);
254 |
255 | return System.Reflection.AssemblyName.GetAssemblyName(fullPath);
256 | }
257 |
258 | private Manifest LoadManifest() {
259 | var exts = this.RealManifestType switch {
260 | ManifestKind.Auto => new[] { "json", "yaml" },
261 | ManifestKind.Json => new[] { "json" },
262 | ManifestKind.Yaml => new[] { "yaml" },
263 | _ => throw new ArgumentOutOfRangeException(nameof(this.RealManifestType), $"extension doesn't exist for {this.RealManifestType}"),
264 | };
265 |
266 | Manifest? manifest = null;
267 |
268 | foreach (var ext in exts) {
269 | var manifestPath = Path.Combine(this.ProjectDir, $"{this.AssemblyName}.{ext}");
270 |
271 | if (!File.Exists(manifestPath)) {
272 | continue;
273 | }
274 |
275 | using var manifestFile = File.Open(manifestPath, FileMode.Open);
276 | using var manifestStream = new StreamReader(manifestFile);
277 |
278 | manifest = ext switch {
279 | "json" => LoadJsonManifest(manifestStream),
280 | "yaml" => LoadYamlManifest(manifestStream),
281 | _ => throw new Exception("unreachable"),
282 | };
283 | }
284 |
285 | manifest ??= new();
286 | return ApplyManifestProperties(manifest);
287 | }
288 |
289 | private static Manifest LoadYamlManifest(TextReader reader) {
290 | var yamlDeserialiser = new DeserializerBuilder()
291 | .IgnoreUnmatchedProperties()
292 | .WithNamingConvention(UnderscoredNamingConvention.Instance)
293 | .Build();
294 |
295 | return yamlDeserialiser.Deserialize(reader);
296 | }
297 |
298 | private static Manifest LoadJsonManifest(TextReader reader) {
299 | return JsonSerializer.CreateDefault().Deserialize(new JsonTextReader(reader))!;
300 | }
301 |
302 | private void SaveManifest(Manifest manifest) {
303 | var jsonPath = Path.Combine(this.OutputPath, $"{this.AssemblyName}.json");
304 |
305 | var jsonSerialiser = JsonSerializer.Create(new JsonSerializerSettings {
306 | Formatting = Formatting.Indented,
307 | NullValueHandling = NullValueHandling.Ignore,
308 | });
309 |
310 | using var jsonFile = File.Open(jsonPath, FileMode.Create);
311 | using var jsonStream = new StreamWriter(jsonFile) {
312 | NewLine = "\n",
313 | };
314 | jsonSerialiser.Serialize(jsonStream, manifest);
315 | }
316 |
317 | private List StringToList(string? s, bool normalizePaths = true) {
318 | if (s == null) {
319 | return new List();
320 | }
321 |
322 | return s.Split(';')
323 | .Select(name => normalizePaths ? this.NormalizePath(name.Trim()) : name.Trim())
324 | .ToList();
325 | }
326 |
327 | private Manifest ApplyManifestProperties(Manifest manifest) {
328 | if (!string.IsNullOrEmpty(Author))
329 | manifest.Author = Author;
330 |
331 | if (!string.IsNullOrEmpty(Name))
332 | manifest.Name = Name;
333 |
334 | if (!string.IsNullOrEmpty(InternalName))
335 | manifest.InternalName = InternalName;
336 |
337 | if (!string.IsNullOrEmpty(AssemblyVersion))
338 | manifest.AssemblyVersion = AssemblyVersion;
339 |
340 | if (!string.IsNullOrEmpty(MinimumDalamudVersion))
341 | manifest.MinimumDalamudVersion = MinimumDalamudVersion;
342 |
343 | if (!string.IsNullOrEmpty(Description))
344 | manifest.Description = Description;
345 |
346 | if (!string.IsNullOrEmpty(ApplicableVersion))
347 | manifest.ApplicableVersion = ApplicableVersion!;
348 |
349 | if (!string.IsNullOrEmpty(RepoUrl))
350 | manifest.RepoUrl = RepoUrl;
351 |
352 | if (!string.IsNullOrEmpty(Tags))
353 | manifest.Tags = StringToList(Tags, false);
354 |
355 | if (!string.IsNullOrEmpty(CategoryTags))
356 | manifest.CategoryTags = StringToList(CategoryTags, false);
357 |
358 | if (!string.IsNullOrEmpty(DalamudApiLevel) && int.TryParse(DalamudApiLevel, out var dalamudApiLevel))
359 | manifest.DalamudApiLevel = dalamudApiLevel;
360 |
361 | if (!string.IsNullOrEmpty(LoadRequiredState) && int.TryParse(LoadRequiredState, out var loadRequiredState))
362 | manifest.LoadRequiredState = loadRequiredState;
363 |
364 | if (!string.IsNullOrEmpty(LoadSync) && bool.TryParse(LoadSync, out var loadSync))
365 | manifest.LoadSync = loadSync;
366 |
367 | if (!string.IsNullOrEmpty(CanUnloadAsync) && bool.TryParse(CanUnloadAsync, out var canUnloadAsync))
368 | manifest.CanUnloadAsync = canUnloadAsync;
369 |
370 | if (!string.IsNullOrEmpty(LoadPriority) && int.TryParse(LoadPriority, out var loadPriority))
371 | manifest.LoadPriority = loadPriority;
372 |
373 | if (!string.IsNullOrEmpty(ImageUrls))
374 | manifest.ImageUrls = StringToList(ImageUrls, false);
375 |
376 | if (!string.IsNullOrEmpty(IconUrl))
377 | manifest.IconUrl = IconUrl;
378 |
379 | if (!string.IsNullOrEmpty(Punchline))
380 | manifest.Punchline = Punchline;
381 |
382 | if (!string.IsNullOrEmpty(Changelog))
383 | manifest.Changelog = Changelog;
384 |
385 | if (!string.IsNullOrEmpty(AcceptsFeedback) && bool.TryParse(AcceptsFeedback, out var acceptsFeedback))
386 | manifest.AcceptsFeedback = acceptsFeedback;
387 |
388 | if (!string.IsNullOrEmpty(FeedbackMessage))
389 | manifest.FeedbackMessage = FeedbackMessage;
390 |
391 | return manifest;
392 | }
393 | }
394 |
395 | public enum ManifestKind {
396 | ///
397 | /// Automatically searches for JSON manifests, then searches for YAML manifests if no JSON could be found.
398 | ///
399 | Auto,
400 |
401 | ///
402 | /// Superior manifest type. Easier for human consumption. Will be converted into JSON for machine consumption
403 | /// during the build process.
404 | ///
405 | Yaml,
406 |
407 | ///
408 | /// Inferior manifest type. Not meant for human consumption.
409 | ///
410 | Json,
411 | }
412 |
413 | [Serializable]
414 | public class Manifest {
415 | ///
416 | /// The author/s of the plugin.
417 | ///
418 | public string? Author { get; set; }
419 |
420 | ///
421 | /// The public name of the plugin.
422 | ///
423 | public string? Name { get; set; }
424 |
425 | ///
426 | /// The internal name of the plugin, which should match the assembly name of the plugin.
427 | ///
428 | public string? InternalName { get; set; }
429 |
430 | ///
431 | /// The current assembly version of the plugin.
432 | ///
433 | public string? AssemblyVersion { get; set; }
434 |
435 | ///
436 | /// Gets the minimum Dalamud assembly version this plugin requires.
437 | ///
438 | public string? MinimumDalamudVersion { get; set; }
439 |
440 | ///
441 | /// A description of the plugins functions.
442 | ///
443 | public string? Description { get; set; }
444 |
445 | ///
446 | /// The version of the game this plugin works with.
447 | ///
448 | public string ApplicableVersion { get; set; } = "any";
449 |
450 | ///
451 | /// An URL to the website or source code of the plugin.
452 | ///
453 | public string? RepoUrl { get; set; }
454 |
455 | ///
456 | /// List of tags defined on the plugin.
457 | ///
458 | public List? Tags { get; set; }
459 |
460 | ///
461 | /// List of the category tags defined on the plugin.
462 | ///
463 | public List? CategoryTags { get; set; }
464 |
465 | ///
466 | /// The API level of this plugin.
467 | ///
468 | public int DalamudApiLevel { get; set; } = 14;
469 |
470 | ///
471 | /// Gets the required Dalamud load step for this plugin to load. Takes precedence over LoadPriority.
472 | /// Valid values are:
473 | /// 0. During Framework.Tick, when drawing facilities are available.
474 | /// 1. During Framework.Tick.
475 | /// 2. No requirement.
476 | ///
477 | public int LoadRequiredState { get; set; }
478 |
479 | ///
480 | /// Gets a value indicating whether Dalamud must load this plugin not at the same time with other plugins and the game.
481 | ///
482 | public bool LoadSync { get; set; }
483 |
484 | ///
485 | /// Gets a value indicating whether Dalamud can unload the plugin outside of the Framework thread.
486 | ///
487 | public bool CanUnloadAsync { get; set; }
488 |
489 | ///
490 | /// Load priority for this plugin. Higher values means higher priority. 0 is default priority.
491 | ///
492 | public int LoadPriority { get; set; }
493 |
494 | ///
495 | /// Array of links to screenshots/other images that will be displayed. These images must be 730x380 resolution, with a maximum of 5 images.
496 | ///
497 | public List? ImageUrls { get; set; }
498 |
499 | ///
500 | /// Link to a 512x512 icon for your plugin.
501 | ///
502 | public string? IconUrl { get; set; }
503 |
504 | ///
505 | /// One-sentence description of your plugin.
506 | ///
507 | public string? Punchline { get; set; }
508 |
509 | ///
510 | /// Small description of recent changes to your plugin, only shown for people who have the plugin installed.
511 | ///
512 | public string? Changelog { get; set; }
513 |
514 | ///
515 | /// Gets a value indicating whether this plugin accepts feedback.
516 | ///
517 | public bool AcceptsFeedback { get; set; } = true;
518 |
519 | ///
520 | /// Gets a message that is shown to users when sending feedback.
521 | ///
522 | public string? FeedbackMessage { get; set; }
523 |
524 | internal bool LogMissing(TaskLoggingHelper log) {
525 | var anyNull = this.Name == null || this.Author == null || this.Description == null || this.Punchline == null;
526 |
527 | if (this.Name == null) {
528 | log.LogError("Plugin name is required in your manifest.");
529 | }
530 |
531 | if (this.Author == null) {
532 | log.LogError("Author name is required in your plugin manifest.");
533 | }
534 |
535 | if (this.Description == null) {
536 | log.LogError("Description is required in your plugin manifest.");
537 | }
538 |
539 | if (this.Punchline == null) {
540 | log.LogError("Punchline is required in your plugin manifest.");
541 | }
542 |
543 | return anyNull;
544 | }
545 |
546 | internal void SetProperties(AssemblyName assembly, byte components) {
547 | this.AssemblyVersion = assembly.Version!.ToString(components);
548 | this.InternalName = assembly.Name;
549 | }
550 | }
551 | }
552 |
--------------------------------------------------------------------------------