Jelajahi Sumber

Plant and cold fixes (#159)

* moving some files around

* adds a few more craftables

* buffs cold damage

* plant health effects from blizzards, hail

* 📝 Add docstrings to `ancient_content` (#160)

Docstrings generation was requested by @taislin.

* https://github.com/Civ13/Civ14/pull/159#issuecomment-2831516748

The following files were modified:

* `Content.Server/Botany/Systems/PlantHolderSystem.cs`
* `Content.Server/Weather/WeatherSystem.cs`

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* changelog

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Taislin 7 bulan lalu
induk
melakukan
43dbc07382
38 mengubah file dengan 396 tambahan dan 32 penghapusan
  1. 39 12
      Content.Server/Botany/Systems/PlantHolderSystem.cs
  2. 34 0
      Content.Server/Weather/WeatherSystem.cs
  3. 2 2
      Content.Shared/Weather/WeatherNomadsComponent.cs
  4. 1 1
      README.md
  5. 11 0
      Resources/Changelog/Changelog.yml
  6. 1 1
      Resources/Locale/en-US/botany/components/plant-holder-component.ftl
  7. 14 14
      Resources/Prototypes/Civ14/Recipes/Clothing/recipes_clothing_uniform.yml
  8. 2 2
      Resources/Prototypes/Entities/Mobs/Species/base.yml
  9. 25 0
      Scripts/bat/!README.txt
  10. 12 0
      Scripts/bat/buildAllDebug.bat
  11. 12 0
      Scripts/bat/buildAllRelease.bat
  12. 12 0
      Scripts/bat/buildAllTools.bat
  13. 11 0
      Scripts/bat/runQuickAll.bat
  14. 11 0
      Scripts/bat/runQuickClient.bat
  15. 11 0
      Scripts/bat/runQuickServer.bat
  16. 13 0
      Scripts/bat/runTests.bat
  17. 13 0
      Scripts/bat/runTestsIntegration.bat
  18. 13 0
      Scripts/bat/runTestsYAML.bat
  19. 0 0
      Scripts/bat/runclient-Tools.bat
  20. 0 0
      Scripts/bat/runclient.bat
  21. 0 0
      Scripts/bat/runserver-Tools.bat
  22. 0 0
      Scripts/bat/runserver.bat
  23. 25 0
      Scripts/sh/!README.txt
  24. 16 0
      Scripts/sh/buildAllDebug.sh
  25. 16 0
      Scripts/sh/buildAllRelease.sh
  26. 16 0
      Scripts/sh/buildAllTools.sh
  27. 16 0
      Scripts/sh/runQuickAll.sh
  28. 14 0
      Scripts/sh/runQuickClient.sh
  29. 14 0
      Scripts/sh/runQuickServer.sh
  30. 14 0
      Scripts/sh/runTests.sh
  31. 14 0
      Scripts/sh/runTestsIntegration.sh
  32. 14 0
      Scripts/sh/runTestsYAML.sh
  33. 0 0
      Scripts/sh/runclient-Tools.sh
  34. 0 0
      Scripts/sh/runclient.sh
  35. 0 0
      Scripts/sh/runserver-Tools.sh
  36. 0 0
      Scripts/sh/runserver.sh
  37. 0 0
      Tools/CivMigrations/README.md
  38. 0 0
      Tools/CivMigrations/migrations.json

+ 39 - 12
Content.Server/Botany/Systems/PlantHolderSystem.cs

@@ -46,7 +46,10 @@ public sealed class PlantHolderSystem : EntitySystem
 
     public const float HydroponicsSpeedMultiplier = 1f;
     public const float HydroponicsConsumptionMultiplier = 2f;
-
+    private ISawmill _sawmill = default!;
+    /// <summary>
+    /// Sets up event subscriptions for plant holder interactions and initialises the entity logger.
+    /// </summary>
     public override void Initialize()
     {
         base.Initialize();
@@ -54,8 +57,12 @@ public override void Initialize()
         SubscribeLocalEvent<PlantHolderComponent, InteractUsingEvent>(OnInteractUsing);
         SubscribeLocalEvent<PlantHolderComponent, InteractHandEvent>(OnInteractHand);
         SubscribeLocalEvent<PlantHolderComponent, SolutionTransferredEvent>(OnSolutionTransferred);
+        _sawmill = LogManager.GetSawmill("entity");
     }
 
+    /// <summary>
+    /// Periodically updates all plant holders, advancing their growth and state if their scheduled update time has elapsed.
+    /// </summary>
     public override void Update(float frameTime)
     {
         base.Update(frameTime);
@@ -148,6 +155,18 @@ private void OnExamine(Entity<PlantHolderComponent> entity, ref ExaminedEvent ar
         }
     }
 
+    /// <summary>
+    /// Handles interactions with a plant holder using an item, enabling planting, weeding, plant removal, sampling, and harvesting based on the item used.
+    /// </summary>
+    /// <remarks>
+    /// - Seeds can be planted if the holder is empty, or a message is shown if already seeded.
+    /// - Hoes remove weeds if present.
+    /// - Shovels remove the plant if one exists.
+    /// - Plant sample takers allow sampling if the plant is alive, mature, and not already sampled, reducing plant health and possibly marking it as sampled.
+    /// - Sharp tools trigger harvesting.
+    /// - Composting with produce is currently disabled.
+    /// Displays appropriate feedback messages to the user for each action.
+    /// </remarks>
     private void OnInteractUsing(Entity<PlantHolderComponent> entity, ref InteractUsingEvent args)
     {
         var (uid, component) = entity;
@@ -264,7 +283,7 @@ private void OnInteractUsing(Entity<PlantHolderComponent> entity, ref InteractUs
                 return;
             }
 
-            component.Health -= (_random.Next(3, 5) * 10);
+            component.Health -= _random.Next(3, 5) * 10;
 
             float? healthOverride;
             if (component.Harvest)
@@ -350,6 +369,12 @@ public void WeedInvasion()
     }
 
 
+    /// <summary>
+    /// Advances the growth cycle and health state of a plant holder, applying mutation, environmental, weather, and resource effects.
+    /// </summary>
+    /// <remarks>
+    /// This method processes plant growth, mutation, weed and pest dynamics, resource consumption, environmental hazards (such as gas, pressure, temperature, and toxins), and weather effects. It also manages plant death, harvest readiness, and visual updates. If no seed is present or the plant is dead, only relevant state and visuals are updated.
+    /// </remarks>
     public void Update(EntityUid uid, PlantHolderComponent? component = null)
     {
         if (!Resolve(uid, ref component))
@@ -450,23 +475,25 @@ public void Update(EntityUid uid, PlantHolderComponent? component = null)
         }
 
         // Water consumption.
-        if (component.Seed.WaterConsumption > 0 && component.WaterLevel > 0 && _random.Prob(0.75f))
+
+        var weather = EntityQueryEnumerator<WeatherNomadsComponent>();
+        while (weather.MoveNext(out var uuid, out var weatherComponent))
         {
-            var weather = EntityQueryEnumerator<WeatherNomadsComponent>();
-            while (weather.MoveNext(out var uuid, out var weatherComponent))
+            if (weatherComponent.CurrentPrecipitation == Precipitation.LightWet || weatherComponent.CurrentPrecipitation == Precipitation.HeavyWet || weatherComponent.CurrentPrecipitation == Precipitation.Storm)
             {
-                if (weatherComponent.CurrentPrecipitation == Precipitation.LightWet || weatherComponent.CurrentPrecipitation == Precipitation.HeavyWet  || weatherComponent.CurrentPrecipitation == Precipitation.Storm)
-                {
-                    component.WaterLevel += 2f;
-                }
+                component.WaterLevel += 3f;
             }
-
+            if (weatherComponent.CurrentPrecipitation == Precipitation.Storm)
+            {
+                component.Health -= _random.Next(1, 3) * HydroponicsSpeedMultiplier;
+            }
+        }
+        if (component.Seed.WaterConsumption > 0 && component.WaterLevel > 0 && _random.Prob(0.75f))
+        {
             component.WaterLevel -= MathF.Max(0f,
             component.Seed.WaterConsumption * HydroponicsConsumptionMultiplier * HydroponicsSpeedMultiplier);
             if (component.DrawWarnings)
                 component.UpdateSpriteAfterUpdate = true;
-
-
         }
 
         var healthMod = _random.Next(1, 3) * HydroponicsSpeedMultiplier;

+ 34 - 0
Content.Server/Weather/WeatherSystem.cs

@@ -29,6 +29,19 @@ private void OnWeatherGetState(EntityUid uid, WeatherComponent component, ref Co
         args.State = new WeatherComponentState(component.Weather);
     }
 
+    /// <summary>
+    /// Handles the "weather" admin console command to set the weather on a specified map, optionally for a set duration, and updates precipitation states for all entities with <c>WeatherNomadsComponent</c>.
+    /// </summary>
+    /// <param name="shell">The console shell executing the command.</param>
+    /// <param name="argStr">The raw argument string.</param>
+    /// <param name="args">
+    /// Command arguments:
+    /// <list type="number">
+    /// <item><description>Map ID (integer).</description></item>
+    /// <item><description>Weather prototype ID or "null" to clear weather.</description></item>
+    /// <item><description>(Optional) Duration in seconds for the weather effect.</description></item>
+    /// </list>
+    /// </param>
     [AdminCommand(AdminFlags.Fun)]
     private void WeatherTwo(IConsoleShell shell, string argStr, string[] args)
     {
@@ -76,6 +89,27 @@ private void WeatherTwo(IConsoleShell shell, string argStr, string[] args)
                 shell.WriteError(Loc.GetString("cmd-weather-error-wrong-time"));
             }
         }
+        var nomadsweather = EntityQueryEnumerator<WeatherNomadsComponent>();
+        while (nomadsweather.MoveNext(out var uuid, out var weatherComponent))
+        {
+            var parsedprec = Precipitation.Dry;
+            if (!args[1].Equals("null"))
+            {
+                if (args[1].Equals("Hail") || args[1].Equals("SandstormHeavy") || args[1].Equals("Storm") || args[1].Equals("SnowfallHeavy"))
+                {
+                    parsedprec = Precipitation.Storm;
+                }
+                if (args[1].Equals("Rain") || args[1].Equals("SnowfallLight"))
+                {
+                    parsedprec = Precipitation.LightWet;
+                }
+                if (args[1].Equals("SnowfallMedium"))
+                {
+                    parsedprec = Precipitation.HeavyWet;
+                }
+            }
+            weatherComponent.CurrentPrecipitation = parsedprec;
+        }
 
         SetWeather(mapId, weather, endTime);
     }

