diff --git a/MSBuild/SS14.Engine.targets b/MSBuild/SS14.Engine.targets
index 32676f7a188..7f47fb2c717 100644
--- a/MSBuild/SS14.Engine.targets
+++ b/MSBuild/SS14.Engine.targets
@@ -6,4 +6,8 @@
+
+
+
+
diff --git a/SS14.Client/SS14.Client.csproj b/SS14.Client/SS14.Client.csproj
index c228e08ee93..40232f12fc9 100644
--- a/SS14.Client/SS14.Client.csproj
+++ b/SS14.Client/SS14.Client.csproj
@@ -328,4 +328,5 @@
-
\ No newline at end of file
+
+
diff --git a/SS14.Server/SS14.Server.csproj b/SS14.Server/SS14.Server.csproj
index c4c6d1f50d8..180e013a74a 100644
--- a/SS14.Server/SS14.Server.csproj
+++ b/SS14.Server/SS14.Server.csproj
@@ -209,10 +209,11 @@
+
-
\ No newline at end of file
+
diff --git a/SS14.Shared.Maths/SS14.Shared.Maths.csproj b/SS14.Shared.Maths/SS14.Shared.Maths.csproj
index 4b31ac83f7f..d6b4bbf09e7 100644
--- a/SS14.Shared.Maths/SS14.Shared.Maths.csproj
+++ b/SS14.Shared.Maths/SS14.Shared.Maths.csproj
@@ -95,10 +95,13 @@
+
+
+
\ No newline at end of file
diff --git a/SS14.Shared.Maths/Vector2d.cs b/SS14.Shared.Maths/Vector2d.cs
new file mode 100644
index 00000000000..4f177948dab
--- /dev/null
+++ b/SS14.Shared.Maths/Vector2d.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace SS14.Shared.Maths
+{
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential)]
+ public readonly struct Vector2d
+ {
+ public readonly double X;
+ public readonly double Y;
+
+ public Vector2d(double x, double y)
+ {
+ X = x;
+ Y = y;
+ }
+
+ public static implicit operator Vector2d(Vector2 vector)
+ {
+ return new Vector2d(vector.X, vector.Y);
+ }
+ }
+}
diff --git a/SS14.Shared.Maths/Vector3d.cs b/SS14.Shared.Maths/Vector3d.cs
new file mode 100644
index 00000000000..858f8605230
--- /dev/null
+++ b/SS14.Shared.Maths/Vector3d.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace SS14.Shared.Maths
+{
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential)]
+ public readonly struct Vector3d
+ {
+ public readonly double X;
+ public readonly double Y;
+ public readonly double Z;
+
+ public Vector3d(double x, double y, double z)
+ {
+ X = x;
+ Y = y;
+ Z = z;
+ }
+
+ public static implicit operator Vector3d(Vector3 vector)
+ {
+ return new Vector3d(vector.X, vector.Y, vector.Z);
+ }
+ }
+}
diff --git a/SS14.Shared.Maths/Vector4d.cs b/SS14.Shared.Maths/Vector4d.cs
new file mode 100644
index 00000000000..6759cc3663f
--- /dev/null
+++ b/SS14.Shared.Maths/Vector4d.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace SS14.Shared.Maths
+{
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential)]
+ public readonly struct Vector4d
+ {
+ public readonly double X;
+ public readonly double Y;
+ public readonly double Z;
+ public readonly double W;
+
+ public Vector4d(double x, double y, double z, double w)
+ {
+ X = x;
+ Y = y;
+ Z = z;
+ W = w;
+ }
+
+ public static implicit operator Vector4d(Vector4 vector)
+ {
+ return new Vector4d(vector.X, vector.Y, vector.Z, vector.W);
+ }
+ }
+}
diff --git a/SS14.Shared/Noise/NoiseGenerator.cs b/SS14.Shared/Noise/NoiseGenerator.cs
new file mode 100644
index 00000000000..4dc4eaf7d69
--- /dev/null
+++ b/SS14.Shared/Noise/NoiseGenerator.cs
@@ -0,0 +1,180 @@
+using System;
+using System.Runtime.InteropServices;
+using JetBrains.Annotations;
+using SS14.Shared.Maths;
+
+namespace SS14.Shared.Noise
+{
+ [PublicAPI]
+ public sealed class NoiseGenerator : IDisposable
+ {
+ [PublicAPI]
+ public enum NoiseType
+ {
+ Fbm = 0,
+ Ridged = 1
+ }
+
+ private IntPtr _nativeGenerator;
+
+ public NoiseGenerator(NoiseType type)
+ {
+ _nativeGenerator = _GeneratorMake((byte) type);
+ }
+
+ public bool Disposed => _nativeGenerator == IntPtr.Zero;
+
+ public void Dispose()
+ {
+ if (Disposed) return;
+
+ _GeneratorDispose(_nativeGenerator);
+ _nativeGenerator = IntPtr.Zero;
+ }
+
+ public void SetFrequency(double frequency)
+ {
+ if (Disposed) throw new ObjectDisposedException(nameof(NoiseGenerator));
+ _GeneratorSetFrequency(_nativeGenerator, frequency);
+ }
+
+ public void SetLacunarity(double lacunarity)
+ {
+ if (Disposed) throw new ObjectDisposedException(nameof(NoiseGenerator));
+ _GeneratorSetLacunarity(_nativeGenerator, lacunarity);
+ }
+
+ public void SetPersistence(double persistence)
+ {
+ if (Disposed) throw new ObjectDisposedException(nameof(NoiseGenerator));
+ _GeneratorSetPersistence(_nativeGenerator, persistence);
+ }
+
+ public void SetPeriodX(double periodX)
+ {
+ if (Disposed) throw new ObjectDisposedException(nameof(NoiseGenerator));
+ _GeneratorSetPeriodX(_nativeGenerator, periodX);
+ }
+
+ public void SetPeriodY(double periodY)
+ {
+ if (Disposed) throw new ObjectDisposedException(nameof(NoiseGenerator));
+ _GeneratorSetPeriodY(_nativeGenerator, periodY);
+ }
+
+ public void SetOctaves(uint octaves)
+ {
+ if (Disposed) throw new ObjectDisposedException(nameof(NoiseGenerator));
+ if (octaves > 32)
+ throw new ArgumentOutOfRangeException(nameof(octaves), octaves,
+ "Octave count cannot be greater than 32.");
+ _GeneratorSetOctaves(_nativeGenerator, octaves);
+ }
+
+ public void SetSeed(uint seed)
+ {
+ _GeneratorSetSeed(_nativeGenerator, seed);
+ }
+
+ public double GetNoiseTiled(float x, float y)
+ {
+ return GetNoiseTiled(new Vector2(x, y));
+ }
+
+ public double GetNoiseTiled(Vector2d vec)
+ {
+ if (Disposed) throw new ObjectDisposedException(nameof(NoiseGenerator));
+
+ return _GetNoiseTiled2D(_nativeGenerator, vec);
+ }
+
+ public double GetNoise(float x, float y)
+ {
+ return GetNoise(new Vector2(x, y));
+ }
+
+ public double GetNoise(Vector2d vector)
+ {
+ if (Disposed) throw new ObjectDisposedException(nameof(NoiseGenerator));
+
+ return _GetNoise2D(_nativeGenerator, vector);
+ }
+
+ public double GetNoise(float x, float y, float z)
+ {
+ return GetNoise(new Vector3(x, y, z));
+ }
+
+ public double GetNoise(Vector3d vector)
+ {
+ if (Disposed) throw new ObjectDisposedException(nameof(NoiseGenerator));
+
+ return _GetNoise3D(_nativeGenerator, vector);
+ }
+
+ public double GetNoise(float x, float y, float z, float w)
+ {
+ return GetNoise(new Vector4(x, y, z, w));
+ }
+
+ public double GetNoise(Vector4d vector)
+ {
+ if (Disposed) throw new ObjectDisposedException(nameof(NoiseGenerator));
+
+ return _GetNoise4D(_nativeGenerator, vector);
+ }
+
+ ~NoiseGenerator()
+ {
+ Dispose();
+ }
+
+ #region FFI
+
+ [DllImport("ss14_noise.dll", EntryPoint = "generator_new", CallingConvention = CallingConvention.Cdecl)]
+ private static extern IntPtr _GeneratorMake(byte noiseType);
+
+ [DllImport("ss14_noise.dll", EntryPoint = "generator_set_octaves", CallingConvention = CallingConvention.Cdecl)]
+ private static extern void _GeneratorSetOctaves(IntPtr gen, uint octaves);
+
+ [DllImport("ss14_noise.dll", EntryPoint = "generator_set_persistence",
+ CallingConvention = CallingConvention.Cdecl)]
+ private static extern void _GeneratorSetPersistence(IntPtr gen, double persistence);
+
+ [DllImport("ss14_noise.dll", EntryPoint = "generator_set_lacunarity",
+ CallingConvention = CallingConvention.Cdecl)]
+ private static extern void _GeneratorSetLacunarity(IntPtr gen, double lacunarity);
+
+ [DllImport("ss14_noise.dll", EntryPoint = "generator_set_period_x",
+ CallingConvention = CallingConvention.Cdecl)]
+ private static extern void _GeneratorSetPeriodX(IntPtr gen, double periodX);
+
+ [DllImport("ss14_noise.dll", EntryPoint = "generator_set_period_y",
+ CallingConvention = CallingConvention.Cdecl)]
+ private static extern void _GeneratorSetPeriodY(IntPtr gen, double periodY);
+
+ [DllImport("ss14_noise.dll", EntryPoint = "generator_set_frequency",
+ CallingConvention = CallingConvention.Cdecl)]
+ private static extern void _GeneratorSetFrequency(IntPtr gen, double frequency);
+
+ [DllImport("ss14_noise.dll", EntryPoint = "generator_set_seed", CallingConvention = CallingConvention.Cdecl)]
+ private static extern void _GeneratorSetSeed(IntPtr gen, uint seed);
+
+ [DllImport("ss14_noise.dll", EntryPoint = "generator_dispose", CallingConvention = CallingConvention.Cdecl)]
+ private static extern void _GeneratorDispose(IntPtr gen);
+
+ [DllImport("ss14_noise.dll", EntryPoint = "get_noise_2d", CallingConvention = CallingConvention.Cdecl)]
+ private static extern double _GetNoise2D(IntPtr gen, Vector2d pos);
+
+ [DllImport("ss14_noise.dll", EntryPoint = "get_noise_3d", CallingConvention = CallingConvention.Cdecl)]
+ private static extern double _GetNoise3D(IntPtr gen, Vector3d pos);
+
+ [DllImport("ss14_noise.dll", EntryPoint = "get_noise_4d", CallingConvention = CallingConvention.Cdecl)]
+ private static extern double _GetNoise4D(IntPtr gen, Vector4d pos);
+
+ [DllImport("ss14_noise.dll", EntryPoint = "get_noise_tiled_2d", CallingConvention = CallingConvention.Cdecl)]
+ private static extern double _GetNoiseTiled2D(IntPtr gen, Vector2d pos);
+
+ #endregion
+ }
+}
diff --git a/SS14.Shared/Noise/ss14-noise/.gitignore b/SS14.Shared/Noise/ss14-noise/.gitignore
new file mode 100644
index 00000000000..183dd9cd889
--- /dev/null
+++ b/SS14.Shared/Noise/ss14-noise/.gitignore
@@ -0,0 +1,2 @@
+target/
+*.rs.bk
diff --git a/SS14.Shared/Noise/ss14-noise/Cargo.lock b/SS14.Shared/Noise/ss14-noise/Cargo.lock
new file mode 100644
index 00000000000..b6717619835
--- /dev/null
+++ b/SS14.Shared/Noise/ss14-noise/Cargo.lock
@@ -0,0 +1,78 @@
+[[package]]
+name = "bitflags"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "fuchsia-zircon"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "fuchsia-zircon-sys"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "libc"
+version = "0.2.42"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "noise"
+version = "0.5.1"
+source = "git+https://github.com/space-wizards/noise-rs.git?branch=develop#5beca286b1c0b1bd52e5a0f56011fbec04b077f5"
+dependencies = [
+ "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rand"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "ss14-noise"
+version = "0.1.0"
+dependencies = [
+ "noise 0.5.1 (git+https://github.com/space-wizards/noise-rs.git?branch=develop)",
+]
+
+[[package]]
+name = "winapi"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[metadata]
+"checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789"
+"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
+"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
+"checksum libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)" = "b685088df2b950fccadf07a7187c8ef846a959c142338a48f9dc0b94517eb5f1"
+"checksum noise 0.5.1 (git+https://github.com/space-wizards/noise-rs.git?branch=develop)" = ""
+"checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5"
+"checksum winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "773ef9dcc5f24b7d850d0ff101e542ff24c3b090a9768e03ff889fdef41f00fd"
+"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/SS14.Shared/Noise/ss14-noise/Cargo.toml b/SS14.Shared/Noise/ss14-noise/Cargo.toml
new file mode 100644
index 00000000000..5d5b7cbb5b8
--- /dev/null
+++ b/SS14.Shared/Noise/ss14-noise/Cargo.toml
@@ -0,0 +1,14 @@
+[package]
+name = "ss14-noise"
+version = "0.1.0"
+authors = ["PJB3005 "]
+publish = false
+
+[lib]
+name = "ss14_noise"
+crate-type = ["dylib"]
+
+[dependencies.noise]
+git = "https://github.com/space-wizards/noise-rs.git"
+branch = "develop"
+default-features = false
\ No newline at end of file
diff --git a/SS14.Shared/Noise/ss14-noise/src/lib.rs b/SS14.Shared/Noise/ss14-noise/src/lib.rs
new file mode 100644
index 00000000000..d5d8f17d862
--- /dev/null
+++ b/SS14.Shared/Noise/ss14-noise/src/lib.rs
@@ -0,0 +1,273 @@
+extern crate noise;
+
+use noise::{Fbm, MultiFractal, NoiseFn, Point2, Point3, Point4, RidgedMulti, Seedable};
+use std::mem;
+
+pub struct NoiseGenerator {
+ pub period_x: f64,
+ pub period_y: f64,
+ pub noise_type: NoiseType,
+}
+
+impl NoiseGenerator {
+ fn set_frequency(&mut self, frequency: f64) {
+ match self.noise_type {
+ NoiseType::Fbm(ref mut fbm) => {
+ let mut repl = fbm.clone().set_frequency(frequency);
+ mem::swap(fbm, &mut repl)
+ }
+ NoiseType::Ridged(ref mut ridged) => {
+ let mut repl = ridged.clone().set_frequency(frequency);
+ mem::swap(ridged, &mut repl)
+ }
+ }
+ }
+
+ fn set_lacunarity(&mut self, lacunarity: f64) {
+ match self.noise_type {
+ NoiseType::Fbm(ref mut fbm) => {
+ let mut repl = fbm.clone().set_lacunarity(lacunarity);
+ mem::swap(fbm, &mut repl)
+ }
+ NoiseType::Ridged(ref mut ridged) => {
+ let mut repl = ridged.clone().set_lacunarity(lacunarity);
+ mem::swap(ridged, &mut repl)
+ }
+ }
+ }
+
+ fn set_persistence(&mut self, persistence: f64) {
+ match self.noise_type {
+ NoiseType::Fbm(ref mut fbm) => {
+ let mut repl = fbm.clone().set_persistence(persistence);
+ mem::swap(fbm, &mut repl)
+ }
+ NoiseType::Ridged(ref mut ridged) => {
+ let mut repl = ridged.clone().set_persistence(persistence);
+ mem::swap(ridged, &mut repl)
+ }
+ }
+ }
+
+ fn set_octaves(&mut self, octaves: usize) {
+ match self.noise_type {
+ NoiseType::Fbm(ref mut fbm) => {
+ let mut repl = fbm.clone().set_octaves(octaves);
+ mem::swap(fbm, &mut repl)
+ }
+ NoiseType::Ridged(ref mut ridged) => {
+ let mut repl = ridged.clone().set_octaves(octaves);
+ mem::swap(ridged, &mut repl)
+ }
+ }
+ }
+
+ fn set_seed(&mut self, seed: u32) {
+ match self.noise_type {
+ NoiseType::Fbm(ref mut fbm) => {
+ let mut repl = fbm.clone().set_seed(seed);
+ mem::swap(fbm, &mut repl)
+ }
+ NoiseType::Ridged(ref mut ridged) => {
+ let mut repl = ridged.clone().set_seed(seed);
+ mem::swap(ridged, &mut repl)
+ }
+ }
+ }
+}
+
+impl NoiseFn> for NoiseGenerator {
+ fn get(&self, point: Point2) -> f64 {
+ match self.noise_type {
+ NoiseType::Fbm(ref fbm) => fbm.get(point),
+ NoiseType::Ridged(ref ridged) => ridged.get(point),
+ }
+ }
+}
+
+impl NoiseFn> for NoiseGenerator {
+ fn get(&self, point: Point3) -> f64 {
+ match self.noise_type {
+ NoiseType::Fbm(ref fbm) => fbm.get(point),
+ NoiseType::Ridged(ref ridged) => ridged.get(point),
+ }
+ }
+}
+
+impl NoiseFn> for NoiseGenerator {
+ fn get(&self, point: Point4) -> f64 {
+ match self.noise_type {
+ NoiseType::Fbm(ref fbm) => fbm.get(point),
+ NoiseType::Ridged(ref ridged) => ridged.get(point),
+ }
+ }
+}
+
+
+pub enum NoiseType {
+ Fbm(Fbm),
+ Ridged(RidgedMulti),
+}
+
+impl NoiseType {
+ pub fn new(noise_type: u8) -> Self {
+ match noise_type {
+ 0 => {
+ let fbm = Fbm::new();
+ NoiseType::Fbm(fbm)
+ }
+ 1 => {
+ let ridged = RidgedMulti::new();
+ NoiseType::Ridged(ridged)
+ }
+ _ => {
+ panic!("Invalid type code.");
+ }
+ }
+ }
+}
+
+#[repr(C)]
+#[derive(Copy, Clone, Debug)]
+pub struct Vec4 {
+ pub x: f64,
+ pub y: f64,
+ pub z: f64,
+ pub w: f64,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone, Debug)]
+pub struct Vec3 {
+ pub x: f64,
+ pub y: f64,
+ pub z: f64
+}
+
+#[repr(C)]
+#[derive(Copy, Clone, Debug)]
+pub struct Vec2 {
+ pub x: f64,
+ pub y: f64,
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn generator_new(noise_type: u8) -> *mut NoiseGenerator {
+ let noise = NoiseGenerator {
+ period_x: 1.0,
+ period_y: 1.0,
+ noise_type: NoiseType::new(noise_type),
+ };
+ let boxed = Box::new(noise);
+ Box::into_raw(boxed)
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn generator_dispose(ptr: *mut NoiseGenerator) {
+ let boxed = Box::from_raw(ptr);
+ mem::drop(boxed);
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn get_noise_2d(ptr: *mut NoiseGenerator, vec: Vec2) -> f64 {
+ let boxed = Box::from_raw(ptr);
+ let val = boxed.get([vec.x, vec.y]);
+ mem::forget(boxed);
+ val
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn get_noise_3d(ptr: *mut NoiseGenerator, vec: Vec3) -> f64 {
+ let boxed = Box::from_raw(ptr);
+ let val = boxed.get([vec.x, vec.y, vec.z]);
+ mem::forget(boxed);
+ val
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn get_noise_4d(ptr: *mut NoiseGenerator, vec: Vec4) -> f64 {
+ let boxed = Box::from_raw(ptr);
+ let val = boxed.get([vec.x, vec.y, vec.z, vec.w]);
+ mem::forget(boxed);
+ val
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn get_noise_tiled_2d(ptr: *mut NoiseGenerator, vec: Vec2) -> f64 {
+ let boxed = Box::from_raw(ptr);
+ let val = actual_get_noise_tiled_2d(&boxed, [vec.x, vec.y]);
+ mem::forget(boxed);
+ val
+}
+
+fn actual_get_noise_tiled_2d(gen: &NoiseGenerator, point: Point2) -> f64 {
+ // https://www.gamedev.net/blogs/entry/2138456-seamless-noise/
+ let s = point[0] / gen.period_x;
+ let t = point[1] / gen.period_y;
+
+ const X1: f64 = 0f64;
+ const X2: f64 = 1f64;
+ const Y1: f64 = 0f64;
+ const Y2: f64 = 1f64;
+
+ const DX: f64 = X2 - X1;
+ const DY: f64 = Y2 - Y1;
+
+ const TAU: f64 = std::f64::consts::PI * 2f64;
+
+ let nx = X1 + (s * TAU).cos() * (DX / TAU);
+ let ny = Y1 + (t * TAU).cos() * (DY / TAU);
+ let nz = X1 + (s * TAU).sin() * (DX / TAU);
+ let nw = Y1 + (t * TAU).sin() * (DY / TAU);
+
+ gen.get([nx, ny, nz, nw])
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn generator_set_frequency(ptr: *mut NoiseGenerator, frequency: f64) {
+ let mut boxed = Box::from_raw(ptr);
+ boxed.set_frequency(frequency);
+ mem::forget(boxed);
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn generator_set_octaves(ptr: *mut NoiseGenerator, octaves: u32) {
+ let mut boxed = Box::from_raw(ptr);
+ boxed.set_octaves(octaves as usize);
+ mem::forget(boxed);
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn generator_set_lacunarity(ptr: *mut NoiseGenerator, lacunarity: f64) {
+ let mut boxed = Box::from_raw(ptr);
+ boxed.set_lacunarity(lacunarity);
+ mem::forget(boxed);
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn generator_set_persistence(ptr: *mut NoiseGenerator, persistence: f64) {
+ let mut boxed = Box::from_raw(ptr);
+ boxed.set_persistence(persistence);
+ mem::forget(boxed);
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn generator_set_period_x(ptr: *mut NoiseGenerator, period_x: f64) {
+ let mut boxed = Box::from_raw(ptr);
+ boxed.period_x = period_x;
+ mem::forget(boxed);
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn generator_set_period_y(ptr: *mut NoiseGenerator, period_y: f64) {
+ let mut boxed = Box::from_raw(ptr);
+ boxed.period_y = period_y;
+ mem::forget(boxed);
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn generator_set_seed(ptr: *mut NoiseGenerator, seed: u32) {
+ let mut boxed = Box::from_raw(ptr);
+ boxed.set_seed(seed);
+ mem::forget(boxed);
+}
diff --git a/SS14.Shared/SS14.Shared.csproj b/SS14.Shared/SS14.Shared.csproj
index b7c1057865c..8fae0c9ae0a 100644
--- a/SS14.Shared/SS14.Shared.csproj
+++ b/SS14.Shared/SS14.Shared.csproj
@@ -222,6 +222,7 @@
+
@@ -378,4 +379,9 @@
+
+
+ PreserveNewest
+
+
\ No newline at end of file
diff --git a/SS14.Shared/SS14.Shared.dll.config b/SS14.Shared/SS14.Shared.dll.config
new file mode 100644
index 00000000000..9f7bf30570d
--- /dev/null
+++ b/SS14.Shared/SS14.Shared.dll.config
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/Tools/download_ss14_noise.py b/Tools/download_ss14_noise.py
new file mode 100644
index 00000000000..11d32448fcf
--- /dev/null
+++ b/Tools/download_ss14_noise.py
@@ -0,0 +1,78 @@
+#!/usr/bin/env python3
+import os
+import sys
+import urllib.request
+import shutil
+
+CURRENT_VERSION = "noise_0.0.1"
+RELEASES_ROOT = "https://github.com/space-wizards/space-station-14/releases/download/" \
+ + CURRENT_VERSION + "/"
+WINDOWS_FILENAME = "ss14_noise-x86_64-pc-windows-msvc.dll"
+MACOS_FILENAME = "libss14_noise-x86_64-apple-darwin.dylib"
+LINUX_FILENAME = "libss14_noise-x86_64-unknown-linux-gnu.so"
+
+WINDOWS_TARGET_FILENAME = "ss14_noise.dll"
+LINUX_TARGET_FILENAME = "libss14_noise.so"
+MACOS_TARGET_FILENAME = "libss14_noise.dylib"
+
+
+def main():
+ platform = sys.argv[1]
+ target_os = sys.argv[2]
+ # Hah good luck passing something containing a space to the Exec MSBuild Task.
+ target_dir = " ".join(sys.argv[3:])
+
+ if platform != "x64":
+ print("Error: Unable to download ss14_noise for any platform outside x64. "
+ "If you REALLY want x86 support for some misguided reason, I'm not providing it.")
+ exit(1)
+
+ repo_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
+ dependencies_dir = os.path.join(repo_dir, "Dependencies", "ss14_noise")
+ version_file = os.path.join(dependencies_dir, "VERSION")
+ os.makedirs(dependencies_dir, exist_ok=True)
+
+ existing_version = "?"
+ if os.path.exists(version_file):
+ with open(version_file, "r") as f:
+ existing_version = f.read().strip()
+
+ if existing_version != CURRENT_VERSION:
+ for x in os.listdir(dependencies_dir):
+ os.remove(x)
+
+ with open(version_file, "w") as f:
+ f.write(CURRENT_VERSION)
+
+ filename = None
+ target_filename = None
+
+ if target_os == "Windows":
+ filename = WINDOWS_FILENAME
+ target_filename = WINDOWS_TARGET_FILENAME
+
+ elif target_os == "Linux":
+ filename = LINUX_FILENAME
+ target_filename = LINUX_TARGET_FILENAME
+
+ elif target_os == "MacOS":
+ filename = MACOS_FILENAME
+ target_filename = MACOS_TARGET_FILENAME
+
+ else:
+ print("Error: Unknown platform target:", target_os)
+ exit(2)
+
+ dependency_path = os.path.join(dependencies_dir, filename)
+ if not os.path.exists(dependency_path):
+ urllib.request.urlretrieve(RELEASES_ROOT + filename, dependency_path)
+
+ target_file_path = os.path.join(target_dir, target_filename)
+
+ if not os.path.exists(target_file_path) or \
+ os.stat(dependency_path).st_mtime > os.stat(target_file_path).st_mtime:
+ shutil.copy2(dependency_path, target_file_path)
+
+
+if __name__ == '__main__':
+ main()