Merge origin/master into asteroid-floater-layer
This commit is contained in:
commit
da2a7cc56a
17 changed files with 947 additions and 109 deletions
43
Assets/Scripts/ServerShared/HullFootprint.cs
Normal file
43
Assets/Scripts/ServerShared/HullFootprint.cs
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using CultMath;
|
||||
|
||||
// A hardpoint's schematic footprint: its Shape laid over the hull's cells at its Position, in hull orientation.
|
||||
// The footprint is authored for gameplay and never derived from the model or the Blender add-on
|
||||
// (schematic-and-model-are-separate-spaces). This is the one reading of footprint cells in hull space and the one
|
||||
// edit rule, so any host (the Studio drawer now, a Thing host later) edits footprints the same way.
|
||||
public static class HullFootprint
|
||||
{
|
||||
public static IEnumerable<int2> Cells(HardpointData hardpoint) =>
|
||||
hardpoint.Shape.Coordinates.Select(c => c + hardpoint.Position);
|
||||
|
||||
// Toggles one hull cell of the footprint at `position`. A cell outside the footprint grows it toward any edge;
|
||||
// a cell inside is removed and empty border rows and columns are trimmed; every other cell keeps its hull
|
||||
// coordinate. Removing the last cell is refused (false, outputs are the inputs' values). Builds a new Shape and
|
||||
// never edits the one it is given.
|
||||
public static bool Toggle(Shape footprint, int2 position, int2 hullCell, out Shape shape, out int2 newPosition)
|
||||
{
|
||||
var cells = Cells(footprint, position);
|
||||
if (!cells.Remove(hullCell)) cells.Add(hullCell);
|
||||
else if (cells.Count == 0)
|
||||
{
|
||||
shape = footprint;
|
||||
newPosition = position;
|
||||
return false;
|
||||
}
|
||||
|
||||
var min = cells.Aggregate((a, b) => new int2(math.min(a.x, b.x), math.min(a.y, b.y)));
|
||||
var max = cells.Aggregate((a, b) => new int2(math.max(a.x, b.x), math.max(a.y, b.y)));
|
||||
shape = new Shape(max.x - min.x + 1, max.y - min.y + 1);
|
||||
foreach (var cell in cells) shape[cell - min] = true;
|
||||
newPosition = min;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static HashSet<int2> Cells(Shape footprint, int2 position) =>
|
||||
new HashSet<int2>(footprint.Coordinates.Select(c => c + position));
|
||||
}
|
||||
11
Assets/Scripts/ServerShared/HullFootprint.cs.meta
Normal file
11
Assets/Scripts/ServerShared/HullFootprint.cs.meta
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5e2b8c4a7d1f4a39b6c0e83f91d7a254
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -60,6 +60,7 @@ public class Shape
|
|||
}
|
||||
|
||||
Cells = newCells;
|
||||
_dirty = true;
|
||||
}
|
||||
|
||||
private static int mod(int x, int m) {
|
||||
|
|
@ -85,11 +86,7 @@ public class Shape
|
|||
{
|
||||
get
|
||||
{
|
||||
if (_dirty)
|
||||
{
|
||||
_cachedShapeCoordinates = EnumerateShapeCoordinates().ToArray();
|
||||
_dirty = false;
|
||||
}
|
||||
Refresh();
|
||||
return _cachedShapeCoordinates;
|
||||
}
|
||||
}
|
||||
|
|
@ -108,7 +105,14 @@ public class Shape
|
|||
private int2[] _cachedAllShapeCoordinates;
|
||||
|
||||
[IgnoreMember]
|
||||
public int2[] AllCoordinates => _cachedAllShapeCoordinates ?? (_cachedAllShapeCoordinates = EnumerateAllShapeCoordinates().ToArray());
|
||||
public int2[] AllCoordinates
|
||||
{
|
||||
get
|
||||
{
|
||||
Refresh();
|
||||
return _cachedAllShapeCoordinates;
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<int2> EnumerateAllShapeCoordinates()
|
||||
{
|
||||
|
|
@ -121,11 +125,27 @@ public class Shape
|
|||
}
|
||||
}
|
||||
|
||||
private float2? _centerOfMass;
|
||||
private float2 _centerOfMass;
|
||||
|
||||
[IgnoreMember]
|
||||
public float2 CenterOfMass => _centerOfMass ?? (_centerOfMass = Coordinates
|
||||
.Aggregate(float2.zero, (total, coord) => total + coord) / Coordinates.Length).Value;
|
||||
public float2 CenterOfMass
|
||||
{
|
||||
get
|
||||
{
|
||||
Refresh();
|
||||
return _centerOfMass;
|
||||
}
|
||||
}
|
||||
|
||||
// One dirty flag: Coordinates, AllCoordinates and CenterOfMass are caches of Cells and recompute together.
|
||||
private void Refresh()
|
||||
{
|
||||
if (!_dirty) return;
|
||||
_cachedShapeCoordinates = EnumerateShapeCoordinates().ToArray();
|
||||
_cachedAllShapeCoordinates = EnumerateAllShapeCoordinates().ToArray();
|
||||
_centerOfMass = _cachedShapeCoordinates.Aggregate(float2.zero, (total, coord) => total + coord) / _cachedShapeCoordinates.Length;
|
||||
_dirty = false;
|
||||
}
|
||||
|
||||
public bool this[int2 pos] {
|
||||
get { return pos.x >= 0 && pos.y >= 0 && pos.x < Width && pos.y < Height && Cells[pos.x, pos.y]; }
|
||||
|
|
@ -256,7 +276,7 @@ public class Shape
|
|||
{
|
||||
if (x >= 0 && x < Width && y >= 0 && y < Height)
|
||||
{
|
||||
Cells[steep ? y : x, steep ? x : y] = true;
|
||||
this[int2(steep ? y : x, steep ? x : y)] = true;
|
||||
}
|
||||
error += derr;
|
||||
if (error >= 0.5f)
|
||||
|
|
@ -798,8 +818,8 @@ public static class StatValidation
|
|||
// ApplyModifier threw an unhelpful NullReferenceException at random equip time. Resolving it here, once,
|
||||
// memoized, and failing loudly at catalog load or Upsert (through ValidateStatModifiers below) names the
|
||||
// record instead of leaving the bug for whoever equips the item first.
|
||||
private static readonly Dictionary<(string Target, string Stat), (Type Type, FieldInfo Field)> _resolvedStatFields =
|
||||
new Dictionary<(string, string), (Type, FieldInfo)>();
|
||||
private static readonly System.Collections.Concurrent.ConcurrentDictionary<(string Target, string Stat), (Type Type, FieldInfo Field)> _resolvedStatFields =
|
||||
new System.Collections.Concurrent.ConcurrentDictionary<(string, string), (Type, FieldInfo)>();
|
||||
|
||||
private static Type[] _statReferenceTypes;
|
||||
private static Type[] StatReferenceTypes => _statReferenceTypes ??= typeof(BehaviorData).GetAllChildClasses()
|
||||
|
|
|
|||
Loading…
Reference in a new issue