Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ All notable changes to this package will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [0.12.0] - 2024-10-22

- Added IRngData to PoolService to suppprt read only data structure and allow abtract injection of data into other objects

**Changed**:
- Changed RngData to a class in orther to avoid boxing/unboxing performance when injecting IRngData.

## [0.11.0] - 2024-10-19

- Added Spawn<T>(T data) method to PoolService to allow spawning new objects with defined spawning data
Expand Down
122 changes: 67 additions & 55 deletions Runtime/RngService.cs
Original file line number Diff line number Diff line change
@@ -1,40 +1,67 @@
using System;
using System.Collections.Generic;

namespace GameLovers.Services
{
/// <summary>
/// Contains all the data in the scope to generate and maintain the random generated values
/// Implement this interface if you use a data structure in a class to pass the values by reference
/// and thus updating directly your internal data container.
/// </summary>
[Serializable]
public struct RngData
public interface IRngData
{
public int Seed;
public int Count;
public int[] State;
/// <summary>
/// Gets the seed used to initialize the RNG.
/// </summary>
int Seed { get; }

/// <summary>
/// Gets the number of random numbers generated so far.
/// </summary>
int Count { get; }

/// <summary>
/// Gets the current state of the RNG.
/// </summary>
IReadOnlyList<int> State { get; }
}

/// <summary>
/// Implement this interface if you use a data structure in a class to pass the values by reference
/// and thus updating directly your internal data container
/// Represents a data structure for storing random number generation (RNG) state.
/// </summary>
public interface IRngData
public class RngData : IRngData
{
/// <summary>
/// The data container the state of the RNG information change.
/// The seed used to initialize the RNG.
/// </summary>
RngData Data { get; set; }
}
public int Seed;

/// <summary>
/// The number of random numbers generated so far.
/// </summary>
public int Count;

/// <summary>
/// The current state of the RNG.
/// </summary>
public int[] State;

/// <inheritdoc/>
int IRngData.Seed => Seed;
/// <inheritdoc/>
int IRngData.Count => Count;
/// <inheritdoc/>
IReadOnlyList<int> IRngData.State => Array.AsReadOnly(State);
}
/// <summary>
/// This Service provides the necessary behaviour to manage the random generated values with always a deterministic result
/// Based on the .Net library Random class <see cref="https://referencesource.microsoft.com/#mscorlib/system/random.cs"/>
/// </summary>
public interface IRngService
{
/// <summary>
/// The <see cref="RngData"/> that this service is manipulating
/// The <see cref="IRngData"/> that this service is manipulating
/// </summary>
public RngData Data { get; }
public IRngData Data { get; }

/// <summary>
/// Returns the number of times the Rng has been counted;
Expand Down Expand Up @@ -96,7 +123,7 @@ public class RngService : IRngService
private const int _helperInc = 21;
private const int _valueIndex = 0;

private IRngData _rngData;
private RngData _rngData;

/// <inheritdoc />
public int Counter => Data.Count;
Expand All @@ -114,67 +141,46 @@ public class RngService : IRngService
public floatP Nextfloat => Range((floatP) 0, floatP.MaxValue);

/// <inheritdoc />
public RngData Data
{
get => _rngData.Data;
private set => _rngData.Data = value;
}
public IRngData Data => _rngData;

public RngService(RngData rngData)
{
_rngData = new InternalRngData { Data = rngData };
}

public RngService(IRngData data)
{
_rngData = data;
_rngData = rngData;
}

/// <inheritdoc />
public int PeekRange(int min, int max, bool maxInclusive = false)
{
return Range(min, max, CopyRngState(Data.State), maxInclusive);
return Range(min, max, CopyRngState(_rngData.State), maxInclusive);
}

/// <inheritdoc />
public floatP PeekRange(floatP min, floatP max, bool maxInclusive = true)
{
return Range(min, max, CopyRngState(Data.State), maxInclusive);
return Range(min, max, CopyRngState(_rngData.State), maxInclusive);
}

/// <inheritdoc />
public int Range(int min, int max, bool maxInclusive = false)
{
var data = Data;

data.Count++;

Data = data;
_rngData.Count++;

return Range(min, max, Data.State, maxInclusive);
return Range(min, max, _rngData.State, maxInclusive);
}

/// <inheritdoc />
public floatP Range(floatP min, floatP max, bool maxInclusive = true)
{
var data = Data;
_rngData.Count++;

data.Count++;

Data = data;

return Range(min, max, Data.State, maxInclusive);
return Range(min, max, _rngData.State, maxInclusive);
}

/// <inheritdoc />
public void Restore(int count)
{
var data = Data;

data.Count = count;
data.State = Restore(count, Data.Seed);

Data = data;
_rngData.Count = count;
_rngData.State = Restore(count, _rngData.Seed);
}

/// <summary>
Expand Down Expand Up @@ -254,6 +260,21 @@ public static int[] CopyRngState(int[] state)
return newState;
}

/// <summary>
/// Creates a new instance of <see cref="RngData"/> with the given <paramref name="seed"/>.
/// </summary>
/// <param name="seed">The seed value for the RNG.</param>
/// <returns>A new instance of <see cref="RngData"/> with the given <paramref name="seed"/> and an initial count of 0.</returns>
public static RngData CreateRngData(int seed)
{
return new RngData
{
Seed = seed,
Count = 0,
State = GenerateRngState(seed)
};
}

/// <summary>
/// Generates a completely new state rng state based on the given <paramref name="seed"/>.
/// Based on the publish work of D.E. Knuth <see cref="https://www.informit.com/articles/article.aspx?p=2221790"/>
Expand Down Expand Up @@ -319,14 +340,5 @@ private static int NextNumber(int[] rndState)

return ret;
}

/// <summary>
/// Used only in the scope of this service in case that no class is passed into the object
/// </summary>
private class InternalRngData : IRngData
{
/// <inheritdoc />
public RngData Data { get; set; }
}
}
}
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
"name": "com.gamelovers.services",
"displayName": "Services",
"author": "Miguel Tomas",
"version": "0.11.0",
"version": "0.12.0",
"unity": "2022.4",
"license": "MIT",
"description": "The purpose of this package is to provide a set of services to ease the development of a basic game architecture",
"type": "library",
"hideInEditor": false,
"dependencies": {
"com.gamelovers.dataextensions": "0.5.0"
"com.gamelovers.dataextensions": "0.6.0"
}
}