Unstable 0.15.15.0 (and the one before it I forgor)
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
#nullable enable
|
||||
using Barotrauma.Extensions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -12,13 +13,13 @@ namespace Barotrauma
|
||||
|
||||
private int maxId;
|
||||
|
||||
private readonly List<Range<int>> srcRanges;
|
||||
private readonly List<Range<int>>? srcRanges;
|
||||
private readonly int destOffset;
|
||||
|
||||
public IdRemap(XElement parentElement, int offset)
|
||||
public IdRemap(XElement? parentElement, int offset)
|
||||
{
|
||||
destOffset = offset;
|
||||
if (parentElement != null && parentElement.HasElements)
|
||||
if (parentElement is { HasElements: true })
|
||||
{
|
||||
srcRanges = new List<Range<int>>();
|
||||
foreach (XElement subElement in parentElement.Elements())
|
||||
@@ -26,56 +27,60 @@ namespace Barotrauma
|
||||
int id = subElement.GetAttributeInt("ID", -1);
|
||||
if (id > 0) { InsertId(id); }
|
||||
}
|
||||
maxId = GetOffsetId(srcRanges.Last().End) + 1;
|
||||
maxId = GetOffsetId(srcRanges.Last().End);
|
||||
}
|
||||
else
|
||||
{
|
||||
maxId = offset + 1;
|
||||
maxId = offset;
|
||||
}
|
||||
}
|
||||
|
||||
public ushort AssignMaxId()
|
||||
public void AssignMaxId(out ushort result)
|
||||
{
|
||||
maxId++;
|
||||
return (ushort)maxId;
|
||||
result = (ushort)maxId;
|
||||
}
|
||||
|
||||
private void InsertId(int id)
|
||||
{
|
||||
for (int i = 0; i < srcRanges.Count; i++)
|
||||
if (srcRanges is null) { throw new NullReferenceException("Called InsertId when srcRanges is null"); }
|
||||
|
||||
void tryMergeRangeWithNext(int indexA)
|
||||
{
|
||||
if (srcRanges[i].Start > id)
|
||||
int indexB = indexA + 1;
|
||||
|
||||
if (indexA < 0 /* Index A out of bounds */
|
||||
|| indexB >= srcRanges.Count /* Index B out of bounds */)
|
||||
{
|
||||
if (srcRanges[i].Start == (id + 1))
|
||||
{
|
||||
srcRanges[i] = new Range<int>(id, srcRanges[i].End);
|
||||
if (i > 0 && srcRanges[i].Start == srcRanges[i - 1].End)
|
||||
{
|
||||
srcRanges[i - 1] = new Range<int>(srcRanges[i - 1].Start, srcRanges[i].End);
|
||||
srcRanges.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
srcRanges.Insert(i, new Range<int>(id, id));
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (srcRanges[i].End < id)
|
||||
|
||||
Range<int> rangeA = srcRanges[indexA];
|
||||
Range<int> rangeB = srcRanges[indexB];
|
||||
|
||||
if ((rangeA.End+1) >= rangeB.Start) //The end of range A is right before the start of range B, this should be one range
|
||||
{
|
||||
if (srcRanges[i].End == (id - 1))
|
||||
{
|
||||
srcRanges[i] = new Range<int>(srcRanges[i].Start, id);
|
||||
if (i < (srcRanges.Count - 1) && srcRanges[i].End == srcRanges[i + 1].Start)
|
||||
{
|
||||
srcRanges[i] = new Range<int>(srcRanges[i].Start, srcRanges[i + 1].End);
|
||||
srcRanges.RemoveAt(i + 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
srcRanges[indexA] = new Range<int>(rangeA.Start, rangeB.End);
|
||||
srcRanges.RemoveAt(indexB);
|
||||
}
|
||||
}
|
||||
srcRanges.Add(new Range<int>(id, id));
|
||||
|
||||
int insertIndex = srcRanges.Count;
|
||||
for (int i = 0; i < srcRanges.Count; i++)
|
||||
{
|
||||
if (srcRanges[i].Contains(id)) //We already have a range that contains this ID, duplicates are invalid input!
|
||||
{
|
||||
throw new InvalidOperationException($"Duplicate ID: {id}");
|
||||
}
|
||||
if (srcRanges[i].Start > id) //ID is between srcRanges[i-1] and srcRanges[i], insert at i
|
||||
{
|
||||
insertIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
srcRanges.Insert(insertIndex, new Range<int>(id, id)); //Insert new range consisting of solely the new ID
|
||||
tryMergeRangeWithNext(insertIndex); //Try merging new range with the one that comes after it
|
||||
tryMergeRangeWithNext(insertIndex - 1); //Try merging new range with the one that comes before it
|
||||
}
|
||||
|
||||
public ushort GetOffsetId(XElement element)
|
||||
@@ -85,31 +90,47 @@ namespace Barotrauma
|
||||
|
||||
public ushort GetOffsetId(int id)
|
||||
{
|
||||
if (id <= 0) { return 0; }
|
||||
if (destOffset < 0) { return 0; }
|
||||
if (srcRanges == null) { return (ushort)(id + destOffset); }
|
||||
if (id <= 0) //Input cannot be remapped because it's negative
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (destOffset < 0) //Remapper has been defined to discard all input
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (srcRanges is null) //Remapper defines no source ranges so it just adds an offset
|
||||
{
|
||||
return (ushort)(id + destOffset);
|
||||
}
|
||||
|
||||
int rangeSize(in Range<int> r)
|
||||
=> r.End - r.Start + 1;
|
||||
|
||||
int currOffset = destOffset;
|
||||
for (int i = 0; i < srcRanges.Count; i++)
|
||||
{
|
||||
if (id >= srcRanges[i].Start && id <= srcRanges[i].End)
|
||||
if (srcRanges[i].Contains(id))
|
||||
{
|
||||
return (ushort)(id - srcRanges[i].Start + 1 + currOffset);
|
||||
//The source range for this ID has been found!
|
||||
//The return value is such that all IDs that
|
||||
//are returned by this remapper are contiguous,
|
||||
//even if they weren't originally
|
||||
return (ushort)(id - srcRanges[i].Start + currOffset);
|
||||
}
|
||||
currOffset += srcRanges[i].End - srcRanges[i].Start + 1;
|
||||
currOffset += rangeSize(srcRanges[i]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static ushort DetermineNewOffset()
|
||||
{
|
||||
ushort idOffset = 0;
|
||||
int largestEntityId = 0;
|
||||
foreach (Entity e in Entity.GetEntities())
|
||||
{
|
||||
if (e.ID > Entity.ReservedIDStart || e is Submarine) { continue; }
|
||||
idOffset = Math.Max(idOffset, e.ID);
|
||||
largestEntityId = Math.Max(largestEntityId, e.ID);
|
||||
}
|
||||
return idOffset;
|
||||
return (ushort)(largestEntityId+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,12 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public struct Range<T> where T : IComparable
|
||||
/// <summary>
|
||||
/// An inclusive range, i.e. [Start, End] where Start <= End
|
||||
/// </summary>
|
||||
public struct Range<T> where T : notnull, IComparable<T>
|
||||
{
|
||||
private T start; private T end;
|
||||
public T Start
|
||||
@@ -25,6 +29,9 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public bool Contains(in T v)
|
||||
=> start.CompareTo(v) <= 0 && end.CompareTo(v) >= 0;
|
||||
|
||||
private void VerifyStartLessThanEnd()
|
||||
{
|
||||
if (start.CompareTo(end) > 0) { throw new InvalidOperationException($"Range<{typeof(T).Name}>.Start set to a value greater than End ({start} > {end})"); }
|
||||
|
||||
@@ -425,7 +425,7 @@ namespace Barotrauma
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public static T SelectWeightedRandom<T>(IList<T> objects, IList<float> weights, Rand.RandSync randSync)
|
||||
public static T SelectWeightedRandom<T>(IList<T> objects, IList<float> weights, Rand.RandSync randSync = Rand.RandSync.Unsynced)
|
||||
{
|
||||
return SelectWeightedRandom(objects, weights, Rand.GetRNG(randSync));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user