A plugin that allows for the loading of objects contained within sloc files in SCP: Secret Laboratory.
Before this project was started, I had no knowledge of the MapEditorReborn plugin.
This is not meant to be a clone of MER, but a different approach to be able to load Unity Scenes in SCP: Secret Laboratory.
Check out MapEditorReborn here
sloc stands for Secret Laboratory Object Container.
An sloc file can contain primitive Unity objects (spheres, cubes etc.) and also lights.
To create an sloc file, use slocExporter
sloc files are not text, but raw bytes. This means that opening one in a text editor will produce gibberish, since it's not meant to be interpreted as text. It is a sequence of integers and floats.
sloc aims to retain the object hierarchy exactly as is in the Unity editor, meaning you can use GetComponent(s)InChildren on the server to find child objects.
Important
Axwabo.Helpers is required as a dependency.
- Install Axwabo.Helpers
- Install Harmony 2.2.2 as a dependency, you need the net4.8 version
- Download the
Harmony.2.2.2.0.zipasset - Extract the
net48/0Harmony.dllfile from the archive to thedependenciesfolder:- Windows:
%appdata%\SCP Secret Laboratory\LabAPI-Beta\dependencies\<port> - Linux:
.config/SCP Secret Laboratory/LabAPI-Beta/dependencies/<port>
- Windows:
- Download the
- Download the
slocLoader.dllfile from the latest release - Place the DLL into the
pluginsfolder:- Windows:
%appdata%\SCP Secret Laboratory\LabAPI\plugins\<port> - Linux:
.config/SCP Secret Laboratory/LabAPI/plugins/<port>
- Windows:
- Restart your server
To load objects automatically, put your sloc file into:
- Windows:
%appdata%\SCP Secret Laboratory\LabAPI\configs\<port>\slocLoader\Objects - Linux:
.config/SCP Secret Laboratory/LabAPI/configs/<port>/slocLoader/Objects
Make sure the auto_load property in the plugin config is set to true.
The objects in the folder above will be loaded automatically when the map is generated.
Use the sl_spawn command and the name of the object file (without the extension) in-game to spawn an object.
Example: sl_spawn test
To remove previously spawned objects, use the sl_destroy command. It takes the netID of the object, which the spawn command outputs.
Make sure the enable_auto_spawn property in the plugin config is set to true.
View the list of room names and types here
In the plugin config, add an item to the auto_spawn_by_room_name, auto_spawn_by_room_type or auto_spawn_by_location list. There are examples provider for ease of use.
Room name template:
asset_name: example
point:
room_name: HCZ_079
position_offset:
x: 0
y: 0
z: 0
rotation_offset:
x: 0
y: 0
z: 0
make_objects_static: falseRoomType template:
asset_name: example
point:
type: LczClassDSpawn
position_offset:
x: 0
y: 0
z: 0
rotation_offset:
x: 0
y: 0
z: 0
make_objects_static: trueStaticPosition template:
asset_name: example
point:
position:
x: 10
y: 0
z: 50
rotation:
x: 0
y: 90
z: 0
make_objects_static: falseAll assets that have been loaded by the AutomaticObjectLoader will be spawned in the room specified.
If an asset was not loaded, it will be ignored.
Rotation offsets are specified using Euler angles, not Quaternions.
The make_objects_static property defaults to false. Setting it to true will boost server performance as transform updates will not be sent to the client (can cause desync if plugins move the objects).
The sl_spawn command can be used to spawn assets through the Remote Admin. Required permission is FacilityManagement
Example: sl_s MyObject
The asset has to be defined as in automatic spawning
Your position and horizontal rotation will be applied to the objects by default. To modify this behavior, use the sl_position and sl_rotation commands.
For example, sl_pos 0 1000 0 will spawn the specified object at the coordinates 0, 1000, 0 (x, y, z)
To clear the current settings, simply type sl_pos or sl_rot to remove the defined values.
The plugin offers various methods to make loading objects easy.
Add the DLL as an assembly reference to get started.
You can spawn objects directly from a file, or from within your assembly
Use the methods in the slocLoader.API class to load objects.
Make sure to do this after the prefabs are loaded; register a handler to the PrefabsLoaded event contained in the API class.
using AdminToys;
using LabApi.Loader;
using slocLoader;
using slocLoader.AutoObjectLoader;
using slocLoader.ObjectCreation;
var config = MyPlugin.Instance.GetConfigDirectory().FullName;
var test = API.SpawnObjects(
Path.Combine(config, "test.sloc"),
Vector3.up * 300,
Quaternion.Euler(0, 180, 0)
);
// make primitives slightly transparent
foreach (var primitive in test.GetComponentsInChildren<PrimitiveObjectToy>())
primitive.NetworkMaterialColor = primitive.NetworkMaterialColor with {a = 0.8f};
if (AutomaticObjectLoader.TryGetObjects("test2", out var objects))
API.SpawnObjects(objects, new CreateOptions
{
Position = new Vector3(-5, 300, 0),
StaticRoot = true, // root object does not move
IsStatic = true, // children don't move
Scale = Vector3.one * 0.5f
});
// ConstantMove component that moves the root object every frame
API.SpawnObjects(Path.Combine(config, "moving.sloc"), new CreateOptions
{
IsStatic = true, // children don't move, only the root does
RootSmoothing = 20
}).AddComponent<ConstantMove>();Example of spawning a singular object:
using UnityEngine;
using slocLoader;
using slocLoader.Objects;
new PrimitiveObject(ObjecType.Capsule) // non-primitive type will throw an exception
{
Transform =
{
Position = new Vector3(0, 50, 0),
Rotation = Quaternion.Euler(0, 50, 0),
Scale = new Vector3(2, 1, 2)
},
Flags = PrimitiveObjectFlags.ServerCollider | PrimitiveObjectFlags.Trigger,
MaterialColor = Color.red
}.SpawnObject();Each exported sloc file has a version number.
Even if a new version of sloc is released, old sloc files will still be compatible with the current version of the plugin due to the versioning system.
All versions have their own object readers to read the objects from the sloc file. This way, no sloc file will be broken after a new version is released.