+ 2 - 2
Content.Shared/Weather/WeatherNomadsComponent.cs

@@ -22,7 +22,7 @@ public sealed partial class WeatherNomadsComponent : Component
     public int MaxPrecipitationDurationMinutes { get; set; } = 10;
 
     [DataField("currentPrecipitation")]
-    public Precipitation CurrentPrecipitation { get; set; } = Precipitation.Dry;
+    public Precipitation CurrentPrecipitation { get; set; } = Precipitation.LightWet;
 
     [DataField("currentWeather")]
     public string CurrentWeather { get; set; } = "Clear";
@@ -35,4 +35,4 @@ public sealed partial class WeatherNomadsComponent : Component
 
     [DataField("currentSeason")]
     public string CurrentSeason { get; set; } = "Spring";
-}
+}

+ 1 - 1
README.md

@@ -20,7 +20,7 @@ We are happy to accept contributions from anybody. Get in Discord if you want to
 
 1. Clone this repo.
 2. Run `RUN_THIS.py` to init submodules and download the engine.
-3. Compile the solution. You can use `runclient.bat` and `runserver.bat` to launch it locally for testing.
+3. Compile the solution. You can use `Scripts/bat/runclient.bat` and `Scripts/bat/runserver.bat` to launch it locally for testing on Windows (use the scripts in `Scripts/sh/` for linux).
 
 [More detailed instructions on building the project.](https://docs.spacestation14.com/en/general-development/setup.html)
 

+ 11 - 0
Resources/Changelog/Changelog.yml

@@ -134,3 +134,14 @@ Entries:
     id: 11
     time: "2025-04-23T00:00:00.0000000+00:00"
     url: https://github.com/Civ13/Civ14/pull/151
+  - author: Taislin
+    changes:
+      - message: Increased damage from cold.
+        type: Tweak
+      - message: Rain waters plants now.
+        type: Add
+      - message: Storms, blizzards damage plants now.
+        type: Add
+    id: 12
+    time: "2025-04-25T00:00:00.0000000+00:00"
+    url: https://github.com/Civ13/Civ14/pull/159

+ 1 - 1
Resources/Locale/en-US/botany/components/plant-holder-component.ftl

@@ -15,7 +15,7 @@ plant-holder-component-dead-plant-message = This plant is dead.
 plant-holder-component-take-sample-message = You take a sample from the {$seedName}.
 plant-holder-component-compost-message = You compost {$usingItem} into {$owner}.
 plant-holder-component-compost-others-message = {$user} composts {$usingItem} into {$owner}.
-plant-holder-component-nothing-planted-message = It has nothing planted in it..
+plant-holder-component-nothing-planted-message = It has nothing planted in it.
 plant-holder-component-something-already-growing-message = [color=green]{$seedName}[/color] {$toBeForm} growing here.
 plant-holder-component-something-already-growing-low-health-message = The plant looks [color=red]{$healthState}[/color].
 plant-holder-component-plant-old-adjective = old and wilting

+ 14 - 14
Resources/Prototypes/Civ14/Recipes/Clothing/recipes_clothing_uniform.yml

@@ -861,7 +861,7 @@
     sprite: Civ14/Clothing/exported/uniforms/customroman.rsi
     state: icon
   objectType: Item
-  agemin: 8
+  agemin: 1
   agemax: 8
 
 - type: constructionGraph
@@ -889,7 +889,7 @@
     sprite: Civ14/Clothing/exported/uniforms/customtoga.rsi
     state: icon
   objectType: Item
-  agemin: 8
+  agemin: 1
   agemax: 8
 
 - type: constructionGraph
@@ -917,7 +917,7 @@
     sprite: Civ14/Clothing/exported/uniforms/toga2.rsi
     state: icon
   objectType: Item
-  agemin: 8
+  agemin: 1
   agemax: 8
 
 - type: constructionGraph
@@ -929,8 +929,8 @@
         - to: end
           steps:
             - material: Cloth
-              amount: 5
-              doAfter: 5
+              amount: 3
+              doAfter: 6
     - node: end
       entity: civ13_uniform_half_shoulder_white_toga
 - type: construction
@@ -1088,7 +1088,7 @@
     sprite: Civ14/Clothing/exported/uniforms/celtic_short_braccae.rsi
     state: icon
   objectType: Item
-  agemin: 8
+  agemin: 1
   agemax: 8
 
 - type: constructionGraph
@@ -1116,7 +1116,7 @@
     sprite: Civ14/Clothing/exported/uniforms/celtic_long_braccae.rsi
     state: icon
   objectType: Item
-  agemin: 8
+  agemin: 1
   agemax: 8
 
 - type: constructionGraph
@@ -1200,7 +1200,7 @@
     sprite: Civ14/Clothing/exported/uniforms/pharaoh.rsi
     state: icon
   objectType: Item
-  agemin: 8
+  agemin: 1
   agemax: 8
 
 - type: constructionGraph
@@ -1228,7 +1228,7 @@
     sprite: Civ14/Clothing/exported/uniforms/greatshendyt.rsi
     state: icon
   objectType: Item
-  agemin: 8
+  agemin: 1
   agemax: 8
 
 - type: constructionGraph
@@ -1314,7 +1314,7 @@
     sprite: Civ14/Clothing/exported/uniforms/kimono.rsi
     state: icon
   objectType: Item
-  agemin: 8
+  agemin: 2
   agemax: 8
 
 - type: constructionGraph
@@ -2657,7 +2657,7 @@
     sprite: Civ14/Clothing/exported/uniforms/customtoga.rsi
     state: icon
   objectType: Item
-  agemin: 8
+  agemin: 1
   agemax: 8
 
 - type: constructionGraph
@@ -2669,7 +2669,7 @@
         - to: end
           steps:
             - material: Cloth
-              amount: 5
+              amount: 6
               doAfter: 5
     - node: end
       entity: civ13_uniform_purple_toga
@@ -8653,7 +8653,7 @@
     sprite: Civ14/Clothing/exported/uniforms/huipil.rsi
     state: icon
   objectType: Item
-  agemin: 8
+  agemin: 1
   agemax: 8
 
 - type: constructionGraph
@@ -8681,7 +8681,7 @@
     sprite: Civ14/Clothing/exported/uniforms/halfhuipil.rsi
     state: icon
   objectType: Item
-  agemin: 8
+  agemin: 1
   agemax: 8
 
 - type: constructionGraph

+ 2 - 2
Resources/Prototypes/Entities/Mobs/Species/base.yml

@@ -255,12 +255,12 @@
     # Other
     - type: Temperature
       heatDamageThreshold: 325
-      coldDamageThreshold: 260
+      coldDamageThreshold: 270
       currentTemperature: 310.15
       specificHeat: 42
       coldDamage:
         types:
-          Cold: 0.1 #per second, scales with temperature & other constants
+          Cold: 0.3 #per second, scales with temperature & other constants
       heatDamage:
         types:
           Heat: 1.5 #per second, scales with temperature & other constants

+ 25 - 0
Scripts/bat/!README.txt

@@ -0,0 +1,25 @@
+buildAllDebug
+    Builds all projects with debug configuration
+buildAllRelease
+    Builds all projects with release configuration
+buildAllTools
+    Builds all projects with tools configuration
+
+The debug vs release build is simply what people develop in vs the actual server.
+The release build contains various optimizations, while the debug build contains debugging tools.
+If you're mapping, use the release or tools build as it will run smoother with less crashes.
+
+
+runQuickAll
+    Runs the client and server without building
+runQuickClient
+    Runs the client without building
+runQuickServer
+    Runs the server without building
+
+runTests
+    Runs the unit tests, makes sure various C# systems work as intended
+runTestsIntegration
+    Runs the integration tests, makes sure various C# systems work as intended
+runTestsYAML
+    Runs the YAML linter and finds issues with the YAML files that you probably wouldn't otherwise

+ 12 - 0
Scripts/bat/buildAllDebug.bat

@@ -0,0 +1,12 @@
+REM SPDX-FileCopyrightText: 2024 gluesniffler <159397573+gluesniffler@users.noreply.github.com>
+REM SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com>
+REM
+REM SPDX-License-Identifier: AGPL-3.0-or-later
+
+@echo off
+cd ../../
+
+call git submodule update --init --recursive
+call dotnet build -c Debug
+
+pause

+ 12 - 0
Scripts/bat/buildAllRelease.bat

@@ -0,0 +1,12 @@
+REM SPDX-FileCopyrightText: 2024 gluesniffler <159397573+gluesniffler@users.noreply.github.com>
+REM SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com>
+REM
+REM SPDX-License-Identifier: AGPL-3.0-or-later
+
+@echo off
+cd ../../
+
+call git submodule update --init --recursive
+call dotnet build -c Release
+
+pause

+ 12 - 0
Scripts/bat/buildAllTools.bat

@@ -0,0 +1,12 @@
+REM SPDX-FileCopyrightText: 2024 gluesniffler <159397573+gluesniffler@users.noreply.github.com>
+REM SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com>
+REM
+REM SPDX-License-Identifier: AGPL-3.0-or-later
+
+@echo off
+cd ../../
+
+call git submodule update --init --recursive
+call dotnet build -c Tools
+
+pause

+ 11 - 0
Scripts/bat/runQuickAll.bat

@@ -0,0 +1,11 @@
+REM SPDX-FileCopyrightText: 2024 gluesniffler <159397573+gluesniffler@users.noreply.github.com>
+REM SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com>
+REM
+REM SPDX-License-Identifier: AGPL-3.0-or-later
+
+@echo off
+
+start runQuickServer.bat %*
+start runQuickClient.bat %*
+
+exit

+ 11 - 0
Scripts/bat/runQuickClient.bat

@@ -0,0 +1,11 @@
+REM SPDX-FileCopyrightText: 2024 gluesniffler <159397573+gluesniffler@users.noreply.github.com>
+REM SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com>
+REM
+REM SPDX-License-Identifier: AGPL-3.0-or-later
+
+@echo off
+cd ../../
+
+call dotnet run --project Content.Client --no-build %*
+
+pause

+ 11 - 0
Scripts/bat/runQuickServer.bat

@@ -0,0 +1,11 @@
+REM SPDX-FileCopyrightText: 2024 gluesniffler <159397573+gluesniffler@users.noreply.github.com>
+REM SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com>
+REM
+REM SPDX-License-Identifier: AGPL-3.0-or-later
+
+@echo off
+cd ../../
+
+call dotnet run --project Content.Server --no-build %*
+
+pause

+ 13 - 0
Scripts/bat/runTests.bat

@@ -0,0 +1,13 @@
+REM SPDX-FileCopyrightText: 2024 gluesniffler <159397573+gluesniffler@users.noreply.github.com>
+REM SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com>
+REM
+REM SPDX-License-Identifier: AGPL-3.0-or-later
+
+cd ..\..\
+
+mkdir Scripts\logs
+
+del Scripts\logs\Content.Tests.log
+dotnet test Content.Tests/Content.Tests.csproj -c DebugOpt -- NUnit.ConsoleOut=0 > Scripts\logs\Content.Tests.log
+
+pause

+ 13 - 0
Scripts/bat/runTestsIntegration.bat

@@ -0,0 +1,13 @@
+REM SPDX-FileCopyrightText: 2024 gluesniffler <159397573+gluesniffler@users.noreply.github.com>
+REM SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com>
+REM
+REM SPDX-License-Identifier: AGPL-3.0-or-later
+
+cd ..\..\
+
+mkdir Scripts\logs
+
+del Scripts\logs\Content.IntegrationTests.log
+dotnet test Content.IntegrationTests/Content.IntegrationTests.csproj -c DebugOpt -- NUnit.ConsoleOut=0 NUnit.MapWarningTo=Failed > Scripts\logs\Content.IntegrationTests.log
+
+pause

+ 13 - 0
Scripts/bat/runTestsYAML.bat

@@ -0,0 +1,13 @@
+REM SPDX-FileCopyrightText: 2024 gluesniffler <159397573+gluesniffler@users.noreply.github.com>
+REM SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com>
+REM
+REM SPDX-License-Identifier: AGPL-3.0-or-later
+
+cd ..\..\
+
+mkdir Scripts\logs
+
+del Scripts\logs\Content.YAMLLinter.log
+dotnet run --project Content.YAMLLinter/Content.YAMLLinter.csproj -c DebugOpt -- NUnit.ConsoleOut=0 > Scripts\logs\Content.YAMLLinter.log
+
+pause

+ 0 - 0
runclient-Tools.bat → Scripts/bat/runclient-Tools.bat


+ 0 - 0
runclient.bat → Scripts/bat/runclient.bat


+ 0 - 0
runserver-Tools.bat → Scripts/bat/runserver-Tools.bat


+ 0 - 0
runserver.bat → Scripts/bat/runserver.bat


+ 25 - 0
Scripts/sh/!README.txt

@@ -0,0 +1,25 @@
+buildAllDebug
+    Builds all projects with debug configuration
+buildAllRelease
+    Builds all projects with release configuration
+buildAllTools
+    Builds all projects with tools configuration
+
+The debug vs release build is simply what people develop in vs the actual server.
+The release build contains various optimizations, while the debug build contains debugging tools.
+If you're mapping, use the release or tools build as it will run smoother with less crashes.
+
+
+runQuickAll
+    Runs the client and server without building
+runQuickClient
+    Runs the client without building
+runQuickServer
+    Runs the server without building
+
+runTests
+    Runs the unit tests, makes sure various C# systems work as intended
+runTestsIntegration
+    Runs the integration tests, makes sure various C# systems work as intended
+runTestsYAML
+    Runs the YAML linter and finds issues with the YAML files that you probably wouldn't otherwise

+ 16 - 0
Scripts/sh/buildAllDebug.sh

@@ -0,0 +1,16 @@
+# SPDX-FileCopyrightText: 2024 gluesniffler <159397573+gluesniffler@users.noreply.github.com>
+# SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com>
+#
+# SPDX-License-Identifier: AGPL-3.0-or-later
+
+#!/usr/bin/env sh
+
+# make sure to start from script dir
+if [ "$(dirname $0)" != "." ]; then
+    cd "$(dirname $0)"
+fi
+
+cd ../../
+
+git submodule update --init --recursive
+dotnet build -c Debug

+ 16 - 0
Scripts/sh/buildAllRelease.sh

@@ -0,0 +1,16 @@
+# SPDX-FileCopyrightText: 2024 gluesniffler <159397573+gluesniffler@users.noreply.github.com>
+# SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com>
+#
+# SPDX-License-Identifier: AGPL-3.0-or-later
+
+#!/usr/bin/env sh
+
+# make sure to start from script dir
+if [ "$(dirname $0)" != "." ]; then
+    cd "$(dirname $0)"
+fi
+
+cd ../../
+
+git submodule update --init --recursive
+dotnet build -c Release

+ 16 - 0
Scripts/sh/buildAllTools.sh

@@ -0,0 +1,16 @@
+# SPDX-FileCopyrightText: 2024 gluesniffler <159397573+gluesniffler@users.noreply.github.com>
+# SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com>
+#
+# SPDX-License-Identifier: AGPL-3.0-or-later
+
+#!/usr/bin/env sh
+
+# make sure to start from script dir
+if [ "$(dirname $0)" != "." ]; then
+    cd "$(dirname $0)"
+fi
+
+cd ../../
+
+git submodule update --init --recursive
+dotnet build -c Tools

+ 16 - 0
Scripts/sh/runQuickAll.sh

@@ -0,0 +1,16 @@
+# SPDX-FileCopyrightText: 2024 gluesniffler <159397573+gluesniffler@users.noreply.github.com>
+# SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com>
+#
+# SPDX-License-Identifier: AGPL-3.0-or-later
+
+#!/usr/bin/env sh
+
+# make sure to start from script dir
+if [ "$(dirname $0)" != "." ]; then
+    cd "$(dirname $0)"
+fi
+
+sh -e runQuickServer.sh &
+sh -e runQuickClient.sh
+
+exit

+ 14 - 0
Scripts/sh/runQuickClient.sh

@@ -0,0 +1,14 @@
+# SPDX-FileCopyrightText: 2024 gluesniffler <159397573+gluesniffler@users.noreply.github.com>
+# SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com>
+#
+# SPDX-License-Identifier: AGPL-3.0-or-later
+
+#!/usr/bin/env sh
+
+# make sure to start from script dir
+if [ "$(dirname $0)" != "." ]; then
+    cd "$(dirname $0)"
+fi
+
+cd ../../
+dotnet run --project Content.Client --no-build

+ 14 - 0
Scripts/sh/runQuickServer.sh

@@ -0,0 +1,14 @@
+# SPDX-FileCopyrightText: 2024 gluesniffler <159397573+gluesniffler@users.noreply.github.com>
+# SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com>
+#
+# SPDX-License-Identifier: AGPL-3.0-or-later
+
+#!/usr/bin/env sh
+
+# make sure to start from script dir
+if [ "$(dirname $0)" != "." ]; then
+    cd "$(dirname $0)"
+fi
+
+cd ../../
+dotnet run --project Content.Server --no-build

+ 14 - 0
Scripts/sh/runTests.sh

@@ -0,0 +1,14 @@
+# SPDX-FileCopyrightText: 2024 gluesniffler <159397573+gluesniffler@users.noreply.github.com>
+# SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com>
+#
+# SPDX-License-Identifier: AGPL-3.0-or-later
+
+cd ../../
+
+mkdir Scripts/logs
+
+rm Scripts/logs/Content.Tests.log
+dotnet test Content.Tests/Content.Tests.csproj -c DebugOpt -- NUnit.ConsoleOut=0 > Scripts/logs/Content.Tests.log
+
+echo "Tests complete. Press enter to continue."
+read

+ 14 - 0
Scripts/sh/runTestsIntegration.sh

@@ -0,0 +1,14 @@
+# SPDX-FileCopyrightText: 2024 gluesniffler <159397573+gluesniffler@users.noreply.github.com>
+# SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com>
+#
+# SPDX-License-Identifier: AGPL-3.0-or-later
+
+cd ../../
+
+mkdir Scripts/logs
+
+rm Scripts/logs/Content.IntegrationTests.log
+dotnet test Content.IntegrationTests/Content.IntegrationTests.csproj -c DebugOpt -- NUnit.ConsoleOut=0 NUnit.MapWarningTo=Failed > Scripts/logs/Content.IntegrationTests.log
+
+echo "Tests complete. Press enter to continue."
+read

+ 14 - 0
Scripts/sh/runTestsYAML.sh

@@ -0,0 +1,14 @@
+# SPDX-FileCopyrightText: 2024 gluesniffler <159397573+gluesniffler@users.noreply.github.com>
+# SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com>
+#
+# SPDX-License-Identifier: AGPL-3.0-or-later
+
+cd ../../
+
+mkdir Scripts/logs
+
+rm Scripts/logs/Content.YAMLLinter.log
+dotnet run --project Content.YAMLLinter/Content.YAMLLinter.csproj -c DebugOpt -- NUnit.ConsoleOut=0 > Scripts/logs/Content.YAMLLinter.log
+
+echo "Tests complete. Press enter to continue."
+read

+ 0 - 0
runclient-Tools.sh → Scripts/sh/runclient-Tools.sh


+ 0 - 0
runclient.sh → Scripts/sh/runclient.sh


+ 0 - 0
runserver-Tools.sh → Scripts/sh/runserver-Tools.sh


+ 0 - 0
runserver.sh → Scripts/sh/runserver.sh


+ 0 - 0
CivMigrations/README.md → Tools/CivMigrations/README.md


+ 0 - 0
CivMigrations/migrations.json → Tools/CivMigrations/migrations.json